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 | |