1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef BERBERIS_INTRINSICS_TYPE_TRAITS_H_
18 #define BERBERIS_INTRINSICS_TYPE_TRAITS_H_
19 
20 #if defined(__i386__) || defined(__x86_64__)
21 #include <xmmintrin.h>
22 #endif
23 
24 #include <cstdint>
25 
26 #include "berberis/intrinsics/common/intrinsics_float.h"
27 #include "berberis/intrinsics/simd_register.h"
28 
29 namespace berberis {
30 
31 // In specializations we define various derivative types:
32 //  Wide - type twice as wide, same signedness
33 template <typename T>
34 struct TypeTraits;
35 
36 template <>
37 struct TypeTraits<uint8_t> {
38   using Wide = uint16_t;
39   static constexpr int kBits = 8;
40   static constexpr char kName[] = "uint8_t";
41 };
42 
43 template <>
44 struct TypeTraits<uint16_t> {
45   using Wide = uint32_t;
46   using Narrow = uint8_t;
47   static constexpr int kBits = 16;
48   static constexpr char kName[] = "uint16_t";
49 };
50 
51 template <>
52 struct TypeTraits<uint32_t> {
53   using Wide = uint64_t;
54   using Narrow = uint16_t;
55   using Float = intrinsics::Float32;
56   static constexpr int kBits = 32;
57   static constexpr char kName[] = "uint32_t";
58 };
59 
60 template <>
61 struct TypeTraits<uint64_t> {
62   using Narrow = uint32_t;
63 #if defined(__x86_64__)
64   using Wide = __uint128_t;
65 #endif
66   using Float = intrinsics::Float64;
67   static constexpr int kBits = 64;
68   static constexpr char kName[] = "uint64_t";
69 };
70 
71 template <>
72 struct TypeTraits<int8_t> {
73   using Wide = int16_t;
74   static constexpr int kBits = 8;
75   static constexpr char kName[] = "int8_t";
76 };
77 
78 template <>
79 struct TypeTraits<int16_t> {
80   using Wide = int32_t;
81   using Narrow = int8_t;
82   static constexpr int kBits = 16;
83   static constexpr char kName[] = "int16_t";
84 };
85 
86 template <>
87 struct TypeTraits<int32_t> {
88   using Wide = int64_t;
89   using Narrow = int16_t;
90   using Float = intrinsics::Float32;
91   static constexpr int kBits = 32;
92   static constexpr char kName[] = "int32_t";
93 };
94 
95 template <>
96 struct TypeTraits<int64_t> {
97   using Narrow = int32_t;
98 #if defined(__x86_64__)
99   using Wide = __int128_t;
100 #endif
101   using Float = intrinsics::Float64;
102   static constexpr int kBits = 64;
103   static constexpr char kName[] = "int64_t";
104 };
105 
106 template <>
107 struct TypeTraits<intrinsics::Float8> {
108   using Int = int8_t;
109   using Raw = intrinsics::Float8PhonyType;
110   using Wide = intrinsics::Float16;
111   static constexpr int kBits = 8;
112   static constexpr char kName[] = "Float8";
113 };
114 
115 template <>
116 struct TypeTraits<intrinsics::Float16> {
117   using Int = int16_t;
118   using Raw = _Float16;
119   using Narrow = intrinsics::Float8;
120   using Wide = intrinsics::Float32;
121   static constexpr int kBits = 16;
122   static constexpr char kName[] = "Float16";
123 };
124 
125 template <>
126 struct TypeTraits<intrinsics::Float32> {
127   using Int = int32_t;
128   using Raw = float;
129   using Narrow = intrinsics::Float16;
130   using Wide = intrinsics::Float64;
131   static constexpr int kBits = 32;
132   static constexpr char kName[] = "Float32";
133 };
134 
135 template <>
136 struct TypeTraits<intrinsics::Float64> {
137   using Int = int64_t;
138   using Raw = double;
139   using Narrow = intrinsics::Float32;
140 #if defined(__x86_64__)
141   static_assert(sizeof(long double) > sizeof(intrinsics::Float64));
142   using Wide = long double;
143 #endif
144   static constexpr int kBits = 64;
145   static constexpr char kName[] = "Float64";
146 };
147 
148 template <>
149 struct TypeTraits<float> {
150   using Int = int32_t;
151   using Wrapped = intrinsics::Float32;
152   using Wide = double;
153   static constexpr int kBits = 32;
154   static constexpr char kName[] = "float";
155 };
156 
157 template <>
158 struct TypeTraits<double> {
159   using Int = int64_t;
160   using Wrapped = intrinsics::Float64;
161 #if defined(__x86_64__)
162   static_assert(sizeof(long double) > sizeof(intrinsics::Float64));
163   using Wide = long double;
164 #endif
165   using Narrow = float;
166   static constexpr int kBits = 64;
167   static constexpr char kName[] = "double";
168 };
169 
170 template <>
171 struct TypeTraits<SIMD128Register> {
172 #if defined(__i386__) || defined(__x86_64__)
173   using Raw = __m128;
174 #endif
175   static constexpr char kName[] = "SIMD128Register";
176 };
177 
178 #if defined(__x86_64__)
179 
180 template <>
181 struct TypeTraits<long double> {
182   using Narrow = intrinsics::Float64;
183   static constexpr char kName[] = "long double";
184 };
185 
186 template <>
187 struct TypeTraits<__int128_t> {
188   using Narrow = int64_t;
189   static constexpr int kBits = 128;
190   static constexpr char kName[] = "__int128_t";
191 };
192 
193 template <>
194 struct TypeTraits<__uint128_t> {
195   using Narrow = uint64_t;
196   static constexpr int kBits = 128;
197   static constexpr char kName[] = "__uint128_t";
198 };
199 
200 #endif
201 
202 #if defined(__i386__) || defined(__x86_64__)
203 
204 template <>
205 struct TypeTraits<__m128> {
206   static constexpr int kBits = 128;
207   static constexpr char kName[] = "__m128";
208 };
209 
210 #endif
211 
212 }  // namespace berberis
213 
214 #endif  // BERBERIS_INTRINSICS_TYPE_TRAITS_H_
215