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 /************************************************************************/
39 UNATIVE_OFFSET emitInsSize(size_t code);
40 UNATIVE_OFFSET emitInsSizeRM(instruction ins);
41 UNATIVE_OFFSET emitInsSizeSV(size_t code, int var, int dsp);
42 UNATIVE_OFFSET emitInsSizeSV(instrDesc* id, int var, int dsp, int val);
43 UNATIVE_OFFSET emitInsSizeRR(instruction ins, regNumber reg1, regNumber reg2, emitAttr attr);
44 UNATIVE_OFFSET emitInsSizeAM(instrDesc* id, size_t code);
45 UNATIVE_OFFSET emitInsSizeAM(instrDesc* id, size_t code, int val);
46 UNATIVE_OFFSET emitInsSizeCV(instrDesc* id, size_t code);
47 UNATIVE_OFFSET emitInsSizeCV(instrDesc* id, size_t code, int val);
49 BYTE* emitOutputAM(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc = nullptr);
50 BYTE* emitOutputSV(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc = nullptr);
51 BYTE* emitOutputCV(BYTE* dst, instrDesc* id, size_t code, CnsVal* addc = nullptr);
53 BYTE* emitOutputR(BYTE* dst, instrDesc* id);
54 BYTE* emitOutputRI(BYTE* dst, instrDesc* id);
55 BYTE* emitOutputRR(BYTE* dst, instrDesc* id);
56 BYTE* emitOutputIV(BYTE* dst, instrDesc* id);
58 #ifdef FEATURE_AVX_SUPPORT
59 BYTE* emitOutputRRR(BYTE* dst, instrDesc* id);
62 BYTE* emitOutputLJ(BYTE* dst, instrDesc* id);
64 unsigned emitOutputRexOrVexPrefixIfNeeded(instruction ins, BYTE* dst, size_t& code);
65 unsigned emitGetRexPrefixSize(instruction ins);
66 unsigned emitGetVexPrefixSize(instruction ins, emitAttr attr);
67 unsigned emitGetPrefixSize(size_t code);
68 unsigned emitGetVexPrefixAdjustedSize(instruction ins, emitAttr attr, size_t code);
70 unsigned insEncodeReg345(instruction ins, regNumber reg, emitAttr size, size_t* code);
71 unsigned insEncodeReg012(instruction ins, regNumber reg, emitAttr size, size_t* code);
72 size_t insEncodeReg3456(instruction ins, regNumber reg, emitAttr size, size_t code);
73 unsigned insEncodeRegSIB(instruction ins, regNumber reg, size_t* code);
75 size_t insEncodeMRreg(instruction ins, size_t code);
76 size_t insEncodeMRreg(instruction ins, regNumber reg, emitAttr size, size_t code);
77 size_t insEncodeRRIb(instruction ins, regNumber reg, emitAttr size);
78 size_t insEncodeOpreg(instruction ins, regNumber reg, emitAttr size);
80 bool IsAVXInstruction(instruction ins);
81 size_t insEncodeMIreg(instruction ins, regNumber reg, emitAttr size, size_t code);
83 size_t AddRexWPrefix(instruction ins, size_t code);
84 size_t AddRexRPrefix(instruction ins, size_t code);
85 size_t AddRexXPrefix(instruction ins, size_t code);
86 size_t AddRexBPrefix(instruction ins, size_t code);
87 size_t AddRexPrefix(instruction ins, size_t code);
89 #ifdef FEATURE_AVX_SUPPORT
90 // 3-byte VEX prefix starts with byte 0xC4
91 #define VEX_PREFIX_MASK_3BYTE 0xC4000000000000LL
92 bool TakesVexPrefix(instruction ins);
93 // Returns true if the instruction encoding already contains VEX prefix
94 bool hasVexPrefix(size_t code)
96 return (code & VEX_PREFIX_MASK_3BYTE) != 0;
98 size_t AddVexPrefix(instruction ins, size_t code, emitAttr attr);
99 size_t AddVexPrefixIfNeeded(instruction ins, size_t code, emitAttr size)
101 if (TakesVexPrefix(ins))
103 code = AddVexPrefix(ins, code, size);
107 size_t AddVexPrefixIfNeededAndNotPresent(instruction ins, size_t code, emitAttr size)
109 if (TakesVexPrefix(ins) && !hasVexPrefix(code))
111 code = AddVexPrefix(ins, code, size);
115 bool useAVXEncodings;
118 return useAVXEncodings;
120 void SetUseAVX(bool value)
122 useAVXEncodings = value;
124 bool IsThreeOperandBinaryAVXInstruction(instruction ins);
125 bool IsThreeOperandMoveAVXInstruction(instruction ins);
126 bool IsThreeOperandAVXInstruction(instruction ins)
128 return (IsThreeOperandBinaryAVXInstruction(ins) || IsThreeOperandMoveAVXInstruction(ins));
130 #else // !FEATURE_AVX_SUPPORT
135 bool hasVexPrefix(size_t code)
139 bool IsThreeOperandBinaryAVXInstruction(instruction ins)
143 bool IsThreeOperandMoveAVXInstruction(instruction ins)
147 bool IsThreeOperandAVXInstruction(instruction ins)
151 bool TakesVexPrefix(instruction ins)
155 size_t AddVexPrefixIfNeeded(instruction ins, size_t code, emitAttr attr)
159 size_t AddVexPrefixIfNeededAndNotPresent(instruction ins, size_t code, emitAttr size)
163 #endif // !FEATURE_AVX_SUPPORT
165 /************************************************************************/
166 /* Debug-only routines to display instructions */
167 /************************************************************************/
171 const char* emitFPregName(unsigned reg, bool varName = true);
173 void emitDispReloc(ssize_t value);
174 void emitDispAddrMode(instrDesc* id, bool noDetail = false);
175 void emitDispShift(instruction ins, int cnt = 0);
177 void emitDispIns(instrDesc* id,
182 BYTE* code = nullptr,
184 insGroup* ig = nullptr);
186 const char* emitXMMregName(unsigned reg);
187 const char* emitYMMregName(unsigned reg);
191 /************************************************************************/
192 /* Private members that deal with target-dependent instr. descriptors */
193 /************************************************************************/
196 void emitSetAmdDisp(instrDescAmd* id, ssize_t dsp);
197 instrDesc* emitNewInstrAmd(emitAttr attr, ssize_t dsp);
198 instrDesc* emitNewInstrAmdCns(emitAttr attr, ssize_t dsp, int cns);
200 instrDesc* emitNewInstrCallDir(int argCnt,
201 VARSET_VALARG_TP GCvars,
204 emitAttr retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize));
206 instrDesc* emitNewInstrCallInd(int argCnt,
208 VARSET_VALARG_TP GCvars,
211 emitAttr retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize));
213 void emitGetInsCns(instrDesc* id, CnsVal* cv);
214 ssize_t emitGetInsAmdCns(instrDesc* id, CnsVal* cv);
215 void emitGetInsDcmCns(instrDesc* id, CnsVal* cv);
216 ssize_t emitGetInsAmdAny(instrDesc* id);
218 /************************************************************************/
219 /* Private helpers for instruction output */
220 /************************************************************************/
223 insFormat emitInsModeFormat(instruction ins, insFormat base, insFormat FPld, insFormat FPst);
225 bool emitVerifyEncodable(instruction ins, emitAttr size, regNumber reg1, regNumber reg2 = REG_NA);
227 bool emitInsCanOnlyWriteSSE2OrAVXReg(instrDesc* id);
229 /*****************************************************************************
231 * Convert between an index scale in bytes to a smaller encoding used for
232 * storage in instruction descriptors.
235 inline emitter::opSize emitEncodeScale(size_t scale)
237 assert(scale == 1 || scale == 2 || scale == 4 || scale == 8);
239 return emitSizeEncode[scale - 1];
242 inline emitAttr emitDecodeScale(unsigned ensz)
246 return emitter::emitSizeDecode[ensz];
249 /************************************************************************/
250 /* The public entry points to output instructions */
251 /************************************************************************/
254 void emitLoopAlign();
256 void emitIns(instruction ins);
258 void emitIns(instruction ins, emitAttr attr);
260 void emitInsRMW(instruction inst, emitAttr attr, GenTreeStoreInd* storeInd, GenTreePtr src);
262 void emitInsRMW(instruction inst, emitAttr attr, GenTreeStoreInd* storeInd);
264 void emitIns_Nop(unsigned size);
266 void emitIns_I(instruction ins, emitAttr attr, int val);
268 void emitIns_R(instruction ins, emitAttr attr, regNumber reg);
270 void emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fdlHnd, int offs);
272 void emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t val);
274 void emitIns_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2);
276 void emitIns_R_R_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int ival);
278 #ifdef FEATURE_AVX_SUPPORT
279 void emitIns_R_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3);
282 void emitIns_S(instruction ins, emitAttr attr, int varx, int offs);
284 void emitIns_S_R(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs);
286 void emitIns_R_S(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs);
288 void emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val);
290 void emitIns_R_C(instruction ins, emitAttr attr, regNumber reg, CORINFO_FIELD_HANDLE fldHnd, int offs);
292 void emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs);
294 void emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fdlHnd, int offs, int val);
296 void emitIns_IJ(emitAttr attr, regNumber reg, unsigned base);
298 void emitIns_J_S(instruction ins, emitAttr attr, BasicBlock* dst, int varx, int offs);
300 void emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg);
302 void emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg);
305 instruction ins, emitAttr attr, int val, regNumber reg, int offs, int memCookie = 0, void* clsCookie = nullptr);
307 void emitIns_I_AI(instruction ins, emitAttr attr, int val, ssize_t disp);
309 void emitIns_R_AR(instruction ins,
315 void* clsCookie = nullptr);
317 void emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t disp);
319 void emitIns_AR_R(instruction ins,
325 void* clsCookie = nullptr);
327 void emitIns_AI_R(instruction ins, emitAttr attr, regNumber ireg, ssize_t disp);
329 void emitIns_I_ARR(instruction ins, emitAttr attr, int val, regNumber reg, regNumber rg2, int disp);
331 void emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp);
333 void emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp);
335 void emitIns_I_ARX(instruction ins, emitAttr attr, int val, regNumber reg, regNumber rg2, unsigned mul, int disp);
338 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp);
341 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp);
343 void emitIns_I_AX(instruction ins, emitAttr attr, int val, regNumber reg, unsigned mul, int disp);
345 void emitIns_R_AX(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, unsigned mul, int disp);
347 void emitIns_AX_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, unsigned mul, int disp);
349 #if FEATURE_STACK_FP_X87
350 void emitIns_F_F0(instruction ins, unsigned fpreg);
352 void emitIns_F0_F(instruction ins, unsigned fpreg);
353 #endif // FEATURE_STACK_FP_X87
357 EC_FUNC_TOKEN, // Direct call to a helper/static/nonvirtual/global method
358 EC_FUNC_TOKEN_INDIR, // Indirect call to a helper/static/nonvirtual/global method
359 EC_FUNC_ADDR, // Direct call to an absolute address
361 EC_FUNC_VIRTUAL, // Call to a virtual method (using the vtable)
362 EC_INDIR_R, // Indirect call via register
363 EC_INDIR_SR, // Indirect call via stack-reference (local var)
364 EC_INDIR_C, // Indirect call via static class var
365 EC_INDIR_ARD, // Indirect call via an addressing mode
370 void emitIns_Call(EmitCallType callType,
371 CORINFO_METHOD_HANDLE methHnd,
372 CORINFO_SIG_INFO* sigInfo, // used to report call sites to the EE
375 emitAttr retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize),
376 VARSET_VALARG_TP ptrVars,
381 bool isNoGC = false);
383 void emitIns_Call(EmitCallType callType,
384 CORINFO_METHOD_HANDLE methHnd,
385 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
388 emitAttr retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize),
389 VARSET_VALARG_TP ptrVars,
392 IL_OFFSETX ilOffset = BAD_IL_OFFSET,
393 regNumber ireg = REG_NA,
394 regNumber xreg = REG_NA,
398 bool isNoGC = false);
400 #ifdef _TARGET_AMD64_
401 // Is the last instruction emitted a call instruction?
402 bool emitIsLastInsCall();
404 // Insert a NOP at the end of the the current instruction group if the last emitted instruction was a 'call',
405 // because the next instruction group will be an epilog.
406 void emitOutputPreEpilogNOP();
407 #endif // _TARGET_AMD64_
409 /*****************************************************************************
411 * Given a jump, return true if it's a conditional jump.
414 inline bool emitIsCondJump(instrDesc* jmp)
416 instruction ins = jmp->idIns();
418 assert(jmp->idInsFmt() == IF_LABEL);
420 return (ins != INS_call && ins != INS_jmp);
423 /*****************************************************************************
425 * Given a jump, return true if it's an unconditional jump.
428 inline bool emitIsUncondJump(instrDesc* jmp)
430 instruction ins = jmp->idIns();
432 assert(jmp->idInsFmt() == IF_LABEL);
434 return (ins == INS_jmp);
437 #endif // _TARGET_XARCH_