5b06838b0709387db718021fcb956bb4f22bc9da
[platform/upstream/coreclr.git] / src / jit / emitxarch.h
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 #if defined(_TARGET_XARCH_)
6
7 /************************************************************************/
8 /*           Public inline informational methods                        */
9 /************************************************************************/
10
11 public:
12 inline static bool isGeneralRegister(regNumber reg)
13 {
14     return (reg <= REG_INT_LAST);
15 }
16
17 inline static bool isFloatReg(regNumber reg)
18 {
19     return (reg >= REG_FP_FIRST && reg <= REG_FP_LAST);
20 }
21
22 inline static bool isDoubleReg(regNumber reg)
23 {
24     return isFloatReg(reg);
25 }
26
27 /************************************************************************/
28 /*         Routines that compute the size of / encode instructions      */
29 /************************************************************************/
30
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;
35
36 struct CnsVal
37 {
38     ssize_t cnsVal;
39     bool    cnsReloc;
40 };
41
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);
52
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);
56
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);
61
62 BYTE* emitOutputRRR(BYTE* dst, instrDesc* id);
63
64 BYTE* emitOutputLJ(BYTE* dst, instrDesc* id);
65
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);
71
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);
76
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);
82
83 unsigned insSSval(unsigned scale);
84
85 bool IsAVXInstruction(instruction ins);
86 code_t insEncodeMIreg(instruction ins, regNumber reg, emitAttr size, code_t code);
87
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);
93
94 bool EncodedBySSE38orSSE3A(instruction ins);
95 bool Is4ByteSSEInstruction(instruction ins);
96
97 bool AreUpper32BitsZero(regNumber reg);
98
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)
102 {
103     UNATIVE_OFFSET szDelta = 0;
104     if (ins == INS_crc32)
105     {
106         szDelta += 1;
107         if (attr == EA_2BYTE)
108         {
109             szDelta += 1;
110         }
111     }
112     return szDelta;
113 }
114
115 bool hasRexPrefix(code_t code)
116 {
117 #ifdef _TARGET_AMD64_
118     const code_t REX_PREFIX_MASK = 0xFF00000000LL;
119     return (code & REX_PREFIX_MASK) != 0;
120 #else  // !_TARGET_AMD64_
121     return false;
122 #endif // !_TARGET_AMD64_
123 }
124
125 // 3-byte VEX prefix starts with byte 0xC4
126 #define VEX_PREFIX_MASK_3BYTE 0xFF000000000000ULL
127 #define VEX_PREFIX_CODE_3BYTE 0xC4000000000000ULL
128
129 bool TakesVexPrefix(instruction ins);
130
131 // Returns true if the instruction encoding already contains VEX prefix
132 bool hasVexPrefix(code_t code)
133 {
134     return (code & VEX_PREFIX_MASK_3BYTE) == VEX_PREFIX_CODE_3BYTE;
135 }
136 code_t AddVexPrefix(instruction ins, code_t code, emitAttr attr);
137 code_t AddVexPrefixIfNeeded(instruction ins, code_t code, emitAttr size)
138 {
139     if (TakesVexPrefix(ins))
140     {
141         code = AddVexPrefix(ins, code, size);
142     }
143     return code;
144 }
145 code_t AddVexPrefixIfNeededAndNotPresent(instruction ins, code_t code, emitAttr size)
146 {
147     if (TakesVexPrefix(ins) && !hasVexPrefix(code))
148     {
149         code = AddVexPrefix(ins, code, size);
150     }
151     return code;
152 }
153
154 bool useVEXEncodings;
155 bool UseVEXEncoding()
156 {
157     return useVEXEncodings;
158 }
159 void SetUseVEXEncoding(bool value)
160 {
161     useVEXEncodings = value;
162 }
163
164 bool containsAVXInstruction = false;
165 bool ContainsAVX()
166 {
167     return containsAVXInstruction;
168 }
169 void SetContainsAVX(bool value)
170 {
171     containsAVXInstruction = value;
172 }
173
174 bool contains256bitAVXInstruction = false;
175 bool Contains256bitAVX()
176 {
177     return contains256bitAVXInstruction;
178 }
179 void SetContains256bitAVX(bool value)
180 {
181     contains256bitAVXInstruction = value;
182 }
183
184 bool IsDstDstSrcAVXInstruction(instruction ins);
185 bool IsDstSrcSrcAVXInstruction(instruction ins);
186 bool IsThreeOperandAVXInstruction(instruction ins)
187 {
188     return (IsDstDstSrcAVXInstruction(ins) || IsDstSrcSrcAVXInstruction(ins));
189 }
190 bool isAvxBlendv(instruction ins)
191 {
192     return ins == INS_vblendvps || ins == INS_vblendvpd || ins == INS_vpblendvb;
193 }
194 bool isSse41Blendv(instruction ins)
195 {
196     return ins == INS_blendvps || ins == INS_blendvpd || ins == INS_pblendvb;
197 }
198 bool isPrefetch(instruction ins)
199 {
200     return (ins == INS_prefetcht0) || (ins == INS_prefetcht1) || (ins == INS_prefetcht2) || (ins == INS_prefetchnta);
201 }
202
203 /************************************************************************/
204 /*             Debug-only routines to display instructions              */
205 /************************************************************************/
206
207 #ifdef DEBUG
208
209 const char* emitFPregName(unsigned reg, bool varName = true);
210
211 void emitDispReloc(ssize_t value);
212 void emitDispAddrMode(instrDesc* id, bool noDetail = false);
213 void emitDispShift(instruction ins, int cnt = 0);
214
215 void emitDispIns(instrDesc* id,
216                  bool       isNew,
217                  bool       doffs,
218                  bool       asmfm,
219                  unsigned   offs = 0,
220                  BYTE*      code = nullptr,
221                  size_t     sz   = 0,
222                  insGroup*  ig   = nullptr);
223
224 const char* emitXMMregName(unsigned reg);
225 const char* emitYMMregName(unsigned reg);
226
227 #endif
228
229 /************************************************************************/
230 /*  Private members that deal with target-dependent instr. descriptors  */
231 /************************************************************************/
232
233 private:
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);
237
238 instrDesc* emitNewInstrCallDir(int              argCnt,
239                                VARSET_VALARG_TP GCvars,
240                                regMaskTP        gcrefRegs,
241                                regMaskTP        byrefRegs,
242                                emitAttr retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize));
243
244 instrDesc* emitNewInstrCallInd(int              argCnt,
245                                ssize_t          disp,
246                                VARSET_VALARG_TP GCvars,
247                                regMaskTP        gcrefRegs,
248                                regMaskTP        byrefRegs,
249                                emitAttr retSize MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize));
250
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);
255
256 /************************************************************************/
257 /*               Private helpers for instruction output                 */
258 /************************************************************************/
259
260 private:
261 insFormat emitInsModeFormat(instruction ins, insFormat base, insFormat FPld, insFormat FPst);
262
263 bool emitVerifyEncodable(instruction ins, emitAttr size, regNumber reg1, regNumber reg2 = REG_NA);
264
265 bool emitInsCanOnlyWriteSSE2OrAVXReg(instrDesc* id);
266
267 #if FEATURE_FIXED_OUT_ARGS
268 void emitAdjustStackDepthPushPop(instruction ins)
269 {
270 }
271 void emitAdjustStackDepth(instruction ins, ssize_t val)
272 {
273 }
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
278
279 /*****************************************************************************
280 *
281 *  Convert between an index scale in bytes to a smaller encoding used for
282 *  storage in instruction descriptors.
283 */
284
285 inline emitter::opSize emitEncodeScale(size_t scale)
286 {
287     assert(scale == 1 || scale == 2 || scale == 4 || scale == 8);
288
289     return emitSizeEncode[scale - 1];
290 }
291
292 inline emitAttr emitDecodeScale(unsigned ensz)
293 {
294     assert(ensz < 4);
295
296     return emitter::emitSizeDecode[ensz];
297 }
298
299 /************************************************************************/
300 /*           The public entry points to output instructions             */
301 /************************************************************************/
302
303 public:
304 void emitLoopAlign();
305
306 void emitIns(instruction ins);
307
308 void emitIns(instruction ins, emitAttr attr);
309
310 void emitInsRMW(instruction inst, emitAttr attr, GenTreeStoreInd* storeInd, GenTree* src);
311
312 void emitInsRMW(instruction inst, emitAttr attr, GenTreeStoreInd* storeInd);
313
314 void emitIns_Nop(unsigned size);
315
316 void emitIns_I(instruction ins, emitAttr attr, int val);
317
318 void emitIns_R(instruction ins, emitAttr attr, regNumber reg);
319
320 void emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fdlHnd, int offs);
321
322 void emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t val);
323
324 void emitIns_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2);
325
326 void emitIns_R_R_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int ival);
327
328 void emitIns_AR(instruction ins, emitAttr attr, regNumber base, int offs);
329
330 void emitIns_AR_R_R(instruction ins, emitAttr attr, regNumber op2Reg, regNumber op3Reg, regNumber base, int offs);
331
332 void emitIns_R_A(instruction ins, emitAttr attr, regNumber reg1, GenTreeIndir* indir);
333
334 void emitIns_R_A_I(instruction ins, emitAttr attr, regNumber reg1, GenTreeIndir* indir, int ival);
335
336 void emitIns_R_AR_I(instruction ins, emitAttr attr, regNumber reg1, regNumber base, int offs, int ival);
337
338 void emitIns_R_C_I(instruction ins, emitAttr attr, regNumber reg1, CORINFO_FIELD_HANDLE fldHnd, int offs, int ival);
339
340 void emitIns_R_S_I(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs, int ival);
341
342 void emitIns_R_R_A(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, GenTreeIndir* indir);
343
344 void emitIns_R_R_AR(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber base, int offs);
345
346 void emitIns_R_AR_R(instruction ins,
347                     emitAttr    attr,
348                     regNumber   reg1,
349                     regNumber   reg2,
350                     regNumber   base,
351                     regNumber   index,
352                     int         scale,
353                     int         offs);
354
355 void emitIns_R_R_C(
356     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, CORINFO_FIELD_HANDLE fldHnd, int offs);
357
358 void emitIns_R_R_S(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int varx, int offs);
359
360 void emitIns_R_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3);
361
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);
367
368 void emitIns_R_R_C_I(
369     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, CORINFO_FIELD_HANDLE fldHnd, int offs, int ival);
370
371 void emitIns_R_R_R_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, int ival);
372
373 void emitIns_R_R_S_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int varx, int offs, int ival);
374
375 void emitIns_R_R_A_R(
376     instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op3Reg, GenTreeIndir* indir);
377
378 void emitIns_R_R_AR_R(
379     instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op3Reg, regNumber base, int offs);
380
381 void emitIns_R_R_C_R(instruction          ins,
382                      emitAttr             attr,
383                      regNumber            targetReg,
384                      regNumber            op1Reg,
385                      regNumber            op3Reg,
386                      CORINFO_FIELD_HANDLE fldHnd,
387                      int                  offs);
388
389 void emitIns_R_R_S_R(
390     instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op3Reg, int varx, int offs);
391
392 void emitIns_R_R_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4);
393
394 void emitIns_S(instruction ins, emitAttr attr, int varx, int offs);
395
396 void emitIns_S_R(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs);
397
398 void emitIns_R_S(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs);
399
400 void emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val);
401
402 void emitIns_R_C(instruction ins, emitAttr attr, regNumber reg, CORINFO_FIELD_HANDLE fldHnd, int offs);
403
404 void emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs);
405
406 void emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fdlHnd, int offs, int val);
407
408 void emitIns_IJ(emitAttr attr, regNumber reg, unsigned base);
409
410 void emitIns_J_S(instruction ins, emitAttr attr, BasicBlock* dst, int varx, int offs);
411
412 void emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg);
413
414 void emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg);
415
416 void emitIns_I_AR(instruction ins, emitAttr attr, int val, regNumber reg, int offs);
417
418 void emitIns_I_AI(instruction ins, emitAttr attr, int val, ssize_t disp);
419
420 void emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs);
421
422 void emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t disp);
423
424 void emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs);
425
426 void emitIns_AI_R(instruction ins, emitAttr attr, regNumber ireg, ssize_t disp);
427
428 void emitIns_I_ARR(instruction ins, emitAttr attr, int val, regNumber reg, regNumber rg2, int disp);
429
430 void emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp);
431
432 void emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp);
433
434 void emitIns_I_ARX(instruction ins, emitAttr attr, int val, regNumber reg, regNumber rg2, unsigned mul, int disp);
435
436 void emitIns_R_ARX(
437     instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp);
438
439 void emitIns_ARX_R(
440     instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp);
441
442 void emitIns_I_AX(instruction ins, emitAttr attr, int val, regNumber reg, unsigned mul, int disp);
443
444 void emitIns_R_AX(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, unsigned mul, int disp);
445
446 void emitIns_AX_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, unsigned mul, int disp);
447
448 #ifdef FEATURE_HW_INTRINSICS
449 void emitIns_SIMD_R_R_I(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int ival);
450
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);
457
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,
463                           emitAttr             attr,
464                           regNumber            targetReg,
465                           regNumber            op1Reg,
466                           CORINFO_FIELD_HANDLE fldHnd,
467                           int                  offs,
468                           int                  ival);
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);
473
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,
479                           emitAttr             attr,
480                           regNumber            targetReg,
481                           regNumber            op1Reg,
482                           regNumber            op2Reg,
483                           CORINFO_FIELD_HANDLE fldHnd,
484                           int                  offs);
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);
489
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,
495                           emitAttr             attr,
496                           regNumber            targetReg,
497                           regNumber            op1Reg,
498                           regNumber            op2Reg,
499                           CORINFO_FIELD_HANDLE fldHnd,
500                           int                  offs);
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
504
505 enum EmitCallType
506 {
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
510
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
516
517     EC_COUNT
518 };
519
520 // clang-format off
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
524                   void*                 addr,
525                   ssize_t               argSize,
526                   emitAttr              retSize
527                   MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(emitAttr secondRetSize),
528                   VARSET_VALARG_TP      ptrVars,
529                   regMaskTP             gcrefRegs,
530                   regMaskTP             byrefRegs,
531                   IL_OFFSETX            ilOffset = BAD_IL_OFFSET,
532                   regNumber             ireg     = REG_NA,
533                   regNumber             xreg     = REG_NA,
534                   unsigned              xmul     = 0,
535                   ssize_t               disp     = 0,
536                   bool                  isJump   = false);
537 // clang-format on
538
539 #ifdef _TARGET_AMD64_
540 // Is the last instruction emitted a call instruction?
541 bool emitIsLastInsCall();
542
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_
547
548 /*****************************************************************************
549  *
550  *  Given a jump, return true if it's a conditional jump.
551  */
552
553 inline bool emitIsCondJump(instrDesc* jmp)
554 {
555     instruction ins = jmp->idIns();
556
557     assert(jmp->idInsFmt() == IF_LABEL);
558
559     return (ins != INS_call && ins != INS_jmp);
560 }
561
562 /*****************************************************************************
563  *
564  *  Given a jump, return true if it's an unconditional jump.
565  */
566
567 inline bool emitIsUncondJump(instrDesc* jmp)
568 {
569     instruction ins = jmp->idIns();
570
571     assert(jmp->idInsFmt() == IF_LABEL);
572
573     return (ins == INS_jmp);
574 }
575
576 #endif // _TARGET_XARCH_