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.
5 #if defined(_TARGET_XARCH_)
7 /************************************************************************/
8 /* Public inline informational methods */
9 /************************************************************************/
12 inline static bool isGeneralRegister(regNumber reg)
14 return (reg <= REG_INT_LAST);
17 inline static bool isFloatReg(regNumber reg)
19 return (reg >= REG_FP_FIRST && reg <= REG_FP_LAST);
22 inline static bool isDoubleReg(regNumber reg)
24 return isFloatReg(reg);
27 /************************************************************************/
28 /* Routines that compute the size of / encode instructions */
29 /************************************************************************/
31 // code_t is a type used to accumulate bits of opcode + prefixes. On amd64, it must be 64 bits
32 // to support the REX prefixes. On both x86 and amd64, it must be 64 bits to support AVX, with
33 // its 3-byte VEX prefix.
34 typedef unsigned __int64 code_t;
42 UNATIVE_OFFSET emitInsSize(code_t code);
43 UNATIVE_OFFSET emitInsSizeRM(instruction ins);
44 UNATIVE_OFFSET emitInsSizeSV(code_t code, int var, int dsp);
45 UNATIVE_OFFSET emitInsSizeSV(instrDesc* id, code_t code, int var, int dsp);
46 UNATIVE_OFFSET emitInsSizeSV(instrDesc* id, code_t code, int var, int dsp, int val);
47 UNATIVE_OFFSET emitInsSizeRR(instruction ins, regNumber reg1, regNumber reg2, emitAttr attr);
48 UNATIVE_OFFSET emitInsSizeAM(instrDesc* id, code_t code);
49 UNATIVE_OFFSET emitInsSizeAM(instrDesc* id, code_t code, int val);
50 UNATIVE_OFFSET emitInsSizeCV(instrDesc* id, code_t code);
51 UNATIVE_OFFSET emitInsSizeCV(instrDesc* id, code_t code, int val);
53 BYTE* emitOutputAM(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc = nullptr);
54 BYTE* emitOutputSV(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc = nullptr);
55 BYTE* emitOutputCV(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc = nullptr);
57 BYTE* emitOutputR(BYTE* dst, instrDesc* id);
58 BYTE* emitOutputRI(BYTE* dst, instrDesc* id);
59 BYTE* emitOutputRR(BYTE* dst, instrDesc* id);
60 BYTE* emitOutputIV(BYTE* dst, instrDesc* id);
62 BYTE* emitOutputRRR(BYTE* dst, instrDesc* id);
64 BYTE* emitOutputLJ(BYTE* dst, instrDesc* id);
66 unsigned emitOutputRexOrVexPrefixIfNeeded(instruction ins, BYTE* dst, code_t& code);
67 unsigned emitGetRexPrefixSize(instruction ins);
68 unsigned emitGetVexPrefixSize(instruction ins, emitAttr attr);
69 unsigned emitGetPrefixSize(code_t code);
70 unsigned emitGetVexPrefixAdjustedSize(instruction ins, emitAttr attr, code_t code);
72 unsigned insEncodeReg012(instruction ins, regNumber reg, emitAttr size, code_t* code);
73 unsigned insEncodeReg345(instruction ins, regNumber reg, emitAttr size, code_t* code);
74 code_t insEncodeReg3456(instruction ins, regNumber reg, emitAttr size, code_t code);
75 unsigned insEncodeRegSIB(instruction ins, regNumber reg, code_t* code);
77 code_t insEncodeMRreg(instruction ins, code_t code);
78 code_t insEncodeRMreg(instruction ins, code_t code);
79 code_t insEncodeMRreg(instruction ins, regNumber reg, emitAttr size, code_t code);
80 code_t insEncodeRRIb(instruction ins, regNumber reg, emitAttr size);
81 code_t insEncodeOpreg(instruction ins, regNumber reg, emitAttr size);
83 unsigned insSSval(unsigned scale);
85 bool IsAVXInstruction(instruction ins);
86 code_t insEncodeMIreg(instruction ins, regNumber reg, emitAttr size, code_t code);
88 code_t AddRexWPrefix(instruction ins, code_t code);
89 code_t AddRexRPrefix(instruction ins, code_t code);
90 code_t AddRexXPrefix(instruction ins, code_t code);
91 code_t AddRexBPrefix(instruction ins, code_t code);
92 code_t AddRexPrefix(instruction ins, code_t code);
94 bool EncodedBySSE38orSSE3A(instruction ins);
95 bool Is4ByteSSEInstruction(instruction ins);
97 bool AreUpper32BitsZero(regNumber reg);
99 // Adjust code size for CRC32 that has 4-byte opcode
100 // but does not use SSE38 or EES3A encoding.
101 UNATIVE_OFFSET emitAdjustSizeCrc32(instruction ins, emitAttr attr)
103 UNATIVE_OFFSET szDelta = 0;
104 if (ins == INS_crc32)
107 if (attr == EA_2BYTE)
115 bool hasRexPrefix(code_t code)
117 #ifdef _TARGET_AMD64_
118 const code_t REX_PREFIX_MASK = 0xFF00000000LL;
119 return (code & REX_PREFIX_MASK) != 0;
120 #else // !_TARGET_AMD64_
122 #endif // !_TARGET_AMD64_
125 // 3-byte VEX prefix starts with byte 0xC4
126 #define VEX_PREFIX_MASK_3BYTE 0xFF000000000000ULL
127 #define VEX_PREFIX_CODE_3BYTE 0xC4000000000000ULL
129 bool TakesVexPrefix(instruction ins);
131 // Returns true if the instruction encoding already contains VEX prefix
132 bool hasVexPrefix(code_t code)
134 return (code & VEX_PREFIX_MASK_3BYTE) == VEX_PREFIX_CODE_3BYTE;
136 code_t AddVexPrefix(instruction ins, code_t code, emitAttr attr);
137 code_t AddVexPrefixIfNeeded(instruction ins, code_t code, emitAttr size)
139 if (TakesVexPrefix(ins))
141 code = AddVexPrefix(ins, code, size);
145 code_t AddVexPrefixIfNeededAndNotPresent(instruction ins, code_t code, emitAttr size)
147 if (TakesVexPrefix(ins) && !hasVexPrefix(code))
149 code = AddVexPrefix(ins, code, size);
154 bool useVEXEncodings;
155 bool UseVEXEncoding()
157 return useVEXEncodings;
159 void SetUseVEXEncoding(bool value)
161 useVEXEncodings = value;
164 bool containsAVXInstruction = false;
167 return containsAVXInstruction;
169 void SetContainsAVX(bool value)
171 containsAVXInstruction = value;
174 bool contains256bitAVXInstruction = false;
175 bool Contains256bitAVX()
177 return contains256bitAVXInstruction;
179 void SetContains256bitAVX(bool value)
181 contains256bitAVXInstruction = value;
184 bool IsDstDstSrcAVXInstruction(instruction ins);
185 bool IsDstSrcSrcAVXInstruction(instruction ins);
186 bool IsThreeOperandAVXInstruction(instruction ins)
188 return (IsDstDstSrcAVXInstruction(ins) || IsDstSrcSrcAVXInstruction(ins));
190 bool isAvxBlendv(instruction ins)
192 return ins == INS_vblendvps || ins == INS_vblendvpd || ins == INS_vpblendvb;
194 bool isSse41Blendv(instruction ins)
196 return ins == INS_blendvps || ins == INS_blendvpd || ins == INS_pblendvb;
198 bool isPrefetch(instruction ins)
200 return (ins == INS_prefetcht0) || (ins == INS_prefetcht1) || (ins == INS_prefetcht2) || (ins == INS_prefetchnta);
203 /************************************************************************/
204 /* Debug-only routines to display instructions */
205 /************************************************************************/
209 const char* emitFPregName(unsigned reg, bool varName = true);
211 void emitDispReloc(ssize_t value);
212 void emitDispAddrMode(instrDesc* id, bool noDetail = false);
213 void emitDispShift(instruction ins, int cnt = 0);
215 void emitDispIns(instrDesc* id,
220 BYTE* code = nullptr,
222 insGroup* ig = nullptr);
224 const char* emitXMMregName(unsigned reg);
225 const char* emitYMMregName(unsigned reg);
229 /************************************************************************/
230 /* Private members that deal with target-dependent instr. descriptors */
231 /************************************************************************/
234 void emitSetAmdDisp(instrDescAmd* id, ssize_t dsp);
235 instrDesc* emitNewInstrAmd(emitAttr attr, ssize_t dsp);
236 instrDesc* emitNewInstrAmdCns(emitAttr attr, ssize_t dsp, int cns);
238 instrDesc* emitNewInstrCallDir(int argCnt,
239 VARSET_VALARG_TP GCvars,
242 emitAttr retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize));
244 instrDesc* emitNewInstrCallInd(int argCnt,
246 VARSET_VALARG_TP GCvars,
249 emitAttr retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize));
251 void emitGetInsCns(instrDesc* id, CnsVal* cv);
252 ssize_t emitGetInsAmdCns(instrDesc* id, CnsVal* cv);
253 void emitGetInsDcmCns(instrDesc* id, CnsVal* cv);
254 ssize_t emitGetInsAmdAny(instrDesc* id);
256 /************************************************************************/
257 /* Private helpers for instruction output */
258 /************************************************************************/
261 insFormat emitInsModeFormat(instruction ins, insFormat base, insFormat FPld, insFormat FPst);
263 bool emitVerifyEncodable(instruction ins, emitAttr size, regNumber reg1, regNumber reg2 = REG_NA);
265 bool emitInsCanOnlyWriteSSE2OrAVXReg(instrDesc* id);
267 #if FEATURE_FIXED_OUT_ARGS
268 void emitAdjustStackDepthPushPop(instruction ins)
271 void emitAdjustStackDepth(instruction ins, ssize_t val)
274 #else // !FEATURE_FIXED_OUT_ARGS
275 void emitAdjustStackDepthPushPop(instruction ins);
276 void emitAdjustStackDepth(instruction ins, ssize_t val);
277 #endif // !FEATURE_FIXED_OUT_ARGS
279 /*****************************************************************************
281 * Convert between an index scale in bytes to a smaller encoding used for
282 * storage in instruction descriptors.
285 inline emitter::opSize emitEncodeScale(size_t scale)
287 assert(scale == 1 || scale == 2 || scale == 4 || scale == 8);
289 return emitSizeEncode[scale - 1];
292 inline emitAttr emitDecodeScale(unsigned ensz)
296 return emitter::emitSizeDecode[ensz];
299 /************************************************************************/
300 /* The public entry points to output instructions */
301 /************************************************************************/
304 void emitLoopAlign();
306 void emitIns(instruction ins);
308 void emitIns(instruction ins, emitAttr attr);
310 void emitInsRMW(instruction inst, emitAttr attr, GenTreeStoreInd* storeInd, GenTree* src);
312 void emitInsRMW(instruction inst, emitAttr attr, GenTreeStoreInd* storeInd);
314 void emitIns_Nop(unsigned size);
316 void emitIns_I(instruction ins, emitAttr attr, int val);
318 void emitIns_R(instruction ins, emitAttr attr, regNumber reg);
320 void emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fdlHnd, int offs);
322 void emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t val);
324 void emitIns_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2);
326 void emitIns_R_R_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int ival);
328 void emitIns_AR(instruction ins, emitAttr attr, regNumber base, int offs);
330 void emitIns_AR_R_R(instruction ins, emitAttr attr, regNumber op2Reg, regNumber op3Reg, regNumber base, int offs);
332 void emitIns_R_A(instruction ins, emitAttr attr, regNumber reg1, GenTreeIndir* indir);
334 void emitIns_R_A_I(instruction ins, emitAttr attr, regNumber reg1, GenTreeIndir* indir, int ival);
336 void emitIns_R_AR_I(instruction ins, emitAttr attr, regNumber reg1, regNumber base, int offs, int ival);
338 void emitIns_R_C_I(instruction ins, emitAttr attr, regNumber reg1, CORINFO_FIELD_HANDLE fldHnd, int offs, int ival);
340 void emitIns_R_S_I(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs, int ival);
342 void emitIns_R_R_A(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, GenTreeIndir* indir);
344 void emitIns_R_R_AR(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber base, int offs);
346 void emitIns_R_AR_R(instruction ins,
356 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, CORINFO_FIELD_HANDLE fldHnd, int offs);
358 void emitIns_R_R_S(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int varx, int offs);
360 void emitIns_R_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3);
362 void emitIns_R_R_A_I(
363 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, GenTreeIndir* indir, int ival, insFormat fmt);
364 void emitIns_R_R_AR_I(
365 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber base, int offs, int ival);
366 void emitIns_AR_R_I(instruction ins, emitAttr attr, regNumber base, int disp, regNumber ireg, int ival);
368 void emitIns_R_R_C_I(
369 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, CORINFO_FIELD_HANDLE fldHnd, int offs, int ival);
371 void emitIns_R_R_R_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, int ival);
373 void emitIns_R_R_S_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int varx, int offs, int ival);
375 void emitIns_R_R_A_R(
376 instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op3Reg, GenTreeIndir* indir);
378 void emitIns_R_R_AR_R(
379 instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op3Reg, regNumber base, int offs);
381 void emitIns_R_R_C_R(instruction ins,
386 CORINFO_FIELD_HANDLE fldHnd,
389 void emitIns_R_R_S_R(
390 instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op3Reg, int varx, int offs);
392 void emitIns_R_R_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4);
394 void emitIns_S(instruction ins, emitAttr attr, int varx, int offs);
396 void emitIns_S_R(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs);
398 void emitIns_R_S(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs);
400 void emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val);
402 void emitIns_R_C(instruction ins, emitAttr attr, regNumber reg, CORINFO_FIELD_HANDLE fldHnd, int offs);
404 void emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs);
406 void emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fdlHnd, int offs, int val);
408 void emitIns_IJ(emitAttr attr, regNumber reg, unsigned base);
410 void emitIns_J_S(instruction ins, emitAttr attr, BasicBlock* dst, int varx, int offs);
412 void emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg);
414 void emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg);
416 void emitIns_I_AR(instruction ins, emitAttr attr, int val, regNumber reg, int offs);
418 void emitIns_I_AI(instruction ins, emitAttr attr, int val, ssize_t disp);
420 void emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs);
422 void emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t disp);
424 void emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs);
426 void emitIns_AI_R(instruction ins, emitAttr attr, regNumber ireg, ssize_t disp);
428 void emitIns_I_ARR(instruction ins, emitAttr attr, int val, regNumber reg, regNumber rg2, int disp);
430 void emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp);
432 void emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp);
434 void emitIns_I_ARX(instruction ins, emitAttr attr, int val, regNumber reg, regNumber rg2, unsigned mul, int disp);
437 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp);
440 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp);
442 void emitIns_I_AX(instruction ins, emitAttr attr, int val, regNumber reg, unsigned mul, int disp);
444 void emitIns_R_AX(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, unsigned mul, int disp);
446 void emitIns_AX_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, unsigned mul, int disp);
448 #ifdef FEATURE_HW_INTRINSICS
449 void emitIns_SIMD_R_R_I(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int ival);
451 void emitIns_SIMD_R_R_A(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, GenTreeIndir* indir);
452 void emitIns_SIMD_R_R_AR(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber base);
453 void emitIns_SIMD_R_R_C(
454 instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, CORINFO_FIELD_HANDLE fldHnd, int offs);
455 void emitIns_SIMD_R_R_R(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg);
456 void emitIns_SIMD_R_R_S(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int varx, int offs);
458 void emitIns_SIMD_R_R_A_I(
459 instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, GenTreeIndir* indir, int ival);
460 void emitIns_SIMD_R_R_AR_I(
461 instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber base, int ival);
462 void emitIns_SIMD_R_R_C_I(instruction ins,
466 CORINFO_FIELD_HANDLE fldHnd,
469 void emitIns_SIMD_R_R_R_I(
470 instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, int ival);
471 void emitIns_SIMD_R_R_S_I(
472 instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int varx, int offs, int ival);
474 void emitIns_SIMD_R_R_R_A(
475 instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, GenTreeIndir* indir);
476 void emitIns_SIMD_R_R_R_AR(
477 instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, regNumber base);
478 void emitIns_SIMD_R_R_R_C(instruction ins,
483 CORINFO_FIELD_HANDLE fldHnd,
485 void emitIns_SIMD_R_R_R_R(
486 instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, regNumber op3Reg);
487 void emitIns_SIMD_R_R_R_S(
488 instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, int varx, int offs);
490 void emitIns_SIMD_R_R_A_R(
491 instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, GenTreeIndir* indir);
492 void emitIns_SIMD_R_R_AR_R(
493 instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, regNumber base);
494 void emitIns_SIMD_R_R_C_R(instruction ins,
499 CORINFO_FIELD_HANDLE fldHnd,
501 void emitIns_SIMD_R_R_S_R(
502 instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, int varx, int offs);
503 #endif // FEATURE_HW_INTRINSICS
507 EC_FUNC_TOKEN, // Direct call to a helper/static/nonvirtual/global method
508 EC_FUNC_TOKEN_INDIR, // Indirect call to a helper/static/nonvirtual/global method
509 EC_FUNC_ADDR, // Direct call to an absolute address
511 EC_FUNC_VIRTUAL, // Call to a virtual method (using the vtable)
512 EC_INDIR_R, // Indirect call via register
513 EC_INDIR_SR, // Indirect call via stack-reference (local var)
514 EC_INDIR_C, // Indirect call via static class var
515 EC_INDIR_ARD, // Indirect call via an addressing mode
521 void emitIns_Call(EmitCallType callType,
522 CORINFO_METHOD_HANDLE methHnd,
523 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
527 MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize),
528 VARSET_VALARG_TP ptrVars,
531 IL_OFFSETX ilOffset = BAD_IL_OFFSET,
532 regNumber ireg = REG_NA,
533 regNumber xreg = REG_NA,
536 bool isJump = false);
539 #ifdef _TARGET_AMD64_
540 // Is the last instruction emitted a call instruction?
541 bool emitIsLastInsCall();
543 // Insert a NOP at the end of the the current instruction group if the last emitted instruction was a 'call',
544 // because the next instruction group will be an epilog.
545 void emitOutputPreEpilogNOP();
546 #endif // _TARGET_AMD64_
548 /*****************************************************************************
550 * Given a jump, return true if it's a conditional jump.
553 inline bool emitIsCondJump(instrDesc* jmp)
555 instruction ins = jmp->idIns();
557 assert(jmp->idInsFmt() == IF_LABEL);
559 return (ins != INS_call && ins != INS_jmp);
562 /*****************************************************************************
564 * Given a jump, return true if it's an unconditional jump.
567 inline bool emitIsUncondJump(instrDesc* jmp)
569 instruction ins = jmp->idIns();
571 assert(jmp->idInsFmt() == IF_LABEL);
573 return (ins == INS_jmp);
576 #endif // _TARGET_XARCH_