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