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
15enum 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
61enum insUpdateModes
62{
63 IUM_RD,
64 IUM_WR,
65 IUM_RW,
66};
67
68/*****************************************************************************/
69
70enum 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
82enum GCtype : unsigned
83{
84 GCT_NONE,
85 GCT_GCREF,
86 GCT_BYREF
87};
88
89#if defined(_TARGET_XARCH_)
90enum 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_
104enum 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_)
115enum 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_)
128enum 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
184enum 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
205enum 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
228enum 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
249enum 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
295enum 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