| 1 | // Licensed to the .NET Foundation under one or more agreements. |
| 2 | // The .NET Foundation licenses this file to you under the MIT license. |
| 3 | // See the LICENSE file in the project root for more information. |
| 4 | |
| 5 | #ifndef _SIMD_H_ |
| 6 | #define _SIMD_H_ |
| 7 | |
| 8 | // Underlying hardware information |
| 9 | // This type is used to control |
| 10 | // 1. The length of System.Numerics.Vector<T>. |
| 11 | // 2. Codegen of System.Numerics.Vectors. |
| 12 | // 3. Codegen of floating-point arithmetics (VEX-encoding or not). |
| 13 | // |
| 14 | // Note |
| 15 | // - Hardware SIMD support is classified to the levels. Do not directly use |
| 16 | // InstructionSet (instr.h) for System.Numerics.Vectors. |
| 17 | // - Values of SIMDLevel have strictly increasing order that each SIMD level |
| 18 | // is a superset of the previous levels. |
| 19 | enum SIMDLevel |
| 20 | { |
| 21 | SIMD_Not_Supported = 0, |
| 22 | #ifdef _TARGET_XARCH_ |
| 23 | // SSE2 - The min bar of SIMD ISA on x86/x64. |
| 24 | // Vector<T> length is 128-bit. |
| 25 | // Floating-point instructions are legacy SSE encoded. |
| 26 | SIMD_SSE2_Supported = 1, |
| 27 | |
| 28 | // SSE4 - RyuJIT may generate SSE3, SSSE3, SSE4.1 and SSE4.2 instructions for certain intrinsics. |
| 29 | // Vector<T> length is 128-bit. |
| 30 | // Floating-point instructions are legacy SSE encoded. |
| 31 | SIMD_SSE4_Supported = 2, |
| 32 | |
| 33 | // AVX2 - Hardware has AVX and AVX2 instruction set. |
| 34 | // Vector<T> length is 256-bit and SIMD instructions are VEX-256 encoded. |
| 35 | // Floating-point instructions are VEX-128 encoded. |
| 36 | SIMD_AVX2_Supported = 3 |
| 37 | #endif |
| 38 | }; |
| 39 | |
| 40 | #ifdef FEATURE_SIMD |
| 41 | |
| 42 | #ifdef DEBUG |
| 43 | extern const char* const simdIntrinsicNames[]; |
| 44 | #endif |
| 45 | |
| 46 | enum SIMDIntrinsicID |
| 47 | { |
| 48 | #define SIMD_INTRINSIC(m, i, id, n, r, ac, arg1, arg2, arg3, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) SIMDIntrinsic##id, |
| 49 | #include "simdintrinsiclist.h" |
| 50 | }; |
| 51 | |
| 52 | // Static info about a SIMD intrinsic |
| 53 | struct SIMDIntrinsicInfo |
| 54 | { |
| 55 | SIMDIntrinsicID id; |
| 56 | const char* methodName; |
| 57 | bool isInstMethod; |
| 58 | var_types retType; |
| 59 | unsigned char argCount; |
| 60 | var_types argType[SIMD_INTRINSIC_MAX_MODELED_PARAM_COUNT]; |
| 61 | var_types supportedBaseTypes[SIMD_INTRINSIC_MAX_BASETYPE_COUNT]; |
| 62 | }; |
| 63 | |
| 64 | #ifdef _TARGET_XARCH_ |
| 65 | // SSE2 Shuffle control byte to shuffle vector <W, Z, Y, X> |
| 66 | // These correspond to shuffle immediate byte in shufps SSE2 instruction. |
| 67 | #define SHUFFLE_XXXX 0x00 // 00 00 00 00 |
| 68 | #define SHUFFLE_XXZX 0x08 // 00 00 10 00 |
| 69 | #define SHUFFLE_XXWW 0x0F // 00 00 11 11 |
| 70 | #define SHUFFLE_XYZW 0x1B // 00 01 10 11 |
| 71 | #define SHUFFLE_YXYX 0x44 // 01 00 01 00 |
| 72 | #define SHUFFLE_YWXZ 0x72 // 01 11 00 10 |
| 73 | #define SHUFFLE_YYZZ 0x5A // 01 01 10 10 |
| 74 | #define SHUFFLE_ZXXX 0x80 // 10 00 00 00 |
| 75 | #define SHUFFLE_ZXXY 0x81 // 10 00 00 01 |
| 76 | #define SHUFFLE_ZWXY 0xB1 // 10 11 00 01 |
| 77 | #define SHUFFLE_WYZX 0xD8 // 11 01 10 00 |
| 78 | #define SHUFFLE_WWYY 0xF5 // 11 11 01 01 |
| 79 | #define SHUFFLE_ZZXX 0xA0 // 10 10 00 00 |
| 80 | #endif |
| 81 | |
| 82 | #endif // FEATURE_SIMD |
| 83 | |
| 84 | #endif //_SIMD_H_ |
| 85 | |