Merge pull request #10706 from sdmaclea/PR-ARM64-GC-EmitInsLdStOp
[platform/upstream/coreclr.git] / src / jit / codegenxarch.cpp
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 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7 XX                                                                           XX
8 XX                        Amd64/x86 Code Generator                           XX
9 XX                                                                           XX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
12 */
13 #include "jitpch.h"
14 #ifdef _MSC_VER
15 #pragma hdrstop
16 #endif
17
18 #ifndef LEGACY_BACKEND // This file is ONLY used for the RyuJIT backend that uses the linear scan register allocator.
19
20 #ifdef _TARGET_XARCH_
21 #include "emit.h"
22 #include "codegen.h"
23 #include "lower.h"
24 #include "gcinfo.h"
25 #include "gcinfoencoder.h"
26
27 /*****************************************************************************
28  *
29  *  Generate code that will set the given register to the integer constant.
30  */
31
32 void CodeGen::genSetRegToIcon(regNumber reg, ssize_t val, var_types type, insFlags flags)
33 {
34     // Reg cannot be a FP reg
35     assert(!genIsValidFloatReg(reg));
36
37     // The only TYP_REF constant that can come this path is a managed 'null' since it is not
38     // relocatable.  Other ref type constants (e.g. string objects) go through a different
39     // code path.
40     noway_assert(type != TYP_REF || val == 0);
41
42     if (val == 0)
43     {
44         instGen_Set_Reg_To_Zero(emitActualTypeSize(type), reg, flags);
45     }
46     else
47     {
48         // TODO-XArch-CQ: needs all the optimized cases
49         getEmitter()->emitIns_R_I(INS_mov, emitActualTypeSize(type), reg, val);
50     }
51 }
52
53 /*****************************************************************************
54  *
55  *   Generate code to check that the GS cookie wasn't thrashed by a buffer
56  *   overrun.  If pushReg is true, preserve all registers around code sequence.
57  *   Otherwise ECX could be modified.
58  *
59  *   Implementation Note: pushReg = true, in case of tail calls.
60  */
61 void CodeGen::genEmitGSCookieCheck(bool pushReg)
62 {
63     noway_assert(compiler->gsGlobalSecurityCookieAddr || compiler->gsGlobalSecurityCookieVal);
64
65     // Make sure that EAX is reported as live GC-ref so that any GC that kicks in while
66     // executing GS cookie check will not collect the object pointed to by EAX.
67     //
68     // For Amd64 System V, a two-register-returned struct could be returned in RAX and RDX
69     // In such case make sure that the correct GC-ness of RDX is reported as well, so
70     // a GC object pointed by RDX will not be collected.
71     if (!pushReg)
72     {
73         // Handle multi-reg return type values
74         if (compiler->compMethodReturnsMultiRegRetType())
75         {
76             ReturnTypeDesc retTypeDesc;
77             if (varTypeIsLong(compiler->info.compRetNativeType))
78             {
79                 retTypeDesc.InitializeLongReturnType(compiler);
80             }
81             else // we must have a struct return type
82             {
83                 retTypeDesc.InitializeStructReturnType(compiler, compiler->info.compMethodInfo->args.retTypeClass);
84             }
85
86             unsigned regCount = retTypeDesc.GetReturnRegCount();
87
88             // Only x86 and x64 Unix ABI allows multi-reg return and
89             // number of result regs should be equal to MAX_RET_REG_COUNT.
90             assert(regCount == MAX_RET_REG_COUNT);
91
92             for (unsigned i = 0; i < regCount; ++i)
93             {
94                 gcInfo.gcMarkRegPtrVal(retTypeDesc.GetABIReturnReg(i), retTypeDesc.GetReturnRegType(i));
95             }
96         }
97         else if (compiler->compMethodReturnsRetBufAddr())
98         {
99             // This is for returning in an implicit RetBuf.
100             // If the address of the buffer is returned in REG_INTRET, mark the content of INTRET as ByRef.
101
102             // In case the return is in an implicit RetBuf, the native return type should be a struct
103             assert(varTypeIsStruct(compiler->info.compRetNativeType));
104
105             gcInfo.gcMarkRegPtrVal(REG_INTRET, TYP_BYREF);
106         }
107         // ... all other cases.
108         else
109         {
110 #ifdef _TARGET_AMD64_
111             // For x64, structs that are not returned in registers are always
112             // returned in implicit RetBuf. If we reached here, we should not have
113             // a RetBuf and the return type should not be a struct.
114             assert(compiler->info.compRetBuffArg == BAD_VAR_NUM);
115             assert(!varTypeIsStruct(compiler->info.compRetNativeType));
116 #endif // _TARGET_AMD64_
117
118             // For x86 Windows we can't make such assertions since we generate code for returning of
119             // the RetBuf in REG_INTRET only when the ProfilerHook is enabled. Otherwise
120             // compRetNativeType could be TYP_STRUCT.
121             gcInfo.gcMarkRegPtrVal(REG_INTRET, compiler->info.compRetNativeType);
122         }
123     }
124
125     regNumber regGSCheck;
126     regMaskTP regMaskGSCheck = RBM_NONE;
127
128     if (!pushReg)
129     {
130         // Non-tail call: we can use any callee trash register that is not
131         // a return register or contain 'this' pointer (keep alive this), since
132         // we are generating GS cookie check after a GT_RETURN block.
133         // Note: On Amd64 System V RDX is an arg register - REG_ARG_2 - as well
134         // as return register for two-register-returned structs.
135         if (compiler->lvaKeepAliveAndReportThis() && compiler->lvaTable[compiler->info.compThisArg].lvRegister &&
136             (compiler->lvaTable[compiler->info.compThisArg].lvRegNum == REG_ARG_0))
137         {
138             regGSCheck = REG_ARG_1;
139         }
140         else
141         {
142             regGSCheck = REG_ARG_0;
143         }
144     }
145     else
146     {
147 #ifdef _TARGET_X86_
148         // It doesn't matter which register we pick, since we're going to save and restore it
149         // around the check.
150         // TODO-CQ: Can we optimize the choice of register to avoid doing the push/pop sometimes?
151         regGSCheck     = REG_EAX;
152         regMaskGSCheck = RBM_EAX;
153 #else  // !_TARGET_X86_
154         // Tail calls from methods that need GS check:  We need to preserve registers while
155         // emitting GS cookie check for a tail prefixed call or a jmp. To emit GS cookie
156         // check, we might need a register. This won't be an issue for jmp calls for the
157         // reason mentioned below (see comment starting with "Jmp Calls:").
158         //
159         // The following are the possible solutions in case of tail prefixed calls:
160         // 1) Use R11 - ignore tail prefix on calls that need to pass a param in R11 when
161         //    present in methods that require GS cookie check.  Rest of the tail calls that
162         //    do not require R11 will be honored.
163         // 2) Internal register - GT_CALL node reserves an internal register and emits GS
164         //    cookie check as part of tail call codegen. GenExitCode() needs to special case
165         //    fast tail calls implemented as epilog+jmp or such tail calls should always get
166         //    dispatched via helper.
167         // 3) Materialize GS cookie check as a sperate node hanging off GT_CALL node in
168         //    right execution order during rationalization.
169         //
170         // There are two calls that use R11: VSD and calli pinvokes with cookie param. Tail
171         // prefix on pinvokes is ignored.  That is, options 2 and 3 will allow tail prefixed
172         // VSD calls from methods that need GS check.
173         //
174         // Tail prefixed calls: Right now for Jit64 compat, method requiring GS cookie check
175         // ignores tail prefix.  In future, if we intend to support tail calls from such a method,
176         // consider one of the options mentioned above.  For now adding an assert that we don't
177         // expect to see a tail call in a method that requires GS check.
178         noway_assert(!compiler->compTailCallUsed);
179
180         // Jmp calls: specify method handle using which JIT queries VM for its entry point
181         // address and hence it can neither be a VSD call nor PInvoke calli with cookie
182         // parameter.  Therefore, in case of jmp calls it is safe to use R11.
183         regGSCheck = REG_R11;
184 #endif // !_TARGET_X86_
185     }
186
187     regMaskTP byrefPushedRegs = RBM_NONE;
188     regMaskTP norefPushedRegs = RBM_NONE;
189     regMaskTP pushedRegs      = RBM_NONE;
190
191     if (compiler->gsGlobalSecurityCookieAddr == nullptr)
192     {
193 #if defined(_TARGET_AMD64_)
194         // If GS cookie value fits within 32-bits we can use 'cmp mem64, imm32'.
195         // Otherwise, load the value into a reg and use 'cmp mem64, reg64'.
196         if ((int)compiler->gsGlobalSecurityCookieVal != (ssize_t)compiler->gsGlobalSecurityCookieVal)
197         {
198             genSetRegToIcon(regGSCheck, compiler->gsGlobalSecurityCookieVal, TYP_I_IMPL);
199             getEmitter()->emitIns_S_R(INS_cmp, EA_PTRSIZE, regGSCheck, compiler->lvaGSSecurityCookie, 0);
200         }
201         else
202 #endif // defined(_TARGET_AMD64_)
203         {
204             assert((int)compiler->gsGlobalSecurityCookieVal == (ssize_t)compiler->gsGlobalSecurityCookieVal);
205             getEmitter()->emitIns_S_I(INS_cmp, EA_PTRSIZE, compiler->lvaGSSecurityCookie, 0,
206                                       (int)compiler->gsGlobalSecurityCookieVal);
207         }
208     }
209     else
210     {
211         // Ngen case - GS cookie value needs to be accessed through an indirection.
212
213         pushedRegs = genPushRegs(regMaskGSCheck, &byrefPushedRegs, &norefPushedRegs);
214
215         instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, regGSCheck, (ssize_t)compiler->gsGlobalSecurityCookieAddr);
216         getEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, regGSCheck, regGSCheck, 0);
217         getEmitter()->emitIns_S_R(INS_cmp, EA_PTRSIZE, regGSCheck, compiler->lvaGSSecurityCookie, 0);
218     }
219
220     BasicBlock*  gsCheckBlk = genCreateTempLabel();
221     emitJumpKind jmpEqual   = genJumpKindForOper(GT_EQ, CK_SIGNED);
222     inst_JMP(jmpEqual, gsCheckBlk);
223     genEmitHelperCall(CORINFO_HELP_FAIL_FAST, 0, EA_UNKNOWN);
224     genDefineTempLabel(gsCheckBlk);
225
226     genPopRegs(pushedRegs, byrefPushedRegs, norefPushedRegs);
227 }
228
229 BasicBlock* CodeGen::genCallFinally(BasicBlock* block)
230 {
231 #if FEATURE_EH_FUNCLETS
232     // Generate a call to the finally, like this:
233     //      mov         rcx,qword ptr [rbp + 20H]       // Load rcx with PSPSym
234     //      call        finally-funclet
235     //      jmp         finally-return                  // Only for non-retless finally calls
236     // The jmp can be a NOP if we're going to the next block.
237     // If we're generating code for the main function (not a funclet), and there is no localloc,
238     // then RSP at this point is the same value as that stored in the PSPSym. So just copy RSP
239     // instead of loading the PSPSym in this case, or if PSPSym is not used (CoreRT ABI).
240
241     if ((compiler->lvaPSPSym == BAD_VAR_NUM) ||
242         (!compiler->compLocallocUsed && (compiler->funCurrentFunc()->funKind == FUNC_ROOT)))
243     {
244 #ifndef UNIX_X86_ABI
245         inst_RV_RV(INS_mov, REG_ARG_0, REG_SPBASE, TYP_I_IMPL);
246 #endif // !UNIX_X86_ABI
247     }
248     else
249     {
250         getEmitter()->emitIns_R_S(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_ARG_0, compiler->lvaPSPSym, 0);
251     }
252     getEmitter()->emitIns_J(INS_call, block->bbJumpDest);
253
254     if (block->bbFlags & BBF_RETLESS_CALL)
255     {
256         // We have a retless call, and the last instruction generated was a call.
257         // If the next block is in a different EH region (or is the end of the code
258         // block), then we need to generate a breakpoint here (since it will never
259         // get executed) to get proper unwind behavior.
260
261         if ((block->bbNext == nullptr) || !BasicBlock::sameEHRegion(block, block->bbNext))
262         {
263             instGen(INS_BREAKPOINT); // This should never get executed
264         }
265     }
266     else
267     {
268 // TODO-Linux-x86: Do we need to handle the GC information for this NOP or JMP specially, as is done for other
269 // architectures?
270 #ifndef JIT32_GCENCODER
271         // Because of the way the flowgraph is connected, the liveness info for this one instruction
272         // after the call is not (can not be) correct in cases where a variable has a last use in the
273         // handler.  So turn off GC reporting for this single instruction.
274         getEmitter()->emitDisableGC();
275 #endif // JIT32_GCENCODER
276
277         // Now go to where the finally funclet needs to return to.
278         if (block->bbNext->bbJumpDest == block->bbNext->bbNext)
279         {
280             // Fall-through.
281             // TODO-XArch-CQ: Can we get rid of this instruction, and just have the call return directly
282             // to the next instruction? This would depend on stack walking from within the finally
283             // handler working without this instruction being in this special EH region.
284             instGen(INS_nop);
285         }
286         else
287         {
288             inst_JMP(EJ_jmp, block->bbNext->bbJumpDest);
289         }
290
291 #ifndef JIT32_GCENCODER
292         getEmitter()->emitEnableGC();
293 #endif // JIT32_GCENCODER
294     }
295
296 #else // !FEATURE_EH_FUNCLETS
297
298     // If we are about to invoke a finally locally from a try block, we have to set the ShadowSP slot
299     // corresponding to the finally's nesting level. When invoked in response to an exception, the
300     // EE does this.
301     //
302     // We have a BBJ_CALLFINALLY followed by a BBJ_ALWAYS.
303     //
304     // We will emit :
305     //      mov [ebp - (n + 1)], 0
306     //      mov [ebp -  n     ], 0xFC
307     //      push &step
308     //      jmp  finallyBlock
309     // ...
310     // step:
311     //      mov [ebp -  n     ], 0
312     //      jmp leaveTarget
313     // ...
314     // leaveTarget:
315
316     noway_assert(isFramePointerUsed());
317
318     // Get the nesting level which contains the finally
319     unsigned finallyNesting = 0;
320     compiler->fgGetNestingLevel(block, &finallyNesting);
321
322     // The last slot is reserved for ICodeManager::FixContext(ppEndRegion)
323     unsigned filterEndOffsetSlotOffs;
324     filterEndOffsetSlotOffs = (unsigned)(compiler->lvaLclSize(compiler->lvaShadowSPslotsVar) - TARGET_POINTER_SIZE);
325
326     unsigned curNestingSlotOffs;
327     curNestingSlotOffs = (unsigned)(filterEndOffsetSlotOffs - ((finallyNesting + 1) * TARGET_POINTER_SIZE));
328
329     // Zero out the slot for the next nesting level
330     instGen_Store_Imm_Into_Lcl(TYP_I_IMPL, EA_PTRSIZE, 0, compiler->lvaShadowSPslotsVar,
331                                curNestingSlotOffs - TARGET_POINTER_SIZE);
332     instGen_Store_Imm_Into_Lcl(TYP_I_IMPL, EA_PTRSIZE, LCL_FINALLY_MARK, compiler->lvaShadowSPslotsVar,
333                                curNestingSlotOffs);
334
335     // Now push the address where the finally funclet should return to directly.
336     if (!(block->bbFlags & BBF_RETLESS_CALL))
337     {
338         assert(block->isBBCallAlwaysPair());
339         getEmitter()->emitIns_J(INS_push_hide, block->bbNext->bbJumpDest);
340     }
341     else
342     {
343         // EE expects a DWORD, so we give him 0
344         inst_IV(INS_push_hide, 0);
345     }
346
347     // Jump to the finally BB
348     inst_JMP(EJ_jmp, block->bbJumpDest);
349
350 #endif // !FEATURE_EH_FUNCLETS
351
352     // The BBJ_ALWAYS is used because the BBJ_CALLFINALLY can't point to the
353     // jump target using bbJumpDest - that is already used to point
354     // to the finally block. So just skip past the BBJ_ALWAYS unless the
355     // block is RETLESS.
356     if (!(block->bbFlags & BBF_RETLESS_CALL))
357     {
358         assert(block->isBBCallAlwaysPair());
359         block = block->bbNext;
360     }
361     return block;
362 }
363
364 #if FEATURE_EH_FUNCLETS
365 void CodeGen::genEHCatchRet(BasicBlock* block)
366 {
367     // Set RAX to the address the VM should return to after the catch.
368     // Generate a RIP-relative
369     //         lea reg, [rip + disp32] ; the RIP is implicit
370     // which will be position-indepenent.
371     getEmitter()->emitIns_R_L(INS_lea, EA_PTR_DSP_RELOC, block->bbJumpDest, REG_INTRET);
372 }
373
374 #else // !FEATURE_EH_FUNCLETS
375
376 void CodeGen::genEHFinallyOrFilterRet(BasicBlock* block)
377 {
378     // The last statement of the block must be a GT_RETFILT, which has already been generated.
379     assert(block->lastNode() != nullptr);
380     assert(block->lastNode()->OperGet() == GT_RETFILT);
381
382     if (block->bbJumpKind == BBJ_EHFINALLYRET)
383     {
384         assert(block->lastNode()->gtOp.gtOp1 == nullptr); // op1 == nullptr means endfinally
385
386         // Return using a pop-jmp sequence. As the "try" block calls
387         // the finally with a jmp, this leaves the x86 call-ret stack
388         // balanced in the normal flow of path.
389
390         noway_assert(isFramePointerRequired());
391         inst_RV(INS_pop_hide, REG_EAX, TYP_I_IMPL);
392         inst_RV(INS_i_jmp, REG_EAX, TYP_I_IMPL);
393     }
394     else
395     {
396         assert(block->bbJumpKind == BBJ_EHFILTERRET);
397
398         // The return value has already been computed.
399         instGen_Return(0);
400     }
401 }
402
403 #endif // !FEATURE_EH_FUNCLETS
404
405 //  Move an immediate value into an integer register
406
407 void CodeGen::instGen_Set_Reg_To_Imm(emitAttr size, regNumber reg, ssize_t imm, insFlags flags)
408 {
409     // reg cannot be a FP register
410     assert(!genIsValidFloatReg(reg));
411
412     if (!compiler->opts.compReloc)
413     {
414         size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs
415     }
416
417     if ((imm == 0) && !EA_IS_RELOC(size))
418     {
419         instGen_Set_Reg_To_Zero(size, reg, flags);
420     }
421     else
422     {
423         if (genDataIndirAddrCanBeEncodedAsPCRelOffset(imm))
424         {
425             getEmitter()->emitIns_R_AI(INS_lea, EA_PTR_DSP_RELOC, reg, imm);
426         }
427         else
428         {
429             getEmitter()->emitIns_R_I(INS_mov, size, reg, imm);
430         }
431     }
432     regTracker.rsTrackRegIntCns(reg, imm);
433 }
434
435 /***********************************************************************************
436  *
437  * Generate code to set a register 'targetReg' of type 'targetType' to the constant
438  * specified by the constant (GT_CNS_INT or GT_CNS_DBL) in 'tree'. This does not call
439  * genProduceReg() on the target register.
440  */
441 void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTreePtr tree)
442 {
443
444     switch (tree->gtOper)
445     {
446         case GT_CNS_INT:
447         {
448             // relocatable values tend to come down as a CNS_INT of native int type
449             // so the line between these two opcodes is kind of blurry
450             GenTreeIntConCommon* con    = tree->AsIntConCommon();
451             ssize_t              cnsVal = con->IconValue();
452
453             if (con->ImmedValNeedsReloc(compiler))
454             {
455                 instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, targetReg, cnsVal);
456                 regTracker.rsTrackRegTrash(targetReg);
457             }
458             else
459             {
460                 genSetRegToIcon(targetReg, cnsVal, targetType);
461             }
462         }
463         break;
464
465         case GT_CNS_DBL:
466         {
467             double constValue = tree->gtDblCon.gtDconVal;
468
469             // Make sure we use "xorpd reg, reg"  only for +ve zero constant (0.0) and not for -ve zero (-0.0)
470             if (*(__int64*)&constValue == 0)
471             {
472                 // A faster/smaller way to generate 0
473                 instruction ins = genGetInsForOper(GT_XOR, targetType);
474                 inst_RV_RV(ins, targetReg, targetReg, targetType);
475             }
476             else
477             {
478                 GenTreePtr cns;
479                 if (targetType == TYP_FLOAT)
480                 {
481                     float f = forceCastToFloat(constValue);
482                     cns     = genMakeConst(&f, targetType, tree, false);
483                 }
484                 else
485                 {
486                     cns = genMakeConst(&constValue, targetType, tree, true);
487                 }
488
489                 inst_RV_TT(ins_Load(targetType), targetReg, cns);
490             }
491         }
492         break;
493
494         default:
495             unreached();
496     }
497 }
498
499 // Generate code to get the high N bits of a N*N=2N bit multiplication result
500 void CodeGen::genCodeForMulHi(GenTreeOp* treeNode)
501 {
502     if (treeNode->OperGet() == GT_MULHI)
503     {
504         assert(!(treeNode->gtFlags & GTF_UNSIGNED));
505     }
506     assert(!treeNode->gtOverflowEx());
507
508     regNumber targetReg  = treeNode->gtRegNum;
509     var_types targetType = treeNode->TypeGet();
510     emitter*  emit       = getEmitter();
511     emitAttr  size       = emitTypeSize(treeNode);
512     GenTree*  op1        = treeNode->gtOp.gtOp1;
513     GenTree*  op2        = treeNode->gtOp.gtOp2;
514
515     // to get the high bits of the multiply, we are constrained to using the
516     // 1-op form:  RDX:RAX = RAX * rm
517     // The 3-op form (Rx=Ry*Rz) does not support it.
518
519     genConsumeOperands(treeNode->AsOp());
520
521     GenTree* regOp = op1;
522     GenTree* rmOp  = op2;
523
524     // Set rmOp to the memory operand (if any)
525     if (op1->isUsedFromMemory() || (op2->isUsedFromReg() && (op2->gtRegNum == REG_RAX)))
526     {
527         regOp = op2;
528         rmOp  = op1;
529     }
530     assert(regOp->isUsedFromReg());
531
532     // Setup targetReg when neither of the source operands was a matching register
533     if (regOp->gtRegNum != REG_RAX)
534     {
535         inst_RV_RV(ins_Copy(targetType), REG_RAX, regOp->gtRegNum, targetType);
536     }
537
538     instruction ins;
539     if ((treeNode->gtFlags & GTF_UNSIGNED) == 0)
540     {
541         ins = INS_imulEAX;
542     }
543     else
544     {
545         ins = INS_mulEAX;
546     }
547     emit->emitInsBinary(ins, size, treeNode, rmOp);
548
549     // Move the result to the desired register, if necessary
550     if (treeNode->OperGet() == GT_MULHI && targetReg != REG_RDX)
551     {
552         inst_RV_RV(INS_mov, targetReg, REG_RDX, targetType);
553     }
554 }
555
556 #ifdef _TARGET_X86_
557 //------------------------------------------------------------------------
558 // genCodeForLongUMod: Generate code for a tree of the form
559 //                     `(umod (gt_long x y) (const int))`
560 //
561 // Arguments:
562 //   node - the node for which to generate code
563 //
564 void CodeGen::genCodeForLongUMod(GenTreeOp* node)
565 {
566     assert(node != nullptr);
567     assert(node->OperGet() == GT_UMOD);
568     assert(node->TypeGet() == TYP_INT);
569
570     GenTreeOp* const dividend = node->gtOp1->AsOp();
571     assert(dividend->OperGet() == GT_LONG);
572     assert(varTypeIsLong(dividend));
573
574     genConsumeOperands(node);
575
576     GenTree* const dividendLo = dividend->gtOp1;
577     GenTree* const dividendHi = dividend->gtOp2;
578     assert(dividendLo->isUsedFromReg());
579     assert(dividendHi->isUsedFromReg());
580
581     GenTree* const divisor = node->gtOp2;
582     assert(divisor->gtSkipReloadOrCopy()->OperGet() == GT_CNS_INT);
583     assert(divisor->gtSkipReloadOrCopy()->isUsedFromReg());
584     assert(divisor->gtSkipReloadOrCopy()->AsIntCon()->gtIconVal >= 2);
585     assert(divisor->gtSkipReloadOrCopy()->AsIntCon()->gtIconVal <= 0x3fffffff);
586
587     // dividendLo must be in RAX; dividendHi must be in RDX
588     genCopyRegIfNeeded(dividendLo, REG_EAX);
589     genCopyRegIfNeeded(dividendHi, REG_EDX);
590
591     // At this point, EAX:EDX contains the 64bit dividend and op2->gtRegNum
592     // contains the 32bit divisor. We want to generate the following code:
593     //
594     //   cmp edx, divisor->gtRegNum
595     //   jb noOverflow
596     //
597     //   mov temp, eax
598     //   mov eax, edx
599     //   xor edx, edx
600     //   div divisor->gtRegNum
601     //   mov eax, temp
602     //
603     // noOverflow:
604     //   div divisor->gtRegNum
605     //
606     // This works because (a * 2^32 + b) % c = ((a % c) * 2^32 + b) % c.
607
608     BasicBlock* const noOverflow = genCreateTempLabel();
609
610     //   cmp edx, divisor->gtRegNum
611     //   jb noOverflow
612     inst_RV_RV(INS_cmp, REG_EDX, divisor->gtRegNum);
613     inst_JMP(EJ_jb, noOverflow);
614
615     //   mov temp, eax
616     //   mov eax, edx
617     //   xor edx, edx
618     //   div divisor->gtRegNum
619     //   mov eax, temp
620     const regNumber tempReg = genRegNumFromMask(node->gtRsvdRegs);
621     inst_RV_RV(INS_mov, tempReg, REG_EAX, TYP_INT);
622     inst_RV_RV(INS_mov, REG_EAX, REG_EDX, TYP_INT);
623     instGen_Set_Reg_To_Zero(EA_PTRSIZE, REG_EDX);
624     inst_RV(INS_div, divisor->gtRegNum, TYP_INT);
625     inst_RV_RV(INS_mov, REG_EAX, tempReg, TYP_INT);
626
627     // noOverflow:
628     //   div divisor->gtRegNum
629     genDefineTempLabel(noOverflow);
630     inst_RV(INS_div, divisor->gtRegNum, TYP_INT);
631
632     const regNumber targetReg = node->gtRegNum;
633     if (targetReg != REG_EDX)
634     {
635         inst_RV_RV(INS_mov, targetReg, REG_RDX, TYP_INT);
636     }
637     genProduceReg(node);
638 }
639 #endif // _TARGET_X86_
640
641 //------------------------------------------------------------------------
642 // genCodeForDivMod: Generate code for a DIV or MOD operation.
643 //
644 // Arguments:
645 //    treeNode - the node to generate the code for
646 //
647 void CodeGen::genCodeForDivMod(GenTreeOp* treeNode)
648 {
649     GenTree* dividend = treeNode->gtOp1;
650 #ifdef _TARGET_X86_
651     if (varTypeIsLong(dividend->TypeGet()))
652     {
653         genCodeForLongUMod(treeNode);
654         return;
655     }
656 #endif // _TARGET_X86_
657
658     GenTree*   divisor    = treeNode->gtOp2;
659     genTreeOps oper       = treeNode->OperGet();
660     emitAttr   size       = emitTypeSize(treeNode);
661     regNumber  targetReg  = treeNode->gtRegNum;
662     var_types  targetType = treeNode->TypeGet();
663     emitter*   emit       = getEmitter();
664
665     // dividend is in a register.
666     assert(dividend->isUsedFromReg());
667
668     genConsumeOperands(treeNode->AsOp());
669     if (varTypeIsFloating(targetType))
670     {
671         // Check that divisor is a valid operand.
672         // Note that a reg optional operand is a treated as a memory op
673         // if no register is allocated to it.
674         assert(divisor->isUsedFromReg() || divisor->isMemoryOp() || divisor->IsCnsFltOrDbl() ||
675                divisor->IsRegOptional());
676
677         // Floating point div/rem operation
678         assert(oper == GT_DIV || oper == GT_MOD);
679
680         if (dividend->gtRegNum == targetReg)
681         {
682             emit->emitInsBinary(genGetInsForOper(treeNode->gtOper, targetType), size, treeNode, divisor);
683         }
684         else if (divisor->isUsedFromReg() && divisor->gtRegNum == targetReg)
685         {
686             // It is not possible to generate 2-operand divss or divsd where reg2 = reg1 / reg2
687             // because divss/divsd reg1, reg2 will over-write reg1.  Therefore, in case of AMD64
688             // LSRA has to make sure that such a register assignment is not generated for floating
689             // point div/rem operations.
690             noway_assert(
691                 !"GT_DIV/GT_MOD (float): case of reg2 = reg1 / reg2, LSRA should never generate such a reg assignment");
692         }
693         else
694         {
695             inst_RV_RV(ins_Copy(targetType), targetReg, dividend->gtRegNum, targetType);
696             emit->emitInsBinary(genGetInsForOper(treeNode->gtOper, targetType), size, treeNode, divisor);
697         }
698     }
699     else
700     {
701         // dividend must be in RAX
702         genCopyRegIfNeeded(dividend, REG_RAX);
703
704         // zero or sign extend rax to rdx
705         if (oper == GT_UMOD || oper == GT_UDIV)
706         {
707             instGen_Set_Reg_To_Zero(EA_PTRSIZE, REG_EDX);
708         }
709         else
710         {
711             emit->emitIns(INS_cdq, size);
712             // the cdq instruction writes RDX, So clear the gcInfo for RDX
713             gcInfo.gcMarkRegSetNpt(RBM_RDX);
714         }
715
716         // Perform the 'targetType' (64-bit or 32-bit) divide instruction
717         instruction ins;
718         if (oper == GT_UMOD || oper == GT_UDIV)
719         {
720             ins = INS_div;
721         }
722         else
723         {
724             ins = INS_idiv;
725         }
726
727         emit->emitInsBinary(ins, size, treeNode, divisor);
728
729         // DIV/IDIV instructions always store the quotient in RAX and the remainder in RDX.
730         // Move the result to the desired register, if necessary
731         if (oper == GT_DIV || oper == GT_UDIV)
732         {
733             if (targetReg != REG_RAX)
734             {
735                 inst_RV_RV(INS_mov, targetReg, REG_RAX, targetType);
736             }
737         }
738         else
739         {
740             assert((oper == GT_MOD) || (oper == GT_UMOD));
741             if (targetReg != REG_RDX)
742             {
743                 inst_RV_RV(INS_mov, targetReg, REG_RDX, targetType);
744             }
745         }
746     }
747     genProduceReg(treeNode);
748 }
749
750 //------------------------------------------------------------------------
751 // genCodeForBinary: Generate code for many binary arithmetic operators
752 // This method is expected to have called genConsumeOperands() before calling it.
753 //
754 // Arguments:
755 //    treeNode - The binary operation for which we are generating code.
756 //
757 // Return Value:
758 //    None.
759 //
760 // Notes:
761 //    Mul and div variants have special constraints on x64 so are not handled here.
762 //    See teh assert below for the operators that are handled.
763
764 void CodeGen::genCodeForBinary(GenTree* treeNode)
765 {
766     const genTreeOps oper       = treeNode->OperGet();
767     regNumber        targetReg  = treeNode->gtRegNum;
768     var_types        targetType = treeNode->TypeGet();
769     emitter*         emit       = getEmitter();
770
771 #if defined(_TARGET_64BIT_)
772     assert(oper == GT_OR || oper == GT_XOR || oper == GT_AND || oper == GT_ADD || oper == GT_SUB);
773 #else  // !defined(_TARGET_64BIT_)
774     assert(oper == GT_OR || oper == GT_XOR || oper == GT_AND || oper == GT_ADD_LO || oper == GT_ADD_HI ||
775            oper == GT_SUB_LO || oper == GT_SUB_HI || oper == GT_MUL_LONG || oper == GT_DIV_HI || oper == GT_MOD_HI ||
776            oper == GT_ADD || oper == GT_SUB);
777 #endif // !defined(_TARGET_64BIT_)
778
779     GenTreePtr op1 = treeNode->gtGetOp1();
780     GenTreePtr op2 = treeNode->gtGetOp2();
781
782     // Commutative operations can mark op1 as contained or reg-optional to generate "op reg, memop/immed"
783     if (!op1->isUsedFromReg())
784     {
785         assert(treeNode->OperIsCommutative());
786         assert(op1->isMemoryOp() || op1->IsCnsNonZeroFltOrDbl() || op1->IsIntCnsFitsInI32() || op1->IsRegOptional());
787
788         op1 = treeNode->gtGetOp2();
789         op2 = treeNode->gtGetOp1();
790     }
791
792     instruction ins = genGetInsForOper(treeNode->OperGet(), targetType);
793
794     // The arithmetic node must be sitting in a register (since it's not contained)
795     noway_assert(targetReg != REG_NA);
796
797     regNumber op1reg = op1->isUsedFromReg() ? op1->gtRegNum : REG_NA;
798     regNumber op2reg = op2->isUsedFromReg() ? op2->gtRegNum : REG_NA;
799
800     GenTreePtr dst;
801     GenTreePtr src;
802
803     // This is the case of reg1 = reg1 op reg2
804     // We're ready to emit the instruction without any moves
805     if (op1reg == targetReg)
806     {
807         dst = op1;
808         src = op2;
809     }
810     // We have reg1 = reg2 op reg1
811     // In order for this operation to be correct
812     // we need that op is a commutative operation so
813     // we can convert it into reg1 = reg1 op reg2 and emit
814     // the same code as above
815     else if (op2reg == targetReg)
816     {
817         noway_assert(GenTree::OperIsCommutative(oper));
818         dst = op2;
819         src = op1;
820     }
821     // now we know there are 3 different operands so attempt to use LEA
822     else if (oper == GT_ADD && !varTypeIsFloating(treeNode) && !treeNode->gtOverflowEx() // LEA does not set flags
823              && (op2->isContainedIntOrIImmed() || op2->isUsedFromReg()) && !treeNode->gtSetFlags())
824     {
825         if (op2->isContainedIntOrIImmed())
826         {
827             emit->emitIns_R_AR(INS_lea, emitTypeSize(treeNode), targetReg, op1reg,
828                                (int)op2->AsIntConCommon()->IconValue());
829         }
830         else
831         {
832             assert(op2reg != REG_NA);
833             emit->emitIns_R_ARX(INS_lea, emitTypeSize(treeNode), targetReg, op1reg, op2reg, 1, 0);
834         }
835         genProduceReg(treeNode);
836         return;
837     }
838     // dest, op1 and op2 registers are different:
839     // reg3 = reg1 op reg2
840     // We can implement this by issuing a mov:
841     // reg3 = reg1
842     // reg3 = reg3 op reg2
843     else
844     {
845         inst_RV_RV(ins_Copy(targetType), targetReg, op1reg, targetType);
846         regTracker.rsTrackRegCopy(targetReg, op1reg);
847         gcInfo.gcMarkRegPtrVal(targetReg, targetType);
848         dst = treeNode;
849         src = op2;
850     }
851
852     // try to use an inc or dec
853     if (oper == GT_ADD && !varTypeIsFloating(treeNode) && src->isContainedIntOrIImmed() && !treeNode->gtOverflowEx())
854     {
855         if (src->IsIntegralConst(1))
856         {
857             emit->emitIns_R(INS_inc, emitTypeSize(treeNode), targetReg);
858             genProduceReg(treeNode);
859             return;
860         }
861         else if (src->IsIntegralConst(-1))
862         {
863             emit->emitIns_R(INS_dec, emitTypeSize(treeNode), targetReg);
864             genProduceReg(treeNode);
865             return;
866         }
867     }
868     regNumber r = emit->emitInsBinary(ins, emitTypeSize(treeNode), dst, src);
869     noway_assert(r == targetReg);
870
871     if (treeNode->gtOverflowEx())
872     {
873 #if !defined(_TARGET_64BIT_)
874         assert(oper == GT_ADD || oper == GT_SUB || oper == GT_ADD_HI || oper == GT_SUB_HI);
875 #else
876         assert(oper == GT_ADD || oper == GT_SUB);
877 #endif
878         genCheckOverflow(treeNode);
879     }
880     genProduceReg(treeNode);
881 }
882
883 //------------------------------------------------------------------------
884 // isStructReturn: Returns whether the 'treeNode' is returning a struct.
885 //
886 // Arguments:
887 //    treeNode - The tree node to evaluate whether is a struct return.
888 //
889 // Return Value:
890 //    For AMD64 *nix: returns true if the 'treeNode" is a GT_RETURN node, of type struct.
891 //                    Otherwise returns false.
892 //    For other platforms always returns false.
893 //
894 bool CodeGen::isStructReturn(GenTreePtr treeNode)
895 {
896     // This method could be called for 'treeNode' of GT_RET_FILT or GT_RETURN.
897     // For the GT_RET_FILT, the return is always
898     // a bool or a void, for the end of a finally block.
899     noway_assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT);
900     if (treeNode->OperGet() != GT_RETURN)
901     {
902         return false;
903     }
904
905 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
906     return varTypeIsStruct(treeNode);
907 #else  // !FEATURE_UNIX_AMD64_STRUCT_PASSING
908     assert(!varTypeIsStruct(treeNode));
909     return false;
910 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
911 }
912
913 //------------------------------------------------------------------------
914 // genStructReturn: Generates code for returning a struct.
915 //
916 // Arguments:
917 //    treeNode - The GT_RETURN tree node.
918 //
919 // Return Value:
920 //    None
921 //
922 // Assumption:
923 //    op1 of GT_RETURN node is either GT_LCL_VAR or multi-reg GT_CALL
924 void CodeGen::genStructReturn(GenTreePtr treeNode)
925 {
926     assert(treeNode->OperGet() == GT_RETURN);
927     GenTreePtr op1 = treeNode->gtGetOp1();
928
929 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
930     if (op1->OperGet() == GT_LCL_VAR)
931     {
932         GenTreeLclVarCommon* lclVar = op1->AsLclVarCommon();
933         LclVarDsc*           varDsc = &(compiler->lvaTable[lclVar->gtLclNum]);
934         assert(varDsc->lvIsMultiRegRet);
935
936         ReturnTypeDesc retTypeDesc;
937         retTypeDesc.InitializeStructReturnType(compiler, varDsc->lvVerTypeInfo.GetClassHandle());
938         unsigned regCount = retTypeDesc.GetReturnRegCount();
939         assert(regCount == MAX_RET_REG_COUNT);
940
941         if (varTypeIsEnregisterableStruct(op1))
942         {
943             // Right now the only enregistrable structs supported are SIMD vector types.
944             assert(varTypeIsSIMD(op1));
945             assert(op1->isUsedFromReg());
946
947             // This is a case of operand is in a single reg and needs to be
948             // returned in multiple ABI return registers.
949             regNumber opReg = genConsumeReg(op1);
950             regNumber reg0  = retTypeDesc.GetABIReturnReg(0);
951             regNumber reg1  = retTypeDesc.GetABIReturnReg(1);
952
953             if (opReg != reg0 && opReg != reg1)
954             {
955                 // Operand reg is different from return regs.
956                 // Copy opReg to reg0 and let it to be handled by one of the
957                 // two cases below.
958                 inst_RV_RV(ins_Copy(TYP_DOUBLE), reg0, opReg, TYP_DOUBLE);
959                 opReg = reg0;
960             }
961
962             if (opReg == reg0)
963             {
964                 assert(opReg != reg1);
965
966                 // reg0 - already has required 8-byte in bit position [63:0].
967                 // reg1 = opReg.
968                 // swap upper and lower 8-bytes of reg1 so that desired 8-byte is in bit position [63:0].
969                 inst_RV_RV(ins_Copy(TYP_DOUBLE), reg1, opReg, TYP_DOUBLE);
970             }
971             else
972             {
973                 assert(opReg == reg1);
974
975                 // reg0 = opReg.
976                 // swap upper and lower 8-bytes of reg1 so that desired 8-byte is in bit position [63:0].
977                 inst_RV_RV(ins_Copy(TYP_DOUBLE), reg0, opReg, TYP_DOUBLE);
978             }
979             inst_RV_RV_IV(INS_shufpd, EA_16BYTE, reg1, reg1, 0x01);
980         }
981         else
982         {
983             assert(op1->isUsedFromMemory());
984
985             // Copy var on stack into ABI return registers
986             int offset = 0;
987             for (unsigned i = 0; i < regCount; ++i)
988             {
989                 var_types type = retTypeDesc.GetReturnRegType(i);
990                 regNumber reg  = retTypeDesc.GetABIReturnReg(i);
991                 getEmitter()->emitIns_R_S(ins_Load(type), emitTypeSize(type), reg, lclVar->gtLclNum, offset);
992                 offset += genTypeSize(type);
993             }
994         }
995     }
996     else
997     {
998         assert(op1->IsMultiRegCall() || op1->IsCopyOrReloadOfMultiRegCall());
999
1000         genConsumeRegs(op1);
1001
1002         GenTree*        actualOp1   = op1->gtSkipReloadOrCopy();
1003         GenTreeCall*    call        = actualOp1->AsCall();
1004         ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc();
1005         unsigned        regCount    = retTypeDesc->GetReturnRegCount();
1006         assert(regCount == MAX_RET_REG_COUNT);
1007
1008         // Handle circular dependency between call allocated regs and ABI return regs.
1009         //
1010         // It is possible under LSRA stress that originally allocated regs of call node,
1011         // say rax and rdx, are spilled and reloaded to rdx and rax respectively.  But
1012         // GT_RETURN needs to  move values as follows: rdx->rax, rax->rdx. Similar kind
1013         // kind of circular dependency could arise between xmm0 and xmm1 return regs.
1014         // Codegen is expected to handle such circular dependency.
1015         //
1016         var_types regType0      = retTypeDesc->GetReturnRegType(0);
1017         regNumber returnReg0    = retTypeDesc->GetABIReturnReg(0);
1018         regNumber allocatedReg0 = call->GetRegNumByIdx(0);
1019
1020         var_types regType1      = retTypeDesc->GetReturnRegType(1);
1021         regNumber returnReg1    = retTypeDesc->GetABIReturnReg(1);
1022         regNumber allocatedReg1 = call->GetRegNumByIdx(1);
1023
1024         if (op1->IsCopyOrReload())
1025         {
1026             // GT_COPY/GT_RELOAD will have valid reg for those positions
1027             // that need to be copied or reloaded.
1028             regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(0);
1029             if (reloadReg != REG_NA)
1030             {
1031                 allocatedReg0 = reloadReg;
1032             }
1033
1034             reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(1);
1035             if (reloadReg != REG_NA)
1036             {
1037                 allocatedReg1 = reloadReg;
1038             }
1039         }
1040
1041         if (allocatedReg0 == returnReg1 && allocatedReg1 == returnReg0)
1042         {
1043             // Circular dependency - swap allocatedReg0 and allocatedReg1
1044             if (varTypeIsFloating(regType0))
1045             {
1046                 assert(varTypeIsFloating(regType1));
1047
1048                 // The fastest way to swap two XMM regs is using PXOR
1049                 inst_RV_RV(INS_pxor, allocatedReg0, allocatedReg1, TYP_DOUBLE);
1050                 inst_RV_RV(INS_pxor, allocatedReg1, allocatedReg0, TYP_DOUBLE);
1051                 inst_RV_RV(INS_pxor, allocatedReg0, allocatedReg1, TYP_DOUBLE);
1052             }
1053             else
1054             {
1055                 assert(varTypeIsIntegral(regType0));
1056                 assert(varTypeIsIntegral(regType1));
1057                 inst_RV_RV(INS_xchg, allocatedReg1, allocatedReg0, TYP_I_IMPL);
1058             }
1059         }
1060         else if (allocatedReg1 == returnReg0)
1061         {
1062             // Change the order of moves to correctly handle dependency.
1063             if (allocatedReg1 != returnReg1)
1064             {
1065                 inst_RV_RV(ins_Copy(regType1), returnReg1, allocatedReg1, regType1);
1066             }
1067
1068             if (allocatedReg0 != returnReg0)
1069             {
1070                 inst_RV_RV(ins_Copy(regType0), returnReg0, allocatedReg0, regType0);
1071             }
1072         }
1073         else
1074         {
1075             // No circular dependency case.
1076             if (allocatedReg0 != returnReg0)
1077             {
1078                 inst_RV_RV(ins_Copy(regType0), returnReg0, allocatedReg0, regType0);
1079             }
1080
1081             if (allocatedReg1 != returnReg1)
1082             {
1083                 inst_RV_RV(ins_Copy(regType1), returnReg1, allocatedReg1, regType1);
1084             }
1085         }
1086     }
1087 #else
1088     unreached();
1089 #endif
1090 }
1091
1092 //------------------------------------------------------------------------
1093 // genReturn: Generates code for return statement.
1094 //            In case of struct return, delegates to the genStructReturn method.
1095 //
1096 // Arguments:
1097 //    treeNode - The GT_RETURN or GT_RETFILT tree node.
1098 //
1099 // Return Value:
1100 //    None
1101 //
1102 void CodeGen::genReturn(GenTreePtr treeNode)
1103 {
1104     assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT);
1105     GenTreePtr op1        = treeNode->gtGetOp1();
1106     var_types  targetType = treeNode->TypeGet();
1107
1108 #ifdef DEBUG
1109     if (targetType == TYP_VOID)
1110     {
1111         assert(op1 == nullptr);
1112     }
1113 #endif
1114
1115 #ifdef _TARGET_X86_
1116     if (treeNode->TypeGet() == TYP_LONG)
1117     {
1118         assert(op1 != nullptr);
1119         noway_assert(op1->OperGet() == GT_LONG);
1120         GenTree* loRetVal = op1->gtGetOp1();
1121         GenTree* hiRetVal = op1->gtGetOp2();
1122         noway_assert((loRetVal->gtRegNum != REG_NA) && (hiRetVal->gtRegNum != REG_NA));
1123
1124         genConsumeReg(loRetVal);
1125         genConsumeReg(hiRetVal);
1126         if (loRetVal->gtRegNum != REG_LNGRET_LO)
1127         {
1128             inst_RV_RV(ins_Copy(targetType), REG_LNGRET_LO, loRetVal->gtRegNum, TYP_INT);
1129         }
1130         if (hiRetVal->gtRegNum != REG_LNGRET_HI)
1131         {
1132             inst_RV_RV(ins_Copy(targetType), REG_LNGRET_HI, hiRetVal->gtRegNum, TYP_INT);
1133         }
1134     }
1135     else
1136 #endif // !defined(_TARGET_X86_)
1137     {
1138         if (isStructReturn(treeNode))
1139         {
1140             genStructReturn(treeNode);
1141         }
1142         else if (targetType != TYP_VOID)
1143         {
1144             assert(op1 != nullptr);
1145             noway_assert(op1->gtRegNum != REG_NA);
1146
1147             // !! NOTE !! genConsumeReg will clear op1 as GC ref after it has
1148             // consumed a reg for the operand. This is because the variable
1149             // is dead after return. But we are issuing more instructions
1150             // like "profiler leave callback" after this consumption. So
1151             // if you are issuing more instructions after this point,
1152             // remember to keep the variable live up until the new method
1153             // exit point where it is actually dead.
1154             genConsumeReg(op1);
1155
1156             regNumber retReg = varTypeIsFloating(treeNode) ? REG_FLOATRET : REG_INTRET;
1157 #ifdef _TARGET_X86_
1158             if (varTypeIsFloating(treeNode))
1159             {
1160                 // Spill the return value register from an XMM register to the stack, then load it on the x87 stack.
1161                 // If it already has a home location, use that. Otherwise, we need a temp.
1162                 if (genIsRegCandidateLocal(op1) && compiler->lvaTable[op1->gtLclVarCommon.gtLclNum].lvOnFrame)
1163                 {
1164                     // Store local variable to its home location, if necessary.
1165                     if ((op1->gtFlags & GTF_REG_VAL) != 0)
1166                     {
1167                         op1->gtFlags &= ~GTF_REG_VAL;
1168                         inst_TT_RV(ins_Store(op1->gtType,
1169                                              compiler->isSIMDTypeLocalAligned(op1->gtLclVarCommon.gtLclNum)),
1170                                    op1, op1->gtRegNum);
1171                     }
1172                     // Now, load it to the fp stack.
1173                     getEmitter()->emitIns_S(INS_fld, emitTypeSize(op1), op1->AsLclVarCommon()->gtLclNum, 0);
1174                 }
1175                 else
1176                 {
1177                     // Spill the value, which should be in a register, then load it to the fp stack.
1178                     // TODO-X86-CQ: Deal with things that are already in memory (don't call genConsumeReg yet).
1179                     op1->gtFlags |= GTF_SPILL;
1180                     regSet.rsSpillTree(op1->gtRegNum, op1);
1181                     op1->gtFlags |= GTF_SPILLED;
1182                     op1->gtFlags &= ~GTF_SPILL;
1183
1184                     TempDsc* t = regSet.rsUnspillInPlace(op1, op1->gtRegNum);
1185                     inst_FS_ST(INS_fld, emitActualTypeSize(op1->gtType), t, 0);
1186                     op1->gtFlags &= ~GTF_SPILLED;
1187                     compiler->tmpRlsTemp(t);
1188                 }
1189             }
1190             else
1191 #endif // _TARGET_X86_
1192             {
1193                 if (op1->gtRegNum != retReg)
1194                 {
1195                     inst_RV_RV(ins_Copy(targetType), retReg, op1->gtRegNum, targetType);
1196                 }
1197             }
1198         }
1199     }
1200
1201 #ifdef PROFILING_SUPPORTED
1202     // !! Note !!
1203     // TODO-AMD64-Unix: If the profiler hook is implemented on *nix, make sure for 2 register returned structs
1204     //                  the RAX and RDX needs to be kept alive. Make the necessary changes in lowerxarch.cpp
1205     //                  in the handling of the GT_RETURN statement.
1206     //                  Such structs containing GC pointers need to be handled by calling gcInfo.gcMarkRegSetNpt
1207     //                  for the return registers containing GC refs.
1208
1209     // There will be a single return block while generating profiler ELT callbacks.
1210     //
1211     // Reason for not materializing Leave callback as a GT_PROF_HOOK node after GT_RETURN:
1212     // In flowgraph and other places assert that the last node of a block marked as
1213     // BBJ_RETURN is either a GT_RETURN or GT_JMP or a tail call.  It would be nice to
1214     // maintain such an invariant irrespective of whether profiler hook needed or not.
1215     // Also, there is not much to be gained by materializing it as an explicit node.
1216     if (compiler->compCurBB == compiler->genReturnBB)
1217     {
1218         // !! NOTE !!
1219         // Since we are invalidating the assumption that we would slip into the epilog
1220         // right after the "return", we need to preserve the return reg's GC state
1221         // across the call until actual method return.
1222         if (varTypeIsGC(compiler->info.compRetType))
1223         {
1224             gcInfo.gcMarkRegPtrVal(REG_INTRET, compiler->info.compRetType);
1225         }
1226
1227         genProfilingLeaveCallback();
1228
1229         if (varTypeIsGC(compiler->info.compRetType))
1230         {
1231             gcInfo.gcMarkRegSetNpt(REG_INTRET);
1232         }
1233     }
1234 #endif
1235 }
1236
1237 /*****************************************************************************
1238  *
1239  * Generate code for a single node in the tree.
1240  * Preconditions: All operands have been evaluated
1241  *
1242  */
1243 void CodeGen::genCodeForTreeNode(GenTreePtr treeNode)
1244 {
1245     regNumber targetReg;
1246 #if !defined(_TARGET_64BIT_)
1247     if (treeNode->TypeGet() == TYP_LONG)
1248     {
1249         // All long enregistered nodes will have been decomposed into their
1250         // constituent lo and hi nodes.
1251         targetReg = REG_NA;
1252     }
1253     else
1254 #endif // !defined(_TARGET_64BIT_)
1255     {
1256         targetReg = treeNode->gtRegNum;
1257     }
1258     var_types targetType = treeNode->TypeGet();
1259     emitter*  emit       = getEmitter();
1260
1261 #ifdef DEBUG
1262     // Validate that all the operands for the current node are consumed in order.
1263     // This is important because LSRA ensures that any necessary copies will be
1264     // handled correctly.
1265     lastConsumedNode = nullptr;
1266     if (compiler->verbose)
1267     {
1268         unsigned seqNum = treeNode->gtSeqNum; // Useful for setting a conditional break in Visual Studio
1269         compiler->gtDispLIRNode(treeNode, "Generating: ");
1270     }
1271 #endif // DEBUG
1272
1273     // Is this a node whose value is already in a register?  LSRA denotes this by
1274     // setting the GTF_REUSE_REG_VAL flag.
1275     if (treeNode->IsReuseRegVal())
1276     {
1277         // For now, this is only used for constant nodes.
1278         assert((treeNode->OperIsConst()));
1279         JITDUMP("  TreeNode is marked ReuseReg\n");
1280         return;
1281     }
1282
1283     // contained nodes are part of their parents for codegen purposes
1284     // ex : immediates, most LEAs
1285     if (treeNode->isContained())
1286     {
1287         return;
1288     }
1289
1290     switch (treeNode->gtOper)
1291     {
1292 #ifndef JIT32_GCENCODER
1293         case GT_START_NONGC:
1294             getEmitter()->emitDisableGC();
1295             break;
1296 #endif // !defined(JIT32_GCENCODER)
1297
1298         case GT_PROF_HOOK:
1299 #ifdef PROFILING_SUPPORTED
1300             // We should be seeing this only if profiler hook is needed
1301             noway_assert(compiler->compIsProfilerHookNeeded());
1302
1303             // Right now this node is used only for tail calls. In future if
1304             // we intend to use it for Enter or Leave hooks, add a data member
1305             // to this node indicating the kind of profiler hook. For example,
1306             // helper number can be used.
1307             genProfilingLeaveCallback(CORINFO_HELP_PROF_FCN_TAILCALL);
1308 #endif // PROFILING_SUPPORTED
1309             break;
1310
1311         case GT_LCLHEAP:
1312             genLclHeap(treeNode);
1313             break;
1314
1315         case GT_CNS_INT:
1316 #ifdef _TARGET_X86_
1317             assert(!treeNode->IsIconHandle(GTF_ICON_TLS_HDL));
1318 #endif // _TARGET_X86_
1319             __fallthrough;
1320
1321         case GT_CNS_DBL:
1322             genSetRegToConst(targetReg, targetType, treeNode);
1323             genProduceReg(treeNode);
1324             break;
1325
1326         case GT_NEG:
1327         case GT_NOT:
1328             if (varTypeIsFloating(targetType))
1329             {
1330                 assert(treeNode->gtOper == GT_NEG);
1331                 genSSE2BitwiseOp(treeNode);
1332             }
1333             else
1334             {
1335                 GenTreePtr operand = treeNode->gtGetOp1();
1336                 assert(operand->isUsedFromReg());
1337                 regNumber operandReg = genConsumeReg(operand);
1338
1339                 if (operandReg != targetReg)
1340                 {
1341                     inst_RV_RV(INS_mov, targetReg, operandReg, targetType);
1342                 }
1343
1344                 instruction ins = genGetInsForOper(treeNode->OperGet(), targetType);
1345                 inst_RV(ins, targetReg, targetType);
1346             }
1347             genProduceReg(treeNode);
1348             break;
1349
1350         case GT_OR:
1351         case GT_XOR:
1352         case GT_AND:
1353             assert(varTypeIsIntegralOrI(treeNode));
1354             __fallthrough;
1355
1356 #if !defined(_TARGET_64BIT_)
1357         case GT_ADD_LO:
1358         case GT_ADD_HI:
1359         case GT_SUB_LO:
1360         case GT_SUB_HI:
1361 #endif // !defined(_TARGET_64BIT_)
1362         case GT_ADD:
1363         case GT_SUB:
1364             genConsumeOperands(treeNode->AsOp());
1365             genCodeForBinary(treeNode);
1366             break;
1367
1368         case GT_LSH:
1369         case GT_RSH:
1370         case GT_RSZ:
1371         case GT_ROL:
1372         case GT_ROR:
1373             genCodeForShift(treeNode);
1374             // genCodeForShift() calls genProduceReg()
1375             break;
1376
1377 #if !defined(_TARGET_64BIT_)
1378         case GT_LSH_HI:
1379         case GT_RSH_LO:
1380             // TODO-X86-CQ: This only handles the case where the operand being shifted is in a register. We don't
1381             // need sourceHi to be always in reg in case of GT_LSH_HI (because it could be moved from memory to
1382             // targetReg if sourceHi is a memory operand). Similarly for GT_RSH_LO, sourceLo could be marked as
1383             // contained memory-op. Even if not a memory-op, we could mark it as reg-optional.
1384             genCodeForShiftLong(treeNode);
1385             break;
1386 #endif
1387
1388         case GT_CAST:
1389             if (varTypeIsFloating(targetType) && varTypeIsFloating(treeNode->gtOp.gtOp1))
1390             {
1391                 // Casts float/double <--> double/float
1392                 genFloatToFloatCast(treeNode);
1393             }
1394             else if (varTypeIsFloating(treeNode->gtOp.gtOp1))
1395             {
1396                 // Casts float/double --> int32/int64
1397                 genFloatToIntCast(treeNode);
1398             }
1399             else if (varTypeIsFloating(targetType))
1400             {
1401                 // Casts int32/uint32/int64/uint64 --> float/double
1402                 genIntToFloatCast(treeNode);
1403             }
1404             else
1405             {
1406                 // Casts int <--> int
1407                 genIntToIntCast(treeNode);
1408             }
1409             // The per-case functions call genProduceReg()
1410             break;
1411
1412         case GT_LCL_VAR:
1413         {
1414             // lcl_vars are not defs
1415             assert((treeNode->gtFlags & GTF_VAR_DEF) == 0);
1416
1417             GenTreeLclVarCommon* lcl            = treeNode->AsLclVarCommon();
1418             bool                 isRegCandidate = compiler->lvaTable[lcl->gtLclNum].lvIsRegCandidate();
1419
1420             if (isRegCandidate && !(treeNode->gtFlags & GTF_VAR_DEATH))
1421             {
1422                 assert(treeNode->InReg() || (treeNode->gtFlags & GTF_SPILLED));
1423             }
1424
1425             // If this is a register candidate that has been spilled, genConsumeReg() will
1426             // reload it at the point of use.  Otherwise, if it's not in a register, we load it here.
1427
1428             if (!treeNode->InReg() && !(treeNode->gtFlags & GTF_SPILLED))
1429             {
1430                 assert(!isRegCandidate);
1431 #if defined(FEATURE_SIMD) && defined(_TARGET_X86_)
1432                 // Loading of TYP_SIMD12 (i.e. Vector3) variable
1433                 if (treeNode->TypeGet() == TYP_SIMD12)
1434                 {
1435                     genLoadLclTypeSIMD12(treeNode);
1436                     break;
1437                 }
1438 #endif // defined(FEATURE_SIMD) && defined(_TARGET_X86_)
1439
1440                 emit->emitIns_R_S(ins_Load(treeNode->TypeGet(), compiler->isSIMDTypeLocalAligned(lcl->gtLclNum)),
1441                                   emitTypeSize(treeNode), treeNode->gtRegNum, lcl->gtLclNum, 0);
1442                 genProduceReg(treeNode);
1443             }
1444         }
1445         break;
1446
1447         case GT_LCL_FLD_ADDR:
1448         case GT_LCL_VAR_ADDR:
1449             // Address of a local var.  This by itself should never be allocated a register.
1450             // If it is worth storing the address in a register then it should be cse'ed into
1451             // a temp and that would be allocated a register.
1452             noway_assert(targetType == TYP_BYREF);
1453             noway_assert(!treeNode->InReg());
1454
1455             inst_RV_TT(INS_lea, targetReg, treeNode, 0, EA_BYREF);
1456             genProduceReg(treeNode);
1457             break;
1458
1459         case GT_LCL_FLD:
1460         {
1461             noway_assert(targetType != TYP_STRUCT);
1462             noway_assert(treeNode->gtRegNum != REG_NA);
1463
1464 #ifdef FEATURE_SIMD
1465             // Loading of TYP_SIMD12 (i.e. Vector3) field
1466             if (treeNode->TypeGet() == TYP_SIMD12)
1467             {
1468                 genLoadLclTypeSIMD12(treeNode);
1469                 break;
1470             }
1471 #endif
1472
1473             emitAttr size   = emitTypeSize(targetType);
1474             unsigned offs   = treeNode->gtLclFld.gtLclOffs;
1475             unsigned varNum = treeNode->gtLclVarCommon.gtLclNum;
1476             assert(varNum < compiler->lvaCount);
1477
1478             emit->emitIns_R_S(ins_Move_Extend(targetType, treeNode->InReg()), size, targetReg, varNum, offs);
1479         }
1480             genProduceReg(treeNode);
1481             break;
1482
1483         case GT_STORE_LCL_FLD:
1484         {
1485             noway_assert(targetType != TYP_STRUCT);
1486             noway_assert(!treeNode->InReg());
1487             assert(!varTypeIsFloating(targetType) || (targetType == treeNode->gtGetOp1()->TypeGet()));
1488
1489 #ifdef FEATURE_SIMD
1490             // storing of TYP_SIMD12 (i.e. Vector3) field
1491             if (treeNode->TypeGet() == TYP_SIMD12)
1492             {
1493                 genStoreLclTypeSIMD12(treeNode);
1494                 break;
1495             }
1496 #endif // FEATURE_SIMD
1497
1498             GenTreePtr op1 = treeNode->gtGetOp1();
1499             genConsumeRegs(op1);
1500             emit->emitInsBinary(ins_Store(targetType), emitTypeSize(treeNode), treeNode, op1);
1501         }
1502         break;
1503
1504         case GT_STORE_LCL_VAR:
1505         {
1506             GenTreePtr op1 = treeNode->gtGetOp1();
1507
1508             // var = call, where call returns a multi-reg return value
1509             // case is handled separately.
1510             if (op1->gtSkipReloadOrCopy()->IsMultiRegCall())
1511             {
1512                 genMultiRegCallStoreToLocal(treeNode);
1513             }
1514             else
1515             {
1516                 noway_assert(targetType != TYP_STRUCT);
1517                 assert(!varTypeIsFloating(targetType) || (targetType == treeNode->gtGetOp1()->TypeGet()));
1518
1519                 unsigned   lclNum = treeNode->AsLclVarCommon()->gtLclNum;
1520                 LclVarDsc* varDsc = &(compiler->lvaTable[lclNum]);
1521
1522                 // Ensure that lclVar nodes are typed correctly.
1523                 assert(!varDsc->lvNormalizeOnStore() || treeNode->TypeGet() == genActualType(varDsc->TypeGet()));
1524
1525 #if !defined(_TARGET_64BIT_)
1526                 if (treeNode->TypeGet() == TYP_LONG)
1527                 {
1528                     genStoreLongLclVar(treeNode);
1529                     break;
1530                 }
1531 #endif // !defined(_TARGET_64BIT_)
1532
1533 #ifdef FEATURE_SIMD
1534                 // storing of TYP_SIMD12 (i.e. Vector3) field
1535                 if (treeNode->TypeGet() == TYP_SIMD12)
1536                 {
1537                     genStoreLclTypeSIMD12(treeNode);
1538                     break;
1539                 }
1540
1541                 if (varTypeIsSIMD(targetType) && (targetReg != REG_NA) && op1->IsCnsIntOrI())
1542                 {
1543                     // This is only possible for a zero-init.
1544                     noway_assert(op1->IsIntegralConst(0));
1545                     genSIMDZero(targetType, varDsc->lvBaseType, targetReg);
1546                     genProduceReg(treeNode);
1547                     break;
1548                 }
1549 #endif // FEATURE_SIMD
1550
1551                 genConsumeRegs(op1);
1552
1553                 if (treeNode->gtRegNum == REG_NA)
1554                 {
1555                     // stack store
1556                     emit->emitInsMov(ins_Store(targetType, compiler->isSIMDTypeLocalAligned(lclNum)),
1557                                      emitTypeSize(targetType), treeNode);
1558                     varDsc->lvRegNum = REG_STK;
1559                 }
1560                 else
1561                 {
1562                     // Look for the case where we have a constant zero which we've marked for reuse,
1563                     // but which isn't actually in the register we want.  In that case, it's better to create
1564                     // zero in the target register, because an xor is smaller than a copy. Note that we could
1565                     // potentially handle this in the register allocator, but we can't always catch it there
1566                     // because the target may not have a register allocated for it yet.
1567                     if (op1->isUsedFromReg() && (op1->gtRegNum != treeNode->gtRegNum) &&
1568                         (op1->IsIntegralConst(0) || op1->IsFPZero()))
1569                     {
1570                         op1->gtRegNum = REG_NA;
1571                         op1->ResetReuseRegVal();
1572                     }
1573
1574                     if (!op1->isUsedFromReg())
1575                     {
1576                         // Currently, we assume that the non-reg source of a GT_STORE_LCL_VAR writing to a register
1577                         // must be a constant. However, in the future we might want to support an operand used from
1578                         // memory.  This is a bit tricky because we have to decide it can be used from memory before
1579                         // register allocation,
1580                         // and this would be a case where, once that's done, we need to mark that node as always
1581                         // requiring a register - which we always assume now anyway, but once we "optimize" that
1582                         // we'll have to take cases like this into account.
1583                         assert((op1->gtRegNum == REG_NA) && op1->OperIsConst());
1584                         genSetRegToConst(treeNode->gtRegNum, targetType, op1);
1585                     }
1586                     else if (op1->gtRegNum != treeNode->gtRegNum)
1587                     {
1588                         assert(op1->gtRegNum != REG_NA);
1589                         emit->emitInsBinary(ins_Move_Extend(targetType, true), emitTypeSize(treeNode), treeNode, op1);
1590                     }
1591                 }
1592             }
1593
1594             if (treeNode->gtRegNum != REG_NA)
1595             {
1596                 genProduceReg(treeNode);
1597             }
1598         }
1599         break;
1600
1601         case GT_RETFILT:
1602             // A void GT_RETFILT is the end of a finally. For non-void filter returns we need to load the result in
1603             // the return register, if it's not already there. The processing is the same as GT_RETURN.
1604             if (targetType != TYP_VOID)
1605             {
1606                 // For filters, the IL spec says the result is type int32. Further, the only specified legal values
1607                 // are 0 or 1, with the use of other values "undefined".
1608                 assert(targetType == TYP_INT);
1609             }
1610
1611             __fallthrough;
1612
1613         case GT_RETURN:
1614             genReturn(treeNode);
1615             break;
1616
1617         case GT_LEA:
1618         {
1619             // if we are here, it is the case where there is an LEA that cannot
1620             // be folded into a parent instruction
1621             GenTreeAddrMode* lea = treeNode->AsAddrMode();
1622             genLeaInstruction(lea);
1623         }
1624         // genLeaInstruction calls genProduceReg()
1625         break;
1626
1627         case GT_IND:
1628         {
1629 #ifdef FEATURE_SIMD
1630             // Handling of Vector3 type values loaded through indirection.
1631             if (treeNode->TypeGet() == TYP_SIMD12)
1632             {
1633                 genLoadIndTypeSIMD12(treeNode);
1634                 break;
1635             }
1636 #endif // FEATURE_SIMD
1637
1638             GenTree* addr = treeNode->AsIndir()->Addr();
1639             if (addr->IsCnsIntOrI() && addr->IsIconHandle(GTF_ICON_TLS_HDL))
1640             {
1641                 noway_assert(EA_ATTR(genTypeSize(treeNode->gtType)) == EA_PTRSIZE);
1642                 emit->emitIns_R_C(ins_Load(TYP_I_IMPL), EA_PTRSIZE, treeNode->gtRegNum, FLD_GLOBAL_FS,
1643                                   (int)addr->gtIntCon.gtIconVal);
1644             }
1645             else
1646             {
1647                 genConsumeAddress(addr);
1648                 emit->emitInsMov(ins_Load(treeNode->TypeGet()), emitTypeSize(treeNode), treeNode);
1649             }
1650             genProduceReg(treeNode);
1651         }
1652         break;
1653
1654         case GT_MULHI:
1655 #ifdef _TARGET_X86_
1656         case GT_MUL_LONG:
1657 #endif
1658             genCodeForMulHi(treeNode->AsOp());
1659             genProduceReg(treeNode);
1660             break;
1661
1662         case GT_MUL:
1663         {
1664             instruction ins;
1665             emitAttr    size                  = emitTypeSize(treeNode);
1666             bool        isUnsignedMultiply    = ((treeNode->gtFlags & GTF_UNSIGNED) != 0);
1667             bool        requiresOverflowCheck = treeNode->gtOverflowEx();
1668
1669             GenTree* op1 = treeNode->gtGetOp1();
1670             GenTree* op2 = treeNode->gtGetOp2();
1671
1672             // there are 3 forms of x64 multiply:
1673             // 1-op form with 128 result:  RDX:RAX = RAX * rm
1674             // 2-op form: reg *= rm
1675             // 3-op form: reg = rm * imm
1676
1677             genConsumeOperands(treeNode->AsOp());
1678
1679             // This matches the 'mul' lowering in Lowering::SetMulOpCounts()
1680             //
1681             // immOp :: Only one operand can be an immediate
1682             // rmOp  :: Only one operand can be a memory op.
1683             // regOp :: A register op (especially the operand that matches 'targetReg')
1684             //          (can be nullptr when we have both a memory op and an immediate op)
1685
1686             GenTree* immOp = nullptr;
1687             GenTree* rmOp  = op1;
1688             GenTree* regOp;
1689
1690             if (op2->isContainedIntOrIImmed())
1691             {
1692                 immOp = op2;
1693             }
1694             else if (op1->isContainedIntOrIImmed())
1695             {
1696                 immOp = op1;
1697                 rmOp  = op2;
1698             }
1699
1700             if (immOp != nullptr)
1701             {
1702                 // This must be a non-floating point operation.
1703                 assert(!varTypeIsFloating(treeNode));
1704
1705                 // CQ: When possible use LEA for mul by imm 3, 5 or 9
1706                 ssize_t imm = immOp->AsIntConCommon()->IconValue();
1707
1708                 if (!requiresOverflowCheck && rmOp->isUsedFromReg() && ((imm == 3) || (imm == 5) || (imm == 9)))
1709                 {
1710                     // We will use the LEA instruction to perform this multiply
1711                     // Note that an LEA with base=x, index=x and scale=(imm-1) computes x*imm when imm=3,5 or 9.
1712                     unsigned int scale = (unsigned int)(imm - 1);
1713                     getEmitter()->emitIns_R_ARX(INS_lea, size, targetReg, rmOp->gtRegNum, rmOp->gtRegNum, scale, 0);
1714                 }
1715                 else
1716                 {
1717                     // use the 3-op form with immediate
1718                     ins = getEmitter()->inst3opImulForReg(targetReg);
1719                     emit->emitInsBinary(ins, size, rmOp, immOp);
1720                 }
1721             }
1722             else // we have no contained immediate operand
1723             {
1724                 regOp = op1;
1725                 rmOp  = op2;
1726
1727                 regNumber mulTargetReg = targetReg;
1728                 if (isUnsignedMultiply && requiresOverflowCheck)
1729                 {
1730                     ins          = INS_mulEAX;
1731                     mulTargetReg = REG_RAX;
1732                 }
1733                 else
1734                 {
1735                     ins = genGetInsForOper(GT_MUL, targetType);
1736                 }
1737
1738                 // Set rmOp to the memory operand (if any)
1739                 // or set regOp to the op2 when it has the matching target register for our multiply op
1740                 //
1741                 if (op1->isUsedFromMemory() || (op2->isUsedFromReg() && (op2->gtRegNum == mulTargetReg)))
1742                 {
1743                     regOp = op2;
1744                     rmOp  = op1;
1745                 }
1746                 assert(regOp->isUsedFromReg());
1747
1748                 // Setup targetReg when neither of the source operands was a matching register
1749                 if (regOp->gtRegNum != mulTargetReg)
1750                 {
1751                     inst_RV_RV(ins_Copy(targetType), mulTargetReg, regOp->gtRegNum, targetType);
1752                 }
1753
1754                 emit->emitInsBinary(ins, size, treeNode, rmOp);
1755
1756                 // Move the result to the desired register, if necessary
1757                 if ((ins == INS_mulEAX) && (targetReg != REG_RAX))
1758                 {
1759                     inst_RV_RV(INS_mov, targetReg, REG_RAX, targetType);
1760                 }
1761             }
1762
1763             if (requiresOverflowCheck)
1764             {
1765                 // Overflow checking is only used for non-floating point types
1766                 noway_assert(!varTypeIsFloating(treeNode));
1767
1768                 genCheckOverflow(treeNode);
1769             }
1770         }
1771             genProduceReg(treeNode);
1772             break;
1773
1774         case GT_MOD:
1775         case GT_UDIV:
1776         case GT_UMOD:
1777             // We shouldn't be seeing GT_MOD on float/double args as it should get morphed into a
1778             // helper call by front-end.  Similarly we shouldn't be seeing GT_UDIV and GT_UMOD
1779             // on float/double args.
1780             noway_assert(!varTypeIsFloating(treeNode));
1781             __fallthrough;
1782
1783         case GT_DIV:
1784             genCodeForDivMod(treeNode->AsOp());
1785             break;
1786
1787         case GT_INTRINSIC:
1788             genIntrinsic(treeNode);
1789             break;
1790
1791 #ifdef FEATURE_SIMD
1792         case GT_SIMD:
1793             genSIMDIntrinsic(treeNode->AsSIMD());
1794             break;
1795 #endif // FEATURE_SIMD
1796
1797         case GT_CKFINITE:
1798             genCkfinite(treeNode);
1799             break;
1800
1801         case GT_EQ:
1802         case GT_NE:
1803         case GT_LT:
1804         case GT_LE:
1805         case GT_GE:
1806         case GT_GT:
1807         case GT_TEST_EQ:
1808         case GT_TEST_NE:
1809         {
1810             // TODO-XArch-CQ: Check if we can use the currently set flags.
1811             // TODO-XArch-CQ: Check for the case where we can simply transfer the carry bit to a register
1812             //         (signed < or >= where targetReg != REG_NA)
1813
1814             GenTreePtr op1     = treeNode->gtGetOp1();
1815             var_types  op1Type = op1->TypeGet();
1816
1817             if (varTypeIsFloating(op1Type))
1818             {
1819                 genCompareFloat(treeNode);
1820             }
1821 #if !defined(_TARGET_64BIT_)
1822             // X86 Long comparison
1823             else if (varTypeIsLong(op1Type))
1824             {
1825 #ifdef DEBUG
1826                 // The result of an unlowered long compare on a 32-bit target must either be
1827                 // a) materialized into a register, or
1828                 // b) unused.
1829                 //
1830                 // A long compare that has a result that is used but not materialized into a register should
1831                 // have been handled by Lowering::LowerCompare.
1832
1833                 LIR::Use use;
1834                 assert((treeNode->gtRegNum != REG_NA) || !LIR::AsRange(compiler->compCurBB).TryGetUse(treeNode, &use));
1835 #endif
1836                 genCompareLong(treeNode);
1837             }
1838 #endif // !defined(_TARGET_64BIT_)
1839             else
1840             {
1841                 genCompareInt(treeNode);
1842             }
1843         }
1844         break;
1845
1846         case GT_JTRUE:
1847         {
1848             GenTree* cmp = treeNode->gtOp.gtOp1;
1849
1850             assert(cmp->OperIsCompare());
1851             assert(compiler->compCurBB->bbJumpKind == BBJ_COND);
1852
1853 #if !defined(_TARGET_64BIT_)
1854             // Long-typed compares should have been handled by Lowering::LowerCompare.
1855             assert(!varTypeIsLong(cmp->gtGetOp1()));
1856 #endif
1857
1858             // Get the "kind" and type of the comparison.  Note that whether it is an unsigned cmp
1859             // is governed by a flag NOT by the inherent type of the node
1860             // TODO-XArch-CQ: Check if we can use the currently set flags.
1861             emitJumpKind jumpKind[2];
1862             bool         branchToTrueLabel[2];
1863             genJumpKindsForTree(cmp, jumpKind, branchToTrueLabel);
1864
1865             BasicBlock* skipLabel = nullptr;
1866             if (jumpKind[0] != EJ_NONE)
1867             {
1868                 BasicBlock* jmpTarget;
1869                 if (branchToTrueLabel[0])
1870                 {
1871                     jmpTarget = compiler->compCurBB->bbJumpDest;
1872                 }
1873                 else
1874                 {
1875                     // This case arises only for ordered GT_EQ right now
1876                     assert((cmp->gtOper == GT_EQ) && ((cmp->gtFlags & GTF_RELOP_NAN_UN) == 0));
1877                     skipLabel = genCreateTempLabel();
1878                     jmpTarget = skipLabel;
1879                 }
1880
1881                 inst_JMP(jumpKind[0], jmpTarget);
1882             }
1883
1884             if (jumpKind[1] != EJ_NONE)
1885             {
1886                 // the second conditional branch always has to be to the true label
1887                 assert(branchToTrueLabel[1]);
1888                 inst_JMP(jumpKind[1], compiler->compCurBB->bbJumpDest);
1889             }
1890
1891             if (skipLabel != nullptr)
1892             {
1893                 genDefineTempLabel(skipLabel);
1894             }
1895         }
1896         break;
1897
1898         case GT_JCC:
1899         {
1900             GenTreeJumpCC* jcc = treeNode->AsJumpCC();
1901
1902             assert(compiler->compCurBB->bbJumpKind == BBJ_COND);
1903
1904             CompareKind  compareKind = ((jcc->gtFlags & GTF_UNSIGNED) != 0) ? CK_UNSIGNED : CK_SIGNED;
1905             emitJumpKind jumpKind    = genJumpKindForOper(jcc->gtCondition, compareKind);
1906
1907             inst_JMP(jumpKind, compiler->compCurBB->bbJumpDest);
1908         }
1909         break;
1910
1911         case GT_RETURNTRAP:
1912         {
1913             // this is nothing but a conditional call to CORINFO_HELP_STOP_FOR_GC
1914             // based on the contents of 'data'
1915
1916             GenTree* data = treeNode->gtOp.gtOp1;
1917             genConsumeRegs(data);
1918             GenTreeIntCon cns = intForm(TYP_INT, 0);
1919             emit->emitInsBinary(INS_cmp, emitTypeSize(TYP_INT), data, &cns);
1920
1921             BasicBlock* skipLabel = genCreateTempLabel();
1922
1923             emitJumpKind jmpEqual = genJumpKindForOper(GT_EQ, CK_SIGNED);
1924             inst_JMP(jmpEqual, skipLabel);
1925
1926             // emit the call to the EE-helper that stops for GC (or other reasons)
1927             assert(treeNode->gtRsvdRegs != RBM_NONE);
1928             assert(genCountBits(treeNode->gtRsvdRegs) == 1);
1929             regNumber tmpReg = genRegNumFromMask(treeNode->gtRsvdRegs);
1930             assert(genIsValidIntReg(tmpReg));
1931
1932             genEmitHelperCall(CORINFO_HELP_STOP_FOR_GC, 0, EA_UNKNOWN, tmpReg);
1933             genDefineTempLabel(skipLabel);
1934         }
1935         break;
1936
1937         case GT_STOREIND:
1938             genStoreInd(treeNode);
1939             break;
1940
1941         case GT_COPY:
1942             // This is handled at the time we call genConsumeReg() on the GT_COPY
1943             break;
1944
1945         case GT_SWAP:
1946         {
1947             // Swap is only supported for lclVar operands that are enregistered
1948             // We do not consume or produce any registers.  Both operands remain enregistered.
1949             // However, the gc-ness may change.
1950             assert(genIsRegCandidateLocal(treeNode->gtOp.gtOp1) && genIsRegCandidateLocal(treeNode->gtOp.gtOp2));
1951
1952             GenTreeLclVarCommon* lcl1    = treeNode->gtOp.gtOp1->AsLclVarCommon();
1953             LclVarDsc*           varDsc1 = &(compiler->lvaTable[lcl1->gtLclNum]);
1954             var_types            type1   = varDsc1->TypeGet();
1955             GenTreeLclVarCommon* lcl2    = treeNode->gtOp.gtOp2->AsLclVarCommon();
1956             LclVarDsc*           varDsc2 = &(compiler->lvaTable[lcl2->gtLclNum]);
1957             var_types            type2   = varDsc2->TypeGet();
1958
1959             // We must have both int or both fp regs
1960             assert(!varTypeIsFloating(type1) || varTypeIsFloating(type2));
1961
1962             // FP swap is not yet implemented (and should have NYI'd in LSRA)
1963             assert(!varTypeIsFloating(type1));
1964
1965             regNumber oldOp1Reg     = lcl1->gtRegNum;
1966             regMaskTP oldOp1RegMask = genRegMask(oldOp1Reg);
1967             regNumber oldOp2Reg     = lcl2->gtRegNum;
1968             regMaskTP oldOp2RegMask = genRegMask(oldOp2Reg);
1969
1970             // We don't call genUpdateVarReg because we don't have a tree node with the new register.
1971             varDsc1->lvRegNum = oldOp2Reg;
1972             varDsc2->lvRegNum = oldOp1Reg;
1973
1974             // Do the xchg
1975             emitAttr size = EA_PTRSIZE;
1976             if (varTypeGCtype(type1) != varTypeGCtype(type2))
1977             {
1978                 // If the type specified to the emitter is a GC type, it will swap the GC-ness of the registers.
1979                 // Otherwise it will leave them alone, which is correct if they have the same GC-ness.
1980                 size = EA_GCREF;
1981             }
1982             inst_RV_RV(INS_xchg, oldOp1Reg, oldOp2Reg, TYP_I_IMPL, size);
1983
1984             // Update the gcInfo.
1985             // Manually remove these regs for the gc sets (mostly to avoid confusing duplicative dump output)
1986             gcInfo.gcRegByrefSetCur &= ~(oldOp1RegMask | oldOp2RegMask);
1987             gcInfo.gcRegGCrefSetCur &= ~(oldOp1RegMask | oldOp2RegMask);
1988
1989             // gcMarkRegPtrVal will do the appropriate thing for non-gc types.
1990             // It will also dump the updates.
1991             gcInfo.gcMarkRegPtrVal(oldOp2Reg, type1);
1992             gcInfo.gcMarkRegPtrVal(oldOp1Reg, type2);
1993         }
1994         break;
1995
1996         case GT_LIST:
1997         case GT_FIELD_LIST:
1998         case GT_ARGPLACE:
1999             // Nothing to do
2000             break;
2001
2002         case GT_PUTARG_STK:
2003             genPutArgStk(treeNode->AsPutArgStk());
2004             break;
2005
2006         case GT_PUTARG_REG:
2007         {
2008 #ifndef FEATURE_UNIX_AMD64_STRUCT_PASSING
2009             noway_assert(targetType != TYP_STRUCT);
2010 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
2011             // commas show up here commonly, as part of a nullchk operation
2012             GenTree* op1 = treeNode->gtOp.gtOp1;
2013             // If child node is not already in the register we need, move it
2014             genConsumeReg(op1);
2015             if (treeNode->gtRegNum != op1->gtRegNum)
2016             {
2017                 inst_RV_RV(ins_Copy(targetType), treeNode->gtRegNum, op1->gtRegNum, targetType);
2018             }
2019             genProduceReg(treeNode);
2020         }
2021         break;
2022
2023         case GT_CALL:
2024             genCallInstruction(treeNode->AsCall());
2025             break;
2026
2027         case GT_JMP:
2028             genJmpMethod(treeNode);
2029             break;
2030
2031         case GT_LOCKADD:
2032         case GT_XCHG:
2033         case GT_XADD:
2034             genLockedInstructions(treeNode->AsOp());
2035             break;
2036
2037         case GT_MEMORYBARRIER:
2038             instGen_MemoryBarrier();
2039             break;
2040
2041         case GT_CMPXCHG:
2042         {
2043             GenTreePtr location  = treeNode->gtCmpXchg.gtOpLocation;  // arg1
2044             GenTreePtr value     = treeNode->gtCmpXchg.gtOpValue;     // arg2
2045             GenTreePtr comparand = treeNode->gtCmpXchg.gtOpComparand; // arg3
2046
2047             assert(location->gtRegNum != REG_NA && location->gtRegNum != REG_RAX);
2048             assert(value->gtRegNum != REG_NA && value->gtRegNum != REG_RAX);
2049
2050             genConsumeReg(location);
2051             genConsumeReg(value);
2052             genConsumeReg(comparand);
2053             // comparand goes to RAX;
2054             // Note that we must issue this move after the genConsumeRegs(), in case any of the above
2055             // have a GT_COPY from RAX.
2056             if (comparand->gtRegNum != REG_RAX)
2057             {
2058                 inst_RV_RV(ins_Copy(comparand->TypeGet()), REG_RAX, comparand->gtRegNum, comparand->TypeGet());
2059             }
2060
2061             // location is Rm
2062             instGen(INS_lock);
2063
2064             emit->emitIns_AR_R(INS_cmpxchg, emitTypeSize(targetType), value->gtRegNum, location->gtRegNum, 0);
2065
2066             // Result is in RAX
2067             if (targetReg != REG_RAX)
2068             {
2069                 inst_RV_RV(ins_Copy(targetType), targetReg, REG_RAX, targetType);
2070             }
2071         }
2072             genProduceReg(treeNode);
2073             break;
2074
2075         case GT_RELOAD:
2076             // do nothing - reload is just a marker.
2077             // The parent node will call genConsumeReg on this which will trigger the unspill of this node's child
2078             // into the register specified in this node.
2079             break;
2080
2081         case GT_NOP:
2082             break;
2083
2084         case GT_NO_OP:
2085             if (treeNode->gtFlags & GTF_NO_OP_NO)
2086             {
2087                 noway_assert(!"GTF_NO_OP_NO should not be set");
2088             }
2089             else
2090             {
2091                 getEmitter()->emitIns_Nop(1);
2092             }
2093             break;
2094
2095         case GT_ARR_BOUNDS_CHECK:
2096 #ifdef FEATURE_SIMD
2097         case GT_SIMD_CHK:
2098 #endif // FEATURE_SIMD
2099             genRangeCheck(treeNode);
2100             break;
2101
2102         case GT_PHYSREG:
2103             if (treeNode->gtRegNum != treeNode->AsPhysReg()->gtSrcReg)
2104             {
2105                 inst_RV_RV(INS_mov, treeNode->gtRegNum, treeNode->AsPhysReg()->gtSrcReg, targetType);
2106
2107                 genTransferRegGCState(treeNode->gtRegNum, treeNode->AsPhysReg()->gtSrcReg);
2108             }
2109             genProduceReg(treeNode);
2110             break;
2111
2112         case GT_PHYSREGDST:
2113             break;
2114
2115         case GT_NULLCHECK:
2116         {
2117             assert(treeNode->gtOp.gtOp1->isUsedFromReg());
2118             regNumber reg = genConsumeReg(treeNode->gtOp.gtOp1);
2119             emit->emitIns_AR_R(INS_cmp, EA_4BYTE, reg, reg, 0);
2120         }
2121         break;
2122
2123         case GT_CATCH_ARG:
2124
2125             noway_assert(handlerGetsXcptnObj(compiler->compCurBB->bbCatchTyp));
2126
2127             /* Catch arguments get passed in a register. genCodeForBBlist()
2128                would have marked it as holding a GC object, but not used. */
2129
2130             noway_assert(gcInfo.gcRegGCrefSetCur & RBM_EXCEPTION_OBJECT);
2131             genConsumeReg(treeNode);
2132             break;
2133
2134 #if !FEATURE_EH_FUNCLETS
2135         case GT_END_LFIN:
2136
2137             // Have to clear the ShadowSP of the nesting level which encloses the finally. Generates:
2138             //     mov dword ptr [ebp-0xC], 0  // for some slot of the ShadowSP local var
2139
2140             unsigned finallyNesting;
2141             finallyNesting = treeNode->gtVal.gtVal1;
2142             noway_assert(treeNode->gtVal.gtVal1 < compiler->compHndBBtabCount);
2143             noway_assert(finallyNesting < compiler->compHndBBtabCount);
2144
2145             // The last slot is reserved for ICodeManager::FixContext(ppEndRegion)
2146             unsigned filterEndOffsetSlotOffs;
2147             PREFIX_ASSUME(compiler->lvaLclSize(compiler->lvaShadowSPslotsVar) >
2148                           TARGET_POINTER_SIZE); // below doesn't underflow.
2149             filterEndOffsetSlotOffs =
2150                 (unsigned)(compiler->lvaLclSize(compiler->lvaShadowSPslotsVar) - TARGET_POINTER_SIZE);
2151
2152             unsigned curNestingSlotOffs;
2153             curNestingSlotOffs = filterEndOffsetSlotOffs - ((finallyNesting + 1) * TARGET_POINTER_SIZE);
2154             instGen_Store_Imm_Into_Lcl(TYP_I_IMPL, EA_PTRSIZE, 0, compiler->lvaShadowSPslotsVar, curNestingSlotOffs);
2155             break;
2156 #endif // !FEATURE_EH_FUNCLETS
2157
2158         case GT_PINVOKE_PROLOG:
2159             noway_assert(((gcInfo.gcRegGCrefSetCur | gcInfo.gcRegByrefSetCur) & ~fullIntArgRegMask()) == 0);
2160
2161             // the runtime side requires the codegen here to be consistent
2162             emit->emitDisableRandomNops();
2163             break;
2164
2165         case GT_LABEL:
2166             genPendingCallLabel       = genCreateTempLabel();
2167             treeNode->gtLabel.gtLabBB = genPendingCallLabel;
2168             emit->emitIns_R_L(INS_lea, EA_PTR_DSP_RELOC, genPendingCallLabel, treeNode->gtRegNum);
2169             break;
2170
2171         case GT_STORE_OBJ:
2172             if (treeNode->OperIsCopyBlkOp() && !treeNode->AsBlk()->gtBlkOpGcUnsafe)
2173             {
2174                 assert(treeNode->AsObj()->gtGcPtrCount != 0);
2175                 genCodeForCpObj(treeNode->AsObj());
2176                 break;
2177             }
2178             __fallthrough;
2179
2180         case GT_STORE_DYN_BLK:
2181         case GT_STORE_BLK:
2182             genCodeForStoreBlk(treeNode->AsBlk());
2183             break;
2184
2185         case GT_JMPTABLE:
2186             genJumpTable(treeNode);
2187             break;
2188
2189         case GT_SWITCH_TABLE:
2190             genTableBasedSwitch(treeNode);
2191             break;
2192
2193         case GT_ARR_INDEX:
2194             genCodeForArrIndex(treeNode->AsArrIndex());
2195             break;
2196
2197         case GT_ARR_OFFSET:
2198             genCodeForArrOffset(treeNode->AsArrOffs());
2199             break;
2200
2201         case GT_CLS_VAR_ADDR:
2202             getEmitter()->emitIns_R_C(INS_lea, EA_PTRSIZE, targetReg, treeNode->gtClsVar.gtClsVarHnd, 0);
2203             genProduceReg(treeNode);
2204             break;
2205
2206 #if !defined(_TARGET_64BIT_)
2207         case GT_LONG:
2208             assert(treeNode->isUsedFromReg());
2209             genConsumeRegs(treeNode);
2210             break;
2211 #endif
2212
2213         case GT_IL_OFFSET:
2214             // Do nothing; these nodes are simply markers for debug info.
2215             break;
2216
2217         default:
2218         {
2219 #ifdef DEBUG
2220             char message[256];
2221             _snprintf_s(message, _countof(message), _TRUNCATE, "Unimplemented node type %s\n",
2222                         GenTree::NodeName(treeNode->OperGet()));
2223 #endif
2224             assert(!"Unknown node in codegen");
2225         }
2226         break;
2227     }
2228 }
2229
2230 //----------------------------------------------------------------------------------
2231 // genMultiRegCallStoreToLocal: store multi-reg return value of a call node to a local
2232 //
2233 // Arguments:
2234 //    treeNode  -  Gentree of GT_STORE_LCL_VAR
2235 //
2236 // Return Value:
2237 //    None
2238 //
2239 // Assumption:
2240 //    The child of store is a multi-reg call node.
2241 //    genProduceReg() on treeNode is made by caller of this routine.
2242 //
2243 void CodeGen::genMultiRegCallStoreToLocal(GenTreePtr treeNode)
2244 {
2245     assert(treeNode->OperGet() == GT_STORE_LCL_VAR);
2246
2247 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
2248     // Structs of size >=9 and <=16 are returned in two return registers on x64 Unix.
2249     assert(varTypeIsStruct(treeNode));
2250
2251     // Assumption: current x64 Unix implementation requires that a multi-reg struct
2252     // var in 'var = call' is flagged as lvIsMultiRegRet to prevent it from
2253     // being struct promoted.
2254     unsigned   lclNum = treeNode->AsLclVarCommon()->gtLclNum;
2255     LclVarDsc* varDsc = &(compiler->lvaTable[lclNum]);
2256     noway_assert(varDsc->lvIsMultiRegRet);
2257
2258     GenTree*     op1       = treeNode->gtGetOp1();
2259     GenTree*     actualOp1 = op1->gtSkipReloadOrCopy();
2260     GenTreeCall* call      = actualOp1->AsCall();
2261     assert(call->HasMultiRegRetVal());
2262
2263     genConsumeRegs(op1);
2264
2265     ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc();
2266     assert(retTypeDesc->GetReturnRegCount() == MAX_RET_REG_COUNT);
2267     unsigned regCount = retTypeDesc->GetReturnRegCount();
2268
2269     if (treeNode->gtRegNum != REG_NA)
2270     {
2271         // Right now the only enregistrable structs supported are SIMD types.
2272         assert(varTypeIsSIMD(treeNode));
2273         assert(varTypeIsFloating(retTypeDesc->GetReturnRegType(0)));
2274         assert(varTypeIsFloating(retTypeDesc->GetReturnRegType(1)));
2275
2276         // This is a case of two 8-bytes that comprise the operand is in
2277         // two different xmm registers and needs to assembled into a single
2278         // xmm register.
2279         regNumber targetReg = treeNode->gtRegNum;
2280         regNumber reg0      = call->GetRegNumByIdx(0);
2281         regNumber reg1      = call->GetRegNumByIdx(1);
2282
2283         if (op1->IsCopyOrReload())
2284         {
2285             // GT_COPY/GT_RELOAD will have valid reg for those positions
2286             // that need to be copied or reloaded.
2287             regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(0);
2288             if (reloadReg != REG_NA)
2289             {
2290                 reg0 = reloadReg;
2291             }
2292
2293             reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(1);
2294             if (reloadReg != REG_NA)
2295             {
2296                 reg1 = reloadReg;
2297             }
2298         }
2299
2300         if (targetReg != reg0 && targetReg != reg1)
2301         {
2302             // Copy reg0 into targetReg and let it to be handled by one
2303             // of the cases below.
2304             inst_RV_RV(ins_Copy(TYP_DOUBLE), targetReg, reg0, TYP_DOUBLE);
2305             targetReg = reg0;
2306         }
2307
2308         if (targetReg == reg0)
2309         {
2310             // targeReg[63:0] = targetReg[63:0]
2311             // targetReg[127:64] = reg1[127:64]
2312             inst_RV_RV_IV(INS_shufpd, EA_16BYTE, targetReg, reg1, 0x00);
2313         }
2314         else
2315         {
2316             assert(targetReg == reg1);
2317
2318             // We need two shuffles to achieve this
2319             // First:
2320             // targeReg[63:0] = targetReg[63:0]
2321             // targetReg[127:64] = reg0[63:0]
2322             //
2323             // Second:
2324             // targeReg[63:0] = targetReg[127:64]
2325             // targetReg[127:64] = targetReg[63:0]
2326             //
2327             // Essentially copy low 8-bytes from reg0 to high 8-bytes of targetReg
2328             // and next swap low and high 8-bytes of targetReg to have them
2329             // rearranged in the right order.
2330             inst_RV_RV_IV(INS_shufpd, EA_16BYTE, targetReg, reg0, 0x00);
2331             inst_RV_RV_IV(INS_shufpd, EA_16BYTE, targetReg, targetReg, 0x01);
2332         }
2333     }
2334     else
2335     {
2336         // Stack store
2337         int offset = 0;
2338         for (unsigned i = 0; i < regCount; ++i)
2339         {
2340             var_types type = retTypeDesc->GetReturnRegType(i);
2341             regNumber reg  = call->GetRegNumByIdx(i);
2342             if (op1->IsCopyOrReload())
2343             {
2344                 // GT_COPY/GT_RELOAD will have valid reg for those positions
2345                 // that need to be copied or reloaded.
2346                 regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(i);
2347                 if (reloadReg != REG_NA)
2348                 {
2349                     reg = reloadReg;
2350                 }
2351             }
2352
2353             assert(reg != REG_NA);
2354             getEmitter()->emitIns_S_R(ins_Store(type), emitTypeSize(type), reg, lclNum, offset);
2355             offset += genTypeSize(type);
2356         }
2357
2358         varDsc->lvRegNum = REG_STK;
2359     }
2360 #elif defined(_TARGET_X86_)
2361     // Longs are returned in two return registers on x86.
2362     assert(varTypeIsLong(treeNode));
2363
2364     // Assumption: current x86 implementation requires that a multi-reg long
2365     // var in 'var = call' is flagged as lvIsMultiRegRet to prevent it from
2366     // being promoted.
2367     unsigned   lclNum = treeNode->AsLclVarCommon()->gtLclNum;
2368     LclVarDsc* varDsc = &(compiler->lvaTable[lclNum]);
2369     noway_assert(varDsc->lvIsMultiRegRet);
2370
2371     GenTree*     op1       = treeNode->gtGetOp1();
2372     GenTree*     actualOp1 = op1->gtSkipReloadOrCopy();
2373     GenTreeCall* call      = actualOp1->AsCall();
2374     assert(call->HasMultiRegRetVal());
2375
2376     genConsumeRegs(op1);
2377
2378     ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc();
2379     unsigned        regCount    = retTypeDesc->GetReturnRegCount();
2380     assert(regCount == MAX_RET_REG_COUNT);
2381
2382     // Stack store
2383     int offset = 0;
2384     for (unsigned i = 0; i < regCount; ++i)
2385     {
2386         var_types type = retTypeDesc->GetReturnRegType(i);
2387         regNumber reg  = call->GetRegNumByIdx(i);
2388         if (op1->IsCopyOrReload())
2389         {
2390             // GT_COPY/GT_RELOAD will have valid reg for those positions
2391             // that need to be copied or reloaded.
2392             regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(i);
2393             if (reloadReg != REG_NA)
2394             {
2395                 reg = reloadReg;
2396             }
2397         }
2398
2399         assert(reg != REG_NA);
2400         getEmitter()->emitIns_S_R(ins_Store(type), emitTypeSize(type), reg, lclNum, offset);
2401         offset += genTypeSize(type);
2402     }
2403
2404     varDsc->lvRegNum            = REG_STK;
2405 #else  // !FEATURE_UNIX_AMD64_STRUCT_PASSING && !_TARGET_X86_
2406     assert(!"Unreached");
2407 #endif // !FEATURE_UNIX_AMD64_STRUCT_PASSING && !_TARGET_X86_
2408 }
2409
2410 //------------------------------------------------------------------------
2411 // genLclHeap: Generate code for localloc.
2412 //
2413 // Arguments:
2414 //      tree - the localloc tree to generate.
2415 //
2416 // Notes:
2417 //      Note that for x86, we don't track ESP movements while generating the localloc code.
2418 //      The ESP tracking is used to report stack pointer-relative GC info, which is not
2419 //      interesting while doing the localloc construction. Also, for functions with localloc,
2420 //      we have EBP frames, and EBP-relative locals, and ESP-relative accesses only for function
2421 //      call arguments. We store the ESP after the localloc is complete in the LocAllocSP
2422 //      variable. This variable is implicitly reported to the VM in the GC info (its position
2423 //      is defined by convention relative to other items), and is used by the GC to find the
2424 //      "base" stack pointer in functions with localloc.
2425 //
2426 void CodeGen::genLclHeap(GenTreePtr tree)
2427 {
2428     assert(tree->OperGet() == GT_LCLHEAP);
2429     assert(compiler->compLocallocUsed);
2430
2431     GenTreePtr size = tree->gtOp.gtOp1;
2432     noway_assert((genActualType(size->gtType) == TYP_INT) || (genActualType(size->gtType) == TYP_I_IMPL));
2433
2434     regNumber   targetReg   = tree->gtRegNum;
2435     regMaskTP   tmpRegsMask = tree->gtRsvdRegs;
2436     regNumber   regCnt      = REG_NA;
2437     var_types   type        = genActualType(size->gtType);
2438     emitAttr    easz        = emitTypeSize(type);
2439     BasicBlock* endLabel    = nullptr;
2440
2441 #ifdef DEBUG
2442     // Verify ESP
2443     if (compiler->opts.compStackCheckOnRet)
2444     {
2445         noway_assert(compiler->lvaReturnEspCheck != 0xCCCCCCCC &&
2446                      compiler->lvaTable[compiler->lvaReturnEspCheck].lvDoNotEnregister &&
2447                      compiler->lvaTable[compiler->lvaReturnEspCheck].lvOnFrame);
2448         getEmitter()->emitIns_S_R(INS_cmp, EA_PTRSIZE, REG_SPBASE, compiler->lvaReturnEspCheck, 0);
2449
2450         BasicBlock*  esp_check = genCreateTempLabel();
2451         emitJumpKind jmpEqual  = genJumpKindForOper(GT_EQ, CK_SIGNED);
2452         inst_JMP(jmpEqual, esp_check);
2453         getEmitter()->emitIns(INS_BREAKPOINT);
2454         genDefineTempLabel(esp_check);
2455     }
2456 #endif
2457
2458     noway_assert(isFramePointerUsed()); // localloc requires Frame Pointer to be established since SP changes
2459     noway_assert(genStackLevel == 0);   // Can't have anything on the stack
2460
2461     unsigned    stackAdjustment = 0;
2462     BasicBlock* loop            = nullptr;
2463
2464     // compute the amount of memory to allocate to properly STACK_ALIGN.
2465     size_t amount = 0;
2466     if (size->IsCnsIntOrI())
2467     {
2468         // If size is a constant, then it must be contained.
2469         assert(size->isContained());
2470
2471         // If amount is zero then return null in targetReg
2472         amount = size->gtIntCon.gtIconVal;
2473         if (amount == 0)
2474         {
2475             instGen_Set_Reg_To_Zero(EA_PTRSIZE, targetReg);
2476             goto BAILOUT;
2477         }
2478
2479         // 'amount' is the total number of bytes to localloc to properly STACK_ALIGN
2480         amount = AlignUp(amount, STACK_ALIGN);
2481     }
2482     else
2483     {
2484         // The localloc requested memory size is non-constant.
2485
2486         // Put the size value in targetReg. If it is zero, bail out by returning null in targetReg.
2487         genConsumeRegAndCopy(size, targetReg);
2488         endLabel = genCreateTempLabel();
2489         getEmitter()->emitIns_R_R(INS_test, easz, targetReg, targetReg);
2490         inst_JMP(EJ_je, endLabel);
2491
2492         // Compute the size of the block to allocate and perform alignment.
2493         // If compInitMem=true, we can reuse targetReg as regcnt,
2494         // since we don't need any internal registers.
2495         if (compiler->info.compInitMem)
2496         {
2497             assert(genCountBits(tmpRegsMask) == 0);
2498             regCnt = targetReg;
2499         }
2500         else
2501         {
2502             assert(genCountBits(tmpRegsMask) >= 1);
2503             regMaskTP regCntMask = genFindLowestBit(tmpRegsMask);
2504             tmpRegsMask &= ~regCntMask;
2505             regCnt = genRegNumFromMask(regCntMask);
2506             if (regCnt != targetReg)
2507             {
2508                 // Above, we put the size in targetReg. Now, copy it to our new temp register if necessary.
2509                 inst_RV_RV(INS_mov, regCnt, targetReg, size->TypeGet());
2510             }
2511         }
2512
2513         // Round up the number of bytes to allocate to a STACK_ALIGN boundary. This is done
2514         // by code like:
2515         //      add reg, 15
2516         //      and reg, -16
2517         // However, in the initialized memory case, we need the count of STACK_ALIGN-sized
2518         // elements, not a byte count, after the alignment. So instead of the "and", which
2519         // becomes unnecessary, generate a shift, e.g.:
2520         //      add reg, 15
2521         //      shr reg, 4
2522
2523         inst_RV_IV(INS_add, regCnt, STACK_ALIGN - 1, emitActualTypeSize(type));
2524
2525         if (compiler->info.compInitMem)
2526         {
2527             // Convert the count from a count of bytes to a loop count. We will loop once per
2528             // stack alignment size, so each loop will zero 4 bytes on x86 and 16 bytes on x64.
2529             // Note that we zero a single reg-size word per iteration on x86, and 2 reg-size
2530             // words per iteration on x64. We will shift off all the stack alignment bits
2531             // added above, so there is no need for an 'and' instruction.
2532
2533             // --- shr regCnt, 2 (or 4) ---
2534             inst_RV_SH(INS_SHIFT_RIGHT_LOGICAL, EA_PTRSIZE, regCnt, STACK_ALIGN_SHIFT_ALL);
2535         }
2536         else
2537         {
2538             // Otherwise, mask off the low bits to align the byte count.
2539             inst_RV_IV(INS_AND, regCnt, ~(STACK_ALIGN - 1), emitActualTypeSize(type));
2540         }
2541     }
2542
2543 #if FEATURE_FIXED_OUT_ARGS
2544     // If we have an outgoing arg area then we must adjust the SP by popping off the
2545     // outgoing arg area. We will restore it right before we return from this method.
2546     //
2547     // Localloc returns stack space that aligned to STACK_ALIGN bytes. The following
2548     // are the cases that need to be handled:
2549     //   i) Method has out-going arg area.
2550     //      It is guaranteed that size of out-going arg area is STACK_ALIGN'ed (see fgMorphArgs).
2551     //      Therefore, we will pop off the out-going arg area from RSP before allocating the localloc space.
2552     //  ii) Method has no out-going arg area.
2553     //      Nothing to pop off from the stack.
2554     if (compiler->lvaOutgoingArgSpaceSize > 0)
2555     {
2556         assert((compiler->lvaOutgoingArgSpaceSize % STACK_ALIGN) == 0); // This must be true for the stack to remain
2557                                                                         // aligned
2558         inst_RV_IV(INS_add, REG_SPBASE, compiler->lvaOutgoingArgSpaceSize, EA_PTRSIZE);
2559         stackAdjustment += compiler->lvaOutgoingArgSpaceSize;
2560     }
2561 #endif
2562
2563     if (size->IsCnsIntOrI())
2564     {
2565         // We should reach here only for non-zero, constant size allocations.
2566         assert(amount > 0);
2567         assert((amount % STACK_ALIGN) == 0);
2568         assert((amount % REGSIZE_BYTES) == 0);
2569
2570         // For small allocations we will generate up to six push 0 inline
2571         size_t cntRegSizedWords = amount / REGSIZE_BYTES;
2572         if (cntRegSizedWords <= 6)
2573         {
2574             for (; cntRegSizedWords != 0; cntRegSizedWords--)
2575             {
2576                 inst_IV(INS_push_hide, 0); // push_hide means don't track the stack
2577             }
2578             goto ALLOC_DONE;
2579         }
2580
2581         bool doNoInitLessThanOnePageAlloc =
2582             !compiler->info.compInitMem && (amount < compiler->eeGetPageSize()); // must be < not <=
2583
2584 #ifdef _TARGET_X86_
2585         bool needRegCntRegister = true;
2586 #else  // !_TARGET_X86_
2587         bool needRegCntRegister = !doNoInitLessThanOnePageAlloc;
2588 #endif // !_TARGET_X86_
2589
2590         if (needRegCntRegister)
2591         {
2592             // If compInitMem=true, we can reuse targetReg as regcnt.
2593             // Since size is a constant, regCnt is not yet initialized.
2594             assert(regCnt == REG_NA);
2595             if (compiler->info.compInitMem)
2596             {
2597                 assert(genCountBits(tmpRegsMask) == 0);
2598                 regCnt = targetReg;
2599             }
2600             else
2601             {
2602                 assert(genCountBits(tmpRegsMask) >= 1);
2603                 regMaskTP regCntMask = genFindLowestBit(tmpRegsMask);
2604                 tmpRegsMask &= ~regCntMask;
2605                 regCnt = genRegNumFromMask(regCntMask);
2606             }
2607         }
2608
2609         if (doNoInitLessThanOnePageAlloc)
2610         {
2611             // Since the size is less than a page, simply adjust ESP.
2612             // ESP might already be in the guard page, so we must touch it BEFORE
2613             // the alloc, not after.
2614             CLANG_FORMAT_COMMENT_ANCHOR;
2615
2616 #ifdef _TARGET_X86_
2617             // For x86, we don't want to use "sub ESP" because we don't want the emitter to track the adjustment
2618             // to ESP. So do the work in the count register.
2619             // TODO-CQ: manipulate ESP directly, to share code, reduce #ifdefs, and improve CQ. This would require
2620             // creating a way to temporarily turn off the emitter's tracking of ESP, maybe marking instrDescs as "don't
2621             // track".
2622             inst_RV_RV(INS_mov, regCnt, REG_SPBASE, TYP_I_IMPL);
2623             getEmitter()->emitIns_AR_R(INS_TEST, EA_4BYTE, REG_SPBASE, REG_SPBASE, 0);
2624             inst_RV_IV(INS_sub, regCnt, amount, EA_PTRSIZE);
2625             inst_RV_RV(INS_mov, REG_SPBASE, regCnt, TYP_I_IMPL);
2626 #else  // !_TARGET_X86_
2627             getEmitter()->emitIns_AR_R(INS_TEST, EA_4BYTE, REG_SPBASE, REG_SPBASE, 0);
2628             inst_RV_IV(INS_sub, REG_SPBASE, amount, EA_PTRSIZE);
2629 #endif // !_TARGET_X86_
2630
2631             goto ALLOC_DONE;
2632         }
2633
2634         // else, "mov regCnt, amount"
2635
2636         if (compiler->info.compInitMem)
2637         {
2638             // When initializing memory, we want 'amount' to be the loop count.
2639             assert((amount % STACK_ALIGN) == 0);
2640             amount /= STACK_ALIGN;
2641         }
2642
2643         genSetRegToIcon(regCnt, amount, ((int)amount == amount) ? TYP_INT : TYP_LONG);
2644     }
2645
2646     loop = genCreateTempLabel();
2647     if (compiler->info.compInitMem)
2648     {
2649         // At this point 'regCnt' is set to the number of loop iterations for this loop, if each
2650         // iteration zeros (and subtracts from the stack pointer) STACK_ALIGN bytes.
2651         // Since we have to zero out the allocated memory AND ensure that RSP is always valid
2652         // by tickling the pages, we will just push 0's on the stack.
2653
2654         assert(genIsValidIntReg(regCnt));
2655
2656         // Loop:
2657         genDefineTempLabel(loop);
2658
2659         static_assert_no_msg((STACK_ALIGN % REGSIZE_BYTES) == 0);
2660         unsigned const count = (STACK_ALIGN / REGSIZE_BYTES);
2661
2662         for (unsigned i = 0; i < count; i++)
2663         {
2664             inst_IV(INS_push_hide, 0); // --- push REG_SIZE bytes of 0
2665         }
2666         // Note that the stack must always be aligned to STACK_ALIGN bytes
2667
2668         // Decrement the loop counter and loop if not done.
2669         inst_RV(INS_dec, regCnt, TYP_I_IMPL);
2670         inst_JMP(EJ_jne, loop);
2671     }
2672     else
2673     {
2674         // At this point 'regCnt' is set to the total number of bytes to localloc.
2675         //
2676         // We don't need to zero out the allocated memory. However, we do have
2677         // to tickle the pages to ensure that ESP is always valid and is
2678         // in sync with the "stack guard page".  Note that in the worst
2679         // case ESP is on the last byte of the guard page.  Thus you must
2680         // touch ESP+0 first not ESP+x01000.
2681         //
2682         // Another subtlety is that you don't want ESP to be exactly on the
2683         // boundary of the guard page because PUSH is predecrement, thus
2684         // call setup would not touch the guard page but just beyond it
2685         //
2686         // Note that we go through a few hoops so that ESP never points to
2687         // illegal pages at any time during the tickling process
2688         //
2689         //       neg   REGCNT
2690         //       add   REGCNT, ESP      // reg now holds ultimate ESP
2691         //       jb    loop             // result is smaller than orignial ESP (no wrap around)
2692         //       xor   REGCNT, REGCNT,  // Overflow, pick lowest possible number
2693         //  loop:
2694         //       test  ESP, [ESP+0]     // tickle the page
2695         //       mov   REGTMP, ESP
2696         //       sub   REGTMP, PAGE_SIZE
2697         //       mov   ESP, REGTMP
2698         //       cmp   ESP, REGCNT
2699         //       jae   loop
2700         //
2701         //       mov   ESP, REG
2702         //  end:
2703         inst_RV(INS_NEG, regCnt, TYP_I_IMPL);
2704         inst_RV_RV(INS_add, regCnt, REG_SPBASE, TYP_I_IMPL);
2705         inst_JMP(EJ_jb, loop);
2706
2707         instGen_Set_Reg_To_Zero(EA_PTRSIZE, regCnt);
2708
2709         genDefineTempLabel(loop);
2710
2711         // Tickle the decremented value, and move back to ESP,
2712         // note that it has to be done BEFORE the update of ESP since
2713         // ESP might already be on the guard page.  It is OK to leave
2714         // the final value of ESP on the guard page
2715         getEmitter()->emitIns_AR_R(INS_TEST, EA_4BYTE, REG_SPBASE, REG_SPBASE, 0);
2716
2717         // This is a harmless trick to avoid the emitter trying to track the
2718         // decrement of the ESP - we do the subtraction in another reg instead
2719         // of adjusting ESP directly.
2720         assert(tmpRegsMask != RBM_NONE);
2721         assert(genCountBits(tmpRegsMask) == 1);
2722         regNumber regTmp = genRegNumFromMask(tmpRegsMask);
2723
2724         inst_RV_RV(INS_mov, regTmp, REG_SPBASE, TYP_I_IMPL);
2725         inst_RV_IV(INS_sub, regTmp, compiler->eeGetPageSize(), EA_PTRSIZE);
2726         inst_RV_RV(INS_mov, REG_SPBASE, regTmp, TYP_I_IMPL);
2727
2728         inst_RV_RV(INS_cmp, REG_SPBASE, regCnt, TYP_I_IMPL);
2729         inst_JMP(EJ_jae, loop);
2730
2731         // Move the final value to ESP
2732         inst_RV_RV(INS_mov, REG_SPBASE, regCnt);
2733     }
2734
2735 ALLOC_DONE:
2736     // Re-adjust SP to allocate out-going arg area
2737     if (stackAdjustment > 0)
2738     {
2739         assert((stackAdjustment % STACK_ALIGN) == 0); // This must be true for the stack to remain aligned
2740         inst_RV_IV(INS_sub, REG_SPBASE, stackAdjustment, EA_PTRSIZE);
2741     }
2742
2743     // Return the stackalloc'ed address in result register.
2744     // TargetReg = RSP + stackAdjustment.
2745     getEmitter()->emitIns_R_AR(INS_lea, EA_PTRSIZE, targetReg, REG_SPBASE, stackAdjustment);
2746
2747     if (endLabel != nullptr)
2748     {
2749         genDefineTempLabel(endLabel);
2750     }
2751
2752 BAILOUT:
2753
2754     // Write the lvaLocAllocSPvar stack frame slot
2755     if (compiler->lvaLocAllocSPvar != BAD_VAR_NUM)
2756     {
2757         getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SPBASE, compiler->lvaLocAllocSPvar, 0);
2758     }
2759
2760 #if STACK_PROBES
2761     if (compiler->opts.compNeedStackProbes)
2762     {
2763         genGenerateStackProbe();
2764     }
2765 #endif
2766
2767 #ifdef DEBUG
2768     // Update new ESP
2769     if (compiler->opts.compStackCheckOnRet)
2770     {
2771         noway_assert(compiler->lvaReturnEspCheck != 0xCCCCCCCC &&
2772                      compiler->lvaTable[compiler->lvaReturnEspCheck].lvDoNotEnregister &&
2773                      compiler->lvaTable[compiler->lvaReturnEspCheck].lvOnFrame);
2774         getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SPBASE, compiler->lvaReturnEspCheck, 0);
2775     }
2776 #endif
2777
2778     genProduceReg(tree);
2779 }
2780
2781 void CodeGen::genCodeForStoreBlk(GenTreeBlk* storeBlkNode)
2782 {
2783 #ifdef JIT32_GCENCODER
2784     assert(!storeBlkNode->gtBlkOpGcUnsafe);
2785 #else
2786     if (storeBlkNode->gtBlkOpGcUnsafe)
2787     {
2788         getEmitter()->emitDisableGC();
2789     }
2790 #endif // JIT32_GCENCODER
2791
2792     bool isCopyBlk = storeBlkNode->OperIsCopyBlkOp();
2793
2794     switch (storeBlkNode->gtBlkOpKind)
2795     {
2796 #ifdef _TARGET_AMD64_
2797         case GenTreeBlk::BlkOpKindHelper:
2798             if (isCopyBlk)
2799             {
2800                 genCodeForCpBlk(storeBlkNode);
2801             }
2802             else
2803             {
2804                 genCodeForInitBlk(storeBlkNode);
2805             }
2806             break;
2807 #endif // _TARGET_AMD64_
2808         case GenTreeBlk::BlkOpKindRepInstr:
2809             if (isCopyBlk)
2810             {
2811                 genCodeForCpBlkRepMovs(storeBlkNode);
2812             }
2813             else
2814             {
2815                 genCodeForInitBlkRepStos(storeBlkNode);
2816             }
2817             break;
2818         case GenTreeBlk::BlkOpKindUnroll:
2819             if (isCopyBlk)
2820             {
2821                 genCodeForCpBlkUnroll(storeBlkNode);
2822             }
2823             else
2824             {
2825                 genCodeForInitBlkUnroll(storeBlkNode);
2826             }
2827             break;
2828         default:
2829             unreached();
2830     }
2831
2832 #ifndef JIT32_GCENCODER
2833     if (storeBlkNode->gtBlkOpGcUnsafe)
2834     {
2835         getEmitter()->emitEnableGC();
2836     }
2837 #endif // !defined(JIT32_GCENCODER)
2838 }
2839
2840 //
2841 //------------------------------------------------------------------------
2842 // genCodeForInitBlkRepStos: Generate code for InitBlk using rep stos.
2843 //
2844 // Arguments:
2845 //    initBlkNode - The Block store for which we are generating code.
2846 //
2847 // Preconditions:
2848 //    On x64:
2849 //      The size of the buffers must be a constant and also less than INITBLK_STOS_LIMIT bytes.
2850 //      Any value larger than that, we'll use the helper even if both the fill byte and the
2851 //      size are integer constants.
2852 //  On x86:
2853 //      The size must either be a non-constant or less than INITBLK_STOS_LIMIT bytes.
2854 //
2855 void CodeGen::genCodeForInitBlkRepStos(GenTreeBlk* initBlkNode)
2856 {
2857     // Make sure we got the arguments of the initblk/initobj operation in the right registers.
2858     unsigned   size    = initBlkNode->Size();
2859     GenTreePtr dstAddr = initBlkNode->Addr();
2860     GenTreePtr initVal = initBlkNode->Data();
2861     if (initVal->OperIsInitVal())
2862     {
2863         initVal = initVal->gtGetOp1();
2864     }
2865
2866 #ifdef DEBUG
2867     assert(dstAddr->isUsedFromReg());
2868     assert(initVal->isUsedFromReg());
2869 #ifdef _TARGET_AMD64_
2870     assert(size != 0);
2871 #endif
2872     if (initVal->IsCnsIntOrI())
2873     {
2874 #ifdef _TARGET_AMD64_
2875         assert(size > CPBLK_UNROLL_LIMIT && size < CPBLK_MOVS_LIMIT);
2876 #else
2877         // Note that a size of zero means a non-constant size.
2878         assert((size == 0) || (size > CPBLK_UNROLL_LIMIT));
2879 #endif
2880     }
2881
2882 #endif // DEBUG
2883
2884     genConsumeBlockOp(initBlkNode, REG_RDI, REG_RAX, REG_RCX);
2885     instGen(INS_r_stosb);
2886 }
2887
2888 // Generate code for InitBlk by performing a loop unroll
2889 // Preconditions:
2890 //   a) Both the size and fill byte value are integer constants.
2891 //   b) The size of the struct to initialize is smaller than INITBLK_UNROLL_LIMIT bytes.
2892 //
2893 void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* initBlkNode)
2894 {
2895     // Make sure we got the arguments of the initblk/initobj operation in the right registers
2896     unsigned   size    = initBlkNode->Size();
2897     GenTreePtr dstAddr = initBlkNode->Addr();
2898     GenTreePtr initVal = initBlkNode->Data();
2899     if (initVal->OperIsInitVal())
2900     {
2901         initVal = initVal->gtGetOp1();
2902     }
2903
2904     assert(dstAddr->isUsedFromReg());
2905     assert(initVal->isUsedFromReg() || (initVal->IsIntegralConst(0) && ((size & 0xf) == 0)));
2906     assert(size != 0);
2907     assert(size <= INITBLK_UNROLL_LIMIT);
2908     assert(initVal->gtSkipReloadOrCopy()->IsCnsIntOrI());
2909
2910     emitter* emit = getEmitter();
2911
2912     genConsumeOperands(initBlkNode);
2913
2914     // If the initVal was moved, or spilled and reloaded to a different register,
2915     // get the original initVal from below the GT_RELOAD, but only after capturing the valReg,
2916     // which needs to be the new register.
2917     regNumber valReg = initVal->gtRegNum;
2918     initVal          = initVal->gtSkipReloadOrCopy();
2919
2920     unsigned offset = 0;
2921
2922     // Perform an unroll using SSE2 loads and stores.
2923     if (size >= XMM_REGSIZE_BYTES)
2924     {
2925         regNumber tmpReg = genRegNumFromMask(initBlkNode->gtRsvdRegs);
2926
2927 #ifdef DEBUG
2928         assert(initBlkNode->gtRsvdRegs != RBM_NONE);
2929         assert(genCountBits(initBlkNode->gtRsvdRegs) == 1);
2930         assert(genIsValidFloatReg(tmpReg));
2931 #endif // DEBUG
2932
2933         if (initVal->gtIntCon.gtIconVal != 0)
2934         {
2935             emit->emitIns_R_R(INS_mov_i2xmm, EA_PTRSIZE, tmpReg, valReg);
2936             emit->emitIns_R_R(INS_punpckldq, EA_8BYTE, tmpReg, tmpReg);
2937 #ifdef _TARGET_X86_
2938             // For x86, we need one more to convert it from 8 bytes to 16 bytes.
2939             emit->emitIns_R_R(INS_punpckldq, EA_8BYTE, tmpReg, tmpReg);
2940 #endif // _TARGET_X86_
2941         }
2942         else
2943         {
2944             emit->emitIns_R_R(INS_xorpd, EA_8BYTE, tmpReg, tmpReg);
2945         }
2946
2947         // Determine how many 16 byte slots we're going to fill using SSE movs.
2948         size_t slots = size / XMM_REGSIZE_BYTES;
2949
2950         while (slots-- > 0)
2951         {
2952             emit->emitIns_AR_R(INS_movdqu, EA_8BYTE, tmpReg, dstAddr->gtRegNum, offset);
2953             offset += XMM_REGSIZE_BYTES;
2954         }
2955     }
2956
2957     // Fill the remainder (or a < 16 byte sized struct)
2958     if ((size & 8) != 0)
2959     {
2960 #ifdef _TARGET_X86_
2961         // TODO-X86-CQ: [1091735] Revisit block ops codegen. One example: use movq for 8 byte movs.
2962         emit->emitIns_AR_R(INS_mov, EA_4BYTE, valReg, dstAddr->gtRegNum, offset);
2963         offset += 4;
2964         emit->emitIns_AR_R(INS_mov, EA_4BYTE, valReg, dstAddr->gtRegNum, offset);
2965         offset += 4;
2966 #else // !_TARGET_X86_
2967
2968         emit->emitIns_AR_R(INS_mov, EA_8BYTE, valReg, dstAddr->gtRegNum, offset);
2969         offset += 8;
2970
2971 #endif // !_TARGET_X86_
2972     }
2973     if ((size & 4) != 0)
2974     {
2975         emit->emitIns_AR_R(INS_mov, EA_4BYTE, valReg, dstAddr->gtRegNum, offset);
2976         offset += 4;
2977     }
2978     if ((size & 2) != 0)
2979     {
2980         emit->emitIns_AR_R(INS_mov, EA_2BYTE, valReg, dstAddr->gtRegNum, offset);
2981         offset += 2;
2982     }
2983     if ((size & 1) != 0)
2984     {
2985         emit->emitIns_AR_R(INS_mov, EA_1BYTE, valReg, dstAddr->gtRegNum, offset);
2986     }
2987 }
2988
2989 // Generates code for InitBlk by calling the VM memset helper function.
2990 // Preconditions:
2991 // a) The size argument of the InitBlk is not an integer constant.
2992 // b) The size argument of the InitBlk is >= INITBLK_STOS_LIMIT bytes.
2993 void CodeGen::genCodeForInitBlk(GenTreeBlk* initBlkNode)
2994 {
2995 #ifdef _TARGET_AMD64_
2996     // Make sure we got the arguments of the initblk operation in the right registers
2997     unsigned   blockSize = initBlkNode->Size();
2998     GenTreePtr dstAddr   = initBlkNode->Addr();
2999     GenTreePtr initVal   = initBlkNode->Data();
3000     if (initVal->OperIsInitVal())
3001     {
3002         initVal = initVal->gtGetOp1();
3003     }
3004
3005     assert(dstAddr->isUsedFromReg());
3006     assert(initVal->isUsedFromReg());
3007
3008     if (blockSize != 0)
3009     {
3010         assert(blockSize >= CPBLK_MOVS_LIMIT);
3011     }
3012
3013     genConsumeBlockOp(initBlkNode, REG_ARG_0, REG_ARG_1, REG_ARG_2);
3014
3015     genEmitHelperCall(CORINFO_HELP_MEMSET, 0, EA_UNKNOWN);
3016 #else  // !_TARGET_AMD64_
3017     NYI_X86("Helper call for InitBlk");
3018 #endif // !_TARGET_AMD64_
3019 }
3020
3021 // Generate code for a load from some address + offset
3022 //   baseNode: tree node which can be either a local address or arbitrary node
3023 //   offset: distance from the baseNode from which to load
3024 void CodeGen::genCodeForLoadOffset(instruction ins, emitAttr size, regNumber dst, GenTree* baseNode, unsigned offset)
3025 {
3026     emitter* emit = getEmitter();
3027
3028     if (baseNode->OperIsLocalAddr())
3029     {
3030         if (baseNode->gtOper == GT_LCL_FLD_ADDR)
3031         {
3032             offset += baseNode->gtLclFld.gtLclOffs;
3033         }
3034         emit->emitIns_R_S(ins, size, dst, baseNode->gtLclVarCommon.gtLclNum, offset);
3035     }
3036     else
3037     {
3038         emit->emitIns_R_AR(ins, size, dst, baseNode->gtRegNum, offset);
3039     }
3040 }
3041
3042 //------------------------------------------------------------------------
3043 // genCodeForStoreOffset: Generate code to store a reg to [base + offset].
3044 //
3045 // Arguments:
3046 //      ins         - the instruction to generate.
3047 //      size        - the size that needs to be stored.
3048 //      src         - the register which needs to be stored.
3049 //      baseNode    - the base, relative to which to store the src register.
3050 //      offset      - the offset that is added to the baseNode to calculate the address to store into.
3051 //
3052 void CodeGen::genCodeForStoreOffset(instruction ins, emitAttr size, regNumber src, GenTree* baseNode, unsigned offset)
3053 {
3054     emitter* emit = getEmitter();
3055
3056     if (baseNode->OperIsLocalAddr())
3057     {
3058         if (baseNode->gtOper == GT_LCL_FLD_ADDR)
3059         {
3060             offset += baseNode->gtLclFld.gtLclOffs;
3061         }
3062
3063         emit->emitIns_S_R(ins, size, src, baseNode->AsLclVarCommon()->GetLclNum(), offset);
3064     }
3065     else
3066     {
3067         emit->emitIns_AR_R(ins, size, src, baseNode->gtRegNum, offset);
3068     }
3069 }
3070
3071 // Generates CpBlk code by performing a loop unroll
3072 // Preconditions:
3073 //  The size argument of the CpBlk node is a constant and <= 64 bytes.
3074 //  This may seem small but covers >95% of the cases in several framework assemblies.
3075 //
3076 void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode)
3077 {
3078     // Make sure we got the arguments of the cpblk operation in the right registers
3079     unsigned   size    = cpBlkNode->Size();
3080     GenTreePtr dstAddr = cpBlkNode->Addr();
3081     GenTreePtr source  = cpBlkNode->Data();
3082     GenTreePtr srcAddr = nullptr;
3083     assert(size <= CPBLK_UNROLL_LIMIT);
3084
3085     emitter* emit = getEmitter();
3086
3087     if (source->gtOper == GT_IND)
3088     {
3089         srcAddr = source->gtGetOp1();
3090         if (srcAddr->isUsedFromReg())
3091         {
3092             genConsumeReg(srcAddr);
3093         }
3094     }
3095     else
3096     {
3097         noway_assert(source->IsLocal());
3098         // TODO-Cleanup: Consider making the addrForm() method in Rationalize public, e.g. in GenTree.
3099         // OR: transform source to GT_IND(GT_LCL_VAR_ADDR)
3100         if (source->OperGet() == GT_LCL_VAR)
3101         {
3102             source->SetOper(GT_LCL_VAR_ADDR);
3103         }
3104         else
3105         {
3106             assert(source->OperGet() == GT_LCL_FLD);
3107             source->SetOper(GT_LCL_FLD_ADDR);
3108         }
3109         srcAddr = source;
3110     }
3111
3112     if (dstAddr->isUsedFromReg())
3113     {
3114         genConsumeReg(dstAddr);
3115     }
3116
3117     unsigned offset = 0;
3118
3119     // If the size of this struct is larger than 16 bytes
3120     // let's use SSE2 to be able to do 16 byte at a time
3121     // loads and stores.
3122
3123     if (size >= XMM_REGSIZE_BYTES)
3124     {
3125         assert(cpBlkNode->gtRsvdRegs != RBM_NONE);
3126         regNumber xmmReg = genRegNumFromMask(cpBlkNode->gtRsvdRegs & RBM_ALLFLOAT);
3127         assert(genIsValidFloatReg(xmmReg));
3128         size_t slots = size / XMM_REGSIZE_BYTES;
3129
3130         // TODO: In the below code the load and store instructions are for 16 bytes, but the
3131         //       type is EA_8BYTE. The movdqa/u are 16 byte instructions, so it works, but
3132         //       this probably needs to be changed.
3133         while (slots-- > 0)
3134         {
3135             // Load
3136             genCodeForLoadOffset(INS_movdqu, EA_8BYTE, xmmReg, srcAddr, offset);
3137             // Store
3138             genCodeForStoreOffset(INS_movdqu, EA_8BYTE, xmmReg, dstAddr, offset);
3139             offset += XMM_REGSIZE_BYTES;
3140         }
3141     }
3142
3143     // Fill the remainder (15 bytes or less) if there's one.
3144     if ((size & 0xf) != 0)
3145     {
3146         // Grab the integer temp register to emit the remaining loads and stores.
3147         regNumber tmpReg = genRegNumFromMask(cpBlkNode->gtRsvdRegs & RBM_ALLINT);
3148
3149         if ((size & 8) != 0)
3150         {
3151 #ifdef _TARGET_X86_
3152             // TODO-X86-CQ: [1091735] Revisit block ops codegen. One example: use movq for 8 byte movs.
3153             for (unsigned savedOffs = offset; offset < savedOffs + 8; offset += 4)
3154             {
3155                 genCodeForLoadOffset(INS_mov, EA_4BYTE, tmpReg, srcAddr, offset);
3156                 genCodeForStoreOffset(INS_mov, EA_4BYTE, tmpReg, dstAddr, offset);
3157             }
3158 #else  // !_TARGET_X86_
3159             genCodeForLoadOffset(INS_mov, EA_8BYTE, tmpReg, srcAddr, offset);
3160             genCodeForStoreOffset(INS_mov, EA_8BYTE, tmpReg, dstAddr, offset);
3161             offset += 8;
3162 #endif // !_TARGET_X86_
3163         }
3164         if ((size & 4) != 0)
3165         {
3166             genCodeForLoadOffset(INS_mov, EA_4BYTE, tmpReg, srcAddr, offset);
3167             genCodeForStoreOffset(INS_mov, EA_4BYTE, tmpReg, dstAddr, offset);
3168             offset += 4;
3169         }
3170         if ((size & 2) != 0)
3171         {
3172             genCodeForLoadOffset(INS_mov, EA_2BYTE, tmpReg, srcAddr, offset);
3173             genCodeForStoreOffset(INS_mov, EA_2BYTE, tmpReg, dstAddr, offset);
3174             offset += 2;
3175         }
3176         if ((size & 1) != 0)
3177         {
3178             genCodeForLoadOffset(INS_mov, EA_1BYTE, tmpReg, srcAddr, offset);
3179             genCodeForStoreOffset(INS_mov, EA_1BYTE, tmpReg, dstAddr, offset);
3180         }
3181     }
3182 }
3183
3184 // Generate code for CpBlk by using rep movs
3185 // Preconditions:
3186 // The size argument of the CpBlk is a constant and is between
3187 // CPBLK_UNROLL_LIMIT and CPBLK_MOVS_LIMIT bytes.
3188 void CodeGen::genCodeForCpBlkRepMovs(GenTreeBlk* cpBlkNode)
3189 {
3190     // Make sure we got the arguments of the cpblk operation in the right registers
3191     unsigned   size    = cpBlkNode->Size();
3192     GenTreePtr dstAddr = cpBlkNode->Addr();
3193     GenTreePtr source  = cpBlkNode->Data();
3194     GenTreePtr srcAddr = nullptr;
3195
3196 #ifdef DEBUG
3197     assert(dstAddr->isUsedFromReg());
3198     assert(source->isContained());
3199
3200 #ifdef _TARGET_X86_
3201     if (size == 0)
3202     {
3203         noway_assert(cpBlkNode->OperGet() == GT_STORE_DYN_BLK);
3204     }
3205     else
3206 #endif
3207     {
3208 #ifdef _TARGET_X64_
3209         assert(size > CPBLK_UNROLL_LIMIT && size < CPBLK_MOVS_LIMIT);
3210 #else
3211         assert(size > CPBLK_UNROLL_LIMIT);
3212 #endif
3213     }
3214 #endif // DEBUG
3215
3216     genConsumeBlockOp(cpBlkNode, REG_RDI, REG_RSI, REG_RCX);
3217     instGen(INS_r_movsb);
3218 }
3219
3220 #ifdef FEATURE_PUT_STRUCT_ARG_STK
3221 //------------------------------------------------------------------------
3222 // CodeGen::genMove8IfNeeded: Conditionally move 8 bytes of a struct to the argument area
3223 //
3224 // Arguments:
3225 //    size       - The size of bytes remaining to be moved
3226 //    longTmpReg - The tmp register to be used for the long value
3227 //    srcAddr    - The address of the source struct
3228 //    offset     - The current offset being copied
3229 //
3230 // Return Value:
3231 //    Returns the number of bytes moved (8 or 0).
3232 //
3233 // Notes:
3234 //    This is used in the PutArgStkKindUnroll case, to move any bytes that are
3235 //    not an even multiple of 16.
3236 //    On x86, longTmpReg must be an xmm reg; on x64 it must be an integer register.
3237 //    This is checked by genStoreRegToStackArg.
3238 //
3239 unsigned CodeGen::genMove8IfNeeded(unsigned size, regNumber longTmpReg, GenTree* srcAddr, unsigned offset)
3240 {
3241 #ifdef _TARGET_X86_
3242     instruction longMovIns = INS_movq;
3243 #else  // !_TARGET_X86_
3244     instruction longMovIns = INS_mov;
3245 #endif // !_TARGET_X86_
3246     if ((size & 8) != 0)
3247     {
3248         genCodeForLoadOffset(longMovIns, EA_8BYTE, longTmpReg, srcAddr, offset);
3249         genStoreRegToStackArg(TYP_LONG, longTmpReg, offset);
3250         return 8;
3251     }
3252     return 0;
3253 }
3254
3255 //------------------------------------------------------------------------
3256 // CodeGen::genMove4IfNeeded: Conditionally move 4 bytes of a struct to the argument area
3257 //
3258 // Arguments:
3259 //    size      - The size of bytes remaining to be moved
3260 //    intTmpReg - The tmp register to be used for the long value
3261 //    srcAddr   - The address of the source struct
3262 //    offset    - The current offset being copied
3263 //
3264 // Return Value:
3265 //    Returns the number of bytes moved (4 or 0).
3266 //
3267 // Notes:
3268 //    This is used in the PutArgStkKindUnroll case, to move any bytes that are
3269 //    not an even multiple of 16.
3270 //    intTmpReg must be an integer register.
3271 //    This is checked by genStoreRegToStackArg.
3272 //
3273 unsigned CodeGen::genMove4IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset)
3274 {
3275     if ((size & 4) != 0)
3276     {
3277         genCodeForLoadOffset(INS_mov, EA_4BYTE, intTmpReg, srcAddr, offset);
3278         genStoreRegToStackArg(TYP_INT, intTmpReg, offset);
3279         return 4;
3280     }
3281     return 0;
3282 }
3283
3284 //------------------------------------------------------------------------
3285 // CodeGen::genMove2IfNeeded: Conditionally move 2 bytes of a struct to the argument area
3286 //
3287 // Arguments:
3288 //    size      - The size of bytes remaining to be moved
3289 //    intTmpReg - The tmp register to be used for the long value
3290 //    srcAddr   - The address of the source struct
3291 //    offset    - The current offset being copied
3292 //
3293 // Return Value:
3294 //    Returns the number of bytes moved (2 or 0).
3295 //
3296 // Notes:
3297 //    This is used in the PutArgStkKindUnroll case, to move any bytes that are
3298 //    not an even multiple of 16.
3299 //    intTmpReg must be an integer register.
3300 //    This is checked by genStoreRegToStackArg.
3301 //
3302 unsigned CodeGen::genMove2IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset)
3303 {
3304     if ((size & 2) != 0)
3305     {
3306         genCodeForLoadOffset(INS_mov, EA_2BYTE, intTmpReg, srcAddr, offset);
3307         genStoreRegToStackArg(TYP_SHORT, intTmpReg, offset);
3308         return 2;
3309     }
3310     return 0;
3311 }
3312
3313 //------------------------------------------------------------------------
3314 // CodeGen::genMove1IfNeeded: Conditionally move 1 byte of a struct to the argument area
3315 //
3316 // Arguments:
3317 //    size      - The size of bytes remaining to be moved
3318 //    intTmpReg - The tmp register to be used for the long value
3319 //    srcAddr   - The address of the source struct
3320 //    offset    - The current offset being copied
3321 //
3322 // Return Value:
3323 //    Returns the number of bytes moved (1 or 0).
3324 //
3325 // Notes:
3326 //    This is used in the PutArgStkKindUnroll case, to move any bytes that are
3327 //    not an even multiple of 16.
3328 //    intTmpReg must be an integer register.
3329 //    This is checked by genStoreRegToStackArg.
3330 //
3331 unsigned CodeGen::genMove1IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset)
3332 {
3333
3334     if ((size & 1) != 0)
3335     {
3336         genCodeForLoadOffset(INS_mov, EA_1BYTE, intTmpReg, srcAddr, offset);
3337         genStoreRegToStackArg(TYP_BYTE, intTmpReg, offset);
3338         return 1;
3339     }
3340     return 0;
3341 }
3342
3343 //---------------------------------------------------------------------------------------------------------------//
3344 // genStructPutArgUnroll: Generates code for passing a struct arg on stack by value using loop unrolling.
3345 //
3346 // Arguments:
3347 //     putArgNode  - the PutArgStk tree.
3348 //
3349 // Notes:
3350 //     m_stkArgVarNum must be set to the base var number, relative to which the by-val struct will be copied to the
3351 //     stack.
3352 //
3353 // TODO-Amd64-Unix: Try to share code with copyblk.
3354 //      Need refactoring of copyblk before it could be used for putarg_stk.
3355 //      The difference for now is that a putarg_stk contains its children, while cpyblk does not.
3356 //      This creates differences in code. After some significant refactoring it could be reused.
3357 //
3358 void CodeGen::genStructPutArgUnroll(GenTreePutArgStk* putArgNode)
3359 {
3360     // We will never call this method for SIMD types, which are stored directly
3361     // in genPutStructArgStk().
3362     noway_assert(putArgNode->TypeGet() == TYP_STRUCT);
3363
3364     // Make sure we got the arguments of the cpblk operation in the right registers
3365     GenTreePtr dstAddr = putArgNode;
3366     GenTreePtr src     = putArgNode->gtOp.gtOp1;
3367
3368     unsigned size = putArgNode->getArgSize();
3369     assert(size <= CPBLK_UNROLL_LIMIT);
3370
3371     emitter* emit         = getEmitter();
3372     unsigned putArgOffset = putArgNode->getArgOffset();
3373
3374     assert(src->isContained());
3375
3376     assert(src->gtOper == GT_OBJ);
3377
3378     if (src->gtOp.gtOp1->isUsedFromReg())
3379     {
3380         genConsumeReg(src->gtOp.gtOp1);
3381     }
3382
3383     unsigned offset = 0;
3384
3385     regNumber xmmTmpReg  = REG_NA;
3386     regNumber intTmpReg  = REG_NA;
3387     regNumber longTmpReg = REG_NA;
3388 #ifdef _TARGET_X86_
3389     // On x86 we use an XMM register for both 16 and 8-byte chunks, but if it's
3390     // less than 16 bytes, we will just be using pushes
3391     if (size >= 8)
3392     {
3393         xmmTmpReg  = genRegNumFromMask(putArgNode->gtRsvdRegs & RBM_ALLFLOAT);
3394         longTmpReg = xmmTmpReg;
3395     }
3396     if ((size & 0x7) != 0)
3397     {
3398         intTmpReg = genRegNumFromMask(putArgNode->gtRsvdRegs & RBM_ALLINT);
3399     }
3400 #else  // !_TARGET_X86_
3401     // On x64 we use an XMM register only for 16-byte chunks.
3402     if (size >= XMM_REGSIZE_BYTES)
3403     {
3404         xmmTmpReg = genRegNumFromMask(putArgNode->gtRsvdRegs & RBM_ALLFLOAT);
3405     }
3406     if ((size & 0xf) != 0)
3407     {
3408         intTmpReg  = genRegNumFromMask(putArgNode->gtRsvdRegs & RBM_ALLINT);
3409         longTmpReg = intTmpReg;
3410     }
3411 #endif // !_TARGET_X86_
3412
3413     // If the size of this struct is larger than 16 bytes
3414     // let's use SSE2 to be able to do 16 byte at a time
3415     // loads and stores.
3416     if (size >= XMM_REGSIZE_BYTES)
3417     {
3418 #ifdef _TARGET_X86_
3419         assert(!m_pushStkArg);
3420 #endif // _TARGET_X86_
3421         assert(putArgNode->gtRsvdRegs != RBM_NONE);
3422         size_t slots = size / XMM_REGSIZE_BYTES;
3423
3424         assert(putArgNode->gtGetOp1()->isContained());
3425         assert(putArgNode->gtGetOp1()->gtOp.gtOper == GT_OBJ);
3426
3427         // TODO: In the below code the load and store instructions are for 16 bytes, but the
3428         //          type is EA_8BYTE. The movdqa/u are 16 byte instructions, so it works, but
3429         //          this probably needs to be changed.
3430         while (slots-- > 0)
3431         {
3432             // Load
3433             genCodeForLoadOffset(INS_movdqu, EA_8BYTE, xmmTmpReg, src->gtGetOp1(), offset);
3434
3435             // Store
3436             genStoreRegToStackArg(TYP_STRUCT, xmmTmpReg, offset);
3437
3438             offset += XMM_REGSIZE_BYTES;
3439         }
3440     }
3441
3442     // Fill the remainder (15 bytes or less) if there's one.
3443     if ((size & 0xf) != 0)
3444     {
3445 #ifdef _TARGET_X86_
3446         if (m_pushStkArg)
3447         {
3448             // This case is currently supported only for the case where the total size is
3449             // less than XMM_REGSIZE_BYTES. We need to push the remaining chunks in reverse
3450             // order. However, morph has ensured that we have a struct that is an even
3451             // multiple of TARGET_POINTER_SIZE, so we don't need to worry about alignment.
3452             assert(((size & 0xc) == size) && (offset == 0));
3453             // If we have a 4 byte chunk, load it from either offset 0 or 8, depending on
3454             // whether we've got an 8 byte chunk, and then push it on the stack.
3455             unsigned pushedBytes = genMove4IfNeeded(size, intTmpReg, src->gtOp.gtOp1, size & 0x8);
3456             // Now if we have an 8 byte chunk, load it from offset 0 (it's the first chunk)
3457             // and push it on the stack.
3458             pushedBytes += genMove8IfNeeded(size, longTmpReg, src->gtOp.gtOp1, 0);
3459         }
3460         else
3461 #endif // _TARGET_X86_
3462         {
3463             offset += genMove8IfNeeded(size, longTmpReg, src->gtOp.gtOp1, offset);
3464             offset += genMove4IfNeeded(size, intTmpReg, src->gtOp.gtOp1, offset);
3465             offset += genMove2IfNeeded(size, intTmpReg, src->gtOp.gtOp1, offset);
3466             offset += genMove1IfNeeded(size, intTmpReg, src->gtOp.gtOp1, offset);
3467             assert(offset == size);
3468         }
3469     }
3470 }
3471
3472 //------------------------------------------------------------------------
3473 // genStructPutArgRepMovs: Generates code for passing a struct arg by value on stack using Rep Movs.
3474 //
3475 // Arguments:
3476 //     putArgNode  - the PutArgStk tree.
3477 //
3478 // Preconditions:
3479 //     The size argument of the PutArgStk (for structs) is a constant and is between
3480 //     CPBLK_UNROLL_LIMIT and CPBLK_MOVS_LIMIT bytes.
3481 //     m_stkArgVarNum must be set to the base var number, relative to which the by-val struct bits will go.
3482 //
3483 void CodeGen::genStructPutArgRepMovs(GenTreePutArgStk* putArgNode)
3484 {
3485     assert(putArgNode->TypeGet() == TYP_STRUCT);
3486     assert(putArgNode->getArgSize() > CPBLK_UNROLL_LIMIT);
3487
3488     // Make sure we got the arguments of the cpblk operation in the right registers
3489     GenTreePtr dstAddr = putArgNode;
3490     GenTreePtr srcAddr = putArgNode->gtGetOp1();
3491
3492     // Validate state.
3493     assert(putArgNode->gtRsvdRegs == (RBM_RDI | RBM_RCX | RBM_RSI));
3494     assert(srcAddr->isContained());
3495
3496     genConsumePutStructArgStk(putArgNode, REG_RDI, REG_RSI, REG_RCX);
3497     instGen(INS_r_movsb);
3498 }
3499
3500 //------------------------------------------------------------------------
3501 // If any Vector3 args are on stack and they are not pass-by-ref, the upper 32bits
3502 // must be cleared to zeroes. The native compiler doesn't clear the upper bits
3503 // and there is no way to know if the caller is native or not. So, the upper
3504 // 32 bits of Vector argument on stack are always cleared to zero.
3505 #if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) && defined(FEATURE_SIMD)
3506 void CodeGen::genClearStackVec3ArgUpperBits()
3507 {
3508 #ifdef DEBUG
3509     if (verbose)
3510     {
3511         printf("*************** In genClearStackVec3ArgUpperBits()\n");
3512     }
3513 #endif
3514
3515     assert(compiler->compGeneratingProlog);
3516
3517     unsigned varNum = 0;
3518
3519     for (unsigned varNum = 0; varNum < compiler->info.compArgsCount; varNum++)
3520     {
3521         LclVarDsc* varDsc = &(compiler->lvaTable[varNum]);
3522         assert(varDsc->lvIsParam);
3523
3524         // Does var has simd12 type?
3525         if (varDsc->lvType != TYP_SIMD12)
3526         {
3527             continue;
3528         }
3529
3530         if (!varDsc->lvIsRegArg)
3531         {
3532             // Clear the upper 32 bits by mov dword ptr [V_ARG_BASE+0xC], 0
3533             getEmitter()->emitIns_S_I(ins_Store(TYP_INT), EA_4BYTE, varNum, genTypeSize(TYP_FLOAT) * 3, 0);
3534         }
3535         else
3536         {
3537             // Assume that for x64 linux, an argument is fully in registers
3538             // or fully on stack.
3539             regNumber argReg = varDsc->GetOtherArgReg();
3540
3541             // Clear the upper 32 bits by two shift instructions.
3542             // argReg = argReg << 96
3543             getEmitter()->emitIns_R_I(INS_pslldq, emitActualTypeSize(TYP_SIMD12), argReg, 12);
3544             // argReg = argReg >> 96
3545             getEmitter()->emitIns_R_I(INS_psrldq, emitActualTypeSize(TYP_SIMD12), argReg, 12);
3546         }
3547     }
3548 }
3549 #endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) && defined(FEATURE_SIMD)
3550 #endif // FEATURE_PUT_STRUCT_ARG_STK
3551
3552 // Generate code for CpObj nodes wich copy structs that have interleaved
3553 // GC pointers.
3554 // This will generate a sequence of movsp instructions for the cases of non-gc members.
3555 // Note that movsp is an alias for movsd on x86 and movsq on x64.
3556 // and calls to the BY_REF_ASSIGN helper otherwise.
3557 void CodeGen::genCodeForCpObj(GenTreeObj* cpObjNode)
3558 {
3559     // Make sure we got the arguments of the cpobj operation in the right registers
3560     GenTreePtr dstAddr       = cpObjNode->Addr();
3561     GenTreePtr source        = cpObjNode->Data();
3562     GenTreePtr srcAddr       = nullptr;
3563     var_types  srcAddrType   = TYP_BYREF;
3564     bool       sourceIsLocal = false;
3565
3566     assert(source->isContained());
3567     if (source->gtOper == GT_IND)
3568     {
3569         srcAddr = source->gtGetOp1();
3570         assert(srcAddr->isUsedFromReg());
3571     }
3572     else
3573     {
3574         noway_assert(source->IsLocal());
3575         sourceIsLocal = true;
3576     }
3577
3578     bool dstOnStack = dstAddr->OperIsLocalAddr();
3579
3580 #ifdef DEBUG
3581     bool isRepMovspUsed = false;
3582
3583     assert(dstAddr->isUsedFromReg());
3584
3585     // If the GenTree node has data about GC pointers, this means we're dealing
3586     // with CpObj, so this requires special logic.
3587     assert(cpObjNode->gtGcPtrCount > 0);
3588
3589     // MovSp (alias for movsq on x64 and movsd on x86) instruction is used for copying non-gcref fields
3590     // and it needs src = RSI and dst = RDI.
3591     // Either these registers must not contain lclVars, or they must be dying or marked for spill.
3592     // This is because these registers are incremented as we go through the struct.
3593     if (!sourceIsLocal)
3594     {
3595         GenTree* actualSrcAddr    = srcAddr->gtSkipReloadOrCopy();
3596         GenTree* actualDstAddr    = dstAddr->gtSkipReloadOrCopy();
3597         unsigned srcLclVarNum     = BAD_VAR_NUM;
3598         unsigned dstLclVarNum     = BAD_VAR_NUM;
3599         bool     isSrcAddrLiveOut = false;
3600         bool     isDstAddrLiveOut = false;
3601         if (genIsRegCandidateLocal(actualSrcAddr))
3602         {
3603             srcLclVarNum     = actualSrcAddr->AsLclVarCommon()->gtLclNum;
3604             isSrcAddrLiveOut = ((actualSrcAddr->gtFlags & (GTF_VAR_DEATH | GTF_SPILL)) == 0);
3605         }
3606         if (genIsRegCandidateLocal(actualDstAddr))
3607         {
3608             dstLclVarNum     = actualDstAddr->AsLclVarCommon()->gtLclNum;
3609             isDstAddrLiveOut = ((actualDstAddr->gtFlags & (GTF_VAR_DEATH | GTF_SPILL)) == 0);
3610         }
3611         assert((actualSrcAddr->gtRegNum != REG_RSI) || !isSrcAddrLiveOut ||
3612                ((srcLclVarNum == dstLclVarNum) && !isDstAddrLiveOut));
3613         assert((actualDstAddr->gtRegNum != REG_RDI) || !isDstAddrLiveOut ||
3614                ((srcLclVarNum == dstLclVarNum) && !isSrcAddrLiveOut));
3615         srcAddrType = srcAddr->TypeGet();
3616     }
3617 #endif // DEBUG
3618
3619     // Consume the operands and get them into the right registers.
3620     // They may now contain gc pointers (depending on their type; gcMarkRegPtrVal will "do the right thing").
3621     genConsumeBlockOp(cpObjNode, REG_RDI, REG_RSI, REG_NA);
3622     gcInfo.gcMarkRegPtrVal(REG_RSI, srcAddrType);
3623     gcInfo.gcMarkRegPtrVal(REG_RDI, dstAddr->TypeGet());
3624
3625     unsigned slots = cpObjNode->gtSlots;
3626
3627     // If we can prove it's on the stack we don't need to use the write barrier.
3628     if (dstOnStack)
3629     {
3630         if (slots >= CPOBJ_NONGC_SLOTS_LIMIT)
3631         {
3632 #ifdef DEBUG
3633             // If the destination of the CpObj is on the stack, make sure we allocated
3634             // RCX to emit the movsp (alias for movsd or movsq for 32 and 64 bits respectively).
3635             assert((cpObjNode->gtRsvdRegs & RBM_RCX) != 0);
3636             regNumber tmpReg = REG_RCX;
3637             isRepMovspUsed   = true;
3638 #endif // DEBUG
3639
3640             getEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, REG_RCX, slots);
3641             instGen(INS_r_movsp);
3642         }
3643         else
3644         {
3645             // For small structs, it's better to emit a sequence of movsp than to
3646             // emit a rep movsp instruction.
3647             while (slots > 0)
3648             {
3649                 instGen(INS_movsp);
3650                 slots--;
3651             }
3652         }
3653     }
3654     else
3655     {
3656         BYTE*    gcPtrs     = cpObjNode->gtGcPtrs;
3657         unsigned gcPtrCount = cpObjNode->gtGcPtrCount;
3658
3659         unsigned i = 0;
3660         while (i < slots)
3661         {
3662             switch (gcPtrs[i])
3663             {
3664                 case TYPE_GC_NONE:
3665                     // Let's see if we can use rep movsp instead of a sequence of movsp instructions
3666                     // to save cycles and code size.
3667                     {
3668                         unsigned nonGcSlotCount = 0;
3669
3670                         do
3671                         {
3672                             nonGcSlotCount++;
3673                             i++;
3674                         } while (i < slots && gcPtrs[i] == TYPE_GC_NONE);
3675
3676                         // If we have a very small contiguous non-gc region, it's better just to
3677                         // emit a sequence of movsp instructions
3678                         if (nonGcSlotCount < CPOBJ_NONGC_SLOTS_LIMIT)
3679                         {
3680                             while (nonGcSlotCount > 0)
3681                             {
3682                                 instGen(INS_movsp);
3683                                 nonGcSlotCount--;
3684                             }
3685                         }
3686                         else
3687                         {
3688 #ifdef DEBUG
3689                             // Otherwise, we can save code-size and improve CQ by emitting
3690                             // rep movsp (alias for movsd/movsq for x86/x64)
3691                             assert((cpObjNode->gtRsvdRegs & RBM_RCX) != 0);
3692                             regNumber tmpReg = REG_RCX;
3693                             isRepMovspUsed   = true;
3694 #endif // DEBUG
3695                             getEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, REG_RCX, nonGcSlotCount);
3696                             instGen(INS_r_movsp);
3697                         }
3698                     }
3699                     break;
3700                 default:
3701                     // We have a GC pointer, call the memory barrier.
3702                     genEmitHelperCall(CORINFO_HELP_ASSIGN_BYREF, 0, EA_PTRSIZE);
3703                     gcPtrCount--;
3704                     i++;
3705             }
3706         }
3707
3708         assert(gcPtrCount == 0);
3709     }
3710
3711     // Clear the gcInfo for RSI and RDI.
3712     // While we normally update GC info prior to the last instruction that uses them,
3713     // these actually live into the helper call.
3714     gcInfo.gcMarkRegSetNpt(RBM_RSI);
3715     gcInfo.gcMarkRegSetNpt(RBM_RDI);
3716 }
3717
3718 // Generate code for a CpBlk node by the means of the VM memcpy helper call
3719 // Preconditions:
3720 // a) The size argument of the CpBlk is not an integer constant
3721 // b) The size argument is a constant but is larger than CPBLK_MOVS_LIMIT bytes.
3722 void CodeGen::genCodeForCpBlk(GenTreeBlk* cpBlkNode)
3723 {
3724 #ifdef _TARGET_AMD64_
3725     // Make sure we got the arguments of the cpblk operation in the right registers
3726     unsigned   blockSize = cpBlkNode->Size();
3727     GenTreePtr dstAddr   = cpBlkNode->Addr();
3728     GenTreePtr source    = cpBlkNode->Data();
3729     GenTreePtr srcAddr   = nullptr;
3730
3731     // Size goes in arg2
3732     if (blockSize != 0)
3733     {
3734         assert(blockSize >= CPBLK_MOVS_LIMIT);
3735         assert((cpBlkNode->gtRsvdRegs & RBM_ARG_2) != 0);
3736     }
3737     else
3738     {
3739         noway_assert(cpBlkNode->gtOper == GT_STORE_DYN_BLK);
3740     }
3741
3742     // Source address goes in arg1
3743     if (source->gtOper == GT_IND)
3744     {
3745         srcAddr = source->gtGetOp1();
3746         assert(srcAddr->isUsedFromReg());
3747     }
3748     else
3749     {
3750         noway_assert(source->IsLocal());
3751         assert((cpBlkNode->gtRsvdRegs & RBM_ARG_1) != 0);
3752         inst_RV_TT(INS_lea, REG_ARG_1, source, 0, EA_BYREF);
3753     }
3754
3755     genConsumeBlockOp(cpBlkNode, REG_ARG_0, REG_ARG_1, REG_ARG_2);
3756
3757     genEmitHelperCall(CORINFO_HELP_MEMCPY, 0, EA_UNKNOWN);
3758 #else  // !_TARGET_AMD64_
3759     noway_assert(false && "Helper call for CpBlk is not needed.");
3760 #endif // !_TARGET_AMD64_
3761 }
3762
3763 // generate code do a switch statement based on a table of ip-relative offsets
3764 void CodeGen::genTableBasedSwitch(GenTree* treeNode)
3765 {
3766     genConsumeOperands(treeNode->AsOp());
3767     regNumber idxReg  = treeNode->gtOp.gtOp1->gtRegNum;
3768     regNumber baseReg = treeNode->gtOp.gtOp2->gtRegNum;
3769
3770     regNumber tmpReg = genRegNumFromMask(treeNode->gtRsvdRegs);
3771
3772     // load the ip-relative offset (which is relative to start of fgFirstBB)
3773     getEmitter()->emitIns_R_ARX(INS_mov, EA_4BYTE, baseReg, baseReg, idxReg, 4, 0);
3774
3775     // add it to the absolute address of fgFirstBB
3776     compiler->fgFirstBB->bbFlags |= BBF_JMP_TARGET;
3777     getEmitter()->emitIns_R_L(INS_lea, EA_PTR_DSP_RELOC, compiler->fgFirstBB, tmpReg);
3778     getEmitter()->emitIns_R_R(INS_add, EA_PTRSIZE, baseReg, tmpReg);
3779     // jmp baseReg
3780     getEmitter()->emitIns_R(INS_i_jmp, emitTypeSize(TYP_I_IMPL), baseReg);
3781 }
3782
3783 // emits the table and an instruction to get the address of the first element
3784 void CodeGen::genJumpTable(GenTree* treeNode)
3785 {
3786     noway_assert(compiler->compCurBB->bbJumpKind == BBJ_SWITCH);
3787     assert(treeNode->OperGet() == GT_JMPTABLE);
3788
3789     unsigned     jumpCount = compiler->compCurBB->bbJumpSwt->bbsCount;
3790     BasicBlock** jumpTable = compiler->compCurBB->bbJumpSwt->bbsDstTab;
3791     unsigned     jmpTabOffs;
3792     unsigned     jmpTabBase;
3793
3794     jmpTabBase = getEmitter()->emitBBTableDataGenBeg(jumpCount, true);
3795
3796     jmpTabOffs = 0;
3797
3798     JITDUMP("\n      J_M%03u_DS%02u LABEL   DWORD\n", Compiler::s_compMethodsCount, jmpTabBase);
3799
3800     for (unsigned i = 0; i < jumpCount; i++)
3801     {
3802         BasicBlock* target = *jumpTable++;
3803         noway_assert(target->bbFlags & BBF_JMP_TARGET);
3804
3805         JITDUMP("            DD      L_M%03u_BB%02u\n", Compiler::s_compMethodsCount, target->bbNum);
3806
3807         getEmitter()->emitDataGenData(i, target);
3808     };
3809
3810     getEmitter()->emitDataGenEnd();
3811
3812     // Access to inline data is 'abstracted' by a special type of static member
3813     // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference
3814     // to constant data, not a real static field.
3815     getEmitter()->emitIns_R_C(INS_lea, emitTypeSize(TYP_I_IMPL), treeNode->gtRegNum,
3816                               compiler->eeFindJitDataOffs(jmpTabBase), 0);
3817     genProduceReg(treeNode);
3818 }
3819
3820 // generate code for the locked operations:
3821 // GT_LOCKADD, GT_XCHG, GT_XADD
3822 void CodeGen::genLockedInstructions(GenTreeOp* treeNode)
3823 {
3824     GenTree*    data      = treeNode->gtOp.gtOp2;
3825     GenTree*    addr      = treeNode->gtOp.gtOp1;
3826     regNumber   targetReg = treeNode->gtRegNum;
3827     regNumber   dataReg   = data->gtRegNum;
3828     regNumber   addrReg   = addr->gtRegNum;
3829     var_types   type      = genActualType(data->TypeGet());
3830     instruction ins;
3831
3832     // The register allocator should have extended the lifetime of the address
3833     // so that it is not used as the target.
3834     noway_assert(addrReg != targetReg);
3835
3836     // If data is a lclVar that's not a last use, we'd better have allocated a register
3837     // for the result (except in the case of GT_LOCKADD which does not produce a register result).
3838     assert(targetReg != REG_NA || treeNode->OperGet() == GT_LOCKADD || !genIsRegCandidateLocal(data) ||
3839            (data->gtFlags & GTF_VAR_DEATH) != 0);
3840
3841     genConsumeOperands(treeNode);
3842     if (targetReg != REG_NA && dataReg != REG_NA && dataReg != targetReg)
3843     {
3844         inst_RV_RV(ins_Copy(type), targetReg, dataReg);
3845         data->gtRegNum = targetReg;
3846
3847         // TODO-XArch-Cleanup: Consider whether it is worth it, for debugging purposes, to restore the
3848         // original gtRegNum on data, after calling emitInsBinary below.
3849     }
3850     switch (treeNode->OperGet())
3851     {
3852         case GT_LOCKADD:
3853             instGen(INS_lock);
3854             ins = INS_add;
3855             break;
3856         case GT_XCHG:
3857             // lock is implied by xchg
3858             ins = INS_xchg;
3859             break;
3860         case GT_XADD:
3861             instGen(INS_lock);
3862             ins = INS_xadd;
3863             break;
3864         default:
3865             unreached();
3866     }
3867
3868     // all of these nodes implicitly do an indirection on op1
3869     // so create a temporary node to feed into the pattern matching
3870     GenTreeIndir i = indirForm(type, addr);
3871     getEmitter()->emitInsBinary(ins, emitTypeSize(type), &i, data);
3872
3873     if (treeNode->gtRegNum != REG_NA)
3874     {
3875         genProduceReg(treeNode);
3876     }
3877 }
3878
3879 // generate code for BoundsCheck nodes
3880 void CodeGen::genRangeCheck(GenTreePtr oper)
3881 {
3882 #ifdef FEATURE_SIMD
3883     noway_assert(oper->OperGet() == GT_ARR_BOUNDS_CHECK || oper->OperGet() == GT_SIMD_CHK);
3884 #else  // !FEATURE_SIMD
3885     noway_assert(oper->OperGet() == GT_ARR_BOUNDS_CHECK);
3886 #endif // !FEATURE_SIMD
3887
3888     GenTreeBoundsChk* bndsChk = oper->AsBoundsChk();
3889
3890     GenTreePtr arrIndex  = bndsChk->gtIndex;
3891     GenTreePtr arrLen    = bndsChk->gtArrLen;
3892     GenTreePtr arrRef    = nullptr;
3893     int        lenOffset = 0;
3894
3895     GenTree *    src1, *src2;
3896     emitJumpKind jmpKind;
3897
3898     genConsumeRegs(arrIndex);
3899     genConsumeRegs(arrLen);
3900
3901     if (arrIndex->isContainedIntOrIImmed())
3902     {
3903         // arrIndex is a contained constant.  In this case
3904         // we will generate one of the following
3905         //      cmp [mem], immed    (if arrLen is a memory op)
3906         //      cmp reg, immed      (if arrLen is in a reg)
3907         //
3908         // That is arrLen cannot be a contained immed.
3909         assert(!arrLen->isContainedIntOrIImmed());
3910
3911         src1    = arrLen;
3912         src2    = arrIndex;
3913         jmpKind = EJ_jbe;
3914     }
3915     else
3916     {
3917         // arrIndex could either be a contained memory op or a reg
3918         // In this case we will generate one of the following
3919         //      cmp  [mem], immed   (if arrLen is a constant)
3920         //      cmp  [mem], reg     (if arrLen is in a reg)
3921         //      cmp  reg, immed     (if arrIndex is in a reg)
3922         //      cmp  reg1, reg2     (if arraIndex is in reg1)
3923         //      cmp  reg, [mem]     (if arrLen is a memory op)
3924         //
3925         // That is only one of arrIndex or arrLen can be a memory op.
3926         assert(!arrIndex->isUsedFromMemory() || !arrLen->isUsedFromMemory());
3927
3928         src1    = arrIndex;
3929         src2    = arrLen;
3930         jmpKind = EJ_jae;
3931     }
3932
3933     var_types bndsChkType = src2->TypeGet();
3934 #if DEBUG
3935     // Bounds checks can only be 32 or 64 bit sized comparisons.
3936     assert(bndsChkType == TYP_INT || bndsChkType == TYP_LONG);
3937
3938     // The type of the bounds check should always wide enough to compare against the index.
3939     assert(emitTypeSize(bndsChkType) >= emitTypeSize(src1->TypeGet()));
3940 #endif // DEBUG
3941
3942     getEmitter()->emitInsBinary(INS_cmp, emitTypeSize(bndsChkType), src1, src2);
3943     genJumpToThrowHlpBlk(jmpKind, bndsChk->gtThrowKind, bndsChk->gtIndRngFailBB);
3944 }
3945
3946 //------------------------------------------------------------------------
3947 // genOffsetOfMDArrayLowerBound: Returns the offset from the Array object to the
3948 //   lower bound for the given dimension.
3949 //
3950 // Arguments:
3951 //    elemType  - the element type of the array
3952 //    rank      - the rank of the array
3953 //    dimension - the dimension for which the lower bound offset will be returned.
3954 //
3955 // Return Value:
3956 //    The offset.
3957
3958 unsigned CodeGen::genOffsetOfMDArrayLowerBound(var_types elemType, unsigned rank, unsigned dimension)
3959 {
3960     // Note that the lower bound and length fields of the Array object are always TYP_INT, even on 64-bit targets.
3961     return compiler->eeGetArrayDataOffset(elemType) + genTypeSize(TYP_INT) * (dimension + rank);
3962 }
3963
3964 //------------------------------------------------------------------------
3965 // genOffsetOfMDArrayLength: Returns the offset from the Array object to the
3966 //   size for the given dimension.
3967 //
3968 // Arguments:
3969 //    elemType  - the element type of the array
3970 //    rank      - the rank of the array
3971 //    dimension - the dimension for which the lower bound offset will be returned.
3972 //
3973 // Return Value:
3974 //    The offset.
3975
3976 unsigned CodeGen::genOffsetOfMDArrayDimensionSize(var_types elemType, unsigned rank, unsigned dimension)
3977 {
3978     // Note that the lower bound and length fields of the Array object are always TYP_INT, even on 64-bit targets.
3979     return compiler->eeGetArrayDataOffset(elemType) + genTypeSize(TYP_INT) * dimension;
3980 }
3981
3982 //------------------------------------------------------------------------
3983 // genCodeForArrIndex: Generates code to bounds check the index for one dimension of an array reference,
3984 //                     producing the effective index by subtracting the lower bound.
3985 //
3986 // Arguments:
3987 //    arrIndex - the node for which we're generating code
3988 //
3989 // Return Value:
3990 //    None.
3991 //
3992
3993 void CodeGen::genCodeForArrIndex(GenTreeArrIndex* arrIndex)
3994 {
3995     GenTreePtr arrObj    = arrIndex->ArrObj();
3996     GenTreePtr indexNode = arrIndex->IndexExpr();
3997
3998     regNumber arrReg   = genConsumeReg(arrObj);
3999     regNumber indexReg = genConsumeReg(indexNode);
4000     regNumber tgtReg   = arrIndex->gtRegNum;
4001
4002     unsigned  dim      = arrIndex->gtCurrDim;
4003     unsigned  rank     = arrIndex->gtArrRank;
4004     var_types elemType = arrIndex->gtArrElemType;
4005
4006     noway_assert(tgtReg != REG_NA);
4007
4008     // Subtract the lower bound for this dimension.
4009     // TODO-XArch-CQ: make this contained if it's an immediate that fits.
4010     if (tgtReg != indexReg)
4011     {
4012         inst_RV_RV(INS_mov, tgtReg, indexReg, indexNode->TypeGet());
4013     }
4014     getEmitter()->emitIns_R_AR(INS_sub, emitActualTypeSize(TYP_INT), tgtReg, arrReg,
4015                                genOffsetOfMDArrayLowerBound(elemType, rank, dim));
4016     getEmitter()->emitIns_R_AR(INS_cmp, emitActualTypeSize(TYP_INT), tgtReg, arrReg,
4017                                genOffsetOfMDArrayDimensionSize(elemType, rank, dim));
4018     genJumpToThrowHlpBlk(EJ_jae, SCK_RNGCHK_FAIL);
4019
4020     genProduceReg(arrIndex);
4021 }
4022
4023 //------------------------------------------------------------------------
4024 // genCodeForArrOffset: Generates code to compute the flattened array offset for
4025 //    one dimension of an array reference:
4026 //        result = (prevDimOffset * dimSize) + effectiveIndex
4027 //    where dimSize is obtained from the arrObj operand
4028 //
4029 // Arguments:
4030 //    arrOffset - the node for which we're generating code
4031 //
4032 // Return Value:
4033 //    None.
4034 //
4035 // Notes:
4036 //    dimSize and effectiveIndex are always non-negative, the former by design,
4037 //    and the latter because it has been normalized to be zero-based.
4038
4039 void CodeGen::genCodeForArrOffset(GenTreeArrOffs* arrOffset)
4040 {
4041     GenTreePtr offsetNode = arrOffset->gtOffset;
4042     GenTreePtr indexNode  = arrOffset->gtIndex;
4043     GenTreePtr arrObj     = arrOffset->gtArrObj;
4044
4045     regNumber tgtReg = arrOffset->gtRegNum;
4046     assert(tgtReg != REG_NA);
4047
4048     unsigned  dim      = arrOffset->gtCurrDim;
4049     unsigned  rank     = arrOffset->gtArrRank;
4050     var_types elemType = arrOffset->gtArrElemType;
4051
4052     // First, consume the operands in the correct order.
4053     regNumber offsetReg = REG_NA;
4054     regNumber tmpReg    = REG_NA;
4055     if (!offsetNode->IsIntegralConst(0))
4056     {
4057         offsetReg = genConsumeReg(offsetNode);
4058
4059         // We will use a temp register for the offset*scale+effectiveIndex computation.
4060         regMaskTP tmpRegMask = arrOffset->gtRsvdRegs;
4061         tmpReg               = genRegNumFromMask(tmpRegMask);
4062     }
4063     else
4064     {
4065         assert(offsetNode->isContained());
4066     }
4067     regNumber indexReg = genConsumeReg(indexNode);
4068     // Although arrReg may not be used in the constant-index case, if we have generated
4069     // the value into a register, we must consume it, otherwise we will fail to end the
4070     // live range of the gc ptr.
4071     // TODO-CQ: Currently arrObj will always have a register allocated to it.
4072     // We could avoid allocating a register for it, which would be of value if the arrObj
4073     // is an on-stack lclVar.
4074     regNumber arrReg = REG_NA;
4075     if (arrObj->gtHasReg())
4076     {
4077         arrReg = genConsumeReg(arrObj);
4078     }
4079
4080     if (!offsetNode->IsIntegralConst(0))
4081     {
4082         assert(tmpReg != REG_NA);
4083         assert(arrReg != REG_NA);
4084
4085         // Evaluate tgtReg = offsetReg*dim_size + indexReg.
4086         // tmpReg is used to load dim_size and the result of the multiplication.
4087         // Note that dim_size will never be negative.
4088
4089         getEmitter()->emitIns_R_AR(INS_mov, emitActualTypeSize(TYP_INT), tmpReg, arrReg,
4090                                    genOffsetOfMDArrayDimensionSize(elemType, rank, dim));
4091         inst_RV_RV(INS_imul, tmpReg, offsetReg);
4092
4093         if (tmpReg == tgtReg)
4094         {
4095             inst_RV_RV(INS_add, tmpReg, indexReg);
4096         }
4097         else
4098         {
4099             if (indexReg != tgtReg)
4100             {
4101                 inst_RV_RV(INS_mov, tgtReg, indexReg, TYP_I_IMPL);
4102             }
4103             inst_RV_RV(INS_add, tgtReg, tmpReg);
4104         }
4105     }
4106     else
4107     {
4108         if (indexReg != tgtReg)
4109         {
4110             inst_RV_RV(INS_mov, tgtReg, indexReg, TYP_INT);
4111         }
4112     }
4113     genProduceReg(arrOffset);
4114 }
4115
4116 // make a temporary indir we can feed to pattern matching routines
4117 // in cases where we don't want to instantiate all the indirs that happen
4118 //
4119 GenTreeIndir CodeGen::indirForm(var_types type, GenTree* base)
4120 {
4121     GenTreeIndir i(GT_IND, type, base, nullptr);
4122     i.gtRegNum = REG_NA;
4123     // has to be nonnull (because contained nodes can't be the last in block)
4124     // but don't want it to be a valid pointer
4125     i.gtNext = (GenTree*)(-1);
4126     return i;
4127 }
4128
4129 // make a temporary int we can feed to pattern matching routines
4130 // in cases where we don't want to instantiate
4131 //
4132 GenTreeIntCon CodeGen::intForm(var_types type, ssize_t value)
4133 {
4134     GenTreeIntCon i(type, value);
4135     i.gtRegNum = REG_NA;
4136     // has to be nonnull (because contained nodes can't be the last in block)
4137     // but don't want it to be a valid pointer
4138     i.gtNext = (GenTree*)(-1);
4139     return i;
4140 }
4141
4142 instruction CodeGen::genGetInsForOper(genTreeOps oper, var_types type)
4143 {
4144     instruction ins;
4145
4146     // Operations on SIMD vectors shouldn't come this path
4147     assert(!varTypeIsSIMD(type));
4148     if (varTypeIsFloating(type))
4149     {
4150         return ins_MathOp(oper, type);
4151     }
4152
4153     switch (oper)
4154     {
4155         case GT_ADD:
4156             ins = INS_add;
4157             break;
4158         case GT_AND:
4159             ins = INS_and;
4160             break;
4161         case GT_LSH:
4162             ins = INS_shl;
4163             break;
4164         case GT_MUL:
4165             ins = INS_imul;
4166             break;
4167         case GT_NEG:
4168             ins = INS_neg;
4169             break;
4170         case GT_NOT:
4171             ins = INS_not;
4172             break;
4173         case GT_OR:
4174             ins = INS_or;
4175             break;
4176         case GT_ROL:
4177             ins = INS_rol;
4178             break;
4179         case GT_ROR:
4180             ins = INS_ror;
4181             break;
4182         case GT_RSH:
4183             ins = INS_sar;
4184             break;
4185         case GT_RSZ:
4186             ins = INS_shr;
4187             break;
4188         case GT_SUB:
4189             ins = INS_sub;
4190             break;
4191         case GT_XOR:
4192             ins = INS_xor;
4193             break;
4194 #if !defined(_TARGET_64BIT_)
4195         case GT_ADD_LO:
4196             ins = INS_add;
4197             break;
4198         case GT_ADD_HI:
4199             ins = INS_adc;
4200             break;
4201         case GT_SUB_LO:
4202             ins = INS_sub;
4203             break;
4204         case GT_SUB_HI:
4205             ins = INS_sbb;
4206             break;
4207         case GT_LSH_HI:
4208             ins = INS_shld;
4209             break;
4210         case GT_RSH_LO:
4211             ins = INS_shrd;
4212             break;
4213 #endif // !defined(_TARGET_64BIT_)
4214         default:
4215             unreached();
4216             break;
4217     }
4218     return ins;
4219 }
4220
4221 //------------------------------------------------------------------------
4222 // genCodeForShift: Generates the code sequence for a GenTree node that
4223 // represents a bit shift or rotate operation (<<, >>, >>>, rol, ror).
4224 //
4225 // Arguments:
4226 //    tree - the bit shift node (that specifies the type of bit shift to perform).
4227 //
4228 // Assumptions:
4229 //    a) All GenTrees are register allocated.
4230 //    b) The shift-by-amount in tree->gtOp.gtOp2 is either a contained constant or
4231 //       it's a register-allocated expression. If it is in a register that is
4232 //       not RCX, it will be moved to RCX (so RCX better not be in use!).
4233 //
4234 void CodeGen::genCodeForShift(GenTreePtr tree)
4235 {
4236     // Only the non-RMW case here.
4237     assert(tree->OperIsShiftOrRotate());
4238     assert(tree->gtOp.gtOp1->isUsedFromReg());
4239     assert(tree->gtRegNum != REG_NA);
4240
4241     genConsumeOperands(tree->AsOp());
4242
4243     var_types   targetType = tree->TypeGet();
4244     instruction ins        = genGetInsForOper(tree->OperGet(), targetType);
4245
4246     GenTreePtr operand    = tree->gtGetOp1();
4247     regNumber  operandReg = operand->gtRegNum;
4248
4249     GenTreePtr shiftBy = tree->gtGetOp2();
4250
4251     if (shiftBy->isContainedIntOrIImmed())
4252     {
4253         // First, move the operand to the destination register and
4254         // later on perform the shift in-place.
4255         // (LSRA will try to avoid this situation through preferencing.)
4256         if (tree->gtRegNum != operandReg)
4257         {
4258             inst_RV_RV(INS_mov, tree->gtRegNum, operandReg, targetType);
4259         }
4260
4261         int shiftByValue = (int)shiftBy->AsIntConCommon()->IconValue();
4262         inst_RV_SH(ins, emitTypeSize(tree), tree->gtRegNum, shiftByValue);
4263     }
4264     else
4265     {
4266         // We must have the number of bits to shift stored in ECX, since we constrained this node to
4267         // sit in ECX. In case this didn't happen, LSRA expects the code generator to move it since it's a single
4268         // register destination requirement.
4269         genCopyRegIfNeeded(shiftBy, REG_RCX);
4270
4271         // The operand to be shifted must not be in ECX
4272         noway_assert(operandReg != REG_RCX);
4273
4274         if (tree->gtRegNum != operandReg)
4275         {
4276             inst_RV_RV(INS_mov, tree->gtRegNum, operandReg, targetType);
4277         }
4278         inst_RV_CL(ins, tree->gtRegNum, targetType);
4279     }
4280
4281     genProduceReg(tree);
4282 }
4283
4284 #ifdef _TARGET_X86_
4285 //------------------------------------------------------------------------
4286 // genCodeForShiftLong: Generates the code sequence for a GenTree node that
4287 // represents a three operand bit shift or rotate operation (<<Hi, >>Lo).
4288 //
4289 // Arguments:
4290 //    tree - the bit shift node (that specifies the type of bit shift to perform).
4291 //
4292 // Assumptions:
4293 //    a) All GenTrees are register allocated.
4294 //    b) The shift-by-amount in tree->gtOp.gtOp2 is a contained constant
4295 //
4296 void CodeGen::genCodeForShiftLong(GenTreePtr tree)
4297 {
4298     // Only the non-RMW case here.
4299     genTreeOps oper = tree->OperGet();
4300     assert(oper == GT_LSH_HI || oper == GT_RSH_LO);
4301
4302     GenTree* operand = tree->gtOp.gtOp1;
4303     assert(operand->OperGet() == GT_LONG);
4304     assert(operand->gtOp.gtOp1->isUsedFromReg());
4305     assert(operand->gtOp.gtOp2->isUsedFromReg());
4306
4307     GenTree* operandLo = operand->gtGetOp1();
4308     GenTree* operandHi = operand->gtGetOp2();
4309
4310     regNumber regLo = operandLo->gtRegNum;
4311     regNumber regHi = operandHi->gtRegNum;
4312
4313     genConsumeOperands(tree->AsOp());
4314
4315     var_types   targetType = tree->TypeGet();
4316     instruction ins        = genGetInsForOper(oper, targetType);
4317
4318     GenTreePtr shiftBy = tree->gtGetOp2();
4319
4320     assert(shiftBy->isContainedIntOrIImmed());
4321
4322     unsigned int count = shiftBy->AsIntConCommon()->IconValue();
4323
4324     regNumber regResult = (oper == GT_LSH_HI) ? regHi : regLo;
4325
4326     if (regResult != tree->gtRegNum)
4327     {
4328         inst_RV_RV(INS_mov, tree->gtRegNum, regResult, targetType);
4329     }
4330
4331     if (oper == GT_LSH_HI)
4332     {
4333         inst_RV_RV_IV(ins, emitTypeSize(targetType), tree->gtRegNum, regLo, count);
4334     }
4335     else
4336     {
4337         assert(oper == GT_RSH_LO);
4338         inst_RV_RV_IV(ins, emitTypeSize(targetType), tree->gtRegNum, regHi, count);
4339     }
4340
4341     genProduceReg(tree);
4342 }
4343 #endif
4344
4345 //------------------------------------------------------------------------
4346 // genCodeForShiftRMW: Generates the code sequence for a GT_STOREIND GenTree node that
4347 // represents a RMW bit shift or rotate operation (<<, >>, >>>, rol, ror), for example:
4348 //      GT_STOREIND( AddressTree, GT_SHL( Ind ( AddressTree ), Operand ) )
4349 //
4350 // Arguments:
4351 //    storeIndNode: the GT_STOREIND node.
4352 //
4353 void CodeGen::genCodeForShiftRMW(GenTreeStoreInd* storeInd)
4354 {
4355     GenTree* data = storeInd->Data();
4356     GenTree* addr = storeInd->Addr();
4357
4358     assert(data->OperIsShiftOrRotate());
4359
4360     // This function only handles the RMW case.
4361     assert(data->gtOp.gtOp1->isUsedFromMemory());
4362     assert(data->gtOp.gtOp1->isIndir());
4363     assert(Lowering::IndirsAreEquivalent(data->gtOp.gtOp1, storeInd));
4364     assert(data->gtRegNum == REG_NA);
4365
4366     var_types   targetType = data->TypeGet();
4367     genTreeOps  oper       = data->OperGet();
4368     instruction ins        = genGetInsForOper(oper, targetType);
4369     emitAttr    attr       = EA_ATTR(genTypeSize(targetType));
4370
4371     GenTree* shiftBy = data->gtOp.gtOp2;
4372     if (shiftBy->isContainedIntOrIImmed())
4373     {
4374         int shiftByValue = (int)shiftBy->AsIntConCommon()->IconValue();
4375         ins              = genMapShiftInsToShiftByConstantIns(ins, shiftByValue);
4376         if (shiftByValue == 1)
4377         {
4378             // There is no source in this case, as the shift by count is embedded in the instruction opcode itself.
4379             getEmitter()->emitInsRMW(ins, attr, storeInd);
4380         }
4381         else
4382         {
4383             getEmitter()->emitInsRMW(ins, attr, storeInd, shiftBy);
4384         }
4385     }
4386     else
4387     {
4388         // We must have the number of bits to shift stored in ECX, since we constrained this node to
4389         // sit in ECX. In case this didn't happen, LSRA expects the code generator to move it since it's a single
4390         // register destination requirement.
4391         regNumber shiftReg = shiftBy->gtRegNum;
4392         genCopyRegIfNeeded(shiftBy, REG_RCX);
4393
4394         // The shiftBy operand is implicit, so call the unary version of emitInsRMW.
4395         getEmitter()->emitInsRMW(ins, attr, storeInd);
4396     }
4397 }
4398
4399 void CodeGen::genRegCopy(GenTree* treeNode)
4400 {
4401     assert(treeNode->OperGet() == GT_COPY);
4402     GenTree* op1 = treeNode->gtOp.gtOp1;
4403
4404     if (op1->IsMultiRegCall())
4405     {
4406         genConsumeReg(op1);
4407
4408         GenTreeCopyOrReload* copyTree    = treeNode->AsCopyOrReload();
4409         GenTreeCall*         call        = op1->AsCall();
4410         ReturnTypeDesc*      retTypeDesc = call->GetReturnTypeDesc();
4411         unsigned             regCount    = retTypeDesc->GetReturnRegCount();
4412
4413         for (unsigned i = 0; i < regCount; ++i)
4414         {
4415             var_types type    = retTypeDesc->GetReturnRegType(i);
4416             regNumber fromReg = call->GetRegNumByIdx(i);
4417             regNumber toReg   = copyTree->GetRegNumByIdx(i);
4418
4419             // A Multi-reg GT_COPY node will have valid reg only for those
4420             // positions that corresponding result reg of call node needs
4421             // to be copied.
4422             if (toReg != REG_NA)
4423             {
4424                 assert(toReg != fromReg);
4425                 inst_RV_RV(ins_Copy(type), toReg, fromReg, type);
4426             }
4427         }
4428     }
4429     else
4430     {
4431         var_types targetType = treeNode->TypeGet();
4432         regNumber targetReg  = treeNode->gtRegNum;
4433         assert(targetReg != REG_NA);
4434
4435         // Check whether this node and the node from which we're copying the value have
4436         // different register types. This can happen if (currently iff) we have a SIMD
4437         // vector type that fits in an integer register, in which case it is passed as
4438         // an argument, or returned from a call, in an integer register and must be
4439         // copied if it's in an xmm register.
4440
4441         bool srcFltReg = (varTypeIsFloating(op1) || varTypeIsSIMD(op1));
4442         bool tgtFltReg = (varTypeIsFloating(treeNode) || varTypeIsSIMD(treeNode));
4443         if (srcFltReg != tgtFltReg)
4444         {
4445             instruction ins;
4446             regNumber   fpReg;
4447             regNumber   intReg;
4448             if (tgtFltReg)
4449             {
4450                 ins    = ins_CopyIntToFloat(op1->TypeGet(), treeNode->TypeGet());
4451                 fpReg  = targetReg;
4452                 intReg = op1->gtRegNum;
4453             }
4454             else
4455             {
4456                 ins    = ins_CopyFloatToInt(op1->TypeGet(), treeNode->TypeGet());
4457                 intReg = targetReg;
4458                 fpReg  = op1->gtRegNum;
4459             }
4460             inst_RV_RV(ins, fpReg, intReg, targetType);
4461         }
4462         else
4463         {
4464             inst_RV_RV(ins_Copy(targetType), targetReg, genConsumeReg(op1), targetType);
4465         }
4466
4467         if (op1->IsLocal())
4468         {
4469             // The lclVar will never be a def.
4470             // If it is a last use, the lclVar will be killed by genConsumeReg(), as usual, and genProduceReg will
4471             // appropriately set the gcInfo for the copied value.
4472             // If not, there are two cases we need to handle:
4473             // - If this is a TEMPORARY copy (indicated by the GTF_VAR_DEATH flag) the variable
4474             //   will remain live in its original register.
4475             //   genProduceReg() will appropriately set the gcInfo for the copied value,
4476             //   and genConsumeReg will reset it.
4477             // - Otherwise, we need to update register info for the lclVar.
4478
4479             GenTreeLclVarCommon* lcl = op1->AsLclVarCommon();
4480             assert((lcl->gtFlags & GTF_VAR_DEF) == 0);
4481
4482             if ((lcl->gtFlags & GTF_VAR_DEATH) == 0 && (treeNode->gtFlags & GTF_VAR_DEATH) == 0)
4483             {
4484                 LclVarDsc* varDsc = &compiler->lvaTable[lcl->gtLclNum];
4485
4486                 // If we didn't just spill it (in genConsumeReg, above), then update the register info
4487                 if (varDsc->lvRegNum != REG_STK)
4488                 {
4489                     // The old location is dying
4490                     genUpdateRegLife(varDsc, /*isBorn*/ false, /*isDying*/ true DEBUGARG(op1));
4491
4492                     gcInfo.gcMarkRegSetNpt(genRegMask(op1->gtRegNum));
4493
4494                     genUpdateVarReg(varDsc, treeNode);
4495
4496                     // The new location is going live
4497                     genUpdateRegLife(varDsc, /*isBorn*/ true, /*isDying*/ false DEBUGARG(treeNode));
4498                 }
4499             }
4500         }
4501     }
4502
4503     genProduceReg(treeNode);
4504 }
4505
4506 //------------------------------------------------------------------------
4507 // genStoreInd: Generate code for a GT_STOREIND node.
4508 //
4509 // Arguments:
4510 //    treeNode - The GT_STOREIND node for which to generate code.
4511 //
4512 // Return Value:
4513 //    none
4514
4515 void CodeGen::genStoreInd(GenTreePtr node)
4516 {
4517     assert(node->OperGet() == GT_STOREIND);
4518
4519 #ifdef FEATURE_SIMD
4520     // Storing Vector3 of size 12 bytes through indirection
4521     if (node->TypeGet() == TYP_SIMD12)
4522     {
4523         genStoreIndTypeSIMD12(node);
4524         return;
4525     }
4526 #endif // FEATURE_SIMD
4527
4528     GenTreeStoreInd* storeInd   = node->AsStoreInd();
4529     GenTree*         data       = storeInd->Data();
4530     GenTree*         addr       = storeInd->Addr();
4531     var_types        targetType = storeInd->TypeGet();
4532
4533     assert(!varTypeIsFloating(targetType) || (targetType == data->TypeGet()));
4534
4535     GCInfo::WriteBarrierForm writeBarrierForm = gcInfo.gcIsWriteBarrierCandidate(storeInd, data);
4536     if (writeBarrierForm != GCInfo::WBF_NoBarrier)
4537     {
4538         // data and addr must be in registers.
4539         // Consume both registers so that any copies of interfering registers are taken care of.
4540         genConsumeOperands(storeInd->AsOp());
4541
4542         if (genEmitOptimizedGCWriteBarrier(writeBarrierForm, addr, data))
4543         {
4544             return;
4545         }
4546
4547         // At this point, we should not have any interference.
4548         // That is, 'data' must not be in REG_ARG_0, as that is where 'addr' must go.
4549         noway_assert(data->gtRegNum != REG_ARG_0);
4550
4551         // addr goes in REG_ARG_0
4552         genCopyRegIfNeeded(addr, REG_ARG_0);
4553
4554         // data goes in REG_ARG_1
4555         genCopyRegIfNeeded(data, REG_ARG_1);
4556
4557         genGCWriteBarrier(storeInd, writeBarrierForm);
4558     }
4559     else
4560     {
4561         bool     reverseOps    = ((storeInd->gtFlags & GTF_REVERSE_OPS) != 0);
4562         bool     dataIsUnary   = false;
4563         bool     isRMWMemoryOp = storeInd->IsRMWMemoryOp();
4564         GenTree* rmwSrc        = nullptr;
4565
4566         // We must consume the operands in the proper execution order, so that liveness is
4567         // updated appropriately.
4568         if (!reverseOps)
4569         {
4570             genConsumeAddress(addr);
4571         }
4572
4573         // If storeInd represents a RMW memory op then its data is a non-leaf node marked as contained
4574         // and non-indir operand of data is the source of RMW memory op.
4575         if (isRMWMemoryOp)
4576         {
4577             assert(data->isContained() && !data->OperIsLeaf());
4578
4579             GenTreePtr rmwDst = nullptr;
4580
4581             dataIsUnary = (GenTree::OperIsUnary(data->OperGet()) != 0);
4582             if (!dataIsUnary)
4583             {
4584                 if (storeInd->IsRMWDstOp1())
4585                 {
4586                     rmwDst = data->gtGetOp1();
4587                     rmwSrc = data->gtGetOp2();
4588                 }
4589                 else
4590                 {
4591                     assert(storeInd->IsRMWDstOp2());
4592                     rmwDst = data->gtGetOp2();
4593                     rmwSrc = data->gtGetOp1();
4594                 }
4595
4596                 genConsumeRegs(rmwSrc);
4597             }
4598             else
4599             {
4600                 // *(p) = oper *(p): Here addr = p, rmwsrc=rmwDst = *(p) i.e. GT_IND(p)
4601                 // For unary RMW ops, src and dst of RMW memory op is the same.  Lower
4602                 // clears operand counts on rmwSrc and we don't need to perform a
4603                 // genConsumeReg() on it.
4604                 assert(storeInd->IsRMWDstOp1());
4605                 rmwSrc = data->gtGetOp1();
4606                 rmwDst = data->gtGetOp1();
4607                 assert(rmwSrc->isUsedFromMemory());
4608             }
4609
4610             assert(rmwSrc != nullptr);
4611             assert(rmwDst != nullptr);
4612             assert(Lowering::IndirsAreEquivalent(rmwDst, storeInd));
4613         }
4614         else
4615         {
4616             genConsumeRegs(data);
4617         }
4618
4619         if (reverseOps)
4620         {
4621             genConsumeAddress(addr);
4622         }
4623
4624         if (isRMWMemoryOp)
4625         {
4626             if (dataIsUnary)
4627             {
4628                 // generate code for unary RMW memory ops like neg/not
4629                 getEmitter()->emitInsRMW(genGetInsForOper(data->OperGet(), data->TypeGet()), emitTypeSize(storeInd),
4630                                          storeInd);
4631             }
4632             else
4633             {
4634                 if (data->OperIsShiftOrRotate())
4635                 {
4636                     // Generate code for shift RMW memory ops.
4637                     // The data address needs to be op1 (it must be [addr] = [addr] <shift> <amount>, not [addr] =
4638                     // <amount> <shift> [addr]).
4639                     assert(storeInd->IsRMWDstOp1());
4640                     assert(rmwSrc == data->gtGetOp2());
4641                     genCodeForShiftRMW(storeInd);
4642                 }
4643                 else if (data->OperGet() == GT_ADD && (rmwSrc->IsIntegralConst(1) || rmwSrc->IsIntegralConst(-1)))
4644                 {
4645                     // Generate "inc/dec [mem]" instead of "add/sub [mem], 1".
4646                     //
4647                     // Notes:
4648                     //  1) Global morph transforms GT_SUB(x, +/-1) into GT_ADD(x, -/+1).
4649                     //  2) TODO-AMD64: Debugger routine NativeWalker::Decode() runs into
4650                     //     an assert while decoding ModR/M byte of "inc dword ptr [rax]".
4651                     //     It is not clear whether Decode() can handle all possible
4652                     //     addr modes with inc/dec.  For this reason, inc/dec [mem]
4653                     //     is not generated while generating debuggable code.  Update
4654                     //     the above if condition once Decode() routine is fixed.
4655                     assert(rmwSrc->isContainedIntOrIImmed());
4656                     instruction ins = rmwSrc->IsIntegralConst(1) ? INS_inc : INS_dec;
4657                     getEmitter()->emitInsRMW(ins, emitTypeSize(storeInd), storeInd);
4658                 }
4659                 else
4660                 {
4661                     // generate code for remaining binary RMW memory ops like add/sub/and/or/xor
4662                     getEmitter()->emitInsRMW(genGetInsForOper(data->OperGet(), data->TypeGet()), emitTypeSize(storeInd),
4663                                              storeInd, rmwSrc);
4664                 }
4665             }
4666         }
4667         else
4668         {
4669             getEmitter()->emitInsMov(ins_Store(data->TypeGet()), emitTypeSize(storeInd), storeInd);
4670         }
4671     }
4672 }
4673
4674 //------------------------------------------------------------------------
4675 // genEmitOptimizedGCWriteBarrier: Generate write barrier store using the optimized
4676 // helper functions.
4677 //
4678 // Arguments:
4679 //    writeBarrierForm - the write barrier form to use
4680 //    addr - the address at which to do the store
4681 //    data - the data to store
4682 //
4683 // Return Value:
4684 //    true if an optimized write barrier form was used, false if not. If this
4685 //    function returns false, the caller must emit a "standard" write barrier.
4686
4687 bool CodeGen::genEmitOptimizedGCWriteBarrier(GCInfo::WriteBarrierForm writeBarrierForm, GenTree* addr, GenTree* data)
4688 {
4689     assert(writeBarrierForm != GCInfo::WBF_NoBarrier);
4690
4691 #if defined(_TARGET_X86_) && NOGC_WRITE_BARRIERS
4692     bool useOptimizedWriteBarriers = true;
4693
4694 #ifdef DEBUG
4695     useOptimizedWriteBarriers =
4696         (writeBarrierForm != GCInfo::WBF_NoBarrier_CheckNotHeapInDebug); // This one is always a call to a C++ method.
4697 #endif
4698
4699     if (!useOptimizedWriteBarriers)
4700     {
4701         return false;
4702     }
4703
4704     const static int regToHelper[2][8] = {
4705         // If the target is known to be in managed memory
4706         {
4707             CORINFO_HELP_ASSIGN_REF_EAX, CORINFO_HELP_ASSIGN_REF_ECX, -1, CORINFO_HELP_ASSIGN_REF_EBX, -1,
4708             CORINFO_HELP_ASSIGN_REF_EBP, CORINFO_HELP_ASSIGN_REF_ESI, CORINFO_HELP_ASSIGN_REF_EDI,
4709         },
4710
4711         // Don't know if the target is in managed memory
4712         {
4713             CORINFO_HELP_CHECKED_ASSIGN_REF_EAX, CORINFO_HELP_CHECKED_ASSIGN_REF_ECX, -1,
4714             CORINFO_HELP_CHECKED_ASSIGN_REF_EBX, -1, CORINFO_HELP_CHECKED_ASSIGN_REF_EBP,
4715             CORINFO_HELP_CHECKED_ASSIGN_REF_ESI, CORINFO_HELP_CHECKED_ASSIGN_REF_EDI,
4716         },
4717     };
4718
4719     noway_assert(regToHelper[0][REG_EAX] == CORINFO_HELP_ASSIGN_REF_EAX);
4720     noway_assert(regToHelper[0][REG_ECX] == CORINFO_HELP_ASSIGN_REF_ECX);
4721     noway_assert(regToHelper[0][REG_EBX] == CORINFO_HELP_ASSIGN_REF_EBX);
4722     noway_assert(regToHelper[0][REG_ESP] == -1);
4723     noway_assert(regToHelper[0][REG_EBP] == CORINFO_HELP_ASSIGN_REF_EBP);
4724     noway_assert(regToHelper[0][REG_ESI] == CORINFO_HELP_ASSIGN_REF_ESI);
4725     noway_assert(regToHelper[0][REG_EDI] == CORINFO_HELP_ASSIGN_REF_EDI);
4726
4727     noway_assert(regToHelper[1][REG_EAX] == CORINFO_HELP_CHECKED_ASSIGN_REF_EAX);
4728     noway_assert(regToHelper[1][REG_ECX] == CORINFO_HELP_CHECKED_ASSIGN_REF_ECX);
4729     noway_assert(regToHelper[1][REG_EBX] == CORINFO_HELP_CHECKED_ASSIGN_REF_EBX);
4730     noway_assert(regToHelper[1][REG_ESP] == -1);
4731     noway_assert(regToHelper[1][REG_EBP] == CORINFO_HELP_CHECKED_ASSIGN_REF_EBP);
4732     noway_assert(regToHelper[1][REG_ESI] == CORINFO_HELP_CHECKED_ASSIGN_REF_ESI);
4733     noway_assert(regToHelper[1][REG_EDI] == CORINFO_HELP_CHECKED_ASSIGN_REF_EDI);
4734
4735     regNumber reg = data->gtRegNum;
4736     noway_assert((reg != REG_ESP) && (reg != REG_WRITE_BARRIER));
4737
4738     // Generate the following code:
4739     //            lea     edx, addr
4740     //            call    write_barrier_helper_reg
4741
4742     // addr goes in REG_ARG_0
4743     genCopyRegIfNeeded(addr, REG_WRITE_BARRIER);
4744
4745     unsigned tgtAnywhere = 0;
4746     if (writeBarrierForm != GCInfo::WBF_BarrierUnchecked)
4747     {
4748         tgtAnywhere = 1;
4749     }
4750
4751     // We might want to call a modified version of genGCWriteBarrier() to get the benefit of
4752     // the FEATURE_COUNT_GC_WRITE_BARRIERS code there, but that code doesn't look like it works
4753     // with rationalized RyuJIT IR. So, for now, just emit the helper call directly here.
4754
4755     genEmitHelperCall(regToHelper[tgtAnywhere][reg],
4756                       0,           // argSize
4757                       EA_PTRSIZE); // retSize
4758
4759     return true;
4760 #else  // !defined(_TARGET_X86_) || !NOGC_WRITE_BARRIERS
4761     return false;
4762 #endif // !defined(_TARGET_X86_) || !NOGC_WRITE_BARRIERS
4763 }
4764
4765 // Produce code for a GT_CALL node
4766 void CodeGen::genCallInstruction(GenTreeCall* call)
4767 {
4768     genAlignStackBeforeCall(call);
4769
4770     gtCallTypes callType = (gtCallTypes)call->gtCallType;
4771
4772     IL_OFFSETX ilOffset = BAD_IL_OFFSET;
4773
4774     // all virtuals should have been expanded into a control expression
4775     assert(!call->IsVirtual() || call->gtControlExpr || call->gtCallAddr);
4776
4777     // Insert a GS check if necessary
4778     if (call->IsTailCallViaHelper())
4779     {
4780         if (compiler->getNeedsGSSecurityCookie())
4781         {
4782 #if FEATURE_FIXED_OUT_ARGS
4783             // If either of the conditions below is true, we will need a temporary register in order to perform the GS
4784             // cookie check. When FEATURE_FIXED_OUT_ARGS is disabled, we save and restore the temporary register using
4785             // push/pop. When FEATURE_FIXED_OUT_ARGS is enabled, however, we need an alternative solution. For now,
4786             // though, the tail prefix is ignored on all platforms that use fixed out args, so we should never hit this
4787             // case.
4788             assert(compiler->gsGlobalSecurityCookieAddr == nullptr);
4789             assert((int)compiler->gsGlobalSecurityCookieVal == (ssize_t)compiler->gsGlobalSecurityCookieVal);
4790 #endif
4791             genEmitGSCookieCheck(true);
4792         }
4793     }
4794
4795     // Consume all the arg regs
4796     for (GenTreePtr list = call->gtCallLateArgs; list; list = list->MoveNext())
4797     {
4798         assert(list->OperIsList());
4799
4800         GenTreePtr argNode = list->Current();
4801
4802         fgArgTabEntryPtr curArgTabEntry = compiler->gtArgEntryByNode(call, argNode->gtSkipReloadOrCopy());
4803         assert(curArgTabEntry);
4804
4805         if (curArgTabEntry->regNum == REG_STK)
4806         {
4807             continue;
4808         }
4809
4810 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
4811         // Deal with multi register passed struct args.
4812         if (argNode->OperGet() == GT_FIELD_LIST)
4813         {
4814             GenTreeFieldList* fieldListPtr = argNode->AsFieldList();
4815             unsigned          iterationNum = 0;
4816             for (; fieldListPtr != nullptr; fieldListPtr = fieldListPtr->Rest(), iterationNum++)
4817             {
4818                 GenTreePtr putArgRegNode = fieldListPtr->gtOp.gtOp1;
4819                 assert(putArgRegNode->gtOper == GT_PUTARG_REG);
4820                 regNumber argReg = REG_NA;
4821
4822                 if (iterationNum == 0)
4823                 {
4824                     argReg = curArgTabEntry->regNum;
4825                 }
4826                 else
4827                 {
4828                     assert(iterationNum == 1);
4829                     argReg = curArgTabEntry->otherRegNum;
4830                 }
4831
4832                 genConsumeReg(putArgRegNode);
4833
4834                 // Validate the putArgRegNode has the right type.
4835                 assert(putArgRegNode->TypeGet() ==
4836                        compiler->GetTypeFromClassificationAndSizes(curArgTabEntry->structDesc
4837                                                                        .eightByteClassifications[iterationNum],
4838                                                                    curArgTabEntry->structDesc
4839                                                                        .eightByteSizes[iterationNum]));
4840                 if (putArgRegNode->gtRegNum != argReg)
4841                 {
4842                     inst_RV_RV(ins_Move_Extend(putArgRegNode->TypeGet(), putArgRegNode->InReg()), argReg,
4843                                putArgRegNode->gtRegNum);
4844                 }
4845             }
4846         }
4847         else
4848 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
4849         {
4850             regNumber argReg = curArgTabEntry->regNum;
4851             genConsumeReg(argNode);
4852             if (argNode->gtRegNum != argReg)
4853             {
4854                 inst_RV_RV(ins_Move_Extend(argNode->TypeGet(), argNode->InReg()), argReg, argNode->gtRegNum);
4855             }
4856         }
4857
4858 #if FEATURE_VARARG
4859         // In the case of a varargs call,
4860         // the ABI dictates that if we have floating point args,
4861         // we must pass the enregistered arguments in both the
4862         // integer and floating point registers so, let's do that.
4863         if (call->IsVarargs() && varTypeIsFloating(argNode))
4864         {
4865             regNumber   targetReg = compiler->getCallArgIntRegister(argNode->gtRegNum);
4866             instruction ins       = ins_CopyFloatToInt(argNode->TypeGet(), TYP_LONG);
4867             inst_RV_RV(ins, argNode->gtRegNum, targetReg);
4868         }
4869 #endif // FEATURE_VARARG
4870     }
4871
4872 #if defined(_TARGET_X86_) || defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
4873     // The call will pop its arguments.
4874     // for each putarg_stk:
4875     ssize_t    stackArgBytes = 0;
4876     GenTreePtr args          = call->gtCallArgs;
4877     while (args)
4878     {
4879         GenTreePtr arg = args->gtOp.gtOp1;
4880         if (arg->OperGet() != GT_ARGPLACE && !(arg->gtFlags & GTF_LATE_ARG))
4881         {
4882 #if defined(_TARGET_X86_)
4883             if ((arg->OperGet() == GT_PUTARG_STK) && (arg->gtGetOp1()->OperGet() == GT_FIELD_LIST))
4884             {
4885                 fgArgTabEntryPtr curArgTabEntry = compiler->gtArgEntryByNode(call, arg);
4886                 assert(curArgTabEntry);
4887                 stackArgBytes += curArgTabEntry->numSlots * TARGET_POINTER_SIZE;
4888             }
4889             else
4890 #endif // defined(_TARGET_X86_)
4891
4892 #ifdef FEATURE_PUT_STRUCT_ARG_STK
4893                 if (genActualType(arg->TypeGet()) == TYP_STRUCT)
4894             {
4895                 assert(arg->OperGet() == GT_PUTARG_STK);
4896
4897                 GenTreeObj* obj      = arg->gtGetOp1()->AsObj();
4898                 unsigned    argBytes = (unsigned)roundUp(obj->gtBlkSize, TARGET_POINTER_SIZE);
4899 #ifdef DEBUG
4900                 fgArgTabEntryPtr curArgTabEntry = compiler->gtArgEntryByNode(call, arg);
4901                 assert((curArgTabEntry->numSlots * TARGET_POINTER_SIZE) == argBytes);
4902 #endif // DEBUG
4903                 stackArgBytes += argBytes;
4904             }
4905             else
4906 #endif // FEATURE_PUT_STRUCT_ARG_STK
4907
4908             {
4909                 stackArgBytes += genTypeSize(genActualType(arg->TypeGet()));
4910             }
4911         }
4912         args = args->gtOp.gtOp2;
4913     }
4914 #endif // defined(_TARGET_X86_) || defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
4915
4916     // Insert a null check on "this" pointer if asked.
4917     if (call->NeedsNullCheck())
4918     {
4919         const regNumber regThis = genGetThisArgReg(call);
4920         getEmitter()->emitIns_AR_R(INS_cmp, EA_4BYTE, regThis, regThis, 0);
4921     }
4922
4923     // Either gtControlExpr != null or gtCallAddr != null or it is a direct non-virtual call to a user or helper method.
4924     CORINFO_METHOD_HANDLE methHnd;
4925     GenTree*              target = call->gtControlExpr;
4926     if (callType == CT_INDIRECT)
4927     {
4928         assert(target == nullptr);
4929         target  = call->gtCallAddr;
4930         methHnd = nullptr;
4931     }
4932     else
4933     {
4934         methHnd = call->gtCallMethHnd;
4935     }
4936
4937     CORINFO_SIG_INFO* sigInfo = nullptr;
4938 #ifdef DEBUG
4939     // Pass the call signature information down into the emitter so the emitter can associate
4940     // native call sites with the signatures they were generated from.
4941     if (callType != CT_HELPER)
4942     {
4943         sigInfo = call->callSig;
4944     }
4945 #endif // DEBUG
4946
4947     // If fast tail call, then we are done.  In this case we setup the args (both reg args
4948     // and stack args in incoming arg area) and call target in rax.  Epilog sequence would
4949     // generate "jmp rax".
4950     if (call->IsFastTailCall())
4951     {
4952         // Don't support fast tail calling JIT helpers
4953         assert(callType != CT_HELPER);
4954
4955         // Fast tail calls materialize call target either in gtControlExpr or in gtCallAddr.
4956         assert(target != nullptr);
4957
4958         genConsumeReg(target);
4959         genCopyRegIfNeeded(target, REG_RAX);
4960         return;
4961     }
4962
4963     // For a pinvoke to unmanged code we emit a label to clear
4964     // the GC pointer state before the callsite.
4965     // We can't utilize the typical lazy killing of GC pointers
4966     // at (or inside) the callsite.
4967     if (call->IsUnmanaged())
4968     {
4969         genDefineTempLabel(genCreateTempLabel());
4970     }
4971
4972     // Determine return value size(s).
4973     ReturnTypeDesc* retTypeDesc   = call->GetReturnTypeDesc();
4974     emitAttr        retSize       = EA_PTRSIZE;
4975     emitAttr        secondRetSize = EA_UNKNOWN;
4976
4977     if (call->HasMultiRegRetVal())
4978     {
4979         retSize       = emitTypeSize(retTypeDesc->GetReturnRegType(0));
4980         secondRetSize = emitTypeSize(retTypeDesc->GetReturnRegType(1));
4981     }
4982     else
4983     {
4984         assert(!varTypeIsStruct(call));
4985
4986         if (call->gtType == TYP_REF || call->gtType == TYP_ARRAY)
4987         {
4988             retSize = EA_GCREF;
4989         }
4990         else if (call->gtType == TYP_BYREF)
4991         {
4992             retSize = EA_BYREF;
4993         }
4994     }
4995
4996     bool            fPossibleSyncHelperCall = false;
4997     CorInfoHelpFunc helperNum               = CORINFO_HELP_UNDEF;
4998
4999     // We need to propagate the IL offset information to the call instruction, so we can emit
5000     // an IL to native mapping record for the call, to support managed return value debugging.
5001     // We don't want tail call helper calls that were converted from normal calls to get a record,
5002     // so we skip this hash table lookup logic in that case.
5003     if (compiler->opts.compDbgInfo && compiler->genCallSite2ILOffsetMap != nullptr && !call->IsTailCall())
5004     {
5005         (void)compiler->genCallSite2ILOffsetMap->Lookup(call, &ilOffset);
5006     }
5007
5008 #if defined(_TARGET_X86_)
5009     bool fCallerPop = (call->gtFlags & GTF_CALL_POP_ARGS) != 0;
5010
5011 #ifdef UNIX_X86_ABI
5012     {
5013         CorInfoCallConv callConv = CORINFO_CALLCONV_DEFAULT;
5014
5015         if ((callType != CT_HELPER) && call->callSig)
5016         {
5017             callConv = call->callSig->callConv;
5018         }
5019
5020         fCallerPop |= IsCallerPop(callConv);
5021     }
5022 #endif // UNIX_X86_ABI
5023
5024     // If the callee pops the arguments, we pass a positive value as the argSize, and the emitter will
5025     // adjust its stack level accordingly.
5026     // If the caller needs to explicitly pop its arguments, we must pass a negative value, and then do the
5027     // pop when we're done.
5028     ssize_t argSizeForEmitter = stackArgBytes;
5029     if (fCallerPop)
5030     {
5031         argSizeForEmitter = -stackArgBytes;
5032     }
5033 #endif // defined(_TARGET_X86_)
5034
5035 #ifdef FEATURE_AVX_SUPPORT
5036     // When it's a PInvoke call and the call type is USER function, we issue VZEROUPPER here
5037     // if the function contains 256bit AVX instructions, this is to avoid AVX-256 to Legacy SSE
5038     // transition penalty, assuming the user function contains legacy SSE instruction.
5039     // To limit code size increase impact: we only issue VZEROUPPER before PInvoke call, not issue
5040     // VZEROUPPER after PInvoke call because transition penalty from legacy SSE to AVX only happens
5041     // when there's preceding 256-bit AVX to legacy SSE transition penalty.
5042     if (call->IsPInvoke() && (call->gtCallType == CT_USER_FUNC) && getEmitter()->Contains256bitAVX())
5043     {
5044         assert(compiler->getSIMDInstructionSet() == InstructionSet_AVX);
5045         instGen(INS_vzeroupper);
5046     }
5047 #endif
5048
5049     if (target != nullptr)
5050     {
5051 #ifdef _TARGET_X86_
5052         if (call->IsVirtualStub() && (call->gtCallType == CT_INDIRECT))
5053         {
5054             // On x86, we need to generate a very specific pattern for indirect VSD calls:
5055             //
5056             //    3-byte nop
5057             //    call dword ptr [eax]
5058             //
5059             // Where EAX is also used as an argument to the stub dispatch helper. Make
5060             // sure that the call target address is computed into EAX in this case.
5061
5062             assert(REG_VIRTUAL_STUB_PARAM == REG_VIRTUAL_STUB_TARGET);
5063
5064             assert(target->isContainedIndir());
5065             assert(target->OperGet() == GT_IND);
5066
5067             GenTree* addr = target->AsIndir()->Addr();
5068             assert(addr->isUsedFromReg());
5069
5070             genConsumeReg(addr);
5071             genCopyRegIfNeeded(addr, REG_VIRTUAL_STUB_TARGET);
5072
5073             getEmitter()->emitIns_Nop(3);
5074
5075             // clang-format off
5076             getEmitter()->emitIns_Call(emitter::EmitCallType(emitter::EC_INDIR_ARD),
5077                                        methHnd,
5078                                        INDEBUG_LDISASM_COMMA(sigInfo)
5079                                        nullptr,
5080                                        argSizeForEmitter,
5081                                        retSize
5082                                        MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize),
5083                                        gcInfo.gcVarPtrSetCur,
5084                                        gcInfo.gcRegGCrefSetCur,
5085                                        gcInfo.gcRegByrefSetCur,
5086                                        ilOffset, REG_VIRTUAL_STUB_TARGET, REG_NA, 1, 0);
5087             // clang-format on
5088         }
5089         else
5090 #endif
5091             if (target->isContainedIndir())
5092         {
5093             if (target->AsIndir()->HasBase() && target->AsIndir()->Base()->isContainedIntOrIImmed())
5094             {
5095                 // Note that if gtControlExpr is an indir of an absolute address, we mark it as
5096                 // contained only if it can be encoded as PC-relative offset.
5097                 assert(target->AsIndir()->Base()->AsIntConCommon()->FitsInAddrBase(compiler));
5098
5099                 // clang-format off
5100                 genEmitCall(emitter::EC_FUNC_TOKEN_INDIR,
5101                             methHnd,
5102                             INDEBUG_LDISASM_COMMA(sigInfo)
5103                             (void*) target->AsIndir()->Base()->AsIntConCommon()->IconValue()
5104                             X86_ARG(argSizeForEmitter),
5105                             retSize
5106                             MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize),
5107                             ilOffset);
5108                 // clang-format on
5109             }
5110             else
5111             {
5112                 // clang-format off
5113                 genEmitCall(emitter::EC_INDIR_ARD,
5114                             methHnd,
5115                             INDEBUG_LDISASM_COMMA(sigInfo)
5116                             target->AsIndir()
5117                             X86_ARG(argSizeForEmitter),
5118                             retSize
5119                             MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize),
5120                             ilOffset);
5121                 // clang-format on
5122             }
5123         }
5124         else
5125         {
5126             // We have already generated code for gtControlExpr evaluating it into a register.
5127             // We just need to emit "call reg" in this case.
5128             assert(genIsValidIntReg(target->gtRegNum));
5129
5130             // clang-format off
5131             genEmitCall(emitter::EC_INDIR_R,
5132                         methHnd,
5133                         INDEBUG_LDISASM_COMMA(sigInfo)
5134                         nullptr // addr
5135                         X86_ARG(argSizeForEmitter),
5136                         retSize
5137                         MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize),
5138                         ilOffset,
5139                         genConsumeReg(target));
5140             // clang-format on
5141         }
5142     }
5143 #ifdef FEATURE_READYTORUN_COMPILER
5144     else if (call->gtEntryPoint.addr != nullptr)
5145     {
5146         // clang-format off
5147         genEmitCall((call->gtEntryPoint.accessType == IAT_VALUE) ? emitter::EC_FUNC_TOKEN
5148                                                                  : emitter::EC_FUNC_TOKEN_INDIR,
5149                     methHnd,
5150                     INDEBUG_LDISASM_COMMA(sigInfo)
5151                     (void*) call->gtEntryPoint.addr
5152                     X86_ARG(argSizeForEmitter),
5153                     retSize
5154                     MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize),
5155                     ilOffset);
5156         // clang-format on
5157     }
5158 #endif
5159     else
5160     {
5161         // Generate a direct call to a non-virtual user defined or helper method
5162         assert(callType == CT_HELPER || callType == CT_USER_FUNC);
5163
5164         void* addr = nullptr;
5165         if (callType == CT_HELPER)
5166         {
5167             // Direct call to a helper method.
5168             helperNum = compiler->eeGetHelperNum(methHnd);
5169             noway_assert(helperNum != CORINFO_HELP_UNDEF);
5170
5171             void* pAddr = nullptr;
5172             addr        = compiler->compGetHelperFtn(helperNum, (void**)&pAddr);
5173
5174             if (addr == nullptr)
5175             {
5176                 addr = pAddr;
5177             }
5178
5179             // tracking of region protected by the monitor in synchronized methods
5180             if (compiler->info.compFlags & CORINFO_FLG_SYNCH)
5181             {
5182                 fPossibleSyncHelperCall = true;
5183             }
5184         }
5185         else
5186         {
5187             // Direct call to a non-virtual user function.
5188             addr = call->gtDirectCallAddress;
5189         }
5190
5191         // Non-virtual direct calls to known addresses
5192
5193         // clang-format off
5194         genEmitCall(emitter::EC_FUNC_TOKEN,
5195                     methHnd,
5196                     INDEBUG_LDISASM_COMMA(sigInfo)
5197                     addr
5198                     X86_ARG(argSizeForEmitter),
5199                     retSize
5200                     MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize),
5201                     ilOffset);
5202         // clang-format on
5203     }
5204
5205     // if it was a pinvoke we may have needed to get the address of a label
5206     if (genPendingCallLabel)
5207     {
5208         assert(call->IsUnmanaged());
5209         genDefineTempLabel(genPendingCallLabel);
5210         genPendingCallLabel = nullptr;
5211     }
5212
5213     // Update GC info:
5214     // All Callee arg registers are trashed and no longer contain any GC pointers.
5215     // TODO-XArch-Bug?: As a matter of fact shouldn't we be killing all of callee trashed regs here?
5216     // For now we will assert that other than arg regs gc ref/byref set doesn't contain any other
5217     // registers from RBM_CALLEE_TRASH.
5218     assert((gcInfo.gcRegGCrefSetCur & (RBM_CALLEE_TRASH & ~RBM_ARG_REGS)) == 0);
5219     assert((gcInfo.gcRegByrefSetCur & (RBM_CALLEE_TRASH & ~RBM_ARG_REGS)) == 0);
5220     gcInfo.gcRegGCrefSetCur &= ~RBM_ARG_REGS;
5221     gcInfo.gcRegByrefSetCur &= ~RBM_ARG_REGS;
5222
5223     var_types returnType = call->TypeGet();
5224     if (returnType != TYP_VOID)
5225     {
5226 #ifdef _TARGET_X86_
5227         if (varTypeIsFloating(returnType))
5228         {
5229             // Spill the value from the fp stack.
5230             // Then, load it into the target register.
5231             call->gtFlags |= GTF_SPILL;
5232             regSet.rsSpillFPStack(call);
5233             call->gtFlags |= GTF_SPILLED;
5234             call->gtFlags &= ~GTF_SPILL;
5235         }
5236         else
5237 #endif // _TARGET_X86_
5238         {
5239             regNumber returnReg;
5240
5241             if (call->HasMultiRegRetVal())
5242             {
5243                 assert(retTypeDesc != nullptr);
5244                 unsigned regCount = retTypeDesc->GetReturnRegCount();
5245
5246                 // If regs allocated to call node are different from ABI return
5247                 // regs in which the call has returned its result, move the result
5248                 // to regs allocated to call node.
5249                 for (unsigned i = 0; i < regCount; ++i)
5250                 {
5251                     var_types regType      = retTypeDesc->GetReturnRegType(i);
5252                     returnReg              = retTypeDesc->GetABIReturnReg(i);
5253                     regNumber allocatedReg = call->GetRegNumByIdx(i);
5254                     if (returnReg != allocatedReg)
5255                     {
5256                         inst_RV_RV(ins_Copy(regType), allocatedReg, returnReg, regType);
5257                     }
5258                 }
5259
5260 #ifdef FEATURE_SIMD
5261                 // A Vector3 return value is stored in xmm0 and xmm1.
5262                 // RyuJIT assumes that the upper unused bits of xmm1 are cleared but
5263                 // the native compiler doesn't guarantee it.
5264                 if (returnType == TYP_SIMD12)
5265                 {
5266                     returnReg = retTypeDesc->GetABIReturnReg(1);
5267                     // Clear the upper 32 bits by two shift instructions.
5268                     // retReg = retReg << 96
5269                     // retReg = retReg >> 96
5270                     getEmitter()->emitIns_R_I(INS_pslldq, emitActualTypeSize(TYP_SIMD12), returnReg, 12);
5271                     getEmitter()->emitIns_R_I(INS_psrldq, emitActualTypeSize(TYP_SIMD12), returnReg, 12);
5272                 }
5273 #endif // FEATURE_SIMD
5274             }
5275             else
5276             {
5277 #ifdef _TARGET_X86_
5278                 if (call->IsHelperCall(compiler, CORINFO_HELP_INIT_PINVOKE_FRAME))
5279                 {
5280                     // The x86 CORINFO_HELP_INIT_PINVOKE_FRAME helper uses a custom calling convention that returns with
5281                     // TCB in REG_PINVOKE_TCB. AMD64/ARM64 use the standard calling convention. fgMorphCall() sets the
5282                     // correct argument registers.
5283                     returnReg = REG_PINVOKE_TCB;
5284                 }
5285                 else
5286 #endif // _TARGET_X86_
5287                     if (varTypeIsFloating(returnType))
5288                 {
5289                     returnReg = REG_FLOATRET;
5290                 }
5291                 else
5292                 {
5293                     returnReg = REG_INTRET;
5294                 }
5295
5296                 if (call->gtRegNum != returnReg)
5297                 {
5298                     inst_RV_RV(ins_Copy(returnType), call->gtRegNum, returnReg, returnType);
5299                 }
5300             }
5301
5302             genProduceReg(call);
5303         }
5304     }
5305
5306     // If there is nothing next, that means the result is thrown away, so this value is not live.
5307     // However, for minopts or debuggable code, we keep it live to support managed return value debugging.
5308     if ((call->gtNext == nullptr) && !compiler->opts.MinOpts() && !compiler->opts.compDbgCode)
5309     {
5310         gcInfo.gcMarkRegSetNpt(RBM_INTRET);
5311     }
5312
5313 #if !FEATURE_EH_FUNCLETS
5314     //-------------------------------------------------------------------------
5315     // Create a label for tracking of region protected by the monitor in synchronized methods.
5316     // This needs to be here, rather than above where fPossibleSyncHelperCall is set,
5317     // so the GC state vars have been updated before creating the label.
5318
5319     if (fPossibleSyncHelperCall)
5320     {
5321         switch (helperNum)
5322         {
5323             case CORINFO_HELP_MON_ENTER:
5324             case CORINFO_HELP_MON_ENTER_STATIC:
5325                 noway_assert(compiler->syncStartEmitCookie == NULL);
5326                 compiler->syncStartEmitCookie =
5327                     getEmitter()->emitAddLabel(gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur);
5328                 noway_assert(compiler->syncStartEmitCookie != NULL);
5329                 break;
5330             case CORINFO_HELP_MON_EXIT:
5331             case CORINFO_HELP_MON_EXIT_STATIC:
5332                 noway_assert(compiler->syncEndEmitCookie == NULL);
5333                 compiler->syncEndEmitCookie =
5334                     getEmitter()->emitAddLabel(gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur);
5335                 noway_assert(compiler->syncEndEmitCookie != NULL);
5336                 break;
5337             default:
5338                 break;
5339         }
5340     }
5341 #endif // !FEATURE_EH_FUNCLETS
5342
5343     unsigned stackAdjustBias = 0;
5344
5345 #if defined(_TARGET_X86_)
5346     // Is the caller supposed to pop the arguments?
5347     if (fCallerPop && (stackArgBytes != 0))
5348     {
5349         stackAdjustBias = stackArgBytes;
5350     }
5351
5352     SubtractStackLevel(stackArgBytes);
5353 #endif // _TARGET_X86_
5354
5355     genRemoveAlignmentAfterCall(call, stackAdjustBias);
5356 }
5357
5358 // Produce code for a GT_JMP node.
5359 // The arguments of the caller needs to be transferred to the callee before exiting caller.
5360 // The actual jump to callee is generated as part of caller epilog sequence.
5361 // Therefore the codegen of GT_JMP is to ensure that the callee arguments are correctly setup.
5362 void CodeGen::genJmpMethod(GenTreePtr jmp)
5363 {
5364     assert(jmp->OperGet() == GT_JMP);
5365     assert(compiler->compJmpOpUsed);
5366
5367     // If no arguments, nothing to do
5368     if (compiler->info.compArgsCount == 0)
5369     {
5370         return;
5371     }
5372
5373     // Make sure register arguments are in their initial registers
5374     // and stack arguments are put back as well.
5375     unsigned   varNum;
5376     LclVarDsc* varDsc;
5377
5378     // First move any en-registered stack arguments back to the stack.
5379     // At the same time any reg arg not in correct reg is moved back to its stack location.
5380     //
5381     // We are not strictly required to spill reg args that are not in the desired reg for a jmp call
5382     // But that would require us to deal with circularity while moving values around.  Spilling
5383     // to stack makes the implementation simple, which is not a bad trade off given Jmp calls
5384     // are not frequent.
5385     for (varNum = 0; (varNum < compiler->info.compArgsCount); varNum++)
5386     {
5387         varDsc = compiler->lvaTable + varNum;
5388
5389         if (varDsc->lvPromoted)
5390         {
5391             noway_assert(varDsc->lvFieldCnt == 1); // We only handle one field here
5392
5393             unsigned fieldVarNum = varDsc->lvFieldLclStart;
5394             varDsc               = compiler->lvaTable + fieldVarNum;
5395         }
5396         noway_assert(varDsc->lvIsParam);
5397
5398         if (varDsc->lvIsRegArg && (varDsc->lvRegNum != REG_STK))
5399         {
5400             // Skip reg args which are already in its right register for jmp call.
5401             // If not, we will spill such args to their stack locations.
5402             //
5403             // If we need to generate a tail call profiler hook, then spill all
5404             // arg regs to free them up for the callback.
5405             if (!compiler->compIsProfilerHookNeeded() && (varDsc->lvRegNum == varDsc->lvArgReg))
5406             {
5407                 continue;
5408             }
5409         }
5410         else if (varDsc->lvRegNum == REG_STK)
5411         {
5412             // Skip args which are currently living in stack.
5413             continue;
5414         }
5415
5416         // If we came here it means either a reg argument not in the right register or
5417         // a stack argument currently living in a register.  In either case the following
5418         // assert should hold.
5419         assert(varDsc->lvRegNum != REG_STK);
5420
5421         var_types loadType = varDsc->lvaArgType();
5422         getEmitter()->emitIns_S_R(ins_Store(loadType), emitTypeSize(loadType), varDsc->lvRegNum, varNum, 0);
5423
5424         // Update lvRegNum life and GC info to indicate lvRegNum is dead and varDsc stack slot is going live.
5425         // Note that we cannot modify varDsc->lvRegNum here because another basic block may not be expecting it.
5426         // Therefore manually update life of varDsc->lvRegNum.
5427         regMaskTP tempMask = varDsc->lvRegMask();
5428         regSet.RemoveMaskVars(tempMask);
5429         gcInfo.gcMarkRegSetNpt(tempMask);
5430         if (compiler->lvaIsGCTracked(varDsc))
5431         {
5432 #ifdef DEBUG
5433             if (!VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex))
5434             {
5435                 JITDUMP("\t\t\t\t\t\t\tVar V%02u becoming live\n", varNum);
5436             }
5437             else
5438             {
5439                 JITDUMP("\t\t\t\t\t\t\tVar V%02u continuing live\n", varNum);
5440             }
5441 #endif // DEBUG
5442
5443             VarSetOps::AddElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex);
5444         }
5445     }
5446
5447 #ifdef PROFILING_SUPPORTED
5448     // At this point all arg regs are free.
5449     // Emit tail call profiler callback.
5450     genProfilingLeaveCallback(CORINFO_HELP_PROF_FCN_TAILCALL);
5451 #endif
5452
5453     // Next move any un-enregistered register arguments back to their register.
5454     regMaskTP fixedIntArgMask = RBM_NONE;    // tracks the int arg regs occupying fixed args in case of a vararg method.
5455     unsigned  firstArgVarNum  = BAD_VAR_NUM; // varNum of the first argument in case of a vararg method.
5456     for (varNum = 0; (varNum < compiler->info.compArgsCount); varNum++)
5457     {
5458         varDsc = compiler->lvaTable + varNum;
5459         if (varDsc->lvPromoted)
5460         {
5461             noway_assert(varDsc->lvFieldCnt == 1); // We only handle one field here
5462
5463             unsigned fieldVarNum = varDsc->lvFieldLclStart;
5464             varDsc               = compiler->lvaTable + fieldVarNum;
5465         }
5466         noway_assert(varDsc->lvIsParam);
5467
5468         // Skip if arg not passed in a register.
5469         if (!varDsc->lvIsRegArg)
5470         {
5471             continue;
5472         }
5473
5474 #if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
5475         if (varTypeIsStruct(varDsc))
5476         {
5477             CORINFO_CLASS_HANDLE typeHnd = varDsc->lvVerTypeInfo.GetClassHandle();
5478             assert(typeHnd != nullptr);
5479
5480             SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR structDesc;
5481             compiler->eeGetSystemVAmd64PassStructInRegisterDescriptor(typeHnd, &structDesc);
5482             assert(structDesc.passedInRegisters);
5483
5484             unsigned __int8 offset0 = 0;
5485             unsigned __int8 offset1 = 0;
5486             var_types       type0   = TYP_UNKNOWN;
5487             var_types       type1   = TYP_UNKNOWN;
5488
5489             // Get the eightbyte data
5490             compiler->GetStructTypeOffset(structDesc, &type0, &type1, &offset0, &offset1);
5491
5492             // Move the values into the right registers.
5493             //
5494
5495             // Update varDsc->lvArgReg and lvOtherArgReg life and GC Info to indicate varDsc stack slot is dead and
5496             // argReg is going live. Note that we cannot modify varDsc->lvRegNum and lvOtherArgReg here because another
5497             // basic block may not be expecting it. Therefore manually update life of argReg.  Note that GT_JMP marks
5498             // the end of the basic block and after which reg life and gc info will be recomputed for the new block in
5499             // genCodeForBBList().
5500             if (type0 != TYP_UNKNOWN)
5501             {
5502                 getEmitter()->emitIns_R_S(ins_Load(type0), emitTypeSize(type0), varDsc->lvArgReg, varNum, offset0);
5503                 regSet.rsMaskVars |= genRegMask(varDsc->lvArgReg);
5504                 gcInfo.gcMarkRegPtrVal(varDsc->lvArgReg, type0);
5505             }
5506
5507             if (type1 != TYP_UNKNOWN)
5508             {
5509                 getEmitter()->emitIns_R_S(ins_Load(type1), emitTypeSize(type1), varDsc->lvOtherArgReg, varNum, offset1);
5510                 regSet.rsMaskVars |= genRegMask(varDsc->lvOtherArgReg);
5511                 gcInfo.gcMarkRegPtrVal(varDsc->lvOtherArgReg, type1);
5512             }
5513
5514             if (varDsc->lvTracked)
5515             {
5516                 VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex);
5517             }
5518         }
5519         else
5520 #endif // !defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
5521         {
5522             // Register argument
5523             noway_assert(isRegParamType(genActualType(varDsc->TypeGet())));
5524
5525             // Is register argument already in the right register?
5526             // If not load it from its stack location.
5527             var_types loadType = varDsc->lvaArgType();
5528             regNumber argReg   = varDsc->lvArgReg; // incoming arg register
5529
5530             if (varDsc->lvRegNum != argReg)
5531             {
5532                 assert(genIsValidReg(argReg));
5533                 getEmitter()->emitIns_R_S(ins_Load(loadType), emitTypeSize(loadType), argReg, varNum, 0);
5534
5535                 // Update argReg life and GC Info to indicate varDsc stack slot is dead and argReg is going live.
5536                 // Note that we cannot modify varDsc->lvRegNum here because another basic block may not be expecting it.
5537                 // Therefore manually update life of argReg.  Note that GT_JMP marks the end of the basic block
5538                 // and after which reg life and gc info will be recomputed for the new block in genCodeForBBList().
5539                 regSet.AddMaskVars(genRegMask(argReg));
5540                 gcInfo.gcMarkRegPtrVal(argReg, loadType);
5541                 if (compiler->lvaIsGCTracked(varDsc))
5542                 {
5543 #ifdef DEBUG
5544                     if (VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex))
5545                     {
5546                         JITDUMP("\t\t\t\t\t\t\tVar V%02u becoming dead\n", varNum);
5547                     }
5548                     else
5549                     {
5550                         JITDUMP("\t\t\t\t\t\t\tVar V%02u continuing dead\n", varNum);
5551                     }
5552 #endif // DEBUG
5553
5554                     VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex);
5555                 }
5556             }
5557         }
5558
5559 #if FEATURE_VARARG && defined(_TARGET_AMD64_)
5560         // In case of a jmp call to a vararg method also pass the float/double arg in the corresponding int arg
5561         // register. This is due to the AMD64 ABI which requires floating point values passed to varargs functions to
5562         // be passed in both integer and floating point registers. It doesn't apply to x86, which passes floating point
5563         // values on the stack.
5564         if (compiler->info.compIsVarArgs)
5565         {
5566             regNumber intArgReg;
5567             var_types loadType = varDsc->lvaArgType();
5568             regNumber argReg   = varDsc->lvArgReg; // incoming arg register
5569
5570             if (varTypeIsFloating(loadType))
5571             {
5572                 intArgReg       = compiler->getCallArgIntRegister(argReg);
5573                 instruction ins = ins_CopyFloatToInt(loadType, TYP_LONG);
5574                 inst_RV_RV(ins, argReg, intArgReg, loadType);
5575             }
5576             else
5577             {
5578                 intArgReg = argReg;
5579             }
5580
5581             fixedIntArgMask |= genRegMask(intArgReg);
5582
5583             if (intArgReg == REG_ARG_0)
5584             {
5585                 assert(firstArgVarNum == BAD_VAR_NUM);
5586                 firstArgVarNum = varNum;
5587             }
5588         }
5589 #endif // FEATURE_VARARG
5590     }
5591
5592 #if FEATURE_VARARG && defined(_TARGET_AMD64_)
5593     // Jmp call to a vararg method - if the method has fewer than 4 fixed arguments,
5594     // load the remaining arg registers (both int and float) from the corresponding
5595     // shadow stack slots.  This is for the reason that we don't know the number and type
5596     // of non-fixed params passed by the caller, therefore we have to assume the worst case
5597     // of caller passing float/double args both in int and float arg regs.
5598     //
5599     // This doesn't apply to x86, which doesn't pass floating point values in floating
5600     // point registers.
5601     //
5602     // The caller could have passed gc-ref/byref type var args.  Since these are var args
5603     // the callee no way of knowing their gc-ness.  Therefore, mark the region that loads
5604     // remaining arg registers from shadow stack slots as non-gc interruptible.
5605     if (fixedIntArgMask != RBM_NONE)
5606     {
5607         assert(compiler->info.compIsVarArgs);
5608         assert(firstArgVarNum != BAD_VAR_NUM);
5609
5610         regMaskTP remainingIntArgMask = RBM_ARG_REGS & ~fixedIntArgMask;
5611         if (remainingIntArgMask != RBM_NONE)
5612         {
5613             instruction insCopyIntToFloat = ins_CopyIntToFloat(TYP_LONG, TYP_DOUBLE);
5614             getEmitter()->emitDisableGC();
5615             for (int argNum = 0, argOffset = 0; argNum < MAX_REG_ARG; ++argNum)
5616             {
5617                 regNumber argReg     = intArgRegs[argNum];
5618                 regMaskTP argRegMask = genRegMask(argReg);
5619
5620                 if ((remainingIntArgMask & argRegMask) != 0)
5621                 {
5622                     remainingIntArgMask &= ~argRegMask;
5623                     getEmitter()->emitIns_R_S(INS_mov, EA_8BYTE, argReg, firstArgVarNum, argOffset);
5624
5625                     // also load it in corresponding float arg reg
5626                     regNumber floatReg = compiler->getCallArgFloatRegister(argReg);
5627                     inst_RV_RV(insCopyIntToFloat, floatReg, argReg);
5628                 }
5629
5630                 argOffset += REGSIZE_BYTES;
5631             }
5632             getEmitter()->emitEnableGC();
5633         }
5634     }
5635 #endif // FEATURE_VARARG
5636 }
5637
5638 // produce code for a GT_LEA subnode
5639 void CodeGen::genLeaInstruction(GenTreeAddrMode* lea)
5640 {
5641     emitAttr size = emitTypeSize(lea);
5642     genConsumeOperands(lea);
5643
5644     if (lea->Base() && lea->Index())
5645     {
5646         regNumber baseReg  = lea->Base()->gtRegNum;
5647         regNumber indexReg = lea->Index()->gtRegNum;
5648         getEmitter()->emitIns_R_ARX(INS_lea, size, lea->gtRegNum, baseReg, indexReg, lea->gtScale, lea->gtOffset);
5649     }
5650     else if (lea->Base())
5651     {
5652         getEmitter()->emitIns_R_AR(INS_lea, size, lea->gtRegNum, lea->Base()->gtRegNum, lea->gtOffset);
5653     }
5654     else if (lea->Index())
5655     {
5656         getEmitter()->emitIns_R_ARX(INS_lea, size, lea->gtRegNum, REG_NA, lea->Index()->gtRegNum, lea->gtScale,
5657                                     lea->gtOffset);
5658     }
5659
5660     genProduceReg(lea);
5661 }
5662
5663 //-------------------------------------------------------------------------------------------
5664 // genJumpKindsForTree:  Determine the number and kinds of conditional branches
5665 //                       necessary to implement the given GT_CMP node
5666 //
5667 // Arguments:
5668 //    cmpTree          - (input) The GenTree node that is used to set the Condition codes
5669 //                     - The GenTree Relop node that was used to set the Condition codes
5670 //   jmpKind[2]        - (output) One or two conditional branch instructions
5671 //   jmpToTrueLabel[2] - (output) When true we branch to the true case
5672 //                       When false we create a second label and branch to the false case
5673 //                       Only GT_EQ for a floating point compares can have a false value.
5674 //
5675 // Return Value:
5676 //    Sets the proper values into the array elements of jmpKind[] and jmpToTrueLabel[]
5677 //
5678 // Assumptions:
5679 //    At least one conditional branch instruction will be returned.
5680 //    Typically only one conditional branch is needed
5681 //     and the second jmpKind[] value is set to EJ_NONE
5682 //
5683 // Notes:
5684 //    jmpToTrueLabel[i]= true  implies branch when the compare operation is true.
5685 //    jmpToTrueLabel[i]= false implies branch when the compare operation is false.
5686 //-------------------------------------------------------------------------------------------
5687
5688 // static
5689 void CodeGen::genJumpKindsForTree(GenTreePtr cmpTree, emitJumpKind jmpKind[2], bool jmpToTrueLabel[2])
5690 {
5691     // Except for BEQ (=  ordered GT_EQ) both jumps are to the true label.
5692     jmpToTrueLabel[0] = true;
5693     jmpToTrueLabel[1] = true;
5694
5695     // For integer comparisons just use genJumpKindForOper
5696     if (!varTypeIsFloating(cmpTree->gtOp.gtOp1->gtEffectiveVal()))
5697     {
5698         CompareKind compareKind = ((cmpTree->gtFlags & GTF_UNSIGNED) != 0) ? CK_UNSIGNED : CK_SIGNED;
5699         jmpKind[0]              = genJumpKindForOper(cmpTree->gtOper, compareKind);
5700         jmpKind[1]              = EJ_NONE;
5701     }
5702     else
5703     {
5704         assert(cmpTree->OperIsCompare());
5705
5706         // For details on how we arrived at this mapping, see the comment block in genCodeForTreeNode()
5707         // while generating code for compare opererators (e.g. GT_EQ etc).
5708         if ((cmpTree->gtFlags & GTF_RELOP_NAN_UN) != 0)
5709         {
5710             // Must branch if we have an NaN, unordered
5711             switch (cmpTree->gtOper)
5712             {
5713                 case GT_LT:
5714                 case GT_GT:
5715                     jmpKind[0] = EJ_jb;
5716                     jmpKind[1] = EJ_NONE;
5717                     break;
5718
5719                 case GT_LE:
5720                 case GT_GE:
5721                     jmpKind[0] = EJ_jbe;
5722                     jmpKind[1] = EJ_NONE;
5723                     break;
5724
5725                 case GT_NE:
5726                     jmpKind[0] = EJ_jpe;
5727                     jmpKind[1] = EJ_jne;
5728                     break;
5729
5730                 case GT_EQ:
5731                     jmpKind[0] = EJ_je;
5732                     jmpKind[1] = EJ_NONE;
5733                     break;
5734
5735                 default:
5736                     unreached();
5737             }
5738         }
5739         else // ((cmpTree->gtFlags & GTF_RELOP_NAN_UN) == 0)
5740         {
5741             // Do not branch if we have an NaN, unordered
5742             switch (cmpTree->gtOper)
5743             {
5744                 case GT_LT:
5745                 case GT_GT:
5746                     jmpKind[0] = EJ_ja;
5747                     jmpKind[1] = EJ_NONE;
5748                     break;
5749
5750                 case GT_LE:
5751                 case GT_GE:
5752                     jmpKind[0] = EJ_jae;
5753                     jmpKind[1] = EJ_NONE;
5754                     break;
5755
5756                 case GT_NE:
5757                     jmpKind[0] = EJ_jne;
5758                     jmpKind[1] = EJ_NONE;
5759                     break;
5760
5761                 case GT_EQ:
5762                     jmpKind[0]        = EJ_jpe;
5763                     jmpKind[1]        = EJ_je;
5764                     jmpToTrueLabel[0] = false;
5765                     break;
5766
5767                 default:
5768                     unreached();
5769             }
5770         }
5771     }
5772 }
5773
5774 #if !defined(_TARGET_64BIT_)
5775 //------------------------------------------------------------------------
5776 // genJumpKindsForTreeLongHi: Generate the jump types for compare
5777 // operators of the high parts of a compare with long type operands
5778 // on x86 for the case where rel-op result needs to be materialized into a
5779 // register.
5780 //
5781 // Arguments:
5782 //    cmpTree - The GT_CMP node
5783 //    jmpKind - Return array of jump kinds
5784 //    jmpToTrueLabel - Return array of if the jump is going to true label
5785 //
5786 // Return Value:
5787 //    None.
5788 //
5789 void CodeGen::genJumpKindsForTreeLongHi(GenTreePtr cmpTree, emitJumpKind jmpKind[2])
5790 {
5791     assert(cmpTree->OperIsCompare());
5792     CompareKind compareKind = ((cmpTree->gtFlags & GTF_UNSIGNED) != 0) ? CK_UNSIGNED : CK_SIGNED;
5793
5794     switch (cmpTree->gtOper)
5795     {
5796         case GT_LT:
5797         case GT_LE:
5798             if (compareKind == CK_SIGNED)
5799             {
5800                 jmpKind[0] = EJ_jl;
5801                 jmpKind[1] = EJ_jg;
5802             }
5803             else
5804             {
5805                 jmpKind[0] = EJ_jb;
5806                 jmpKind[1] = EJ_ja;
5807             }
5808             break;
5809
5810         case GT_GT:
5811         case GT_GE:
5812             if (compareKind == CK_SIGNED)
5813             {
5814                 jmpKind[0] = EJ_jg;
5815                 jmpKind[1] = EJ_jl;
5816             }
5817             else
5818             {
5819                 jmpKind[0] = EJ_ja;
5820                 jmpKind[1] = EJ_jb;
5821             }
5822             break;
5823
5824         case GT_EQ:
5825             // GT_EQ will not jump to the true label if the hi parts are equal
5826             jmpKind[0] = EJ_NONE;
5827             jmpKind[1] = EJ_jne;
5828             break;
5829
5830         case GT_NE:
5831             // GT_NE will always jump to the true label if the high parts are not equal
5832             jmpKind[0] = EJ_jne;
5833             jmpKind[1] = EJ_NONE;
5834             break;
5835
5836         default:
5837             unreached();
5838     }
5839 }
5840
5841 //------------------------------------------------------------------------
5842 // genCompareLong: Generate code for comparing two longs on x86 when the result of the compare
5843 // is manifested in a register.
5844 //
5845 // Arguments:
5846 //    treeNode - the compare tree
5847 //
5848 // Return Value:
5849 //    None.
5850 // Comments:
5851 // For long compares, we need to compare the high parts of operands first, then the low parts.
5852 // If the high compare is false, we do not need to compare the low parts. For less than and
5853 // greater than, if the high compare is true, we can assume the entire compare is true. For
5854 // compares that are realized in a register, we will generate:
5855 //
5856 //    Opcode            x86 equivalent          Comment
5857 //    ------            --------------          -------
5858 //    GT_EQ             cmp hiOp1,hiOp2         If any part is not equal, the entire compare
5859 //                      jne label               is false.
5860 //                      cmp loOp1,loOp2
5861 //                      label: sete
5862 //
5863 //    GT_NE             cmp hiOp1,hiOp2         If any part is not equal, the entire compare
5864 //                      jne label               is true.
5865 //                      cmp loOp1,loOp2
5866 //                      label: setne
5867 //
5868 //    GT_LT; unsigned   cmp hiOp1,hiOp2         If hiOp1 is not equal to hiOp2, the flags are set
5869 //                      jne label               correctly and we do not need to check lo. Otherwise,
5870 //                      cmp loOp1,loOp2         we need to compare the lo halves
5871 //                      label: setb
5872 //
5873 //    GT_LE; unsigned   cmp hiOp1,hiOp2         If hiOp1 is not equal to hiOp2, the flags are set
5874 //                      jne label               correctly and we do not need to check lo. Otherwise,
5875 //                      cmp loOp1,loOp2         we need to compare the lo halves
5876 //                      label: setbe
5877 //
5878 //    GT_GT; unsigned   cmp hiOp1,hiOp2         If hiOp1 is not equal to hiOp2, the flags are set
5879 //                      jne label               correctly and we do not need to check lo. Otherwise,
5880 //                      cmp loOp1,loOp2         we need to compare the lo halves
5881 //                      label: seta
5882 //
5883 //    GT_GE; unsigned   cmp hiOp1,hiOp2         If hiOp1 is not equal to hiOp2, the flags are set
5884 //                      jne label               correctly and we do not need to check lo. Otherwise,
5885 //                      cmp loOp1,loOp2         we need to compare the lo halves
5886 //                      label: setae
5887 //
5888 // For signed long comparisons, we need additional labels, as we need to use signed conditions on the
5889 // "set" instruction:
5890 //
5891 //    GT_LT; signed     cmp hiOp1,hiOp2         If hiOp1 is not equal to hiOp2, the flags are set
5892 //                      jne labelHi             correctly and we do not need to check lo. Otherwise,
5893 //                      cmp loOp1,loOp2         we need to compare the lo halves
5894 //                      setb                    Unsigned set for lo compare
5895 //                      jmp labelFinal
5896 //                      labelHi: setl           Signed set for high compare
5897 //                      labelFinal:
5898 //
5899 //    GT_LE; signed     cmp hiOp1,hiOp2         If hiOp1 is not equal to hiOp2, the flags are set
5900 //                      jne labelHi             correctly and we do not need to check lo. Otherwise,
5901 //                      cmp loOp1,loOp2         we need to compare the lo halves
5902 //                      setbe                   Unsigend set for lo compare
5903 //                      jmp labelFinal
5904 //                      labelHi: setle          Signed set for hi compare
5905 //                      labelFinal:
5906 //
5907 //    GT_GT; signed     cmp hiOp1,hiOp2         If hiOp1 is not equal to hiOp2, the flags are set
5908 //                      jne labelHi             correctly and we do not need to check lo. Otherwise,
5909 //                      cmp loOp1,loOp2         we need to compare the lo halves
5910 //                      seta                    Unsigned set for lo compare
5911 //                      jmp labelFinal
5912 //                      labelHi: setg           Signed set for high compare
5913 //                      labelFinal
5914 //
5915 //    GT_GE; signed     cmp hiOp1,hiOp2         If hiOp1 is not equal to hiOp2, the flags are set
5916 //                      jne labelHi             correctly and we do not need to check lo. Otherwise,
5917 //                      cmp loOp1,loOp2         we need to compare the lo halves
5918 //                      setae                   Unsigned set for lo compare
5919 //                      jmp labelFinal
5920 //                      labelHi: setge          Signed set for hi compare
5921 //                      labelFinal:
5922 //
5923 // TODO-X86-CQ: Check if hi or lo parts of op2 are 0 and change the compare to a test.
5924 void CodeGen::genCompareLong(GenTreePtr treeNode)
5925 {
5926     assert(treeNode->OperIsCompare());
5927
5928     GenTreeOp* tree = treeNode->AsOp();
5929     GenTreePtr op1  = tree->gtOp1;
5930     GenTreePtr op2  = tree->gtOp2;
5931
5932     assert(varTypeIsLong(op1->TypeGet()));
5933     assert(varTypeIsLong(op2->TypeGet()));
5934
5935     regNumber targetReg = treeNode->gtRegNum;
5936
5937     genConsumeOperands(tree);
5938
5939     GenTreePtr loOp1 = op1->gtGetOp1();
5940     GenTreePtr hiOp1 = op1->gtGetOp2();
5941     GenTreePtr loOp2 = op2->gtGetOp1();
5942     GenTreePtr hiOp2 = op2->gtGetOp2();
5943
5944     // Create compare for the high parts
5945     instruction ins     = INS_cmp;
5946     var_types   cmpType = TYP_INT;
5947     emitAttr    cmpAttr = emitTypeSize(cmpType);
5948
5949     // Emit the compare instruction
5950     getEmitter()->emitInsBinary(ins, cmpAttr, hiOp1, hiOp2);
5951
5952     // If the result is not being materialized in a register, we're done.
5953     if (targetReg == REG_NA)
5954     {
5955         return;
5956     }
5957
5958     // Generate the first jump for the high compare
5959     CompareKind compareKind = ((tree->gtFlags & GTF_UNSIGNED) != 0) ? CK_UNSIGNED : CK_SIGNED;
5960
5961     BasicBlock* labelHi    = genCreateTempLabel();
5962     BasicBlock* labelFinal = genCreateTempLabel();
5963
5964     if (compareKind == CK_SIGNED && (tree->gtOper != GT_NE && tree->gtOper != GT_EQ))
5965     {
5966         // If we are doing a signed comparison, we need to do a signed set if the high compare is true,
5967         // but an unsigned set if we fall through to the low compare. If we have a GT_NE or GT_EQ, we do not
5968         // need to worry about the sign of the comparison, so we can use the simplified case.
5969
5970         // We only have to check for equality for the hi comparison. If they are not equal, then the set will
5971         // do the right thing. If they are equal, we have to check the lo halves.
5972         inst_JMP(EJ_jne, labelHi);
5973
5974         // Emit the comparison. Perform the set for the lo. Jump to labelFinal
5975         getEmitter()->emitInsBinary(ins, cmpAttr, loOp1, loOp2);
5976
5977         // The low set must be unsigned
5978         emitJumpKind jumpKindLo = genJumpKindForOper(tree->gtOper, CK_UNSIGNED);
5979
5980         inst_SET(jumpKindLo, targetReg);
5981         inst_JMP(EJ_jmp, labelFinal);
5982
5983         // Define the label for hi jump target here. If we have jumped here, we want to set
5984         // the target register based on the jump kind of the actual compare type.
5985
5986         genDefineTempLabel(labelHi);
5987         inst_SET(genJumpKindForOper(tree->gtOper, compareKind), targetReg);
5988
5989         genDefineTempLabel(labelFinal);
5990         // Set the higher bytes to 0
5991         inst_RV_RV(ins_Move_Extend(TYP_UBYTE, true), targetReg, targetReg, TYP_UBYTE, emitTypeSize(TYP_UBYTE));
5992         genProduceReg(tree);
5993     }
5994     else
5995     {
5996         // If the compare is unsigned, or if the sign doesn't change the set instruction, we can use
5997         // the same set logic for both the hi and lo compare, so we don't need to jump to a high label,
5998         // we can just jump to the set that the lo compare will use.
5999
6000         // We only have to check for equality for the hi comparison. If they are not equal, then the set will
6001         // do the right thing. If they are equal, we have to check the lo halves.
6002         inst_JMP(EJ_jne, labelFinal);
6003
6004         // Emit the comparison
6005         getEmitter()->emitInsBinary(ins, cmpAttr, loOp1, loOp2);
6006
6007         // Define the label for hi jump target here. If we have jumped here, we want to set
6008         // the target register based on the jump kind of the lower half (the actual compare
6009         // type). If we have fallen through, then we are doing a normal int compare for the
6010         // lower parts
6011
6012         genDefineTempLabel(labelFinal);
6013
6014         // The low set must be unsigned
6015         emitJumpKind jumpKindLo = genJumpKindForOper(tree->gtOper, CK_UNSIGNED);
6016
6017         inst_SET(jumpKindLo, targetReg);
6018         // Set the higher bytes to 0
6019         inst_RV_RV(ins_Move_Extend(TYP_UBYTE, true), targetReg, targetReg, TYP_UBYTE, emitTypeSize(TYP_UBYTE));
6020         genProduceReg(tree);
6021     }
6022 }
6023 #endif //! defined(_TARGET_64BIT_)
6024
6025 //------------------------------------------------------------------------
6026 // genCompareFloat: Generate code for comparing two floating point values
6027 //
6028 // Arguments:
6029 //    treeNode - the compare tree
6030 //
6031 // Return Value:
6032 //    None.
6033 // Comments:
6034 // SSE2 instruction ucomis[s|d] is performs unordered comparison and
6035 // updates rFLAGS register as follows.
6036 //        Result of compare         ZF  PF CF
6037 //        -----------------        ------------
6038 //        Unordered                 1   1   1     <-- this result implies one of operands of compare is a NAN.
6039 //        Greater                   0   0   0
6040 //        Less Than                 0   0   1
6041 //        Equal                     1   0   0
6042 //
6043 // From the above table the following equalities follow. As per ECMA spec *.UN opcodes perform
6044 // unordered comparison of floating point values.  That is *.UN comparisons result in true when
6045 // one of the operands is a NaN whereas ordered comparisons results in false.
6046 //
6047 //    Opcode          Amd64 equivalent         Comment
6048 //    ------          -----------------        --------
6049 //    BLT.UN(a,b)      ucomis[s|d] a, b        Jb branches if CF=1, which means either a<b or unordered from the above
6050 //                     jb                      table
6051 //
6052 //    BLT(a,b)         ucomis[s|d] b, a        Ja branches if CF=0 and ZF=0, which means b>a that in turn implies a<b
6053 //                     ja
6054 //
6055 //    BGT.UN(a,b)      ucomis[s|d] b, a        branch if b<a or unordered ==> branch if a>b or unordered
6056 //                     jb
6057 //
6058 //    BGT(a, b)        ucomis[s|d] a, b        branch if a>b
6059 //                     ja
6060 //
6061 //    BLE.UN(a,b)      ucomis[s|d] a, b        jbe branches if CF=1 or ZF=1, which implies a<=b or unordered
6062 //                     jbe
6063 //
6064 //    BLE(a,b)         ucomis[s|d] b, a        jae branches if CF=0, which mean b>=a or a<=b
6065 //                     jae
6066 //
6067 //    BGE.UN(a,b)      ucomis[s|d] b, a        branch if b<=a or unordered ==> branch if a>=b or unordered
6068 //                     jbe
6069 //
6070 //    BGE(a,b)         ucomis[s|d] a, b        branch if a>=b
6071 //                     jae
6072 //
6073 //    BEQ.UN(a,b)      ucomis[s|d] a, b        branch if a==b or unordered.  There is no BEQ.UN opcode in ECMA spec.
6074 //                     je                      This case is given for completeness, in case if JIT generates such
6075 //                                             a gentree internally.
6076 //
6077 //    BEQ(a,b)         ucomis[s|d] a, b        From the above table, PF=0 and ZF=1 corresponds to a==b.
6078 //                     jpe L1
6079 //                     je <true label>
6080 //                 L1:
6081 //
6082 //    BNE(a,b)         ucomis[s|d] a, b        branch if a!=b.  There is no BNE opcode in ECMA spec. This case is
6083 //                     jne                     given for completeness, in case if JIT generates such a gentree
6084 //                                             internally.
6085 //
6086 //    BNE.UN(a,b)      ucomis[s|d] a, b        From the above table, PF=1 or ZF=0 implies unordered or a!=b
6087 //                     jpe <true label>
6088 //                     jne <true label>
6089 //
6090 // As we can see from the above equalities that the operands of a compare operator need to be
6091 // reveresed in case of BLT/CLT, BGT.UN/CGT.UN, BLE/CLE, BGE.UN/CGE.UN.
6092 void CodeGen::genCompareFloat(GenTreePtr treeNode)
6093 {
6094     assert(treeNode->OperIsCompare());
6095
6096     GenTreeOp* tree    = treeNode->AsOp();
6097     GenTreePtr op1     = tree->gtOp1;
6098     GenTreePtr op2     = tree->gtOp2;
6099     var_types  op1Type = op1->TypeGet();
6100     var_types  op2Type = op2->TypeGet();
6101
6102     genConsumeOperands(tree);
6103
6104     assert(varTypeIsFloating(op1Type));
6105     assert(op1Type == op2Type);
6106
6107     regNumber   targetReg = treeNode->gtRegNum;
6108     instruction ins;
6109     emitAttr    cmpAttr;
6110
6111     bool reverseOps;
6112     if ((tree->gtFlags & GTF_RELOP_NAN_UN) != 0)
6113     {
6114         // Unordered comparison case
6115         reverseOps = (tree->gtOper == GT_GT || tree->gtOper == GT_GE);
6116     }
6117     else
6118     {
6119         reverseOps = (tree->gtOper == GT_LT || tree->gtOper == GT_LE);
6120     }
6121
6122     if (reverseOps)
6123     {
6124         GenTreePtr tmp = op1;
6125         op1            = op2;
6126         op2            = tmp;
6127     }
6128
6129     ins     = ins_FloatCompare(op1Type);
6130     cmpAttr = emitTypeSize(op1Type);
6131
6132     getEmitter()->emitInsBinary(ins, cmpAttr, op1, op2);
6133
6134     // Are we evaluating this into a register?
6135     if (targetReg != REG_NA)
6136     {
6137         genSetRegToCond(targetReg, tree);
6138         genProduceReg(tree);
6139     }
6140 }
6141
6142 //------------------------------------------------------------------------
6143 // genCompareInt: Generate code for comparing ints or, on amd64, longs.
6144 //
6145 // Arguments:
6146 //    treeNode - the compare tree
6147 //
6148 // Return Value:
6149 //    None.
6150 void CodeGen::genCompareInt(GenTreePtr treeNode)
6151 {
6152     assert(treeNode->OperIsCompare());
6153
6154     GenTreeOp* tree      = treeNode->AsOp();
6155     GenTreePtr op1       = tree->gtOp1;
6156     GenTreePtr op2       = tree->gtOp2;
6157     var_types  op1Type   = op1->TypeGet();
6158     var_types  op2Type   = op2->TypeGet();
6159     regNumber  targetReg = tree->gtRegNum;
6160
6161     // Case of op1 == 0 or op1 != 0:
6162     // Optimize generation of 'test' instruction if op1 sets flags.
6163     //
6164     // Note that if LSRA has inserted any GT_RELOAD/GT_COPY before
6165     // op1, it will not modify the flags set by codegen of op1.
6166     // Similarly op1 could also be reg-optional at its use and
6167     // it was spilled after producing its result in a register.
6168     // Spill code too will not modify the flags set by op1.
6169     GenTree* realOp1 = op1->gtSkipReloadOrCopy();
6170     if (realOp1->gtSetFlags())
6171     {
6172         // op1 must set ZF and SF flags
6173         assert(realOp1->gtSetZSFlags());
6174
6175         // Must be (in)equality against zero.
6176         assert(tree->OperIs(GT_EQ, GT_NE));
6177         assert(op2->IsIntegralConst(0));
6178         assert(op2->isContained());
6179
6180         // Just consume the operands
6181         genConsumeOperands(tree);
6182
6183         // No need to generate test instruction since
6184         // op1 sets flags
6185
6186         // Are we evaluating this into a register?
6187         if (targetReg != REG_NA)
6188         {
6189             genSetRegToCond(targetReg, tree);
6190             genProduceReg(tree);
6191         }
6192
6193         return;
6194     }
6195
6196 #ifdef FEATURE_SIMD
6197     // If we have GT_JTRUE(GT_EQ/NE(GT_SIMD((in)Equality, v1, v2), true/false)),
6198     // then we don't need to generate code for GT_EQ/GT_NE, since SIMD (in)Equality intrinsic
6199     // would set or clear Zero flag.
6200     if ((targetReg == REG_NA) && tree->OperIs(GT_EQ, GT_NE))
6201     {
6202         // Is it a SIMD (in)Equality that doesn't need to materialize result into a register?
6203         if ((op1->gtRegNum == REG_NA) && op1->IsSIMDEqualityOrInequality())
6204         {
6205             // Must be comparing against true or false.
6206             assert(op2->IsIntegralConst(0) || op2->IsIntegralConst(1));
6207             assert(op2->isContainedIntOrIImmed());
6208
6209             // In this case SIMD (in)Equality will set or clear
6210             // Zero flag, based on which GT_JTRUE would generate
6211             // the right conditional jump.
6212             return;
6213         }
6214     }
6215 #endif // FEATURE_SIMD
6216
6217     genConsumeOperands(tree);
6218
6219     // TODO-CQ: We should be able to support swapping op1 and op2 to generate cmp reg, imm.
6220     // https://github.com/dotnet/coreclr/issues/7270
6221     assert(!op1->isContainedIntOrIImmed()); // We no longer support
6222     assert(!varTypeIsFloating(op2Type));
6223
6224     instruction ins;
6225
6226     if (tree->OperIs(GT_TEST_EQ, GT_TEST_NE))
6227     {
6228         ins = INS_test;
6229     }
6230     else if (op1->isUsedFromReg() && op2->IsIntegralConst(0))
6231     {
6232         // We're comparing a register to 0 so we can generate "test reg1, reg1"
6233         // instead of the longer "cmp reg1, 0"
6234         ins = INS_test;
6235         op2 = op1;
6236     }
6237     else
6238     {
6239         ins = INS_cmp;
6240     }
6241
6242     var_types type;
6243
6244     if (op1Type == op2Type)
6245     {
6246         type = op1Type;
6247     }
6248     else if (genTypeSize(op1Type) == genTypeSize(op2Type))
6249     {
6250         // If the types are different but have the same size then we'll use TYP_INT or TYP_LONG.
6251         // This primarily deals with small type mixes (e.g. byte/ubyte) that need to be widened
6252         // and compared as int. We should not get long type mixes here but handle that as well
6253         // just in case.
6254         type = genTypeSize(op1Type) == 8 ? TYP_LONG : TYP_INT;
6255     }
6256     else
6257     {
6258         // In the types are different simply use TYP_INT. This deals with small type/int type
6259         // mixes (e.g. byte/short ubyte/int) that need to be widened and compared as int.
6260         // Lowering is expected to handle any mixes that involve long types (e.g. int/long).
6261         type = TYP_INT;
6262     }
6263
6264     // The common type cannot be larger than the machine word size
6265     assert(genTypeSize(type) <= genTypeSize(TYP_I_IMPL));
6266     // The common type cannot be smaller than any of the operand types, we're probably mixing int/long
6267     assert(genTypeSize(type) >= max(genTypeSize(op1Type), genTypeSize(op2Type)));
6268     // TYP_UINT and TYP_ULONG should not appear here, only small types can be unsigned
6269     assert(!varTypeIsUnsigned(type) || varTypeIsSmall(type));
6270     // Small unsigned int types (TYP_BOOL can use anything) should use unsigned comparisons
6271     assert(!(varTypeIsSmallInt(type) && varTypeIsUnsigned(type)) || ((tree->gtFlags & GTF_UNSIGNED) != 0));
6272     // If op1 is smaller then it cannot be in memory, we're probably missing a cast
6273     assert((genTypeSize(op1Type) >= genTypeSize(type)) || !op1->isUsedFromMemory());
6274     // If op2 is smaller then it cannot be in memory, we're probably missing a cast
6275     assert((genTypeSize(op2Type) >= genTypeSize(type)) || !op2->isUsedFromMemory());
6276     // If op2 is a constant then it should fit in the common type
6277     assert(!op2->IsCnsIntOrI() || genTypeCanRepresentValue(type, op2->AsIntCon()->IconValue()));
6278
6279     getEmitter()->emitInsBinary(ins, emitTypeSize(type), op1, op2);
6280
6281     // Are we evaluating this into a register?
6282     if (targetReg != REG_NA)
6283     {
6284         genSetRegToCond(targetReg, tree);
6285         genProduceReg(tree);
6286     }
6287 }
6288
6289 //-------------------------------------------------------------------------------------------
6290 // genSetRegToCond:  Set a register 'dstReg' to the appropriate one or zero value
6291 //                   corresponding to a binary Relational operator result.
6292 //
6293 // Arguments:
6294 //   dstReg          - The target register to set to 1 or 0
6295 //   tree            - The GenTree Relop node that was used to set the Condition codes
6296 //
6297 // Return Value:     none
6298 //
6299 // Notes:
6300 //    A full 64-bit value of either 1 or 0 is setup in the 'dstReg'
6301 //-------------------------------------------------------------------------------------------
6302
6303 void CodeGen::genSetRegToCond(regNumber dstReg, GenTreePtr tree)
6304 {
6305     noway_assert((genRegMask(dstReg) & RBM_BYTE_REGS) != 0);
6306
6307     emitJumpKind jumpKind[2];
6308     bool         branchToTrueLabel[2];
6309     genJumpKindsForTree(tree, jumpKind, branchToTrueLabel);
6310
6311     if (jumpKind[1] == EJ_NONE)
6312     {
6313         // Set (lower byte of) reg according to the flags
6314         inst_SET(jumpKind[0], dstReg);
6315     }
6316     else
6317     {
6318 #ifdef DEBUG
6319         // jmpKind[1] != EJ_NONE implies BEQ and BEN.UN of floating point values.
6320         // These are represented by two conditions.
6321         if (tree->gtOper == GT_EQ)
6322         {
6323             // This must be an ordered comparison.
6324             assert((tree->gtFlags & GTF_RELOP_NAN_UN) == 0);
6325         }
6326         else
6327         {
6328             // This must be BNE.UN
6329             assert((tree->gtOper == GT_NE) && ((tree->gtFlags & GTF_RELOP_NAN_UN) != 0));
6330         }
6331 #endif
6332
6333         // Here is the sample code generated in each case:
6334         // BEQ ==  cmp, jpe <false label>, je <true label>
6335         // That is, to materialize comparison reg needs to be set if PF=0 and ZF=1
6336         //      setnp reg  // if (PF==0) reg = 1 else reg = 0
6337         //      jpe L1     // Jmp if PF==1
6338         //      sete reg
6339         //  L1:
6340         //
6341         // BNE.UN == cmp, jpe <true label>, jne <true label>
6342         // That is, to materialize the comparison reg needs to be set if either PF=1 or ZF=0;
6343         //     setp reg
6344         //     jpe L1
6345         //     setne reg
6346         //  L1:
6347
6348         // reverse the jmpkind condition before setting dstReg if it is to false label.
6349         inst_SET(branchToTrueLabel[0] ? jumpKind[0] : emitter::emitReverseJumpKind(jumpKind[0]), dstReg);
6350
6351         BasicBlock* label = genCreateTempLabel();
6352         inst_JMP(jumpKind[0], label);
6353
6354         // second branch is always to true label
6355         assert(branchToTrueLabel[1]);
6356         inst_SET(jumpKind[1], dstReg);
6357         genDefineTempLabel(label);
6358     }
6359
6360     var_types treeType = tree->TypeGet();
6361     if (treeType == TYP_INT || treeType == TYP_LONG)
6362     {
6363         // Set the higher bytes to 0
6364         inst_RV_RV(ins_Move_Extend(TYP_UBYTE, true), dstReg, dstReg, TYP_UBYTE, emitTypeSize(TYP_UBYTE));
6365     }
6366     else
6367     {
6368         noway_assert(treeType == TYP_BYTE);
6369     }
6370 }
6371
6372 #if !defined(_TARGET_64BIT_)
6373 //------------------------------------------------------------------------
6374 // genIntToIntCast: Generate code for long to int casts on x86.
6375 //
6376 // Arguments:
6377 //    cast - The GT_CAST node
6378 //
6379 // Return Value:
6380 //    None.
6381 //
6382 // Assumptions:
6383 //    The cast node and its sources (via GT_LONG) must have been assigned registers.
6384 //    The destination cannot be a floating point type or a small integer type.
6385 //
6386 void CodeGen::genLongToIntCast(GenTree* cast)
6387 {
6388     assert(cast->OperGet() == GT_CAST);
6389
6390     GenTree* src = cast->gtGetOp1();
6391     noway_assert(src->OperGet() == GT_LONG);
6392
6393     genConsumeRegs(src);
6394
6395     var_types srcType  = ((cast->gtFlags & GTF_UNSIGNED) != 0) ? TYP_ULONG : TYP_LONG;
6396     var_types dstType  = cast->CastToType();
6397     regNumber loSrcReg = src->gtGetOp1()->gtRegNum;
6398     regNumber hiSrcReg = src->gtGetOp2()->gtRegNum;
6399     regNumber dstReg   = cast->gtRegNum;
6400
6401     assert((dstType == TYP_INT) || (dstType == TYP_UINT));
6402     assert(genIsValidIntReg(loSrcReg));
6403     assert(genIsValidIntReg(hiSrcReg));
6404     assert(genIsValidIntReg(dstReg));
6405
6406     if (cast->gtOverflow())
6407     {
6408         //
6409         // Generate an overflow check for [u]long to [u]int casts:
6410         //
6411         // long  -> int  - check if the upper 33 bits are all 0 or all 1
6412         //
6413         // ulong -> int  - check if the upper 33 bits are all 0
6414         //
6415         // long  -> uint - check if the upper 32 bits are all 0
6416         // ulong -> uint - check if the upper 32 bits are all 0
6417         //
6418
6419         if ((srcType == TYP_LONG) && (dstType == TYP_INT))
6420         {
6421             BasicBlock* allOne  = genCreateTempLabel();
6422             BasicBlock* success = genCreateTempLabel();
6423
6424             inst_RV_RV(INS_test, loSrcReg, loSrcReg, TYP_INT, EA_4BYTE);
6425             inst_JMP(EJ_js, allOne);
6426
6427             inst_RV_RV(INS_test, hiSrcReg, hiSrcReg, TYP_INT, EA_4BYTE);
6428             genJumpToThrowHlpBlk(EJ_jne, SCK_OVERFLOW);
6429             inst_JMP(EJ_jmp, success);
6430
6431             genDefineTempLabel(allOne);
6432             inst_RV_IV(INS_cmp, hiSrcReg, -1, EA_4BYTE);
6433             genJumpToThrowHlpBlk(EJ_jne, SCK_OVERFLOW);
6434
6435             genDefineTempLabel(success);
6436         }
6437         else
6438         {
6439             if ((srcType == TYP_ULONG) && (dstType == TYP_INT))
6440             {
6441                 inst_RV_RV(INS_test, loSrcReg, loSrcReg, TYP_INT, EA_4BYTE);
6442                 genJumpToThrowHlpBlk(EJ_js, SCK_OVERFLOW);
6443             }
6444
6445             inst_RV_RV(INS_test, hiSrcReg, hiSrcReg, TYP_INT, EA_4BYTE);
6446             genJumpToThrowHlpBlk(EJ_jne, SCK_OVERFLOW);
6447         }
6448     }
6449
6450     if (dstReg != loSrcReg)
6451     {
6452         inst_RV_RV(INS_mov, dstReg, loSrcReg, TYP_INT, EA_4BYTE);
6453     }
6454
6455     genProduceReg(cast);
6456 }
6457 #endif
6458
6459 //------------------------------------------------------------------------
6460 // genIntToIntCast: Generate code for an integer cast
6461 //    This method handles integer overflow checking casts
6462 //    as well as ordinary integer casts.
6463 //
6464 // Arguments:
6465 //    treeNode - The GT_CAST node
6466 //
6467 // Return Value:
6468 //    None.
6469 //
6470 // Assumptions:
6471 //    The treeNode is not a contained node and must have an assigned register.
6472 //    For a signed convert from byte, the source must be in a byte-addressable register.
6473 //    Neither the source nor target type can be a floating point type.
6474 //
6475 // TODO-XArch-CQ: Allow castOp to be a contained node without an assigned register.
6476 // TODO: refactor to use getCastDescription
6477 //
6478 void CodeGen::genIntToIntCast(GenTreePtr treeNode)
6479 {
6480     assert(treeNode->OperGet() == GT_CAST);
6481
6482     GenTreePtr castOp  = treeNode->gtCast.CastOp();
6483     var_types  srcType = genActualType(castOp->TypeGet());
6484
6485 #if !defined(_TARGET_64BIT_)
6486     if (varTypeIsLong(srcType))
6487     {
6488         genLongToIntCast(treeNode);
6489         return;
6490     }
6491 #endif // !defined(_TARGET_64BIT_)
6492
6493     regNumber targetReg     = treeNode->gtRegNum;
6494     regNumber sourceReg     = castOp->gtRegNum;
6495     var_types dstType       = treeNode->CastToType();
6496     bool      isUnsignedDst = varTypeIsUnsigned(dstType);
6497     bool      isUnsignedSrc = varTypeIsUnsigned(srcType);
6498
6499     // if necessary, force the srcType to unsigned when the GT_UNSIGNED flag is set
6500     if (!isUnsignedSrc && (treeNode->gtFlags & GTF_UNSIGNED) != 0)
6501     {
6502         srcType       = genUnsignedType(srcType);
6503         isUnsignedSrc = true;
6504     }
6505
6506     bool requiresOverflowCheck = false;
6507     bool needAndAfter          = false;
6508
6509     assert(genIsValidIntReg(targetReg));
6510     assert(genIsValidIntReg(sourceReg));
6511
6512     instruction ins  = INS_invalid;
6513     emitAttr    size = EA_UNKNOWN;
6514
6515     if (genTypeSize(srcType) < genTypeSize(dstType))
6516     {
6517         // Widening cast
6518
6519         // Is this an Overflow checking cast?
6520         // We only need to handle one case, as the other casts can never overflow.
6521         //   cast from TYP_INT to TYP_ULONG
6522         //
6523         if (treeNode->gtOverflow() && (srcType == TYP_INT) && (dstType == TYP_ULONG))
6524         {
6525             requiresOverflowCheck = true;
6526             size                  = EA_ATTR(genTypeSize(srcType));
6527             ins                   = INS_mov;
6528         }
6529         else
6530         {
6531             // we need the source size
6532             size = EA_ATTR(genTypeSize(srcType));
6533             noway_assert(size < EA_PTRSIZE);
6534
6535             ins = ins_Move_Extend(srcType, castOp->InReg());
6536
6537             /*
6538                 Special case: ins_Move_Extend assumes the destination type is no bigger
6539                 than TYP_INT.  movsx and movzx can already extend all the way to
6540                 64-bit, and a regular 32-bit mov clears the high 32 bits (like the non-existant movzxd),
6541                 but for a sign extension from TYP_INT to TYP_LONG, we need to use movsxd opcode.
6542             */
6543             if (!isUnsignedSrc && !isUnsignedDst && (size == EA_4BYTE) && (genTypeSize(dstType) > EA_4BYTE))
6544             {
6545 #ifdef _TARGET_X86_
6546                 NYI_X86("Cast to 64 bit for x86/RyuJIT");
6547 #else  // !_TARGET_X86_
6548                 ins = INS_movsxd;
6549 #endif // !_TARGET_X86_
6550             }
6551
6552             /*
6553                 Special case: for a cast of byte to char we first
6554                 have to expand the byte (w/ sign extension), then
6555                 mask off the high bits.
6556                 Use 'movsx' followed by 'and'
6557             */
6558             if (!isUnsignedSrc && isUnsignedDst && (genTypeSize(dstType) < EA_4BYTE))
6559             {
6560                 noway_assert(genTypeSize(dstType) == EA_2BYTE && size == EA_1BYTE);
6561                 needAndAfter = true;
6562             }
6563         }
6564     }
6565     else
6566     {
6567         // Narrowing cast, or sign-changing cast
6568         noway_assert(genTypeSize(srcType) >= genTypeSize(dstType));
6569
6570         // Is this an Overflow checking cast?
6571         if (treeNode->gtOverflow())
6572         {
6573             requiresOverflowCheck = true;
6574             size                  = EA_ATTR(genTypeSize(srcType));
6575             ins                   = INS_mov;
6576         }
6577         else
6578         {
6579             size = EA_ATTR(genTypeSize(dstType));
6580             ins  = ins_Move_Extend(dstType, castOp->InReg());
6581         }
6582     }
6583
6584     noway_assert(ins != INS_invalid);
6585
6586     genConsumeReg(castOp);
6587
6588     if (requiresOverflowCheck)
6589     {
6590         ssize_t typeMin        = 0;
6591         ssize_t typeMax        = 0;
6592         ssize_t typeMask       = 0;
6593         bool    needScratchReg = false;
6594         bool    signCheckOnly  = false;
6595
6596         /* Do we need to compare the value, or just check masks */
6597
6598         switch (dstType)
6599         {
6600             case TYP_BYTE:
6601                 typeMask = ssize_t((int)0xFFFFFF80);
6602                 typeMin  = SCHAR_MIN;
6603                 typeMax  = SCHAR_MAX;
6604                 break;
6605
6606             case TYP_UBYTE:
6607                 typeMask = ssize_t((int)0xFFFFFF00L);
6608                 break;
6609
6610             case TYP_SHORT:
6611                 typeMask = ssize_t((int)0xFFFF8000);
6612                 typeMin  = SHRT_MIN;
6613                 typeMax  = SHRT_MAX;
6614                 break;
6615
6616             case TYP_CHAR:
6617                 typeMask = ssize_t((int)0xFFFF0000L);
6618                 break;
6619
6620             case TYP_INT:
6621                 if (srcType == TYP_UINT)
6622                 {
6623                     signCheckOnly = true;
6624                 }
6625                 else
6626                 {
6627                     typeMask = 0xFFFFFFFF80000000LL;
6628                     typeMin  = INT_MIN;
6629                     typeMax  = INT_MAX;
6630                 }
6631                 break;
6632
6633             case TYP_UINT:
6634                 if (srcType == TYP_INT)
6635                 {
6636                     signCheckOnly = true;
6637                 }
6638                 else
6639                 {
6640                     needScratchReg = true;
6641                 }
6642                 break;
6643
6644             case TYP_LONG:
6645                 noway_assert(srcType == TYP_ULONG);
6646                 signCheckOnly = true;
6647                 break;
6648
6649             case TYP_ULONG:
6650                 noway_assert((srcType == TYP_LONG) || (srcType == TYP_INT));
6651                 signCheckOnly = true;
6652                 break;
6653
6654             default:
6655                 NO_WAY("Unknown type");
6656                 return;
6657         }
6658
6659         if (signCheckOnly)
6660         {
6661             // We only need to check for a negative value in sourceReg
6662             inst_RV_IV(INS_cmp, sourceReg, 0, size);
6663             genJumpToThrowHlpBlk(EJ_jl, SCK_OVERFLOW);
6664         }
6665         else
6666         {
6667             regNumber tmpReg = REG_NA;
6668
6669             if (needScratchReg)
6670             {
6671                 // We need an additional temp register
6672                 // Make sure we have exactly one allocated.
6673                 assert(treeNode->gtRsvdRegs != RBM_NONE);
6674                 assert(genCountBits(treeNode->gtRsvdRegs) == 1);
6675                 tmpReg = genRegNumFromMask(treeNode->gtRsvdRegs);
6676             }
6677
6678             // When we are converting from unsigned or to unsigned, we
6679             // will only have to check for any bits set using 'typeMask'
6680             if (isUnsignedSrc || isUnsignedDst)
6681             {
6682                 if (needScratchReg)
6683                 {
6684                     inst_RV_RV(INS_mov, tmpReg, sourceReg, TYP_LONG); // Move the 64-bit value to a writeable temp reg
6685                     inst_RV_SH(INS_SHIFT_RIGHT_LOGICAL, size, tmpReg, 32); // Shift right by 32 bits
6686                     genJumpToThrowHlpBlk(EJ_jne, SCK_OVERFLOW);            // Thow if result shift is non-zero
6687                 }
6688                 else
6689                 {
6690                     noway_assert(typeMask != 0);
6691                     inst_RV_IV(INS_TEST, sourceReg, typeMask, size);
6692                     genJumpToThrowHlpBlk(EJ_jne, SCK_OVERFLOW);
6693                 }
6694             }
6695             else
6696             {
6697                 // For a narrowing signed cast
6698                 //
6699                 // We must check the value is in a signed range.
6700
6701                 // Compare with the MAX
6702
6703                 noway_assert((typeMin != 0) && (typeMax != 0));
6704
6705                 inst_RV_IV(INS_cmp, sourceReg, typeMax, size);
6706                 genJumpToThrowHlpBlk(EJ_jg, SCK_OVERFLOW);
6707
6708                 // Compare with the MIN
6709
6710                 inst_RV_IV(INS_cmp, sourceReg, typeMin, size);
6711                 genJumpToThrowHlpBlk(EJ_jl, SCK_OVERFLOW);
6712             }
6713         }
6714
6715         if (targetReg != sourceReg
6716 #ifdef _TARGET_AMD64_
6717             // On amd64, we can hit this path for a same-register
6718             // 4-byte to 8-byte widening conversion, and need to
6719             // emit the instruction to set the high bits correctly.
6720             || (EA_ATTR(genTypeSize(dstType)) == EA_8BYTE && EA_ATTR(genTypeSize(srcType)) == EA_4BYTE)
6721 #endif // _TARGET_AMD64_
6722                 )
6723             inst_RV_RV(ins, targetReg, sourceReg, srcType, size);
6724     }
6725     else // non-overflow checking cast
6726     {
6727         noway_assert(size < EA_PTRSIZE || srcType == dstType);
6728
6729         // We may have code transformations that result in casts where srcType is the same as dstType.
6730         // e.g. Bug 824281, in which a comma is split by the rationalizer, leaving an assignment of a
6731         // long constant to a long lclVar.
6732         if (srcType == dstType)
6733         {
6734             ins = INS_mov;
6735         }
6736         /* Is the value sitting in a non-byte-addressable register? */
6737         else if (castOp->InReg() && (size == EA_1BYTE) && !isByteReg(sourceReg))
6738         {
6739             if (isUnsignedDst)
6740             {
6741                 // for unsigned values we can AND, so it need not be a byte register
6742                 ins = INS_AND;
6743             }
6744             else
6745             {
6746                 // Move the value into a byte register
6747                 noway_assert(!"Signed byte convert from non-byte-addressable register");
6748             }
6749
6750             /* Generate "mov targetReg, castOp->gtReg */
6751             if (targetReg != sourceReg)
6752             {
6753                 inst_RV_RV(INS_mov, targetReg, sourceReg, srcType);
6754             }
6755         }
6756
6757         if (ins == INS_AND)
6758         {
6759             noway_assert((needAndAfter == false) && isUnsignedDst);
6760
6761             /* Generate "and reg, MASK */
6762             unsigned fillPattern;
6763             if (size == EA_1BYTE)
6764             {
6765                 fillPattern = 0xff;
6766             }
6767             else if (size == EA_2BYTE)
6768             {
6769                 fillPattern = 0xffff;
6770             }
6771             else
6772             {
6773                 fillPattern = 0xffffffff;
6774             }
6775
6776             inst_RV_IV(INS_AND, targetReg, fillPattern, EA_4BYTE);
6777         }
6778 #ifdef _TARGET_AMD64_
6779         else if (ins == INS_movsxd)
6780         {
6781             noway_assert(!needAndAfter);
6782             inst_RV_RV(ins, targetReg, sourceReg, srcType, size);
6783         }
6784 #endif // _TARGET_AMD64_
6785         else if (ins == INS_mov)
6786         {
6787             noway_assert(!needAndAfter);
6788             if (targetReg != sourceReg
6789 #ifdef _TARGET_AMD64_
6790                 // On amd64, 'mov' is the opcode used to zero-extend from
6791                 // 4 bytes to 8 bytes.
6792                 || (EA_ATTR(genTypeSize(dstType)) == EA_8BYTE && EA_ATTR(genTypeSize(srcType)) == EA_4BYTE)
6793 #endif // _TARGET_AMD64_
6794                     )
6795             {
6796                 inst_RV_RV(ins, targetReg, sourceReg, srcType, size);
6797             }
6798         }
6799         else
6800         {
6801             noway_assert(ins == INS_movsx || ins == INS_movzx);
6802
6803             /* Generate "mov targetReg, castOp->gtReg */
6804             inst_RV_RV(ins, targetReg, sourceReg, srcType, size);
6805
6806             /* Mask off high bits for cast from byte to char */
6807             if (needAndAfter)
6808             {
6809                 noway_assert(genTypeSize(dstType) == 2 && ins == INS_movsx);
6810                 inst_RV_IV(INS_AND, targetReg, 0xFFFF, EA_4BYTE);
6811             }
6812         }
6813     }
6814
6815     genProduceReg(treeNode);
6816 }
6817
6818 //------------------------------------------------------------------------
6819 // genFloatToFloatCast: Generate code for a cast between float and double
6820 //
6821 // Arguments:
6822 //    treeNode - The GT_CAST node
6823 //
6824 // Return Value:
6825 //    None.
6826 //
6827 // Assumptions:
6828 //    Cast is a non-overflow conversion.
6829 //    The treeNode must have an assigned register.
6830 //    The cast is between float and double or vice versa.
6831 //
6832 void CodeGen::genFloatToFloatCast(GenTreePtr treeNode)
6833 {
6834     // float <--> double conversions are always non-overflow ones
6835     assert(treeNode->OperGet() == GT_CAST);
6836     assert(!treeNode->gtOverflow());
6837
6838     regNumber targetReg = treeNode->gtRegNum;
6839     assert(genIsValidFloatReg(targetReg));
6840
6841     GenTreePtr op1 = treeNode->gtOp.gtOp1;
6842 #ifdef DEBUG
6843     // If not contained, must be a valid float reg.
6844     if (op1->isUsedFromReg())
6845     {
6846         assert(genIsValidFloatReg(op1->gtRegNum));
6847     }
6848 #endif
6849
6850     var_types dstType = treeNode->CastToType();
6851     var_types srcType = op1->TypeGet();
6852     assert(varTypeIsFloating(srcType) && varTypeIsFloating(dstType));
6853
6854     genConsumeOperands(treeNode->AsOp());
6855     if (srcType == dstType && (op1->isUsedFromReg() && (targetReg == op1->gtRegNum)))
6856     {
6857         // source and destinations types are the same and also reside in the same register.
6858         // we just need to consume and produce the reg in this case.
6859         ;
6860     }
6861     else
6862     {
6863         instruction ins = ins_FloatConv(dstType, srcType);
6864         getEmitter()->emitInsBinary(ins, emitTypeSize(dstType), treeNode, op1);
6865     }
6866
6867     genProduceReg(treeNode);
6868 }
6869
6870 //------------------------------------------------------------------------
6871 // genIntToFloatCast: Generate code to cast an int/long to float/double
6872 //
6873 // Arguments:
6874 //    treeNode - The GT_CAST node
6875 //
6876 // Return Value:
6877 //    None.
6878 //
6879 // Assumptions:
6880 //    Cast is a non-overflow conversion.
6881 //    The treeNode must have an assigned register.
6882 //    SrcType= int32/uint32/int64/uint64 and DstType=float/double.
6883 //
6884 void CodeGen::genIntToFloatCast(GenTreePtr treeNode)
6885 {
6886     // int type --> float/double conversions are always non-overflow ones
6887     assert(treeNode->OperGet() == GT_CAST);
6888     assert(!treeNode->gtOverflow());
6889
6890     regNumber targetReg = treeNode->gtRegNum;
6891     assert(genIsValidFloatReg(targetReg));
6892
6893     GenTreePtr op1 = treeNode->gtOp.gtOp1;
6894 #ifdef DEBUG
6895     if (op1->isUsedFromReg())
6896     {
6897         assert(genIsValidIntReg(op1->gtRegNum));
6898     }
6899 #endif
6900
6901     var_types dstType = treeNode->CastToType();
6902     var_types srcType = op1->TypeGet();
6903     assert(!varTypeIsFloating(srcType) && varTypeIsFloating(dstType));
6904
6905 #if !defined(_TARGET_64BIT_)
6906     // We expect morph to replace long to float/double casts with helper calls
6907     noway_assert(!varTypeIsLong(srcType));
6908 #endif // !defined(_TARGET_64BIT_)
6909
6910     // Since xarch emitter doesn't handle reporting gc-info correctly while casting away gc-ness we
6911     // ensure srcType of a cast is non gc-type.  Codegen should never see BYREF as source type except
6912     // for GT_LCL_VAR_ADDR and GT_LCL_FLD_ADDR that represent stack addresses and can be considered
6913     // as TYP_I_IMPL. In all other cases where src operand is a gc-type and not known to be on stack,
6914     // Front-end (see fgMorphCast()) ensures this by assigning gc-type local to a non gc-type
6915     // temp and using temp as operand of cast operation.
6916     if (srcType == TYP_BYREF)
6917     {
6918         noway_assert(op1->OperGet() == GT_LCL_VAR_ADDR || op1->OperGet() == GT_LCL_FLD_ADDR);
6919         srcType = TYP_I_IMPL;
6920     }
6921
6922     // force the srcType to unsigned if GT_UNSIGNED flag is set
6923     if (treeNode->gtFlags & GTF_UNSIGNED)
6924     {
6925         srcType = genUnsignedType(srcType);
6926     }
6927
6928     noway_assert(!varTypeIsGC(srcType));
6929
6930     // We should never be seeing srcType whose size is not sizeof(int) nor sizeof(long).
6931     // For conversions from byte/sbyte/int16/uint16 to float/double, we would expect
6932     // either the front-end or lowering phase to have generated two levels of cast.
6933     // The first one is for widening smaller int type to int32 and the second one is
6934     // to the float/double.
6935     emitAttr srcSize = EA_ATTR(genTypeSize(srcType));
6936     noway_assert((srcSize == EA_ATTR(genTypeSize(TYP_INT))) || (srcSize == EA_ATTR(genTypeSize(TYP_LONG))));
6937
6938     // Also we don't expect to see uint32 -> float/double and uint64 -> float conversions
6939     // here since they should have been lowered apropriately.
6940     noway_assert(srcType != TYP_UINT);
6941     noway_assert((srcType != TYP_ULONG) || (dstType != TYP_FLOAT));
6942
6943     // To convert int to a float/double, cvtsi2ss/sd SSE2 instruction is used
6944     // which does a partial write to lower 4/8 bytes of xmm register keeping the other
6945     // upper bytes unmodified.  If "cvtsi2ss/sd xmmReg, r32/r64" occurs inside a loop,
6946     // the partial write could introduce a false dependency and could cause a stall
6947     // if there are further uses of xmmReg. We have such a case occuring with a
6948     // customer reported version of SpectralNorm benchmark, resulting in 2x perf
6949     // regression.  To avoid false dependency, we emit "xorps xmmReg, xmmReg" before
6950     // cvtsi2ss/sd instruction.
6951
6952     genConsumeOperands(treeNode->AsOp());
6953     getEmitter()->emitIns_R_R(INS_xorps, EA_4BYTE, treeNode->gtRegNum, treeNode->gtRegNum);
6954
6955     // Note that here we need to specify srcType that will determine
6956     // the size of source reg/mem operand and rex.w prefix.
6957     instruction ins = ins_FloatConv(dstType, TYP_INT);
6958     getEmitter()->emitInsBinary(ins, emitTypeSize(srcType), treeNode, op1);
6959
6960     // Handle the case of srcType = TYP_ULONG. SSE2 conversion instruction
6961     // will interpret ULONG value as LONG.  Hence we need to adjust the
6962     // result if sign-bit of srcType is set.
6963     if (srcType == TYP_ULONG)
6964     {
6965         // The instruction sequence below is less accurate than what clang
6966         // and gcc generate. However, we keep the current sequence for backward compatiblity.
6967         // If we change the instructions below, FloatingPointUtils::convertUInt64ToDobule
6968         // should be also updated for consistent conversion result.
6969         assert(dstType == TYP_DOUBLE);
6970         assert(op1->isUsedFromReg());
6971
6972         // Set the flags without modifying op1.
6973         // test op1Reg, op1Reg
6974         inst_RV_RV(INS_test, op1->gtRegNum, op1->gtRegNum, srcType);
6975
6976         // No need to adjust result if op1 >= 0 i.e. positive
6977         // Jge label
6978         BasicBlock* label = genCreateTempLabel();
6979         inst_JMP(EJ_jge, label);
6980
6981         // Adjust the result
6982         // result = result + 0x43f00000 00000000
6983         // addsd resultReg,  0x43f00000 00000000
6984         GenTreePtr* cns = &u8ToDblBitmask;
6985         if (*cns == nullptr)
6986         {
6987             double d;
6988             static_assert_no_msg(sizeof(double) == sizeof(__int64));
6989             *((__int64*)&d) = 0x43f0000000000000LL;
6990
6991             *cns = genMakeConst(&d, dstType, treeNode, true);
6992         }
6993         inst_RV_TT(INS_addsd, treeNode->gtRegNum, *cns);
6994
6995         genDefineTempLabel(label);
6996     }
6997
6998     genProduceReg(treeNode);
6999 }
7000
7001 //------------------------------------------------------------------------
7002 // genFloatToIntCast: Generate code to cast float/double to int/long
7003 //
7004 // Arguments:
7005 //    treeNode - The GT_CAST node
7006 //
7007 // Return Value:
7008 //    None.
7009 //
7010 // Assumptions:
7011 //    Cast is a non-overflow conversion.
7012 //    The treeNode must have an assigned register.
7013 //    SrcType=float/double and DstType= int32/uint32/int64/uint64
7014 //
7015 // TODO-XArch-CQ: (Low-pri) - generate in-line code when DstType = uint64
7016 //
7017 void CodeGen::genFloatToIntCast(GenTreePtr treeNode)
7018 {
7019     // we don't expect to see overflow detecting float/double --> int type conversions here
7020     // as they should have been converted into helper calls by front-end.
7021     assert(treeNode->OperGet() == GT_CAST);
7022     assert(!treeNode->gtOverflow());
7023
7024     regNumber targetReg = treeNode->gtRegNum;
7025     assert(genIsValidIntReg(targetReg));
7026
7027     GenTreePtr op1 = treeNode->gtOp.gtOp1;
7028 #ifdef DEBUG
7029     if (op1->isUsedFromReg())
7030     {
7031         assert(genIsValidFloatReg(op1->gtRegNum));
7032     }
7033 #endif
7034
7035     var_types dstType = treeNode->CastToType();
7036     var_types srcType = op1->TypeGet();
7037     assert(varTypeIsFloating(srcType) && !varTypeIsFloating(dstType));
7038
7039     // We should never be seeing dstType whose size is neither sizeof(TYP_INT) nor sizeof(TYP_LONG).
7040     // For conversions to byte/sbyte/int16/uint16 from float/double, we would expect the
7041     // front-end or lowering phase to have generated two levels of cast. The first one is
7042     // for float or double to int32/uint32 and the second one for narrowing int32/uint32 to
7043     // the required smaller int type.
7044     emitAttr dstSize = EA_ATTR(genTypeSize(dstType));
7045     noway_assert((dstSize == EA_ATTR(genTypeSize(TYP_INT))) || (dstSize == EA_ATTR(genTypeSize(TYP_LONG))));
7046
7047     // We shouldn't be seeing uint64 here as it should have been converted
7048     // into a helper call by either front-end or lowering phase.
7049     noway_assert(!varTypeIsUnsigned(dstType) || (dstSize != EA_ATTR(genTypeSize(TYP_LONG))));
7050
7051     // If the dstType is TYP_UINT, we have 32-bits to encode the
7052     // float number. Any of 33rd or above bits can be the sign bit.
7053     // To acheive it we pretend as if we are converting it to a long.
7054     if (varTypeIsUnsigned(dstType) && (dstSize == EA_ATTR(genTypeSize(TYP_INT))))
7055     {
7056         dstType = TYP_LONG;
7057     }
7058
7059     // Note that we need to specify dstType here so that it will determine
7060     // the size of destination integer register and also the rex.w prefix.
7061     genConsumeOperands(treeNode->AsOp());
7062     instruction ins = ins_FloatConv(TYP_INT, srcType);
7063     getEmitter()->emitInsBinary(ins, emitTypeSize(dstType), treeNode, op1);
7064     genProduceReg(treeNode);
7065 }
7066
7067 //------------------------------------------------------------------------
7068 // genCkfinite: Generate code for ckfinite opcode.
7069 //
7070 // Arguments:
7071 //    treeNode - The GT_CKFINITE node
7072 //
7073 // Return Value:
7074 //    None.
7075 //
7076 // Assumptions:
7077 //    GT_CKFINITE node has reserved an internal register.
7078 //
7079 // TODO-XArch-CQ - mark the operand as contained if known to be in
7080 // memory (e.g. field or an array element).
7081 //
7082 void CodeGen::genCkfinite(GenTreePtr treeNode)
7083 {
7084     assert(treeNode->OperGet() == GT_CKFINITE);
7085
7086     GenTreePtr op1        = treeNode->gtOp.gtOp1;
7087     var_types  targetType = treeNode->TypeGet();
7088     int        expMask    = (targetType == TYP_FLOAT) ? 0x7F800000 : 0x7FF00000; // Bit mask to extract exponent.
7089     regNumber  targetReg  = treeNode->gtRegNum;
7090
7091     // Extract exponent into a register.
7092     assert(treeNode->gtRsvdRegs != RBM_NONE);
7093     assert(genCountBits(treeNode->gtRsvdRegs) == 1);
7094     regNumber tmpReg = genRegNumFromMask(treeNode->gtRsvdRegs);
7095
7096     genConsumeReg(op1);
7097
7098 #ifdef _TARGET_64BIT_
7099
7100     // Copy the floating-point value to an integer register. If we copied a float to a long, then
7101     // right-shift the value so the high 32 bits of the floating-point value sit in the low 32
7102     // bits of the integer register.
7103     instruction ins = ins_CopyFloatToInt(targetType, (targetType == TYP_FLOAT) ? TYP_INT : TYP_LONG);
7104     inst_RV_RV(ins, op1->gtRegNum, tmpReg, targetType);
7105     if (targetType == TYP_DOUBLE)
7106     {
7107         // right shift by 32 bits to get to exponent.
7108         inst_RV_SH(INS_shr, EA_8BYTE, tmpReg, 32);
7109     }
7110
7111     // Mask exponent with all 1's and check if the exponent is all 1's
7112     inst_RV_IV(INS_and, tmpReg, expMask, EA_4BYTE);
7113     inst_RV_IV(INS_cmp, tmpReg, expMask, EA_4BYTE);
7114
7115     // If exponent is all 1's, throw ArithmeticException
7116     genJumpToThrowHlpBlk(EJ_je, SCK_ARITH_EXCPN);
7117
7118     // if it is a finite value copy it to targetReg
7119     if (targetReg != op1->gtRegNum)
7120     {
7121         inst_RV_RV(ins_Copy(targetType), targetReg, op1->gtRegNum, targetType);
7122     }
7123
7124 #else // !_TARGET_64BIT_
7125
7126     // If the target type is TYP_DOUBLE, we want to extract the high 32 bits into the register.
7127     // There is no easy way to do this. To not require an extra register, we'll use shuffles
7128     // to move the high 32 bits into the low 32 bits, then then shuffle it back, since we
7129     // need to produce the value into the target register.
7130     //
7131     // For TYP_DOUBLE, we'll generate (for targetReg != op1->gtRegNum):
7132     //    movaps targetReg, op1->gtRegNum
7133     //    shufps targetReg, targetReg, 0xB1    // WZYX => ZWXY
7134     //    mov_xmm2i tmpReg, targetReg          // tmpReg <= Y
7135     //    and tmpReg, <mask>
7136     //    cmp tmpReg, <mask>
7137     //    je <throw block>
7138     //    movaps targetReg, op1->gtRegNum   // copy the value again, instead of un-shuffling it
7139     //
7140     // For TYP_DOUBLE with (targetReg == op1->gtRegNum):
7141     //    shufps targetReg, targetReg, 0xB1    // WZYX => ZWXY
7142     //    mov_xmm2i tmpReg, targetReg          // tmpReg <= Y
7143     //    and tmpReg, <mask>
7144     //    cmp tmpReg, <mask>
7145     //    je <throw block>
7146     //    shufps targetReg, targetReg, 0xB1    // ZWXY => WZYX
7147     //
7148     // For TYP_FLOAT, it's the same as _TARGET_64BIT_:
7149     //    mov_xmm2i tmpReg, targetReg          // tmpReg <= low 32 bits
7150     //    and tmpReg, <mask>
7151     //    cmp tmpReg, <mask>
7152     //    je <throw block>
7153     //    movaps targetReg, op1->gtRegNum      // only if targetReg != op1->gtRegNum
7154
7155     regNumber copyToTmpSrcReg; // The register we'll copy to the integer temp.
7156
7157     if (targetType == TYP_DOUBLE)
7158     {
7159         if (targetReg != op1->gtRegNum)
7160         {
7161             inst_RV_RV(ins_Copy(targetType), targetReg, op1->gtRegNum, targetType);
7162         }
7163         inst_RV_RV_IV(INS_shufps, EA_16BYTE, targetReg, targetReg, 0xb1);
7164         copyToTmpSrcReg = targetReg;
7165     }
7166     else
7167     {
7168         copyToTmpSrcReg = op1->gtRegNum;
7169     }
7170
7171     // Copy only the low 32 bits. This will be the high order 32 bits of the floating-point
7172     // value, no matter the floating-point type.
7173     inst_RV_RV(ins_CopyFloatToInt(TYP_FLOAT, TYP_INT), copyToTmpSrcReg, tmpReg, TYP_FLOAT);
7174
7175     // Mask exponent with all 1's and check if the exponent is all 1's
7176     inst_RV_IV(INS_and, tmpReg, expMask, EA_4BYTE);
7177     inst_RV_IV(INS_cmp, tmpReg, expMask, EA_4BYTE);
7178
7179     // If exponent is all 1's, throw ArithmeticException
7180     genJumpToThrowHlpBlk(EJ_je, SCK_ARITH_EXCPN);
7181
7182     if (targetReg != op1->gtRegNum)
7183     {
7184         // In both the TYP_FLOAT and TYP_DOUBLE case, the op1 register is untouched,
7185         // so copy it to the targetReg. This is faster and smaller for TYP_DOUBLE
7186         // than re-shuffling the targetReg.
7187         inst_RV_RV(ins_Copy(targetType), targetReg, op1->gtRegNum, targetType);
7188     }
7189     else if (targetType == TYP_DOUBLE)
7190     {
7191         // We need to re-shuffle the targetReg to get the correct result.
7192         inst_RV_RV_IV(INS_shufps, EA_16BYTE, targetReg, targetReg, 0xb1);
7193     }
7194
7195 #endif // !_TARGET_64BIT_
7196
7197     genProduceReg(treeNode);
7198 }
7199
7200 #ifdef _TARGET_AMD64_
7201 int CodeGenInterface::genSPtoFPdelta()
7202 {
7203     int delta;
7204
7205 #ifdef UNIX_AMD64_ABI
7206
7207     // We require frame chaining on Unix to support native tool unwinding (such as
7208     // unwinding by the native debugger). We have a CLR-only extension to the
7209     // unwind codes (UWOP_SET_FPREG_LARGE) to support SP->FP offsets larger than 240.
7210     // If Unix ever supports EnC, the RSP == RBP assumption will have to be reevaluated.
7211     delta = genTotalFrameSize();
7212
7213 #else // !UNIX_AMD64_ABI
7214
7215     // As per Amd64 ABI, RBP offset from initial RSP can be between 0 and 240 if
7216     // RBP needs to be reported in unwind codes.  This case would arise for methods
7217     // with localloc.
7218     if (compiler->compLocallocUsed)
7219     {
7220         // We cannot base delta computation on compLclFrameSize since it changes from
7221         // tentative to final frame layout and hence there is a possibility of
7222         // under-estimating offset of vars from FP, which in turn results in under-
7223         // estimating instruction size.
7224         //
7225         // To be predictive and so as never to under-estimate offset of vars from FP
7226         // we will always position FP at min(240, outgoing arg area size).
7227         delta = Min(240, (int)compiler->lvaOutgoingArgSpaceSize);
7228     }
7229     else if (compiler->opts.compDbgEnC)
7230     {
7231         // vm assumption on EnC methods is that rsp and rbp are equal
7232         delta = 0;
7233     }
7234     else
7235     {
7236         delta = genTotalFrameSize();
7237     }
7238
7239 #endif // !UNIX_AMD64_ABI
7240
7241     return delta;
7242 }
7243
7244 //---------------------------------------------------------------------
7245 // genTotalFrameSize - return the total size of the stack frame, including local size,
7246 // callee-saved register size, etc. For AMD64, this does not include the caller-pushed
7247 // return address.
7248 //
7249 // Return value:
7250 //    Total frame size
7251 //
7252
7253 int CodeGenInterface::genTotalFrameSize()
7254 {
7255     assert(!IsUninitialized(compiler->compCalleeRegsPushed));
7256
7257     int totalFrameSize = compiler->compCalleeRegsPushed * REGSIZE_BYTES + compiler->compLclFrameSize;
7258
7259     assert(totalFrameSize >= 0);
7260     return totalFrameSize;
7261 }
7262
7263 //---------------------------------------------------------------------
7264 // genCallerSPtoFPdelta - return the offset from Caller-SP to the frame pointer.
7265 // This number is going to be negative, since the Caller-SP is at a higher
7266 // address than the frame pointer.
7267 //
7268 // There must be a frame pointer to call this function!
7269 //
7270 // We can't compute this directly from the Caller-SP, since the frame pointer
7271 // is based on a maximum delta from Initial-SP, so first we find SP, then
7272 // compute the FP offset.
7273
7274 int CodeGenInterface::genCallerSPtoFPdelta()
7275 {
7276     assert(isFramePointerUsed());
7277     int callerSPtoFPdelta;
7278
7279     callerSPtoFPdelta = genCallerSPtoInitialSPdelta() + genSPtoFPdelta();
7280
7281     assert(callerSPtoFPdelta <= 0);
7282     return callerSPtoFPdelta;
7283 }
7284
7285 //---------------------------------------------------------------------
7286 // genCallerSPtoInitialSPdelta - return the offset from Caller-SP to Initial SP.
7287 //
7288 // This number will be negative.
7289
7290 int CodeGenInterface::genCallerSPtoInitialSPdelta()
7291 {
7292     int callerSPtoSPdelta = 0;
7293
7294     callerSPtoSPdelta -= genTotalFrameSize();
7295     callerSPtoSPdelta -= REGSIZE_BYTES; // caller-pushed return address
7296
7297     // compCalleeRegsPushed does not account for the frame pointer
7298     // TODO-Cleanup: shouldn't this be part of genTotalFrameSize?
7299     if (isFramePointerUsed())
7300     {
7301         callerSPtoSPdelta -= REGSIZE_BYTES;
7302     }
7303
7304     assert(callerSPtoSPdelta <= 0);
7305     return callerSPtoSPdelta;
7306 }
7307 #endif // _TARGET_AMD64_
7308
7309 //-----------------------------------------------------------------------------------------
7310 // genSSE2BitwiseOp - generate SSE2 code for the given oper as "Operand BitWiseOp BitMask"
7311 //
7312 // Arguments:
7313 //    treeNode  - tree node
7314 //
7315 // Return value:
7316 //    None
7317 //
7318 // Assumptions:
7319 //     i) tree oper is one of GT_NEG or GT_INTRINSIC Abs()
7320 //    ii) tree type is floating point type.
7321 //   iii) caller of this routine needs to call genProduceReg()
7322 void CodeGen::genSSE2BitwiseOp(GenTreePtr treeNode)
7323 {
7324     regNumber targetReg  = treeNode->gtRegNum;
7325     var_types targetType = treeNode->TypeGet();
7326     assert(varTypeIsFloating(targetType));
7327
7328     float       f;
7329     double      d;
7330     GenTreePtr* bitMask  = nullptr;
7331     instruction ins      = INS_invalid;
7332     void*       cnsAddr  = nullptr;
7333     bool        dblAlign = false;
7334
7335     switch (treeNode->OperGet())
7336     {
7337         case GT_NEG:
7338             // Neg(x) = flip the sign bit.
7339             // Neg(f) = f ^ 0x80000000
7340             // Neg(d) = d ^ 0x8000000000000000
7341             ins = genGetInsForOper(GT_XOR, targetType);
7342             if (targetType == TYP_FLOAT)
7343             {
7344                 bitMask = &negBitmaskFlt;
7345
7346                 static_assert_no_msg(sizeof(float) == sizeof(int));
7347                 *((int*)&f) = 0x80000000;
7348                 cnsAddr     = &f;
7349             }
7350             else
7351             {
7352                 bitMask = &negBitmaskDbl;
7353
7354                 static_assert_no_msg(sizeof(double) == sizeof(__int64));
7355                 *((__int64*)&d) = 0x8000000000000000LL;
7356                 cnsAddr         = &d;
7357                 dblAlign        = true;
7358             }
7359             break;
7360
7361         case GT_INTRINSIC:
7362             assert(treeNode->gtIntrinsic.gtIntrinsicId == CORINFO_INTRINSIC_Abs);
7363
7364             // Abs(x) = set sign-bit to zero
7365             // Abs(f) = f & 0x7fffffff
7366             // Abs(d) = d & 0x7fffffffffffffff
7367             ins = genGetInsForOper(GT_AND, targetType);
7368             if (targetType == TYP_FLOAT)
7369             {
7370                 bitMask = &absBitmaskFlt;
7371
7372                 static_assert_no_msg(sizeof(float) == sizeof(int));
7373                 *((int*)&f) = 0x7fffffff;
7374                 cnsAddr     = &f;
7375             }
7376             else
7377             {
7378                 bitMask = &absBitmaskDbl;
7379
7380                 static_assert_no_msg(sizeof(double) == sizeof(__int64));
7381                 *((__int64*)&d) = 0x7fffffffffffffffLL;
7382                 cnsAddr         = &d;
7383                 dblAlign        = true;
7384             }
7385             break;
7386
7387         default:
7388             assert(!"genSSE2: unsupported oper");
7389             unreached();
7390             break;
7391     }
7392
7393     if (*bitMask == nullptr)
7394     {
7395         assert(cnsAddr != nullptr);
7396         *bitMask = genMakeConst(cnsAddr, targetType, treeNode, dblAlign);
7397     }
7398
7399     // We need an additional register for bitmask.
7400     // Make sure we have one allocated.
7401     assert(treeNode->gtRsvdRegs != RBM_NONE);
7402     assert(genCountBits(treeNode->gtRsvdRegs) == 1);
7403     regNumber tmpReg = genRegNumFromMask(treeNode->gtRsvdRegs);
7404
7405     // Move operand into targetReg only if the reg reserved for
7406     // internal purpose is not the same as targetReg.
7407     GenTreePtr op1 = treeNode->gtOp.gtOp1;
7408     assert(op1->isUsedFromReg());
7409     regNumber operandReg = genConsumeReg(op1);
7410     if (tmpReg != targetReg)
7411     {
7412         if (operandReg != targetReg)
7413         {
7414             inst_RV_RV(ins_Copy(targetType), targetReg, operandReg, targetType);
7415         }
7416
7417         operandReg = tmpReg;
7418     }
7419
7420     inst_RV_TT(ins_Load(targetType, false), tmpReg, *bitMask);
7421     assert(ins != INS_invalid);
7422     inst_RV_RV(ins, targetReg, operandReg, targetType);
7423 }
7424
7425 //---------------------------------------------------------------------
7426 // genIntrinsic - generate code for a given intrinsic
7427 //
7428 // Arguments
7429 //    treeNode - the GT_INTRINSIC node
7430 //
7431 // Return value:
7432 //    None
7433 //
7434 void CodeGen::genIntrinsic(GenTreePtr treeNode)
7435 {
7436     // Right now only Sqrt/Abs are treated as math intrinsics.
7437     switch (treeNode->gtIntrinsic.gtIntrinsicId)
7438     {
7439         case CORINFO_INTRINSIC_Sqrt:
7440         {
7441             // Both operand and its result must be of the same floating point type.
7442             GenTreePtr srcNode = treeNode->gtOp.gtOp1;
7443             assert(varTypeIsFloating(srcNode));
7444             assert(srcNode->TypeGet() == treeNode->TypeGet());
7445
7446             genConsumeOperands(treeNode->AsOp());
7447             getEmitter()->emitInsBinary(ins_FloatSqrt(treeNode->TypeGet()), emitTypeSize(treeNode), treeNode, srcNode);
7448             break;
7449         }
7450
7451         case CORINFO_INTRINSIC_Abs:
7452             genSSE2BitwiseOp(treeNode);
7453             break;
7454
7455         default:
7456             assert(!"genIntrinsic: Unsupported intrinsic");
7457             unreached();
7458     }
7459
7460     genProduceReg(treeNode);
7461 }
7462
7463 //-------------------------------------------------------------------------- //
7464 // getBaseVarForPutArgStk - returns the baseVarNum for passing a stack arg.
7465 //
7466 // Arguments
7467 //    treeNode - the GT_PUTARG_STK node
7468 //
7469 // Return value:
7470 //    The number of the base variable.
7471 //
7472 // Note:
7473 //    If tail call the outgoing args are placed in the caller's incoming arg stack space.
7474 //    Otherwise, they go in the outgoing arg area on the current frame.
7475 //
7476 //    On Windows the caller always creates slots (homing space) in its frame for the
7477 //    first 4 arguments of a callee (register passed args). So, the baseVarNum is always 0.
7478 //    For System V systems there is no such calling convention requirement, and the code needs to find
7479 //    the first stack passed argument from the caller. This is done by iterating over
7480 //    all the lvParam variables and finding the first with lvArgReg equals to REG_STK.
7481 //
7482 unsigned CodeGen::getBaseVarForPutArgStk(GenTreePtr treeNode)
7483 {
7484     assert(treeNode->OperGet() == GT_PUTARG_STK);
7485
7486     unsigned baseVarNum;
7487
7488     // Whether to setup stk arg in incoming or out-going arg area?
7489     // Fast tail calls implemented as epilog+jmp = stk arg is setup in incoming arg area.
7490     // All other calls - stk arg is setup in out-going arg area.
7491     if (treeNode->AsPutArgStk()->putInIncomingArgArea())
7492     {
7493         // See the note in the function header re: finding the first stack passed argument.
7494         baseVarNum = getFirstArgWithStackSlot();
7495         assert(baseVarNum != BAD_VAR_NUM);
7496
7497 #ifdef DEBUG
7498         // This must be a fast tail call.
7499         assert(treeNode->AsPutArgStk()->gtCall->AsCall()->IsFastTailCall());
7500
7501         // Since it is a fast tail call, the existence of first incoming arg is guaranteed
7502         // because fast tail call requires that in-coming arg area of caller is >= out-going
7503         // arg area required for tail call.
7504         LclVarDsc* varDsc = &(compiler->lvaTable[baseVarNum]);
7505         assert(varDsc != nullptr);
7506
7507 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
7508         assert(!varDsc->lvIsRegArg && varDsc->lvArgReg == REG_STK);
7509 #else  // !FEATURE_UNIX_AMD64_STRUCT_PASSING
7510         // On Windows this assert is always true. The first argument will always be in REG_ARG_0 or REG_FLTARG_0.
7511         assert(varDsc->lvIsRegArg && (varDsc->lvArgReg == REG_ARG_0 || varDsc->lvArgReg == REG_FLTARG_0));
7512 #endif // !FEATURE_UNIX_AMD64_STRUCT_PASSING
7513 #endif // !DEBUG
7514     }
7515     else
7516     {
7517 #if FEATURE_FIXED_OUT_ARGS
7518         baseVarNum = compiler->lvaOutgoingArgSpaceVar;
7519 #else  // !FEATURE_FIXED_OUT_ARGS
7520         assert(!"No BaseVarForPutArgStk on x86");
7521         baseVarNum = BAD_VAR_NUM;
7522 #endif // !FEATURE_FIXED_OUT_ARGS
7523     }
7524
7525     return baseVarNum;
7526 }
7527
7528 //---------------------------------------------------------------------
7529 // genAlignStackBeforeCall: Align the stack if necessary before a call.
7530 //
7531 // Arguments:
7532 //    putArgStk - the putArgStk node.
7533 //
7534 void CodeGen::genAlignStackBeforeCall(GenTreePutArgStk* putArgStk)
7535 {
7536 #if defined(UNIX_X86_ABI)
7537
7538     genAlignStackBeforeCall(putArgStk->gtCall);
7539
7540 #endif // UNIX_X86_ABI
7541 }
7542
7543 //---------------------------------------------------------------------
7544 // genAlignStackBeforeCall: Align the stack if necessary before a call.
7545 //
7546 // Arguments:
7547 //    call - the call node.
7548 //
7549 void CodeGen::genAlignStackBeforeCall(GenTreeCall* call)
7550 {
7551 #if defined(UNIX_X86_ABI)
7552
7553     // Have we aligned the stack yet?
7554     if (!call->fgArgInfo->IsStkAlignmentDone())
7555     {
7556         // We haven't done any stack alignment yet for this call.  We might need to create
7557         // an alignment adjustment, even if this function itself doesn't have any stack args.
7558         // This can happen if this function call is part of a nested call sequence, and the outer
7559         // call has already pushed some arguments.
7560
7561         unsigned stkLevel = genStackLevel + call->fgArgInfo->GetStkSizeBytes();
7562         call->fgArgInfo->ComputeStackAlignment(stkLevel);
7563
7564         unsigned padStkAlign = call->fgArgInfo->GetStkAlign();
7565         if (padStkAlign != 0)
7566         {
7567             // Now generate the alignment
7568             inst_RV_IV(INS_sub, REG_SPBASE, padStkAlign, EA_PTRSIZE);
7569             AddStackLevel(padStkAlign);
7570             AddNestedAlignment(padStkAlign);
7571         }
7572
7573         call->fgArgInfo->SetStkAlignmentDone();
7574     }
7575
7576 #endif // UNIX_X86_ABI
7577 }
7578
7579 //---------------------------------------------------------------------
7580 // genRemoveAlignmentAfterCall: After a call, remove the alignment
7581 // added before the call, if any.
7582 //
7583 // Arguments:
7584 //    call - the call node.
7585 //    bias - additional stack adjustment
7586 //
7587 // Note:
7588 //    When bias > 0, caller should adjust stack level appropriately as
7589 //    bias is not considered when adjusting stack level.
7590 //
7591 void CodeGen::genRemoveAlignmentAfterCall(GenTreeCall* call, unsigned bias)
7592 {
7593 #if defined(_TARGET_X86_)
7594 #if defined(UNIX_X86_ABI)
7595     // Put back the stack pointer if there was any padding for stack alignment
7596     unsigned padStkAlign  = call->fgArgInfo->GetStkAlign();
7597     unsigned padStkAdjust = padStkAlign + bias;
7598
7599     if (padStkAdjust != 0)
7600     {
7601         inst_RV_IV(INS_add, REG_SPBASE, padStkAdjust, EA_PTRSIZE);
7602         SubtractStackLevel(padStkAlign);
7603         SubtractNestedAlignment(padStkAlign);
7604     }
7605 #else  // UNIX_X86_ABI
7606     if (bias != 0)
7607     {
7608         genAdjustSP(bias);
7609     }
7610 #endif // !UNIX_X86_ABI_
7611 #else  // _TARGET_X86_
7612     assert(bias == 0);
7613 #endif // !_TARGET_X86
7614 }
7615
7616 #ifdef _TARGET_X86_
7617
7618 //---------------------------------------------------------------------
7619 // genAdjustStackForPutArgStk:
7620 //    adjust the stack pointer for a putArgStk node if necessary.
7621 //
7622 // Arguments:
7623 //    putArgStk - the putArgStk node.
7624 //
7625 // Returns: true if the stack pointer was adjusted; false otherwise.
7626 //
7627 // Notes:
7628 //    Sets `m_pushStkArg` to true if the stack arg needs to be pushed,
7629 //    false if the stack arg needs to be stored at the current stack
7630 //    pointer address. This is exactly the opposite of the return value
7631 //    of this function.
7632 //
7633 bool CodeGen::genAdjustStackForPutArgStk(GenTreePutArgStk* putArgStk)
7634 {
7635 #ifdef FEATURE_SIMD
7636     if (varTypeIsSIMD(putArgStk))
7637     {
7638         const unsigned argSize = genTypeSize(putArgStk);
7639         inst_RV_IV(INS_sub, REG_SPBASE, argSize, EA_PTRSIZE);
7640         AddStackLevel(argSize);
7641         m_pushStkArg = false;
7642         return true;
7643     }
7644 #endif // FEATURE_SIMD
7645
7646     const unsigned argSize = putArgStk->getArgSize();
7647
7648     // If the gtPutArgStkKind is one of the push types, we do not pre-adjust the stack.
7649     // This is set in Lowering, and is true if and only if:
7650     // - This argument contains any GC pointers OR
7651     // - It is a GT_FIELD_LIST OR
7652     // - It is less than 16 bytes in size.
7653     CLANG_FORMAT_COMMENT_ANCHOR;
7654
7655 #ifdef DEBUG
7656     switch (putArgStk->gtPutArgStkKind)
7657     {
7658         case GenTreePutArgStk::Kind::RepInstr:
7659         case GenTreePutArgStk::Kind::Unroll:
7660             assert((putArgStk->gtNumberReferenceSlots == 0) && (putArgStk->gtGetOp1()->OperGet() != GT_FIELD_LIST) &&
7661                    (argSize >= 16));
7662             break;
7663         case GenTreePutArgStk::Kind::Push:
7664         case GenTreePutArgStk::Kind::PushAllSlots:
7665             assert((putArgStk->gtNumberReferenceSlots != 0) || (putArgStk->gtGetOp1()->OperGet() == GT_FIELD_LIST) ||
7666                    (argSize < 16));
7667             break;
7668         case GenTreePutArgStk::Kind::Invalid:
7669         default:
7670             assert(!"Uninitialized GenTreePutArgStk::Kind");
7671             break;
7672     }
7673 #endif // DEBUG
7674
7675     if (putArgStk->isPushKind())
7676     {
7677         m_pushStkArg = true;
7678         return false;
7679     }
7680     else
7681     {
7682         m_pushStkArg = false;
7683         inst_RV_IV(INS_sub, REG_SPBASE, argSize, EA_PTRSIZE);
7684         AddStackLevel(argSize);
7685         return true;
7686     }
7687 }
7688
7689 //---------------------------------------------------------------------
7690 // genPutArgStkFieldList - generate code for passing a GT_FIELD_LIST arg on the stack.
7691 //
7692 // Arguments
7693 //    treeNode      - the GT_PUTARG_STK node whose op1 is a GT_FIELD_LIST
7694 //
7695 // Return value:
7696 //    None
7697 //
7698 void CodeGen::genPutArgStkFieldList(GenTreePutArgStk* putArgStk)
7699 {
7700     GenTreeFieldList* const fieldList = putArgStk->gtOp1->AsFieldList();
7701     assert(fieldList != nullptr);
7702
7703     // Set m_pushStkArg and pre-adjust the stack if necessary.
7704     const bool preAdjustedStack = genAdjustStackForPutArgStk(putArgStk);
7705
7706     // For now, we only support the "push" case; we will push a full slot for the first field of each slot
7707     // within the struct.
7708     assert((putArgStk->isPushKind()) && !preAdjustedStack && m_pushStkArg);
7709
7710     // If we have pre-adjusted the stack and are simply storing the fields in order, set the offset to 0.
7711     // (Note that this mode is not currently being used.)
7712     // If we are pushing the arguments (i.e. we have not pre-adjusted the stack), then we are pushing them
7713     // in reverse order, so we start with the current field offset at the size of the struct arg (which must be
7714     // a multiple of the target pointer size).
7715     unsigned  currentOffset   = (preAdjustedStack) ? 0 : putArgStk->getArgSize();
7716     unsigned  prevFieldOffset = currentOffset;
7717     regNumber intTmpReg       = REG_NA;
7718     regNumber simdTmpReg      = REG_NA;
7719     if (putArgStk->gtRsvdRegs != RBM_NONE)
7720     {
7721         regMaskTP rsvdRegs = putArgStk->gtRsvdRegs;
7722         if ((rsvdRegs & RBM_ALLINT) != 0)
7723         {
7724             intTmpReg = genRegNumFromMask(rsvdRegs & RBM_ALLINT);
7725             assert(genIsValidIntReg(intTmpReg));
7726         }
7727         if ((rsvdRegs & RBM_ALLFLOAT) != 0)
7728         {
7729             simdTmpReg = genRegNumFromMask(rsvdRegs & RBM_ALLFLOAT);
7730             assert(genIsValidFloatReg(simdTmpReg));
7731         }
7732         assert(genCountBits(rsvdRegs) == (unsigned)((intTmpReg == REG_NA) ? 0 : 1) + ((simdTmpReg == REG_NA) ? 0 : 1));
7733     }
7734
7735     for (GenTreeFieldList* current = fieldList; current != nullptr; current = current->Rest())
7736     {
7737         GenTree* const fieldNode   = current->Current();
7738         const unsigned fieldOffset = current->gtFieldOffset;
7739         var_types      fieldType   = current->gtFieldType;
7740
7741         // Long-typed nodes should have been handled by the decomposition pass, and lowering should have sorted the
7742         // field list in descending order by offset.
7743         assert(!varTypeIsLong(fieldType));
7744         assert(fieldOffset <= prevFieldOffset);
7745
7746         // Consume the register, if any, for this field. Note that genConsumeRegs() will appropriately
7747         // update the liveness info for a lclVar that has been marked RegOptional, which hasn't been
7748         // assigned a register, and which is therefore contained.
7749         // Unlike genConsumeReg(), it handles the case where no registers are being consumed.
7750         genConsumeRegs(fieldNode);
7751         regNumber argReg = fieldNode->isUsedFromSpillTemp() ? REG_NA : fieldNode->gtRegNum;
7752
7753         // If the field is slot-like, we can use a push instruction to store the entire register no matter the type.
7754         //
7755         // The GC encoder requires that the stack remain 4-byte aligned at all times. Round the adjustment up
7756         // to the next multiple of 4. If we are going to generate a `push` instruction, the adjustment must
7757         // not require rounding.
7758         // NOTE: if the field is of GC type, we must use a push instruction, since the emitter is not otherwise
7759         // able to detect stores into the outgoing argument area of the stack on x86.
7760         const bool fieldIsSlot = ((fieldOffset % 4) == 0) && ((prevFieldOffset - fieldOffset) >= 4);
7761         int        adjustment  = roundUp(currentOffset - fieldOffset, 4);
7762         if (fieldIsSlot && !varTypeIsSIMD(fieldType))
7763         {
7764             fieldType         = genActualType(fieldType);
7765             unsigned pushSize = genTypeSize(fieldType);
7766             assert((pushSize % 4) == 0);
7767             adjustment -= pushSize;
7768             while (adjustment != 0)
7769             {
7770                 inst_IV(INS_push, 0);
7771                 currentOffset -= pushSize;
7772                 AddStackLevel(pushSize);
7773                 adjustment -= pushSize;
7774             }
7775             m_pushStkArg = true;
7776         }
7777         else
7778         {
7779             m_pushStkArg = false;
7780
7781             // We always "push" floating point fields (i.e. they are full slot values that don't
7782             // require special handling).
7783             assert(varTypeIsIntegralOrI(fieldNode) || varTypeIsSIMD(fieldNode));
7784
7785             // If we can't push this field, it needs to be in a register so that we can store
7786             // it to the stack location.
7787             if (adjustment != 0)
7788             {
7789                 // This moves the stack pointer to fieldOffset.
7790                 // For this case, we must adjust the stack and generate stack-relative stores rather than pushes.
7791                 // Adjust the stack pointer to the next slot boundary.
7792                 inst_RV_IV(INS_sub, REG_SPBASE, adjustment, EA_PTRSIZE);
7793                 currentOffset -= adjustment;
7794                 AddStackLevel(adjustment);
7795             }
7796
7797             // Does it need to be in a byte register?
7798             // If so, we'll use intTmpReg, which must have been allocated as a byte register.
7799             // If it's already in a register, but not a byteable one, then move it.
7800             if (varTypeIsByte(fieldType) && ((argReg == REG_NA) || ((genRegMask(argReg) & RBM_BYTE_REGS) == 0)))
7801             {
7802                 assert(intTmpReg != REG_NA);
7803                 noway_assert((genRegMask(intTmpReg) & RBM_BYTE_REGS) != 0);
7804                 if (argReg != REG_NA)
7805                 {
7806                     inst_RV_RV(INS_mov, intTmpReg, argReg, fieldType);
7807                     argReg = intTmpReg;
7808                 }
7809             }
7810         }
7811
7812         if (argReg == REG_NA)
7813         {
7814             if (m_pushStkArg)
7815             {
7816                 if (fieldNode->isUsedFromSpillTemp())
7817                 {
7818                     assert(!varTypeIsSIMD(fieldType)); // Q: can we get here with SIMD?
7819                     assert(fieldNode->IsRegOptional());
7820                     TempDsc* tmp = getSpillTempDsc(fieldNode);
7821                     getEmitter()->emitIns_S(INS_push, emitActualTypeSize(fieldNode->TypeGet()), tmp->tdTempNum(), 0);
7822                     compiler->tmpRlsTemp(tmp);
7823                 }
7824                 else
7825                 {
7826                     assert(varTypeIsIntegralOrI(fieldNode));
7827                     switch (fieldNode->OperGet())
7828                     {
7829                         case GT_LCL_VAR:
7830                             inst_TT(INS_push, fieldNode, 0, 0, emitActualTypeSize(fieldNode->TypeGet()));
7831                             break;
7832                         case GT_CNS_INT:
7833                             if (fieldNode->IsIconHandle())
7834                             {
7835                                 inst_IV_handle(INS_push, fieldNode->gtIntCon.gtIconVal);
7836                             }
7837                             else
7838                             {
7839                                 inst_IV(INS_push, fieldNode->gtIntCon.gtIconVal);
7840                             }
7841                             break;
7842                         default:
7843                             unreached();
7844                     }
7845                 }
7846                 currentOffset -= TARGET_POINTER_SIZE;
7847                 AddStackLevel(TARGET_POINTER_SIZE);
7848             }
7849             else
7850             {
7851                 // The stack has been adjusted and we will load the field to intTmpReg and then store it on the stack.
7852                 assert(varTypeIsIntegralOrI(fieldNode));
7853                 switch (fieldNode->OperGet())
7854                 {
7855                     case GT_LCL_VAR:
7856                         inst_RV_TT(INS_mov, intTmpReg, fieldNode);
7857                         break;
7858                     case GT_CNS_INT:
7859                         genSetRegToConst(intTmpReg, fieldNode->TypeGet(), fieldNode);
7860                         break;
7861                     default:
7862                         unreached();
7863                 }
7864                 genStoreRegToStackArg(fieldType, intTmpReg, fieldOffset - currentOffset);
7865             }
7866         }
7867         else
7868         {
7869 #if defined(FEATURE_SIMD)
7870             if (fieldType == TYP_SIMD12)
7871             {
7872                 assert(genIsValidFloatReg(simdTmpReg));
7873                 genStoreSIMD12ToStack(argReg, simdTmpReg);
7874             }
7875             else
7876 #endif // defined(FEATURE_SIMD)
7877             {
7878                 genStoreRegToStackArg(fieldType, argReg, fieldOffset - currentOffset);
7879             }
7880             if (m_pushStkArg)
7881             {
7882                 // We always push a slot-rounded size
7883                 currentOffset -= genTypeSize(fieldType);
7884             }
7885         }
7886
7887         prevFieldOffset = fieldOffset;
7888     }
7889     if (currentOffset != 0)
7890     {
7891         // We don't expect padding at the beginning of a struct, but it could happen with explicit layout.
7892         inst_RV_IV(INS_sub, REG_SPBASE, currentOffset, EA_PTRSIZE);
7893         AddStackLevel(currentOffset);
7894     }
7895 }
7896 #endif // _TARGET_X86_
7897
7898 //---------------------------------------------------------------------
7899 // genPutArgStk - generate code for passing an arg on the stack.
7900 //
7901 // Arguments
7902 //    treeNode      - the GT_PUTARG_STK node
7903 //    targetType    - the type of the treeNode
7904 //
7905 // Return value:
7906 //    None
7907 //
7908 void CodeGen::genPutArgStk(GenTreePutArgStk* putArgStk)
7909 {
7910     var_types targetType = putArgStk->TypeGet();
7911
7912 #ifdef _TARGET_X86_
7913
7914     genAlignStackBeforeCall(putArgStk);
7915
7916     if (varTypeIsStruct(targetType))
7917     {
7918         (void)genAdjustStackForPutArgStk(putArgStk);
7919         genPutStructArgStk(putArgStk);
7920         return;
7921     }
7922
7923     // The following logic is applicable for x86 arch.
7924     assert(!varTypeIsFloating(targetType) || (targetType == putArgStk->gtOp1->TypeGet()));
7925
7926     GenTreePtr data = putArgStk->gtOp1;
7927
7928     // On a 32-bit target, all of the long arguments are handled with GT_FIELD_LIST,
7929     // and the type of the putArgStk is TYP_VOID.
7930     assert(targetType != TYP_LONG);
7931
7932     const unsigned argSize = putArgStk->getArgSize();
7933     assert((argSize % TARGET_POINTER_SIZE) == 0);
7934
7935     if (data->isContainedIntOrIImmed())
7936     {
7937         if (data->IsIconHandle())
7938         {
7939             inst_IV_handle(INS_push, data->gtIntCon.gtIconVal);
7940         }
7941         else
7942         {
7943             inst_IV(INS_push, data->gtIntCon.gtIconVal);
7944         }
7945         AddStackLevel(argSize);
7946     }
7947     else if (data->OperGet() == GT_FIELD_LIST)
7948     {
7949         genPutArgStkFieldList(putArgStk);
7950     }
7951     else
7952     {
7953         // We should not see any contained nodes that are not immediates.
7954         assert(data->isUsedFromReg());
7955         genConsumeReg(data);
7956         genPushReg(targetType, data->gtRegNum);
7957     }
7958 #else // !_TARGET_X86_
7959     {
7960         unsigned baseVarNum = getBaseVarForPutArgStk(putArgStk);
7961
7962 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
7963
7964         if (varTypeIsStruct(targetType))
7965         {
7966             m_stkArgVarNum = baseVarNum;
7967             m_stkArgOffset = putArgStk->getArgOffset();
7968             genPutStructArgStk(putArgStk);
7969             m_stkArgVarNum = BAD_VAR_NUM;
7970             return;
7971         }
7972 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
7973
7974         noway_assert(targetType != TYP_STRUCT);
7975         assert(!varTypeIsFloating(targetType) || (targetType == putArgStk->gtOp1->TypeGet()));
7976
7977         // Get argument offset on stack.
7978         // Here we cross check that argument offset hasn't changed from lowering to codegen since
7979         // we are storing arg slot number in GT_PUTARG_STK node in lowering phase.
7980         int              argOffset      = putArgStk->getArgOffset();
7981
7982 #ifdef DEBUG
7983         fgArgTabEntryPtr curArgTabEntry = compiler->gtArgEntryByNode(putArgStk->gtCall, putArgStk);
7984         assert(curArgTabEntry);
7985         assert(argOffset == (int)curArgTabEntry->slotNum * TARGET_POINTER_SIZE);
7986 #endif
7987
7988         GenTreePtr data = putArgStk->gtOp1;
7989
7990         if (data->isContainedIntOrIImmed())
7991         {
7992             getEmitter()->emitIns_S_I(ins_Store(targetType), emitTypeSize(targetType), baseVarNum, argOffset,
7993                                       (int)data->AsIntConCommon()->IconValue());
7994         }
7995         else
7996         {
7997             assert(data->isUsedFromReg());
7998             genConsumeReg(data);
7999             getEmitter()->emitIns_S_R(ins_Store(targetType), emitTypeSize(targetType), data->gtRegNum, baseVarNum,
8000                                       argOffset);
8001         }
8002     }
8003 #endif // !_TARGET_X86_
8004 }
8005
8006 #ifdef _TARGET_X86_
8007 // genPushReg: Push a register value onto the stack and adjust the stack level
8008 //
8009 // Arguments:
8010 //    type   - the type of value to be stored
8011 //    reg    - the register containing the value
8012 //
8013 // Notes:
8014 //    For TYP_LONG, the srcReg must be a floating point register.
8015 //    Otherwise, the register type must be consistent with the given type.
8016 //
8017 void CodeGen::genPushReg(var_types type, regNumber srcReg)
8018 {
8019     unsigned size = genTypeSize(type);
8020     if (varTypeIsIntegralOrI(type) && type != TYP_LONG)
8021     {
8022         assert(genIsValidIntReg(srcReg));
8023         inst_RV(INS_push, srcReg, type);
8024     }
8025     else
8026     {
8027         instruction ins;
8028         emitAttr    attr = emitTypeSize(type);
8029         if (type == TYP_LONG)
8030         {
8031             // On x86, the only way we can push a TYP_LONG from a register is if it is in an xmm reg.
8032             // This is only used when we are pushing a struct from memory to memory, and basically is
8033             // handling an 8-byte "chunk", as opposed to strictly a long type.
8034             ins = INS_movq;
8035         }
8036         else
8037         {
8038             ins = ins_Store(type);
8039         }
8040         assert(genIsValidFloatReg(srcReg));
8041         inst_RV_IV(INS_sub, REG_SPBASE, size, EA_PTRSIZE);
8042         getEmitter()->emitIns_AR_R(ins, attr, srcReg, REG_SPBASE, 0);
8043     }
8044     AddStackLevel(size);
8045 }
8046 #endif // _TARGET_X86_
8047
8048 #if defined(FEATURE_PUT_STRUCT_ARG_STK)
8049 // genStoreRegToStackArg: Store a register value into the stack argument area
8050 //
8051 // Arguments:
8052 //    type   - the type of value to be stored
8053 //    reg    - the register containing the value
8054 //    offset - the offset from the base (see Assumptions below)
8055 //
8056 // Notes:
8057 //    A type of TYP_STRUCT instructs this method to store a 16-byte chunk
8058 //    at the given offset (i.e. not the full struct).
8059 //
8060 // Assumptions:
8061 //    The caller must set the context appropriately before calling this method:
8062 //    - On x64, m_stkArgVarNum must be set according to whether this is a regular or tail call.
8063 //    - On x86, the caller must set m_pushStkArg if this method should push the argument.
8064 //      Otherwise, the argument is stored at the given offset from sp.
8065 //
8066 // TODO: In the below code the load and store instructions are for 16 bytes, but the
8067 //          type is EA_8BYTE. The movdqa/u are 16 byte instructions, so it works, but
8068 //          this probably needs to be changed.
8069 //
8070 void CodeGen::genStoreRegToStackArg(var_types type, regNumber srcReg, int offset)
8071 {
8072     assert(srcReg != REG_NA);
8073     instruction ins;
8074     emitAttr    attr;
8075     unsigned    size;
8076
8077     if (type == TYP_STRUCT)
8078     {
8079         ins = INS_movdqu;
8080         // This should be changed!
8081         attr = EA_8BYTE;
8082         size = 16;
8083     }
8084     else
8085     {
8086 #ifdef FEATURE_SIMD
8087         if (varTypeIsSIMD(type))
8088         {
8089             assert(genIsValidFloatReg(srcReg));
8090             ins = ins_Store(type); // TODO-CQ: pass 'aligned' correctly
8091         }
8092         else
8093 #endif // FEATURE_SIMD
8094 #ifdef _TARGET_X86_
8095             if (type == TYP_LONG)
8096         {
8097             assert(genIsValidFloatReg(srcReg));
8098             ins = INS_movq;
8099         }
8100         else
8101 #endif // _TARGET_X86_
8102         {
8103             assert((varTypeIsFloating(type) && genIsValidFloatReg(srcReg)) ||
8104                    (varTypeIsIntegralOrI(type) && genIsValidIntReg(srcReg)));
8105             ins = ins_Store(type);
8106         }
8107         attr = emitTypeSize(type);
8108         size = genTypeSize(type);
8109     }
8110
8111 #ifdef _TARGET_X86_
8112     if (m_pushStkArg)
8113     {
8114         genPushReg(type, srcReg);
8115     }
8116     else
8117     {
8118         getEmitter()->emitIns_AR_R(ins, attr, srcReg, REG_SPBASE, offset);
8119     }
8120 #else  // !_TARGET_X86_
8121     assert(m_stkArgVarNum != BAD_VAR_NUM);
8122     getEmitter()->emitIns_S_R(ins, attr, srcReg, m_stkArgVarNum, m_stkArgOffset + offset);
8123 #endif // !_TARGET_X86_
8124 }
8125
8126 //---------------------------------------------------------------------
8127 // genPutStructArgStk - generate code for copying a struct arg on the stack by value.
8128 //                In case there are references to heap object in the struct,
8129 //                it generates the gcinfo as well.
8130 //
8131 // Arguments
8132 //    putArgStk - the GT_PUTARG_STK node
8133 //
8134 // Notes:
8135 //    In the case of fixed out args, the caller must have set m_stkArgVarNum to the variable number
8136 //    corresponding to the argument area (where we will put the argument on the stack).
8137 //    For tail calls this is the baseVarNum = 0.
8138 //    For non tail calls this is the outgoingArgSpace.
8139 void CodeGen::genPutStructArgStk(GenTreePutArgStk* putArgStk)
8140 {
8141     var_types targetType = putArgStk->TypeGet();
8142
8143 #if defined(_TARGET_X86_) && defined(FEATURE_SIMD)
8144     if (targetType == TYP_SIMD12)
8145     {
8146         genPutArgStkSIMD12(putArgStk);
8147         return;
8148     }
8149 #endif // defined(_TARGET_X86_) && defined(FEATURE_SIMD)
8150
8151     if (varTypeIsSIMD(targetType))
8152     {
8153         regNumber srcReg = genConsumeReg(putArgStk->gtGetOp1());
8154         assert((srcReg != REG_NA) && (genIsValidFloatReg(srcReg)));
8155         genStoreRegToStackArg(targetType, srcReg, 0);
8156         return;
8157     }
8158
8159     assert(targetType == TYP_STRUCT);
8160
8161     if (putArgStk->gtNumberReferenceSlots == 0)
8162     {
8163         switch (putArgStk->gtPutArgStkKind)
8164         {
8165             case GenTreePutArgStk::Kind::RepInstr:
8166                 genStructPutArgRepMovs(putArgStk);
8167                 break;
8168             case GenTreePutArgStk::Kind::Unroll:
8169                 genStructPutArgUnroll(putArgStk);
8170                 break;
8171             case GenTreePutArgStk::Kind::Push:
8172                 genStructPutArgUnroll(putArgStk);
8173                 break;
8174             default:
8175                 unreached();
8176         }
8177     }
8178     else
8179     {
8180         // No need to disable GC the way COPYOBJ does. Here the refs are copied in atomic operations always.
8181         CLANG_FORMAT_COMMENT_ANCHOR;
8182
8183 #ifdef _TARGET_X86_
8184         // On x86, any struct that has contains GC references must be stored to the stack using `push` instructions so
8185         // that the emitter properly detects the need to update the method's GC information.
8186         //
8187         // Strictly speaking, it is only necessary to use `push` to store the GC references themselves, so for structs
8188         // with large numbers of consecutive non-GC-ref-typed fields, we may be able to improve the code size in the
8189         // future.
8190         assert(m_pushStkArg);
8191
8192         GenTree*       srcAddr  = putArgStk->gtGetOp1()->gtGetOp1();
8193         BYTE*          gcPtrs   = putArgStk->gtGcPtrs;
8194         const unsigned numSlots = putArgStk->gtNumSlots;
8195
8196         regNumber  srcRegNum    = srcAddr->gtRegNum;
8197         const bool srcAddrInReg = srcRegNum != REG_NA;
8198
8199         unsigned srcLclNum    = 0;
8200         unsigned srcLclOffset = 0;
8201         if (srcAddrInReg)
8202         {
8203             genConsumeReg(srcAddr);
8204         }
8205         else
8206         {
8207             assert(srcAddr->OperIsLocalAddr());
8208
8209             srcLclNum = srcAddr->AsLclVarCommon()->gtLclNum;
8210             if (srcAddr->OperGet() == GT_LCL_FLD_ADDR)
8211             {
8212                 srcLclOffset = srcAddr->AsLclFld()->gtLclOffs;
8213             }
8214         }
8215
8216         for (int i = numSlots - 1; i >= 0; --i)
8217         {
8218             emitAttr slotAttr;
8219             if (gcPtrs[i] == TYPE_GC_NONE)
8220             {
8221                 slotAttr = EA_4BYTE;
8222             }
8223             else if (gcPtrs[i] == TYPE_GC_REF)
8224             {
8225                 slotAttr = EA_GCREF;
8226             }
8227             else
8228             {
8229                 assert(gcPtrs[i] == TYPE_GC_BYREF);
8230                 slotAttr = EA_BYREF;
8231             }
8232
8233             const unsigned offset = i * TARGET_POINTER_SIZE;
8234             if (srcAddrInReg)
8235             {
8236                 getEmitter()->emitIns_AR_R(INS_push, slotAttr, REG_NA, srcRegNum, offset);
8237             }
8238             else
8239             {
8240                 getEmitter()->emitIns_S(INS_push, slotAttr, srcLclNum, srcLclOffset + offset);
8241             }
8242             AddStackLevel(TARGET_POINTER_SIZE);
8243         }
8244 #else // !defined(_TARGET_X86_)
8245
8246         // Consume these registers.
8247         // They may now contain gc pointers (depending on their type; gcMarkRegPtrVal will "do the right thing").
8248         genConsumePutStructArgStk(putArgStk, REG_RDI, REG_RSI, REG_NA);
8249
8250         const bool     srcIsLocal       = putArgStk->gtOp1->AsObj()->gtOp1->OperIsLocalAddr();
8251         const emitAttr srcAddrAttr      = srcIsLocal ? EA_PTRSIZE : EA_BYREF;
8252
8253 #if DEBUG
8254         unsigned       numGCSlotsCopied = 0;
8255 #endif // DEBUG
8256
8257         BYTE*          gcPtrs   = putArgStk->gtGcPtrs;
8258         const unsigned numSlots = putArgStk->gtNumSlots;
8259         for (unsigned i = 0; i < numSlots;)
8260         {
8261             if (gcPtrs[i] == TYPE_GC_NONE)
8262             {
8263                 // Let's see if we can use rep movsp (alias for movsd or movsq for 32 and 64 bits respectively)
8264                 // instead of a sequence of movsp instructions to save cycles and code size.
8265                 unsigned adjacentNonGCSlotCount = 0;
8266                 do
8267                 {
8268                     adjacentNonGCSlotCount++;
8269                     i++;
8270                 } while ((i < numSlots) && (gcPtrs[i] == TYPE_GC_NONE));
8271
8272                 // If we have a very small contiguous non-ref region, it's better just to
8273                 // emit a sequence of movsp instructions
8274                 if (adjacentNonGCSlotCount < CPOBJ_NONGC_SLOTS_LIMIT)
8275                 {
8276                     for (; adjacentNonGCSlotCount > 0; adjacentNonGCSlotCount--)
8277                     {
8278                         instGen(INS_movsp);
8279                     }
8280                 }
8281                 else
8282                 {
8283                     getEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, REG_RCX, adjacentNonGCSlotCount);
8284                     instGen(INS_r_movsp);
8285                 }
8286             }
8287             else
8288             {
8289                 assert((gcPtrs[i] == TYPE_GC_REF) || (gcPtrs[i] == TYPE_GC_BYREF));
8290
8291                 // We have a GC (byref or ref) pointer
8292                 // TODO-Amd64-Unix: Here a better solution (for code size and CQ) would be to use movsp instruction,
8293                 // but the logic for emitting a GC info record is not available (it is internal for the emitter
8294                 // only.) See emitGCVarLiveUpd function. If we could call it separately, we could do
8295                 // instGen(INS_movsp); and emission of gc info.
8296
8297                 var_types memType = (gcPtrs[i] == TYPE_GC_REF) ? TYP_REF : TYP_BYREF;
8298                 getEmitter()->emitIns_R_AR(ins_Load(memType), emitTypeSize(memType), REG_RCX, REG_RSI, 0);
8299                 genStoreRegToStackArg(memType, REG_RCX, i * TARGET_POINTER_SIZE);
8300
8301 #ifdef DEBUG
8302                 numGCSlotsCopied++;
8303 #endif // DEBUG
8304
8305                 i++;
8306                 if (i < numSlots)
8307                 {
8308                     // Source for the copy operation.
8309                     // If a LocalAddr, use EA_PTRSIZE - copy from stack.
8310                     // If not a LocalAddr, use EA_BYREF - the source location is not on the stack.
8311                     getEmitter()->emitIns_R_I(INS_add, srcAddrAttr, REG_RSI, TARGET_POINTER_SIZE);
8312
8313                     // Always copying to the stack - outgoing arg area
8314                     // (or the outgoing arg area of the caller for a tail call) - use EA_PTRSIZE.
8315                     getEmitter()->emitIns_R_I(INS_add, EA_PTRSIZE, REG_RDI, TARGET_POINTER_SIZE);
8316                 }
8317             }
8318         }
8319
8320         assert(numGCSlotsCopied == putArgStk->gtNumberReferenceSlots);
8321 #endif // _TARGET_X86_
8322     }
8323 }
8324 #endif // defined(FEATURE_PUT_STRUCT_ARG_STK)
8325
8326 /*****************************************************************************
8327  *
8328  *  Create and record GC Info for the function.
8329  */
8330 #ifndef JIT32_GCENCODER
8331 void
8332 #else  // !JIT32_GCENCODER
8333 void*
8334 #endif // !JIT32_GCENCODER
8335 CodeGen::genCreateAndStoreGCInfo(unsigned codeSize, unsigned prologSize, unsigned epilogSize DEBUGARG(void* codePtr))
8336 {
8337 #ifdef JIT32_GCENCODER
8338     return genCreateAndStoreGCInfoJIT32(codeSize, prologSize, epilogSize DEBUGARG(codePtr));
8339 #else  // !JIT32_GCENCODER
8340     genCreateAndStoreGCInfoX64(codeSize, prologSize DEBUGARG(codePtr));
8341 #endif // !JIT32_GCENCODER
8342 }
8343
8344 #ifdef JIT32_GCENCODER
8345 void* CodeGen::genCreateAndStoreGCInfoJIT32(unsigned codeSize,
8346                                             unsigned prologSize,
8347                                             unsigned epilogSize DEBUGARG(void* codePtr))
8348 {
8349     BYTE    headerBuf[64];
8350     InfoHdr header;
8351
8352     int s_cached;
8353 #ifdef DEBUG
8354     size_t headerSize =
8355 #endif
8356         compiler->compInfoBlkSize =
8357             gcInfo.gcInfoBlockHdrSave(headerBuf, 0, codeSize, prologSize, epilogSize, &header, &s_cached);
8358
8359     size_t argTabOffset = 0;
8360     size_t ptrMapSize   = gcInfo.gcPtrTableSize(header, codeSize, &argTabOffset);
8361
8362 #if DISPLAY_SIZES
8363
8364     if (genInterruptible)
8365     {
8366         gcHeaderISize += compiler->compInfoBlkSize;
8367         gcPtrMapISize += ptrMapSize;
8368     }
8369     else
8370     {
8371         gcHeaderNSize += compiler->compInfoBlkSize;
8372         gcPtrMapNSize += ptrMapSize;
8373     }
8374
8375 #endif // DISPLAY_SIZES
8376
8377     compiler->compInfoBlkSize += ptrMapSize;
8378
8379     /* Allocate the info block for the method */
8380
8381     compiler->compInfoBlkAddr = (BYTE*)compiler->info.compCompHnd->allocGCInfo(compiler->compInfoBlkSize);
8382
8383 #if 0 // VERBOSE_SIZES
8384     // TODO-X86-Cleanup: 'dataSize', below, is not defined
8385
8386 //  if  (compiler->compInfoBlkSize > codeSize && compiler->compInfoBlkSize > 100)
8387     {
8388         printf("[%7u VM, %7u+%7u/%7u x86 %03u/%03u%%] %s.%s\n",
8389                compiler->info.compILCodeSize,
8390                compiler->compInfoBlkSize,
8391                codeSize + dataSize,
8392                codeSize + dataSize - prologSize - epilogSize,
8393                100 * (codeSize + dataSize) / compiler->info.compILCodeSize,
8394                100 * (codeSize + dataSize + compiler->compInfoBlkSize) / compiler->info.compILCodeSize,
8395                compiler->info.compClassName,
8396                compiler->info.compMethodName);
8397 }
8398
8399 #endif
8400
8401     /* Fill in the info block and return it to the caller */
8402
8403     void* infoPtr = compiler->compInfoBlkAddr;
8404
8405     /* Create the method info block: header followed by GC tracking tables */
8406
8407     compiler->compInfoBlkAddr +=
8408         gcInfo.gcInfoBlockHdrSave(compiler->compInfoBlkAddr, -1, codeSize, prologSize, epilogSize, &header, &s_cached);
8409
8410     assert(compiler->compInfoBlkAddr == (BYTE*)infoPtr + headerSize);
8411     compiler->compInfoBlkAddr = gcInfo.gcPtrTableSave(compiler->compInfoBlkAddr, header, codeSize, &argTabOffset);
8412     assert(compiler->compInfoBlkAddr == (BYTE*)infoPtr + headerSize + ptrMapSize);
8413
8414 #ifdef DEBUG
8415
8416     if (0)
8417     {
8418         BYTE*    temp = (BYTE*)infoPtr;
8419         unsigned size = compiler->compInfoBlkAddr - temp;
8420         BYTE*    ptab = temp + headerSize;
8421
8422         noway_assert(size == headerSize + ptrMapSize);
8423
8424         printf("Method info block - header [%u bytes]:", headerSize);
8425
8426         for (unsigned i = 0; i < size; i++)
8427         {
8428             if (temp == ptab)
8429             {
8430                 printf("\nMethod info block - ptrtab [%u bytes]:", ptrMapSize);
8431                 printf("\n    %04X: %*c", i & ~0xF, 3 * (i & 0xF), ' ');
8432             }
8433             else
8434             {
8435                 if (!(i % 16))
8436                     printf("\n    %04X: ", i);
8437             }
8438
8439             printf("%02X ", *temp++);
8440         }
8441
8442         printf("\n");
8443     }
8444
8445 #endif // DEBUG
8446
8447 #if DUMP_GC_TABLES
8448
8449     if (compiler->opts.dspGCtbls)
8450     {
8451         const BYTE* base = (BYTE*)infoPtr;
8452         unsigned    size;
8453         unsigned    methodSize;
8454         InfoHdr     dumpHeader;
8455
8456         printf("GC Info for method %s\n", compiler->info.compFullName);
8457         printf("GC info size = %3u\n", compiler->compInfoBlkSize);
8458
8459         size = gcInfo.gcInfoBlockHdrDump(base, &dumpHeader, &methodSize);
8460         // printf("size of header encoding is %3u\n", size);
8461         printf("\n");
8462
8463         if (compiler->opts.dspGCtbls)
8464         {
8465             base += size;
8466             size = gcInfo.gcDumpPtrTable(base, dumpHeader, methodSize);
8467             // printf("size of pointer table is %3u\n", size);
8468             printf("\n");
8469             noway_assert(compiler->compInfoBlkAddr == (base + size));
8470         }
8471     }
8472
8473 #ifdef DEBUG
8474     if (jitOpts.testMask & 128)
8475     {
8476         for (unsigned offs = 0; offs < codeSize; offs++)
8477         {
8478             gcInfo.gcFindPtrsInFrame(infoPtr, codePtr, offs);
8479         }
8480     }
8481 #endif // DEBUG
8482 #endif // DUMP_GC_TABLES
8483
8484     /* Make sure we ended up generating the expected number of bytes */
8485
8486     noway_assert(compiler->compInfoBlkAddr == (BYTE*)infoPtr + compiler->compInfoBlkSize);
8487
8488     return infoPtr;
8489 }
8490
8491 #else  // !JIT32_GCENCODER
8492 void CodeGen::genCreateAndStoreGCInfoX64(unsigned codeSize, unsigned prologSize DEBUGARG(void* codePtr))
8493 {
8494     IAllocator*    allowZeroAlloc = new (compiler, CMK_GC) AllowZeroAllocator(compiler->getAllocatorGC());
8495     GcInfoEncoder* gcInfoEncoder  = new (compiler, CMK_GC)
8496         GcInfoEncoder(compiler->info.compCompHnd, compiler->info.compMethodInfo, allowZeroAlloc, NOMEM);
8497     assert(gcInfoEncoder);
8498
8499     // Follow the code pattern of the x86 gc info encoder (genCreateAndStoreGCInfoJIT32).
8500     gcInfo.gcInfoBlockHdrSave(gcInfoEncoder, codeSize, prologSize);
8501
8502     // We keep the call count for the second call to gcMakeRegPtrTable() below.
8503     unsigned callCnt = 0;
8504     // First we figure out the encoder ID's for the stack slots and registers.
8505     gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_ASSIGN_SLOTS, &callCnt);
8506     // Now we've requested all the slots we'll need; "finalize" these (make more compact data structures for them).
8507     gcInfoEncoder->FinalizeSlotIds();
8508     // Now we can actually use those slot ID's to declare live ranges.
8509     gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_DO_WORK, &callCnt);
8510
8511     if (compiler->opts.compDbgEnC)
8512     {
8513         // what we have to preserve is called the "frame header" (see comments in VM\eetwain.cpp)
8514         // which is:
8515         //  -return address
8516         //  -saved off RBP
8517         //  -saved 'this' pointer and bool for synchronized methods
8518
8519         // 4 slots for RBP + return address + RSI + RDI
8520         int preservedAreaSize = 4 * REGSIZE_BYTES;
8521
8522         if (compiler->info.compFlags & CORINFO_FLG_SYNCH)
8523         {
8524             if (!(compiler->info.compFlags & CORINFO_FLG_STATIC))
8525             {
8526                 preservedAreaSize += REGSIZE_BYTES;
8527             }
8528
8529             // bool in synchronized methods that tracks whether the lock has been taken (takes 4 bytes on stack)
8530             preservedAreaSize += 4;
8531         }
8532
8533         // Used to signal both that the method is compiled for EnC, and also the size of the block at the top of the
8534         // frame
8535         gcInfoEncoder->SetSizeOfEditAndContinuePreservedArea(preservedAreaSize);
8536     }
8537
8538     if (compiler->opts.IsReversePInvoke())
8539     {
8540         unsigned reversePInvokeFrameVarNumber = compiler->lvaReversePInvokeFrameVar;
8541         assert(reversePInvokeFrameVarNumber != BAD_VAR_NUM && reversePInvokeFrameVarNumber < compiler->lvaRefCount);
8542         LclVarDsc& reversePInvokeFrameVar = compiler->lvaTable[reversePInvokeFrameVarNumber];
8543         gcInfoEncoder->SetReversePInvokeFrameSlot(reversePInvokeFrameVar.lvStkOffs);
8544     }
8545
8546     gcInfoEncoder->Build();
8547
8548     // GC Encoder automatically puts the GC info in the right spot using ICorJitInfo::allocGCInfo(size_t)
8549     // let's save the values anyway for debugging purposes
8550     compiler->compInfoBlkAddr = gcInfoEncoder->Emit();
8551     compiler->compInfoBlkSize = 0; // not exposed by the GCEncoder interface
8552 }
8553 #endif // !JIT32_GCENCODER
8554
8555 /*****************************************************************************
8556  *  Emit a call to a helper function.
8557  *
8558  */
8559
8560 void CodeGen::genEmitHelperCall(unsigned helper, int argSize, emitAttr retSize, regNumber callTargetReg)
8561 {
8562     void* addr  = nullptr;
8563     void* pAddr = nullptr;
8564
8565     emitter::EmitCallType callType = emitter::EC_FUNC_TOKEN;
8566     addr                           = compiler->compGetHelperFtn((CorInfoHelpFunc)helper, &pAddr);
8567     regNumber callTarget           = REG_NA;
8568     regMaskTP killMask             = compiler->compHelperCallKillSet((CorInfoHelpFunc)helper);
8569
8570     if (!addr)
8571     {
8572         assert(pAddr != nullptr);
8573
8574         // Absolute indirect call addr
8575         // Note: Order of checks is important. First always check for pc-relative and next
8576         // zero-relative.  Because the former encoding is 1-byte smaller than the latter.
8577         if (genCodeIndirAddrCanBeEncodedAsPCRelOffset((size_t)pAddr) ||
8578             genCodeIndirAddrCanBeEncodedAsZeroRelOffset((size_t)pAddr))
8579         {
8580             // generate call whose target is specified by 32-bit offset relative to PC or zero.
8581             callType = emitter::EC_FUNC_TOKEN_INDIR;
8582             addr     = pAddr;
8583         }
8584         else
8585         {
8586 #ifdef _TARGET_AMD64_
8587             // If this indirect address cannot be encoded as 32-bit offset relative to PC or Zero,
8588             // load it into REG_HELPER_CALL_TARGET and use register indirect addressing mode to
8589             // make the call.
8590             //    mov   reg, addr
8591             //    call  [reg]
8592
8593             if (callTargetReg == REG_NA)
8594             {
8595                 // If a callTargetReg has not been explicitly provided, we will use REG_DEFAULT_HELPER_CALL_TARGET, but
8596                 // this is only a valid assumption if the helper call is known to kill REG_DEFAULT_HELPER_CALL_TARGET.
8597                 callTargetReg            = REG_DEFAULT_HELPER_CALL_TARGET;
8598                 regMaskTP callTargetMask = genRegMask(callTargetReg);
8599                 noway_assert((callTargetMask & killMask) == callTargetMask);
8600             }
8601             else
8602             {
8603                 // The call target must not overwrite any live variable, though it may not be in the
8604                 // kill set for the call.
8605                 regMaskTP callTargetMask = genRegMask(callTargetReg);
8606                 noway_assert((callTargetMask & regSet.rsMaskVars) == RBM_NONE);
8607             }
8608 #endif
8609
8610             callTarget = callTargetReg;
8611             CodeGen::genSetRegToIcon(callTarget, (ssize_t)pAddr, TYP_I_IMPL);
8612             callType = emitter::EC_INDIR_ARD;
8613         }
8614     }
8615
8616     // clang-format off
8617     getEmitter()->emitIns_Call(callType,
8618                                compiler->eeFindHelper(helper),
8619                                INDEBUG_LDISASM_COMMA(nullptr) addr,
8620                                argSize,
8621                                retSize
8622                                MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(EA_UNKNOWN),
8623                                gcInfo.gcVarPtrSetCur,
8624                                gcInfo.gcRegGCrefSetCur,
8625                                gcInfo.gcRegByrefSetCur,
8626                                BAD_IL_OFFSET, // IL offset
8627                                callTarget,    // ireg
8628                                REG_NA, 0, 0,  // xreg, xmul, disp
8629                                false,         // isJump
8630                                emitter::emitNoGChelper(helper));
8631     // clang-format on
8632
8633     regTracker.rsTrashRegSet(killMask);
8634     regTracker.rsTrashRegsForGCInterruptability();
8635 }
8636
8637 #if !defined(_TARGET_64BIT_)
8638 //-----------------------------------------------------------------------------
8639 //
8640 // Code Generation for Long integers
8641 //
8642 //-----------------------------------------------------------------------------
8643
8644 //------------------------------------------------------------------------
8645 // genStoreLongLclVar: Generate code to store a non-enregistered long lclVar
8646 //
8647 // Arguments:
8648 //    treeNode - A TYP_LONG lclVar node.
8649 //
8650 // Return Value:
8651 //    None.
8652 //
8653 // Assumptions:
8654 //    'treeNode' must be a TYP_LONG lclVar node for a lclVar that has NOT been promoted.
8655 //    Its operand must be a GT_LONG node.
8656 //
8657 void CodeGen::genStoreLongLclVar(GenTree* treeNode)
8658 {
8659     emitter* emit = getEmitter();
8660
8661     GenTreeLclVarCommon* lclNode = treeNode->AsLclVarCommon();
8662     unsigned             lclNum  = lclNode->gtLclNum;
8663     LclVarDsc*           varDsc  = &(compiler->lvaTable[lclNum]);
8664     assert(varDsc->TypeGet() == TYP_LONG);
8665     assert(!varDsc->lvPromoted);
8666     GenTreePtr op1 = treeNode->gtOp.gtOp1;
8667     noway_assert(op1->OperGet() == GT_LONG || op1->OperGet() == GT_MUL_LONG);
8668     genConsumeRegs(op1);
8669
8670     if (op1->OperGet() == GT_LONG)
8671     {
8672         // Definitions of register candidates will have been lowered to 2 int lclVars.
8673         assert(!treeNode->InReg());
8674
8675         GenTreePtr loVal = op1->gtGetOp1();
8676         GenTreePtr hiVal = op1->gtGetOp2();
8677
8678         // NYI: Contained immediates.
8679         NYI_IF((loVal->gtRegNum == REG_NA) || (hiVal->gtRegNum == REG_NA),
8680                "Store of long lclVar with contained immediate");
8681
8682         emit->emitIns_S_R(ins_Store(TYP_INT), EA_4BYTE, loVal->gtRegNum, lclNum, 0);
8683         emit->emitIns_S_R(ins_Store(TYP_INT), EA_4BYTE, hiVal->gtRegNum, lclNum, genTypeSize(TYP_INT));
8684     }
8685     else if (op1->OperGet() == GT_MUL_LONG)
8686     {
8687         assert((op1->gtFlags & GTF_MUL_64RSLT) != 0);
8688
8689         // Stack store
8690         getEmitter()->emitIns_S_R(ins_Store(TYP_INT), emitTypeSize(TYP_INT), REG_LNGRET_LO, lclNum, 0);
8691         getEmitter()->emitIns_S_R(ins_Store(TYP_INT), emitTypeSize(TYP_INT), REG_LNGRET_HI, lclNum,
8692                                   genTypeSize(TYP_INT));
8693     }
8694 }
8695 #endif // !defined(_TARGET_64BIT_)
8696
8697 /*****************************************************************************
8698 * Unit testing of the XArch emitter: generate a bunch of instructions into the prolog
8699 * (it's as good a place as any), then use COMPlus_JitLateDisasm=* to see if the late
8700 * disassembler thinks the instructions as the same as we do.
8701 */
8702
8703 // Uncomment "#define ALL_ARM64_EMITTER_UNIT_TESTS" to run all the unit tests here.
8704 // After adding a unit test, and verifying it works, put it under this #ifdef, so we don't see it run every time.
8705 //#define ALL_XARCH_EMITTER_UNIT_TESTS
8706
8707 #if defined(DEBUG) && defined(LATE_DISASM) && defined(_TARGET_AMD64_)
8708 void CodeGen::genAmd64EmitterUnitTests()
8709 {
8710     if (!verbose)
8711     {
8712         return;
8713     }
8714
8715     if (!compiler->opts.altJit)
8716     {
8717         // No point doing this in a "real" JIT.
8718         return;
8719     }
8720
8721     // Mark the "fake" instructions in the output.
8722     printf("*************** In genAmd64EmitterUnitTests()\n");
8723
8724     // We use this:
8725     //      genDefineTempLabel(genCreateTempLabel());
8726     // to create artificial labels to help separate groups of tests.
8727
8728     //
8729     // Loads
8730     //
8731     CLANG_FORMAT_COMMENT_ANCHOR;
8732
8733 #ifdef ALL_XARCH_EMITTER_UNIT_TESTS
8734 #ifdef FEATURE_AVX_SUPPORT
8735     genDefineTempLabel(genCreateTempLabel());
8736
8737     // vhaddpd     ymm0,ymm1,ymm2
8738     getEmitter()->emitIns_R_R_R(INS_haddpd, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8739     // vaddss      xmm0,xmm1,xmm2
8740     getEmitter()->emitIns_R_R_R(INS_addss, EA_4BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8741     // vaddsd      xmm0,xmm1,xmm2
8742     getEmitter()->emitIns_R_R_R(INS_addsd, EA_8BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8743     // vaddps      xmm0,xmm1,xmm2
8744     getEmitter()->emitIns_R_R_R(INS_addps, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8745     // vaddps      ymm0,ymm1,ymm2
8746     getEmitter()->emitIns_R_R_R(INS_addps, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8747     // vaddpd      xmm0,xmm1,xmm2
8748     getEmitter()->emitIns_R_R_R(INS_addpd, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8749     // vaddpd      ymm0,ymm1,ymm2
8750     getEmitter()->emitIns_R_R_R(INS_addpd, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8751     // vsubss      xmm0,xmm1,xmm2
8752     getEmitter()->emitIns_R_R_R(INS_subss, EA_4BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8753     // vsubsd      xmm0,xmm1,xmm2
8754     getEmitter()->emitIns_R_R_R(INS_subsd, EA_8BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8755     // vsubps      ymm0,ymm1,ymm2
8756     getEmitter()->emitIns_R_R_R(INS_subps, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8757     // vsubps      ymm0,ymm1,ymm2
8758     getEmitter()->emitIns_R_R_R(INS_subps, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8759     // vsubpd      xmm0,xmm1,xmm2
8760     getEmitter()->emitIns_R_R_R(INS_subpd, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8761     // vsubpd      ymm0,ymm1,ymm2
8762     getEmitter()->emitIns_R_R_R(INS_subpd, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8763     // vmulss      xmm0,xmm1,xmm2
8764     getEmitter()->emitIns_R_R_R(INS_mulss, EA_4BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8765     // vmulsd      xmm0,xmm1,xmm2
8766     getEmitter()->emitIns_R_R_R(INS_mulsd, EA_8BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8767     // vmulps      xmm0,xmm1,xmm2
8768     getEmitter()->emitIns_R_R_R(INS_mulps, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8769     // vmulpd      xmm0,xmm1,xmm2
8770     getEmitter()->emitIns_R_R_R(INS_mulpd, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8771     // vmulps      ymm0,ymm1,ymm2
8772     getEmitter()->emitIns_R_R_R(INS_mulps, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8773     // vmulpd      ymm0,ymm1,ymm2
8774     getEmitter()->emitIns_R_R_R(INS_mulpd, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8775     // vandps      xmm0,xmm1,xmm2
8776     getEmitter()->emitIns_R_R_R(INS_andps, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8777     // vandpd      xmm0,xmm1,xmm2
8778     getEmitter()->emitIns_R_R_R(INS_andpd, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8779     // vandps      ymm0,ymm1,ymm2
8780     getEmitter()->emitIns_R_R_R(INS_andps, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8781     // vandpd      ymm0,ymm1,ymm2
8782     getEmitter()->emitIns_R_R_R(INS_andpd, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8783     // vorps      xmm0,xmm1,xmm2
8784     getEmitter()->emitIns_R_R_R(INS_orps, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8785     // vorpd      xmm0,xmm1,xmm2
8786     getEmitter()->emitIns_R_R_R(INS_orpd, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8787     // vorps      ymm0,ymm1,ymm2
8788     getEmitter()->emitIns_R_R_R(INS_orps, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8789     // vorpd      ymm0,ymm1,ymm2
8790     getEmitter()->emitIns_R_R_R(INS_orpd, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8791     // vdivss      xmm0,xmm1,xmm2
8792     getEmitter()->emitIns_R_R_R(INS_divss, EA_4BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8793     // vdivsd      xmm0,xmm1,xmm2
8794     getEmitter()->emitIns_R_R_R(INS_divsd, EA_8BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8795     // vdivss      xmm0,xmm1,xmm2
8796     getEmitter()->emitIns_R_R_R(INS_divss, EA_4BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8797     // vdivsd      xmm0,xmm1,xmm2
8798     getEmitter()->emitIns_R_R_R(INS_divsd, EA_8BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8799
8800     // vdivss      xmm0,xmm1,xmm2
8801     getEmitter()->emitIns_R_R_R(INS_cvtss2sd, EA_4BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8802     // vdivsd      xmm0,xmm1,xmm2
8803     getEmitter()->emitIns_R_R_R(INS_cvtsd2ss, EA_8BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8804 #endif // FEATURE_AVX_SUPPORT
8805 #endif // ALL_XARCH_EMITTER_UNIT_TESTS
8806     printf("*************** End of genAmd64EmitterUnitTests()\n");
8807 }
8808
8809 #endif // defined(DEBUG) && defined(LATE_DISASM) && defined(_TARGET_AMD64_)
8810
8811 #endif // _TARGET_AMD64_
8812
8813 #endif // !LEGACY_BACKEND