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