vecconsttable.h (15110B)
1 // This file is part of AsmJit project <https://asmjit.com> 2 // 3 // See <asmjit/core.h> or LICENSE.md for license and copyright information 4 // SPDX-License-Identifier: Zlib 5 6 #ifndef ASMJIT_UJIT_VECCONSTTABLE_H_INCLUDED 7 #define ASMJIT_UJIT_VECCONSTTABLE_H_INCLUDED 8 9 #include "../core/globals.h" 10 11 #if !defined(ASMJIT_NO_UJIT) 12 13 ASMJIT_BEGIN_SUB_NAMESPACE(ujit) 14 15 //! \addtogroup asmjit_ujit 16 //! \{ 17 18 template<typename T, size_t W> 19 struct VecConst; 20 21 //! \cond 22 23 //! A 64-bit vector constant of type `T` aligned to 64 bits. 24 template<typename T> 25 struct ASMJIT_MAY_ALIAS ASMJIT_ALIGNAS(8) VecConst<T, 8> { 26 using ElementType = T; 27 28 static inline constexpr size_t kVectorWidth = 8; 29 static inline constexpr size_t kElementSize = sizeof(ElementType); 30 static inline constexpr size_t kElementCount = kVectorWidth / kElementSize; 31 32 static_assert(kElementCount > 0u, "Vector constant must have at least one element"); 33 34 ElementType data[kElementCount]; 35 36 template<typename DstT> 37 ASMJIT_INLINE_NODEBUG const DstT& as() const noexcept { 38 static_assert(sizeof(DstT) <= sizeof(*this), "Size of the destination type DstT must be <= 8"); 39 return *static_cast<const DstT*>(static_cast<const void*>(this)); 40 } 41 }; 42 43 //! A 128-bit vector constant of type `T` aligned to 128 bits. 44 template<typename T> 45 struct ASMJIT_MAY_ALIAS ASMJIT_ALIGNAS(16) VecConst<T, 16> { 46 using ElementType = T; 47 48 static inline constexpr size_t kVectorWidth = 16; 49 static inline constexpr size_t kElementSize = sizeof(ElementType); 50 static inline constexpr size_t kElementCount = kVectorWidth / kElementSize; 51 52 static_assert(kElementCount > 0u, "Vector constant must have at least one element"); 53 54 ElementType data[kElementCount]; 55 56 template<typename DstT> 57 ASMJIT_INLINE_NODEBUG const DstT& as() const noexcept { 58 static_assert(sizeof(DstT) <= sizeof(*this), "Size of the destination type DstT must be <= 16"); 59 return *static_cast<const DstT*>(static_cast<const void*>(this)); 60 } 61 }; 62 63 //! A 256-bit vector constant of type `T` aligned to 256 bits. 64 template<typename T> 65 struct ASMJIT_MAY_ALIAS ASMJIT_ALIGNAS(32) VecConst<T, 32> { 66 using ElementType = T; 67 68 static inline constexpr size_t kVectorWidth = 32; 69 static inline constexpr size_t kElementSize = sizeof(ElementType); 70 static inline constexpr size_t kElementCount = kVectorWidth / kElementSize; 71 72 static_assert(kElementCount > 0u, "Vector constant must have at least one element"); 73 74 ElementType data[kElementCount]; 75 76 template<typename DstT> 77 ASMJIT_INLINE_NODEBUG const DstT& as() const noexcept { 78 static_assert(sizeof(DstT) <= sizeof(*this), "Size of the destination type DstT must be <= 32"); 79 return *static_cast<const DstT*>(static_cast<const void*>(this)); 80 } 81 }; 82 83 //! A 512-bit vector constant of type `T` aligned to 512 bits. 84 template<typename T> 85 struct ASMJIT_MAY_ALIAS ASMJIT_ALIGNAS(64) VecConst<T, 64> { 86 using ElementType = T; 87 88 static inline constexpr size_t kVectorWidth = 64; 89 static inline constexpr size_t kElementSize = sizeof(ElementType); 90 static inline constexpr size_t kElementCount = kVectorWidth / kElementSize; 91 92 static_assert(kElementCount > 0u, "Vector constant must have at least one element"); 93 94 ElementType data[kElementCount]; 95 96 template<typename DstT> 97 ASMJIT_INLINE_NODEBUG const DstT& as() const noexcept { 98 static_assert(sizeof(DstT) <= sizeof(*this), "Size of the destination type DstT must be <= 64"); 99 return *static_cast<const DstT*>(static_cast<const void*>(this)); 100 } 101 }; 102 103 //! \endcond 104 105 template<typename T> using VecConst64 = VecConst<T, 8>; 106 template<typename T> using VecConst128 = VecConst<T, 16>; 107 template<typename T> using VecConst256 = VecConst<T, 32>; 108 template<typename T> using VecConst512 = VecConst<T, 64>; 109 110 #if ASMJIT_ARCH_X86 111 // The maximum native constants we want to use in X86 case is 256-bit ones, because in AVX-512 case 112 // we want to just broadcast the constant to all lanes. The reason is to not end up with a huge table. 113 template<typename T> using VecConstNative = VecConst256<T>; 114 #else 115 // At the moment all non-x86 platforms support at most 128-bit vectors, thus the maximum width of each 116 // constant is limited to 128 bits as well. Future additions could include LoongArch, which supports 117 // 256-bit SIMD vectors natively. 118 template<typename T> using VecConstNative = VecConst128<T>; 119 #endif 120 121 template<typename V, typename T = typename V::ElementType> 122 static ASMJIT_INLINE_CONSTEXPR V make_const(T v) noexcept { 123 static_assert(V::kElementCount == 1u || 124 V::kElementCount == 2u || 125 V::kElementCount == 4u || 126 V::kElementCount == 8u || 127 V::kElementCount == 16u || 128 V::kElementCount == 32u || 129 V::kElementCount == 64u); 130 131 if constexpr (V::kElementCount == 1u) { 132 return V{{ 133 v 134 }}; 135 } 136 else if constexpr (V::kElementCount == 2u) { 137 return V{{ 138 v, v 139 }}; 140 } 141 else if constexpr (V::kElementCount == 4u) { 142 return V{{ 143 v, v, v, v 144 }}; 145 } 146 else if constexpr (V::kElementCount == 8u) { 147 return V{{ 148 v, v, v, v, v, v, v, v 149 }}; 150 } 151 else if constexpr (V::kElementCount == 16u) { 152 return V{{ 153 v, v, v, v, v, v, v, v, 154 v, v, v, v, v, v, v, v 155 }}; 156 } 157 else if constexpr (V::kElementCount == 32u) { 158 return V{{ 159 v, v, v, v, v, v, v, v, 160 v, v, v, v, v, v, v, v, 161 v, v, v, v, v, v, v, v, 162 v, v, v, v, v, v, v, v 163 }}; 164 } 165 else { 166 return V{{ 167 v, v, v, v, v, v, v, v, 168 v, v, v, v, v, v, v, v, 169 v, v, v, v, v, v, v, v, 170 v, v, v, v, v, v, v, v, 171 v, v, v, v, v, v, v, v, 172 v, v, v, v, v, v, v, v, 173 v, v, v, v, v, v, v, v, 174 v, v, v, v, v, v, v, v 175 }}; 176 } 177 } 178 179 template<typename V, typename T = typename V::ElementType> 180 static ASMJIT_INLINE_CONSTEXPR V make_const(T h, T l) noexcept { 181 static_assert(V::kElementCount == 2u || 182 V::kElementCount == 4u || 183 V::kElementCount == 8u || 184 V::kElementCount == 16u || 185 V::kElementCount == 32u || 186 V::kElementCount == 64u); 187 188 if constexpr (V::kElementCount == 2u) { 189 return V{{ 190 l, h 191 }}; 192 } 193 else if constexpr (V::kElementCount == 4u) { 194 return V{{ 195 l, h, l, h 196 }}; 197 } 198 else if constexpr (V::kElementCount == 8u) { 199 return V{{ 200 l, h, l, h, l, h, l, h 201 }}; 202 } 203 else if constexpr (V::kElementCount == 16u) { 204 return V{{ 205 l, h, l, h, l, h, l, h, 206 l, h, l, h, l, h, l, h 207 }}; 208 } 209 else if constexpr (V::kElementCount == 32u) { 210 return V{{ 211 l, h, l, h, l, h, l, h, 212 l, h, l, h, l, h, l, h, 213 l, h, l, h, l, h, l, h, 214 l, h, l, h, l, h, l, h 215 }}; 216 } 217 else { 218 return V{{ 219 l, h, l, h, l, h, l, h, 220 l, h, l, h, l, h, l, h, 221 l, h, l, h, l, h, l, h, 222 l, h, l, h, l, h, l, h, 223 l, h, l, h, l, h, l, h, 224 l, h, l, h, l, h, l, h, 225 l, h, l, h, l, h, l, h, 226 l, h, l, h, l, h, l, h 227 }}; 228 } 229 } 230 231 template<typename V, typename T = typename V::ElementType> 232 static ASMJIT_INLINE_CONSTEXPR V make_const(T d, T c, T b, T a) noexcept { 233 static_assert(V::kElementCount == 4u || 234 V::kElementCount == 8u || 235 V::kElementCount == 16u || 236 V::kElementCount == 32u || 237 V::kElementCount == 64u); 238 239 if constexpr (V::kElementCount == 4u) { 240 return V{{ 241 a, b, c, d 242 }}; 243 } 244 else if constexpr (V::kElementCount == 8u) { 245 return V{{ 246 a, b, c, d, a, b, c, d 247 }}; 248 } 249 else if constexpr (V::kElementCount == 16u) { 250 return V{{ 251 a, b, c, d, a, b, c, d, 252 a, b, c, d, a, b, c, d 253 }}; 254 } 255 else if constexpr (V::kElementCount == 32u) { 256 return V{{ 257 a, b, c, d, a, b, c, d, 258 a, b, c, d, a, b, c, d, 259 a, b, c, d, a, b, c, d, 260 a, b, c, d, a, b, c, d 261 }}; 262 } 263 else { 264 return V{{ 265 a, b, c, d, a, b, c, d, 266 a, b, c, d, a, b, c, d, 267 a, b, c, d, a, b, c, d, 268 a, b, c, d, a, b, c, d, 269 a, b, c, d, a, b, c, d, 270 a, b, c, d, a, b, c, d, 271 a, b, c, d, a, b, c, d, 272 a, b, c, d, a, b, c, d 273 }}; 274 } 275 } 276 277 template<typename V, typename T = typename V::ElementType> 278 static ASMJIT_INLINE_CONSTEXPR V make_const(T h, T g, T f, T e, T d, T c, T b, T a) noexcept { 279 static_assert(V::kElementCount == 8u || 280 V::kElementCount == 16u || 281 V::kElementCount == 32u || 282 V::kElementCount == 64u); 283 284 if constexpr (V::kElementCount == 8u) { 285 return V{{ 286 a, b, c, d, e, f, g, h 287 }}; 288 } 289 else if constexpr (V::kElementCount == 16u) { 290 return V{{ 291 a, b, c, d, e, f, g, h, 292 a, b, c, d, e, f, g, h 293 }}; 294 } 295 else if constexpr (V::kElementCount == 32u) { 296 return V{{ 297 a, b, c, d, e, f, g, h, 298 a, b, c, d, e, f, g, h, 299 a, b, c, d, e, f, g, h, 300 a, b, c, d, e, f, g, h 301 }}; 302 } 303 else { 304 return V{{ 305 a, b, c, d, e, f, g, h, 306 a, b, c, d, e, f, g, h, 307 a, b, c, d, e, f, g, h, 308 a, b, c, d, e, f, g, h, 309 a, b, c, d, e, f, g, h, 310 a, b, c, d, e, f, g, h, 311 a, b, c, d, e, f, g, h, 312 a, b, c, d, e, f, g, h 313 }}; 314 } 315 } 316 317 template<typename V, typename T = typename V::ElementType> 318 static ASMJIT_INLINE_CONSTEXPR V make_const( 319 T p, T o, T n, T m, T l, T k, T j, T i, T h, T g, T f, T e, T d, T c, T b, T a 320 ) noexcept { 321 static_assert(V::kElementCount == 16u || 322 V::kElementCount == 32u || 323 V::kElementCount == 64u); 324 325 if constexpr (V::kElementCount == 16u) { 326 return V{{ 327 a, b, c, d, e, f, g, h, 328 i, j, k, l, m, n, o, p 329 }}; 330 } 331 else if constexpr (V::kElementCount == 32u) { 332 return V{{ 333 a, b, c, d, e, f, g, h, 334 i, j, k, l, m, n, o, p, 335 a, b, c, d, e, f, g, h, 336 i, j, k, l, m, n, o, p 337 }}; 338 } 339 else { 340 return V{{ 341 a, b, c, d, e, f, g, h, 342 i, j, k, l, m, n, o, p, 343 a, b, c, d, e, f, g, h, 344 i, j, k, l, m, n, o, p, 345 a, b, c, d, e, f, g, h, 346 i, j, k, l, m, n, o, p, 347 a, b, c, d, e, f, g, h, 348 i, j, k, l, m, n, o, p 349 }}; 350 } 351 } 352 353 template<typename V, typename T = typename V::ElementType> 354 static ASMJIT_INLINE_CONSTEXPR V make_const( 355 T p1, T o1, T n1, T m1, T l1, T k1, T j1, T i1, T h1, T g1, T f1, T e1, T d1, T c1, T b1, T a1, 356 T p0, T o0, T n0, T m0, T l0, T k0, T j0, T i0, T h0, T g0, T f0, T e0, T d0, T c0, T b0, T a0 357 ) noexcept { 358 static_assert(V::kElementCount == 32u || 359 V::kElementCount == 64u); 360 361 if constexpr (V::kElementCount == 32u) { 362 return V{{ 363 a0, b0, c0, d0, e0, f0, g0, h0, 364 i0, j0, k0, l0, m0, n0, o0, p0, 365 a1, b1, c1, d1, e1, f1, g1, h1, 366 i1, j1, k1, l1, m1, n1, o1, p1 367 }}; 368 } 369 else { 370 return V{{ 371 a0, b0, c0, d0, e0, f0, g0, h0, 372 i0, j0, k0, l0, m0, n0, o0, p0, 373 a1, b1, c1, d1, e1, f1, g1, h1, 374 i1, j1, k1, l1, m1, n1, o1, p1, 375 a0, b0, c0, d0, e0, f0, g0, h0, 376 i0, j0, k0, l0, m0, n0, o0, p0, 377 a1, b1, c1, d1, e1, f1, g1, h1, 378 i1, j1, k1, l1, m1, n1, o1, p1 379 }}; 380 } 381 } 382 383 template<typename V, typename T = typename V::ElementType> 384 static ASMJIT_INLINE_CONSTEXPR V make_const( 385 T p3, T o3, T n3, T m3, T l3, T k3, T j3, T i3, T h3, T g3, T f3, T e3, T d3, T c3, T b3, T a3, 386 T p2, T o2, T n2, T m2, T l2, T k2, T j2, T i2, T h2, T g2, T f2, T e2, T d2, T c2, T b2, T a2, 387 T p1, T o1, T n1, T m1, T l1, T k1, T j1, T i1, T h1, T g1, T f1, T e1, T d1, T c1, T b1, T a1, 388 T p0, T o0, T n0, T m0, T l0, T k0, T j0, T i0, T h0, T g0, T f0, T e0, T d0, T c0, T b0, T a0 389 ) noexcept { 390 static_assert(V::kElementCount == 64u); 391 392 return V{{ 393 a0, b0, c0, d0, e0, f0, g0, h0, 394 i0, j0, k0, l0, m0, n0, o0, p0, 395 a1, b1, c1, d1, e1, f1, g1, h1, 396 i1, j1, k1, l1, m1, n1, o1, p1, 397 a2, b2, c2, d2, e2, f2, g2, h2, 398 i2, j2, k2, l2, m2, n2, o2, p2, 399 a3, b3, c3, d3, e3, f3, g3, h3, 400 i3, j3, k3, l3, m3, n3, o3, p3 401 }}; 402 } 403 404 struct VecConstTable { 405 VecConstNative<uint64_t> p_0000000000000000 = make_const<VecConstNative<uint64_t>>(uint64_t(0x0000000000000000u)); 406 VecConstNative<uint64_t> p_FFFFFFFFFFFFFFFF = make_const<VecConstNative<uint64_t>>(uint64_t(0xFFFFFFFFFFFFFFFFu)); 407 408 VecConstNative<uint64_t> p_8080808080808080 = make_const<VecConstNative<uint64_t>>(uint64_t(0x8080808080808080u)); 409 VecConstNative<uint64_t> p_8000800080008000 = make_const<VecConstNative<uint64_t>>(uint64_t(0x8000800080008000u)); 410 VecConstNative<uint64_t> p_8000000080000000 = make_const<VecConstNative<uint64_t>>(uint64_t(0x8000000080000000u)); 411 VecConstNative<uint64_t> p_8000000000000000 = make_const<VecConstNative<uint64_t>>(uint64_t(0x8000000000000000u)); 412 413 VecConstNative<uint64_t> p_7F7F7F7F7F7F7F7F = make_const<VecConstNative<uint64_t>>(uint64_t(0x7F7F7F7F7F7F7F7Fu)); 414 VecConstNative<uint64_t> p_7FFF7FFF7FFF7FFF = make_const<VecConstNative<uint64_t>>(uint64_t(0x7FFF7FFF7FFF7FFFu)); 415 VecConstNative<uint64_t> p_7FFFFFFF7FFFFFFF = make_const<VecConstNative<uint64_t>>(uint64_t(0x7FFFFFFF7FFFFFFFu)); 416 VecConstNative<uint64_t> p_7FFFFFFFFFFFFFFF = make_const<VecConstNative<uint64_t>>(uint64_t(0x7FFFFFFFFFFFFFFFu)); 417 418 VecConstNative<uint64_t> p_0100010001000100 = make_const<VecConstNative<uint64_t>>(uint64_t(0x0100010001000100u)); 419 VecConstNative<uint64_t> p_00FF00FF00FF00FF = make_const<VecConstNative<uint64_t>>(uint64_t(0x00FF00FF00FF00FFu)); 420 VecConstNative<uint64_t> p_0F0F0F0F0F0F0F0F = make_const<VecConstNative<uint64_t>>(uint64_t(0x0F0F0F0F0F0F0F0Fu)); 421 422 VecConstNative<uint64_t> p_1010101010101010 = make_const<VecConstNative<uint64_t>>(uint64_t(0x1010101010101010u)); 423 424 VecConstNative<uint64_t> p_FFFFFFFF00000000 = make_const<VecConstNative<uint64_t>>(uint64_t(0xFFFFFFFF00000000u)); 425 426 VecConstNative<uint64_t> p_0000800000008000 = make_const<VecConstNative<uint64_t>>(uint64_t(0x0000800000008000u)); 427 428 VecConst128<uint32_t> sign32_scalar = make_const<VecConst128<uint32_t>>(0u, 0u, 0u, uint32_t(0x80000000u)); 429 VecConst128<uint64_t> sign64_scalar = make_const<VecConst128<uint64_t>>(uint64_t(0u), uint64_t(0x8000000000000000u)); 430 431 VecConstNative<uint64_t> f32_0_5_minus_1ulp = make_const<VecConstNative<uint64_t>>(0x3EFFFFFF3EFFFFFFu); // 0.49999997 (0.5f - 1ulp) 432 VecConstNative<float> f32_0_5 = make_const<VecConstNative<float>>(0.5f); 433 VecConstNative<float> f32_1 = make_const<VecConstNative<float>>(1.0f); 434 VecConstNative<float> f32_round_magic = make_const<VecConstNative<float>>(8388608.0f); 435 436 VecConstNative<uint64_t> f64_0_5_minus_1ulp = make_const<VecConstNative<uint64_t>>(0x3FDFFFFFFFFFFFFFu); // 0.49999999999999994 (0.5 - 1ulp). 437 VecConstNative<double> f64_0_5 = make_const<VecConstNative<double>>(0.5); 438 VecConstNative<double> f64_1 = make_const<VecConstNative<double>>(1.0); 439 VecConstNative<double> f64_round_magic = make_const<VecConstNative<double>>(4503599627370496.0); 440 }; 441 442 ASMJIT_VARAPI const VecConstTable vec_const_table; 443 444 struct VecConstTableRef { 445 const VecConstTable& table; 446 size_t size; 447 }; 448 449 //! \} 450 451 ASMJIT_END_SUB_NAMESPACE 452 453 #endif // !ASMJIT_NO_UJIT 454 #endif // ASMJIT_UJIT_VECCONSTTABLE_H_INCLUDED