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 _INSTR_H_ |
7 | #define _INSTR_H_ |
8 | /*****************************************************************************/ |
9 | |
10 | #define BAD_CODE 0x0BADC0DE // better not match a real encoding! |
11 | |
12 | /*****************************************************************************/ |
13 | |
14 | // clang-format off |
15 | enum instruction : unsigned |
16 | { |
17 | #if defined(_TARGET_XARCH_) |
18 | #define INST0(id, nm, um, mr, flags) INS_##id, |
19 | #define INST1(id, nm, um, mr, flags) INS_##id, |
20 | #define INST2(id, nm, um, mr, mi, flags) INS_##id, |
21 | #define INST3(id, nm, um, mr, mi, rm, flags) INS_##id, |
22 | #define INST4(id, nm, um, mr, mi, rm, a4, flags) INS_##id, |
23 | #define INST5(id, nm, um, mr, mi, rm, a4, rr, flags) INS_##id, |
24 | #include "instrs.h" |
25 | |
26 | #elif defined(_TARGET_ARM_) |
27 | #define INST1(id, nm, fp, ldst, fmt, e1 ) INS_##id, |
28 | #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) INS_##id, |
29 | #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) INS_##id, |
30 | #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) INS_##id, |
31 | #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) INS_##id, |
32 | #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) INS_##id, |
33 | #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) INS_##id, |
34 | #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) INS_##id, |
35 | #include "instrs.h" |
36 | |
37 | INS_lea, // Not a real instruction. It is used for load the address of stack locals |
38 | |
39 | #elif defined(_TARGET_ARM64_) |
40 | #define INST1(id, nm, fp, ldst, fmt, e1 ) INS_##id, |
41 | #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) INS_##id, |
42 | #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) INS_##id, |
43 | #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) INS_##id, |
44 | #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) INS_##id, |
45 | #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) INS_##id, |
46 | #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) INS_##id, |
47 | #include "instrs.h" |
48 | |
49 | INS_lea, // Not a real instruction. It is used for load the address of stack locals |
50 | |
51 | #else |
52 | #error Unsupported target architecture |
53 | #endif |
54 | |
55 | INS_none, |
56 | INS_count = INS_none |
57 | }; |
58 | |
59 | /*****************************************************************************/ |
60 | |
61 | enum insUpdateModes |
62 | { |
63 | IUM_RD, |
64 | IUM_WR, |
65 | IUM_RW, |
66 | }; |
67 | |
68 | /*****************************************************************************/ |
69 | |
70 | enum emitJumpKind |
71 | { |
72 | EJ_NONE, |
73 | |
74 | #define JMP_SMALL(en, rev, ins) EJ_##en, |
75 | #include "emitjmps.h" |
76 | |
77 | EJ_COUNT |
78 | }; |
79 | |
80 | /*****************************************************************************/ |
81 | |
82 | enum GCtype : unsigned |
83 | { |
84 | GCT_NONE, |
85 | GCT_GCREF, |
86 | GCT_BYREF |
87 | }; |
88 | |
89 | #if defined(_TARGET_XARCH_) |
90 | enum insFlags: uint8_t |
91 | { |
92 | INS_FLAGS_None = 0x00, |
93 | INS_FLAGS_ReadsFlags = 0x01, |
94 | INS_FLAGS_WritesFlags = 0x02, |
95 | INS_FLAGS_x87Instr = 0x04, |
96 | INS_Flags_IsDstDstSrcAVXInstruction = 0x08, |
97 | INS_Flags_IsDstSrcSrcAVXInstruction = 0x10, |
98 | |
99 | // TODO-Cleanup: Remove this flag and its usage from _TARGET_XARCH_ |
100 | INS_FLAGS_DONT_CARE = 0x00, |
101 | }; |
102 | #elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) |
103 | // TODO-Cleanup: Move 'insFlags' under _TARGET_ARM_ |
104 | enum insFlags: unsigned |
105 | { |
106 | INS_FLAGS_NOT_SET = 0x00, |
107 | INS_FLAGS_SET = 0x01, |
108 | INS_FLAGS_DONT_CARE = 0x02, |
109 | }; |
110 | #else |
111 | #error Unsupported target architecture |
112 | #endif |
113 | |
114 | #if defined(_TARGET_ARM_) |
115 | enum insOpts: unsigned |
116 | { |
117 | INS_OPTS_NONE, |
118 | INS_OPTS_LDST_PRE_DEC, |
119 | INS_OPTS_LDST_POST_INC, |
120 | |
121 | INS_OPTS_RRX, |
122 | INS_OPTS_LSL, |
123 | INS_OPTS_LSR, |
124 | INS_OPTS_ASR, |
125 | INS_OPTS_ROR |
126 | }; |
127 | #elif defined(_TARGET_ARM64_) |
128 | enum insOpts : unsigned |
129 | { |
130 | INS_OPTS_NONE, |
131 | |
132 | INS_OPTS_PRE_INDEX, |
133 | INS_OPTS_POST_INDEX, |
134 | |
135 | INS_OPTS_LSL12, |
136 | |
137 | INS_OPTS_LSL = 4, |
138 | INS_OPTS_LSR, |
139 | INS_OPTS_ASR, |
140 | INS_OPTS_ROR, |
141 | |
142 | INS_OPTS_UXTB = 8, |
143 | INS_OPTS_UXTH, |
144 | INS_OPTS_UXTW, |
145 | INS_OPTS_UXTX, |
146 | INS_OPTS_SXTB, |
147 | INS_OPTS_SXTH, |
148 | INS_OPTS_SXTW, |
149 | INS_OPTS_SXTX, |
150 | |
151 | INS_OPTS_8B = 16, |
152 | INS_OPTS_16B, |
153 | INS_OPTS_4H, |
154 | INS_OPTS_8H, |
155 | INS_OPTS_2S, |
156 | INS_OPTS_4S, |
157 | INS_OPTS_1D, |
158 | INS_OPTS_2D, |
159 | |
160 | INS_OPTS_MSL, // Vector Immediate (shifting ones variant) |
161 | |
162 | INS_OPTS_S_TO_4BYTE, // Single to INT32 |
163 | INS_OPTS_D_TO_4BYTE, // Double to INT32 |
164 | |
165 | INS_OPTS_S_TO_8BYTE, // Single to INT64 |
166 | INS_OPTS_D_TO_8BYTE, // Double to INT64 |
167 | |
168 | INS_OPTS_4BYTE_TO_S, // INT32 to Single |
169 | INS_OPTS_4BYTE_TO_D, // INT32 to Double |
170 | |
171 | INS_OPTS_8BYTE_TO_S, // INT64 to Single |
172 | INS_OPTS_8BYTE_TO_D, // INT64 to Double |
173 | |
174 | INS_OPTS_S_TO_D, // Single to Double |
175 | INS_OPTS_D_TO_S, // Double to Single |
176 | |
177 | INS_OPTS_H_TO_S, // Half to Single |
178 | INS_OPTS_H_TO_D, // Half to Double |
179 | |
180 | INS_OPTS_S_TO_H, // Single to Half |
181 | INS_OPTS_D_TO_H, // Double to Half |
182 | }; |
183 | |
184 | enum insCond : unsigned |
185 | { |
186 | INS_COND_EQ, |
187 | INS_COND_NE, |
188 | INS_COND_HS, |
189 | INS_COND_LO, |
190 | |
191 | INS_COND_MI, |
192 | INS_COND_PL, |
193 | INS_COND_VS, |
194 | INS_COND_VC, |
195 | |
196 | INS_COND_HI, |
197 | INS_COND_LS, |
198 | INS_COND_GE, |
199 | INS_COND_LT, |
200 | |
201 | INS_COND_GT, |
202 | INS_COND_LE, |
203 | }; |
204 | |
205 | enum insCflags : unsigned |
206 | { |
207 | INS_FLAGS_NONE, |
208 | INS_FLAGS_V, |
209 | INS_FLAGS_C, |
210 | INS_FLAGS_CV, |
211 | |
212 | INS_FLAGS_Z, |
213 | INS_FLAGS_ZV, |
214 | INS_FLAGS_ZC, |
215 | INS_FLAGS_ZCV, |
216 | |
217 | INS_FLAGS_N, |
218 | INS_FLAGS_NV, |
219 | INS_FLAGS_NC, |
220 | INS_FLAGS_NCV, |
221 | |
222 | INS_FLAGS_NZ, |
223 | INS_FLAGS_NZV, |
224 | INS_FLAGS_NZC, |
225 | INS_FLAGS_NZCV, |
226 | }; |
227 | |
228 | enum insBarrier : unsigned |
229 | { |
230 | INS_BARRIER_OSHLD = 1, |
231 | INS_BARRIER_OSHST = 2, |
232 | INS_BARRIER_OSH = 3, |
233 | |
234 | INS_BARRIER_NSHLD = 5, |
235 | INS_BARRIER_NSHST = 6, |
236 | INS_BARRIER_NSH = 7, |
237 | |
238 | INS_BARRIER_ISHLD = 9, |
239 | INS_BARRIER_ISHST = 10, |
240 | INS_BARRIER_ISH = 11, |
241 | |
242 | INS_BARRIER_LD = 13, |
243 | INS_BARRIER_ST = 14, |
244 | INS_BARRIER_SY = 15, |
245 | }; |
246 | #endif |
247 | |
248 | #undef EA_UNKNOWN |
249 | enum emitAttr : unsigned |
250 | { |
251 | EA_UNKNOWN = 0x000, |
252 | EA_1BYTE = 0x001, |
253 | EA_2BYTE = 0x002, |
254 | EA_4BYTE = 0x004, |
255 | EA_8BYTE = 0x008, |
256 | EA_16BYTE = 0x010, |
257 | EA_32BYTE = 0x020, |
258 | EA_SIZE_MASK = 0x03F, |
259 | |
260 | #ifdef _TARGET_64BIT_ |
261 | EA_PTRSIZE = EA_8BYTE, |
262 | #else |
263 | EA_PTRSIZE = EA_4BYTE, |
264 | #endif |
265 | |
266 | EA_OFFSET_FLG = 0x040, |
267 | EA_OFFSET = EA_OFFSET_FLG | EA_PTRSIZE, /* size == 0 */ |
268 | EA_GCREF_FLG = 0x080, |
269 | EA_GCREF = EA_GCREF_FLG | EA_PTRSIZE, /* size == -1 */ |
270 | EA_BYREF_FLG = 0x100, |
271 | EA_BYREF = EA_BYREF_FLG | EA_PTRSIZE, /* size == -2 */ |
272 | EA_DSP_RELOC_FLG = 0x200, |
273 | EA_CNS_RELOC_FLG = 0x400, |
274 | }; |
275 | |
276 | #define EA_ATTR(x) ((emitAttr)(x)) |
277 | #define EA_SIZE(x) ((emitAttr)(((unsigned)(x)) & EA_SIZE_MASK)) |
278 | #define EA_SIZE_IN_BYTES(x) ((UNATIVE_OFFSET)(EA_SIZE(x))) |
279 | #define EA_SET_SIZE(x, sz) ((emitAttr)((((unsigned)(x)) & ~EA_SIZE_MASK) | sz)) |
280 | #define EA_SET_FLG(x, flg) ((emitAttr)(((unsigned)(x)) | flg)) |
281 | #define EA_4BYTE_DSP_RELOC (EA_SET_FLG(EA_4BYTE, EA_DSP_RELOC_FLG)) |
282 | #define EA_PTR_DSP_RELOC (EA_SET_FLG(EA_PTRSIZE, EA_DSP_RELOC_FLG)) |
283 | #define EA_HANDLE_CNS_RELOC (EA_SET_FLG(EA_PTRSIZE, EA_CNS_RELOC_FLG)) |
284 | #define EA_IS_OFFSET(x) ((((unsigned)(x)) & ((unsigned)EA_OFFSET_FLG)) != 0) |
285 | #define EA_IS_GCREF(x) ((((unsigned)(x)) & ((unsigned)EA_GCREF_FLG)) != 0) |
286 | #define EA_IS_BYREF(x) ((((unsigned)(x)) & ((unsigned)EA_BYREF_FLG)) != 0) |
287 | #define EA_IS_GCREF_OR_BYREF(x) ((((unsigned)(x)) & ((unsigned)(EA_BYREF_FLG | EA_GCREF_FLG))) != 0) |
288 | #define EA_IS_DSP_RELOC(x) ((((unsigned)(x)) & ((unsigned)EA_DSP_RELOC_FLG)) != 0) |
289 | #define EA_IS_CNS_RELOC(x) ((((unsigned)(x)) & ((unsigned)EA_CNS_RELOC_FLG)) != 0) |
290 | #define EA_IS_RELOC(x) (EA_IS_DSP_RELOC(x) || EA_IS_CNS_RELOC(x)) |
291 | #define EA_TYPE(x) ((emitAttr)(((unsigned)(x)) & ~(EA_OFFSET_FLG | EA_DSP_RELOC_FLG | EA_CNS_RELOC_FLG))) |
292 | |
293 | #define EmitSize(x) (EA_ATTR(genTypeSize(TypeGet(x)))) |
294 | |
295 | enum InstructionSet |
296 | { |
297 | InstructionSet_ILLEGAL = 0, |
298 | #ifdef _TARGET_XARCH_ |
299 | InstructionSet_Base, |
300 | // Start linear order SIMD instruction sets |
301 | // These ISAs have strictly generation to generation order. |
302 | InstructionSet_SSE, |
303 | InstructionSet_SSE2, |
304 | InstructionSet_SSE3, |
305 | InstructionSet_SSSE3, |
306 | InstructionSet_SSE41, |
307 | InstructionSet_SSE42, |
308 | InstructionSet_AVX, |
309 | InstructionSet_AVX2, |
310 | // End linear order SIMD instruction sets. |
311 | InstructionSet_AES, |
312 | InstructionSet_BMI1, |
313 | InstructionSet_BMI2, |
314 | InstructionSet_FMA, |
315 | InstructionSet_LZCNT, |
316 | InstructionSet_PCLMULQDQ, |
317 | InstructionSet_POPCNT, |
318 | InstructionSet_BMI1_X64, |
319 | InstructionSet_BMI2_X64, |
320 | InstructionSet_LZCNT_X64, |
321 | InstructionSet_POPCNT_X64, |
322 | InstructionSet_SSE_X64, |
323 | InstructionSet_SSE2_X64, |
324 | InstructionSet_SSE41_X64, |
325 | InstructionSet_SSE42_X64, |
326 | #elif defined(_TARGET_ARM_) |
327 | InstructionSet_NEON, |
328 | #elif defined(_TARGET_ARM64_) |
329 | InstructionSet_Base, // Base instructions available on all Arm64 platforms |
330 | InstructionSet_Aes, // ID_AA64ISAR0_EL1.AES is 1 or better |
331 | InstructionSet_Atomics, // ID_AA64ISAR0_EL1.Atomic is 2 or better |
332 | InstructionSet_Crc32, // ID_AA64ISAR0_EL1.CRC32 is 1 or better |
333 | InstructionSet_Dcpop, // ID_AA64ISAR1_EL1.DPB is 1 or better |
334 | InstructionSet_Dp, // ID_AA64ISAR0_EL1.DP is 1 or better |
335 | InstructionSet_Fcma, // ID_AA64ISAR1_EL1.FCMA is 1 or better |
336 | InstructionSet_Fp, // ID_AA64PFR0_EL1.FP is 0 or better |
337 | InstructionSet_Fp16, // ID_AA64PFR0_EL1.FP is 1 or better |
338 | InstructionSet_Jscvt, // ID_AA64ISAR1_EL1.JSCVT is 1 or better |
339 | InstructionSet_Lrcpc, // ID_AA64ISAR1_EL1.LRCPC is 1 or better |
340 | InstructionSet_Pmull, // ID_AA64ISAR0_EL1.AES is 2 or better |
341 | InstructionSet_Sha1, // ID_AA64ISAR0_EL1.SHA1 is 1 or better |
342 | InstructionSet_Sha256, // ID_AA64ISAR0_EL1.SHA2 is 1 or better |
343 | InstructionSet_Sha512, // ID_AA64ISAR0_EL1.SHA2 is 2 or better |
344 | InstructionSet_Sha3, // ID_AA64ISAR0_EL1.SHA3 is 1 or better |
345 | InstructionSet_Simd, // ID_AA64PFR0_EL1.AdvSIMD is 0 or better |
346 | InstructionSet_Simd_v81, // ID_AA64ISAR0_EL1.RDM is 1 or better |
347 | InstructionSet_Simd_fp16, // ID_AA64PFR0_EL1.AdvSIMD is 1 or better |
348 | InstructionSet_Sm3, // ID_AA64ISAR0_EL1.SM3 is 1 or better |
349 | InstructionSet_Sm4, // ID_AA64ISAR0_EL1.SM4 is 1 or better |
350 | InstructionSet_Sve, // ID_AA64PFR0_EL1.SVE is 1 or better |
351 | #endif |
352 | InstructionSet_NONE // No instruction set is available indicating an invalid value |
353 | }; |
354 | // clang-format on |
355 | |
356 | /*****************************************************************************/ |
357 | #endif //_INSTR_H_ |
358 | /*****************************************************************************/ |
359 | |