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 | /*****************************************************************************/ |
6 | #ifndef SIMD_INTRINSIC |
7 | #error Define SIMD_INTRINSIC before including this file |
8 | #endif |
9 | /*****************************************************************************/ |
10 | |
11 | // clang-format off |
12 | #ifdef FEATURE_SIMD |
13 | |
14 | /* |
15 | Notes: |
16 | a) TYP_UNKNOWN means 'baseType' of SIMD vector which is not known apriori |
17 | b) Each method maps to a unique intrinsic Id |
18 | c) To facilitate argument types to be used as an array initializer, args are listed within "{}" braces. |
19 | d) Since comma is used as actual param seperator in a macro, TYP_UNDEF entries are added to keep param count constant. |
20 | e) TODO-Cleanup: when we plumb TYP_SIMD through front-end, replace TYP_STRUCT with TYP_SIMD. |
21 | */ |
22 | |
23 | #if defined(_TARGET_XARCH_) || defined(_TARGET_ARM64_) |
24 | |
25 | // Max number of parameters that we model in the table for SIMD intrinsic methods. |
26 | #define SIMD_INTRINSIC_MAX_MODELED_PARAM_COUNT 3 |
27 | |
28 | // Actual maximum number of parameters for any SIMD intrinsic method. |
29 | // Constructors that take either N values, or a smaller Vector plus additional element values, |
30 | // actually have more arguments than the "modeled" count. |
31 | #define SIMD_INTRINSIC_MAX_PARAM_COUNT 5 |
32 | |
33 | // Max number of base types supported by an intrinsic |
34 | #define SIMD_INTRINSIC_MAX_BASETYPE_COUNT 10 |
35 | |
36 | /*************************************************************************************************************************************************************************************************************************** |
37 | Method Name, Is Instance Intrinsic Id, Display Name, return type, Arg count, Individual argument types Supported base types |
38 | Method (including implicit "this") |
39 | ***************************************************************************************************************************************************************************************************************************/ |
40 | SIMD_INTRINSIC(nullptr, false, None, "None" , TYP_UNDEF, 0, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
41 | |
42 | SIMD_INTRINSIC("get_Count" , false, GetCount, "count" , TYP_INT, 0, {TYP_VOID, TYP_UNDEF, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
43 | SIMD_INTRINSIC("get_One" , false, GetOne, "one" , TYP_STRUCT, 0, {TYP_VOID, TYP_UNDEF, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
44 | SIMD_INTRINSIC("get_Zero" , false, GetZero, "zero" , TYP_STRUCT, 0, {TYP_VOID, TYP_UNDEF, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
45 | SIMD_INTRINSIC("get_AllOnes" , false, GetAllOnes, "allOnes" , TYP_STRUCT, 0, {TYP_VOID, TYP_UNDEF, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
46 | |
47 | // .ctor call or newobj - there are four forms. |
48 | // This form takes the object plus a value of the base (element) type: |
49 | SIMD_INTRINSIC(".ctor" , true, Init, "init" , TYP_VOID, 2, {TYP_BYREF, TYP_UNKNOWN, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
50 | // This form takes the object plus an array of the base (element) type: |
51 | SIMD_INTRINSIC(".ctor" , true, InitArray, "initArray" , TYP_VOID, 2, {TYP_BYREF, TYP_REF, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
52 | // This form takes the object, an array of the base (element) type, and an index into the array: |
53 | SIMD_INTRINSIC(".ctor" , true, InitArrayX, "initArray" , TYP_VOID, 3, {TYP_BYREF, TYP_REF, TYP_INT }, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
54 | // This form takes the object, and N values of the base (element) type. The actual number of arguments depends upon the Vector size, which must be a fixed type such as Vector2f/3f/4f |
55 | // Right now this intrinsic is supported only on fixed float vectors and hence the supported base types lists only TYP_FLOAT. |
56 | // This is currently the intrinsic that has the largest maximum number of operands - if we add new fixed vector types |
57 | // with more than 4 elements, the above SIMD_INTRINSIC_MAX_PARAM_COUNT will have to change. |
58 | SIMD_INTRINSIC(".ctor" , true, InitN, "initN" , TYP_VOID, 2, {TYP_BYREF, TYP_UNKNOWN, TYP_UNKNOWN}, {TYP_FLOAT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
59 | // This form takes the object, a smaller fixed vector, and one or two additional arguments of the base type, e.g. Vector3 V = new Vector3(V2, x); where V2 is a Vector2, and x is a float. |
60 | SIMD_INTRINSIC(".ctor" , true, InitFixed, "initFixed" , TYP_VOID, 3, {TYP_BYREF, TYP_STRUCT, TYP_UNKNOWN}, {TYP_FLOAT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
61 | |
62 | // Copy vector to an array |
63 | SIMD_INTRINSIC("CopyTo" , true, CopyToArray, "CopyToArray" , TYP_VOID, 2, {TYP_BYREF, TYP_REF, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
64 | SIMD_INTRINSIC("CopyTo" , true, CopyToArrayX, "CopyToArray" , TYP_VOID, 3, {TYP_BYREF, TYP_REF, TYP_INT }, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
65 | |
66 | // Get operations |
67 | SIMD_INTRINSIC("get_Item" , true, GetItem, "get[i]" , TYP_UNKNOWN, 2, {TYP_BYREF, TYP_INT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
68 | SIMD_INTRINSIC("get_X" , true, GetX, "getX" , TYP_UNKNOWN, 1, {TYP_BYREF, TYP_UNDEF, TYP_UNDEF}, {TYP_FLOAT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
69 | SIMD_INTRINSIC("get_Y" , true, GetY, "getY" , TYP_UNKNOWN, 1, {TYP_BYREF, TYP_UNDEF, TYP_UNDEF}, {TYP_FLOAT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
70 | SIMD_INTRINSIC("get_Z" , true, GetZ, "getZ" , TYP_UNKNOWN, 1, {TYP_BYREF, TYP_UNDEF, TYP_UNDEF}, {TYP_FLOAT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
71 | SIMD_INTRINSIC("get_W" , true, GetW, "getW" , TYP_UNKNOWN, 1, {TYP_BYREF, TYP_UNDEF, TYP_UNDEF}, {TYP_FLOAT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
72 | |
73 | // Set operations |
74 | SIMD_INTRINSIC("set_X" , true, SetX, "setX" , TYP_VOID, 2, {TYP_BYREF, TYP_UNKNOWN, TYP_UNDEF}, {TYP_FLOAT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
75 | SIMD_INTRINSIC("set_Y" , true, SetY, "setY" , TYP_VOID, 2, {TYP_BYREF, TYP_UNKNOWN, TYP_UNDEF}, {TYP_FLOAT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
76 | SIMD_INTRINSIC("set_Z" , true, SetZ, "setZ" , TYP_VOID, 2, {TYP_BYREF, TYP_UNKNOWN, TYP_UNDEF}, {TYP_FLOAT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
77 | SIMD_INTRINSIC("set_W" , true, SetW, "setW" , TYP_VOID, 2, {TYP_BYREF, TYP_UNKNOWN, TYP_UNDEF}, {TYP_FLOAT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
78 | |
79 | // Object.Equals() |
80 | SIMD_INTRINSIC("Equals" , true, InstEquals, "equals" , TYP_BOOL, 2, {TYP_BYREF, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
81 | |
82 | // Operator == and != |
83 | SIMD_INTRINSIC("op_Equality" , false, OpEquality, "==" , TYP_BOOL, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
84 | SIMD_INTRINSIC("op_Inequality" , false, OpInEquality, "!=" , TYP_BOOL, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
85 | |
86 | // Arithmetic Operations |
87 | SIMD_INTRINSIC("op_Addition" , false, Add, "+" , TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
88 | SIMD_INTRINSIC("op_Subtraction" , false, Sub, "-" , TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
89 | |
90 | #if defined(_TARGET_XARCH_) |
91 | SIMD_INTRINSIC("op_Multiply" , false, Mul, "*" , TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_SHORT,TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
92 | #elif defined(_TARGET_ARM64_) |
93 | // TODO-ARM64-CQ Investigate code sequence to accelerate LONG/ULONG vector multiply |
94 | SIMD_INTRINSIC("op_Multiply" , false, Mul, "*" , TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_UNDEF, TYP_UNDEF}) |
95 | #endif |
96 | |
97 | SIMD_INTRINSIC("op_Division" , false, Div, "/" , TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_FLOAT, TYP_DOUBLE, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
98 | |
99 | // SquareRoot is recognized as an intrinsic only for float or double vectors |
100 | SIMD_INTRINSIC("SquareRoot" , false, Sqrt, "sqrt" , TYP_STRUCT, 1, {TYP_STRUCT, TYP_UNDEF, TYP_UNDEF}, {TYP_FLOAT, TYP_DOUBLE, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
101 | |
102 | SIMD_INTRINSIC("Min" , false, Min, "min" , TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
103 | SIMD_INTRINSIC("Max" , false, Max, "max" , TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
104 | SIMD_INTRINSIC("Abs" , false, Abs, "abs" , TYP_STRUCT, 1, {TYP_STRUCT, TYP_UNDEF, TYP_UNDEF }, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
105 | |
106 | // Vector Relational operators |
107 | SIMD_INTRINSIC("Equals" , false, Equal, "eq" , TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
108 | SIMD_INTRINSIC("LessThan" , false, LessThan, "lt" , TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
109 | SIMD_INTRINSIC("LessThanOrEqual" , false, LessThanOrEqual, "le" , TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
110 | SIMD_INTRINSIC("GreaterThan" , false, GreaterThan, "gt" , TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
111 | SIMD_INTRINSIC("GreaterThanOrEqual" , false, GreaterThanOrEqual, "ge" , TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
112 | |
113 | // Bitwise operations |
114 | SIMD_INTRINSIC("op_BitwiseAnd" , false, BitwiseAnd, "&" , TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
115 | SIMD_INTRINSIC("AndNot" , false, BitwiseAndNot, "&~" , TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
116 | SIMD_INTRINSIC("op_BitwiseOr" , false, BitwiseOr, "|" , TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
117 | SIMD_INTRINSIC("op_ExclusiveOr" , false, BitwiseXor, "^" , TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
118 | |
119 | // Dot Product |
120 | #if defined(_TARGET_XARCH_) |
121 | // Is supported only on Vector<int> on AVX. |
122 | SIMD_INTRINSIC("Dot" , false, DotProduct, "Dot" , TYP_UNKNOWN, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
123 | #elif defined(_TARGET_ARM64_) |
124 | // Dot Product does not support LONG/ULONG due to lack of multiply support (see TODO-ARM64-CQ above) |
125 | SIMD_INTRINSIC("Dot" , false, DotProduct, "Dot" , TYP_UNKNOWN, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_UNDEF, TYP_UNDEF}) |
126 | #endif |
127 | |
128 | // Select |
129 | SIMD_INTRINSIC("ConditionalSelect" , false, Select, "Select" , TYP_STRUCT, 3, {TYP_STRUCT, TYP_STRUCT, TYP_STRUCT}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
130 | |
131 | // Cast |
132 | SIMD_INTRINSIC("op_Explicit" , false, Cast, "Cast" , TYP_STRUCT, 1, {TYP_STRUCT, TYP_UNDEF, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_ULONG}) |
133 | |
134 | // Convert int/uint to single |
135 | SIMD_INTRINSIC("ConvertToSingle" , false, ConvertToSingle, "ConvertToSingle" , TYP_STRUCT, 1, {TYP_STRUCT, TYP_UNDEF, TYP_UNDEF}, {TYP_INT, TYP_UINT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
136 | // Convert long/ulong to double |
137 | SIMD_INTRINSIC("ConvertToDouble" , false, ConvertToDouble, "ConvertToDouble" , TYP_STRUCT, 1, {TYP_STRUCT, TYP_UNDEF, TYP_UNDEF}, {TYP_LONG, TYP_ULONG, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
138 | // Convert single to int |
139 | SIMD_INTRINSIC("ConvertToInt32" , false, ConvertToInt32, "ConvertToInt32" , TYP_STRUCT, 1, {TYP_STRUCT, TYP_UNDEF, TYP_UNDEF}, {TYP_FLOAT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
140 | // Convert double to long |
141 | SIMD_INTRINSIC("ConvertToInt64" , false, ConvertToInt64, "ConvertToInt64" , TYP_STRUCT, 1, {TYP_STRUCT, TYP_UNDEF, TYP_UNDEF}, {TYP_DOUBLE, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
142 | // Narrow two input Vector<T>s to a single Vector<T>. The return value's lower elements are the elements from src1, and the upper elements are from src2. |
143 | SIMD_INTRINSIC("Narrow" , false, Narrow, "Narrow" , TYP_STRUCT, 2, {TYP_STRUCT, TYP_STRUCT, TYP_UNDEF}, {TYP_INT, TYP_DOUBLE, TYP_LONG, TYP_USHORT, TYP_SHORT, TYP_UINT, TYP_ULONG, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
144 | // Widen one input Vector<T> to two Vector<T>s: dest1 contains the lower half of elements in src, and dest2 contains the upper half of elements in src. |
145 | SIMD_INTRINSIC("Widen" , false, Widen, "Widen" , TYP_VOID, 3, {TYP_STRUCT, TYP_BYREF, TYP_BYREF}, {TYP_INT, TYP_FLOAT, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
146 | |
147 | // Miscellaneous |
148 | SIMD_INTRINSIC("get_IsHardwareAccelerated" , false, HWAccel, "HWAccel" , TYP_BOOL, 0, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
149 | |
150 | #ifdef _TARGET_XARCH_ |
151 | // Shuffle and Shift operations - these are internal intrinsics as there is no corresponding managed method. |
152 | // To prevent this being accidentally recognized as an intrinsic, all of the arg types and supported base types is made TYP_UNDEF |
153 | SIMD_INTRINSIC("ShuffleSSE2" , false, ShuffleSSE2, "ShuffleSSE2" , TYP_STRUCT, 2, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
154 | |
155 | // Internal, logical shift operations that shift the entire vector register instead of individual elements of the vector. |
156 | SIMD_INTRINSIC("ShiftLeftInternal" , false, ShiftLeftInternal, "<< Internal" , TYP_STRUCT, 2, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
157 | SIMD_INTRINSIC("ShiftRightInternal" , false, ShiftRightInternal, ">> Internal" , TYP_STRUCT, 2, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
158 | #endif // _TARGET_XARCH_ |
159 | |
160 | // Internal intrinsics for saving & restoring the upper half of a vector register |
161 | SIMD_INTRINSIC("UpperSave" , false, UpperSave, "UpperSave Internal" , TYP_STRUCT, 2, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
162 | SIMD_INTRINSIC("UpperRestore" , false, UpperRestore, "UpperRestore Internal" , TYP_STRUCT, 2, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
163 | |
164 | // Internal intrinsics for Widen |
165 | SIMD_INTRINSIC("WidenHi" , false, WidenHi, "WidenHi" , TYP_VOID, 2, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
166 | SIMD_INTRINSIC("WidenLo" , false, WidenLo, "WidenLo" , TYP_VOID, 2, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}, {TYP_INT, TYP_FLOAT, TYP_USHORT, TYP_UBYTE, TYP_BYTE, TYP_SHORT, TYP_UINT, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
167 | |
168 | SIMD_INTRINSIC(nullptr, false, Invalid, "Invalid" , TYP_UNDEF, 0, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}, {TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF, TYP_UNDEF}) |
169 | #undef SIMD_INTRINSIC |
170 | #else // !defined(_TARGET_XARCH_) && !defined(_TARGET_ARM64_) |
171 | #error SIMD intrinsics not defined for target arch |
172 | #endif // !defined(_TARGET_XARCH_) && !defined(_TARGET_ARM64_) |
173 | |
174 | |
175 | #endif //FEATURE_SIMD |
176 | // clang-format on |
177 | |