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.
6 // This file contains the members of CodeGen that are defined and used
7 // only by the "classic" JIT backend. It is included by CodeGen.h in the
8 // definition of the CodeGen class.
11 #ifndef _CODEGENCLASSIC_H_
12 #define _CODEGENCLASSIC_H_
14 #ifdef LEGACY_BACKEND // Not necessary (it's this way in the #include location), but helpful to IntelliSense
17 regNumber genIsEnregisteredIntVariable(GenTree* tree);
19 void sched_AM(instruction ins,
27 insFlags flags = INS_FLAGS_DONT_CARE);
30 #if FEATURE_STACK_FP_X87
31 VARSET_TP genFPregVars; // mask corresponding to genFPregCnt
32 unsigned genFPdeadRegCnt; // The dead unpopped part of genFPregCnt
33 #endif // FEATURE_STACK_FP_X87
35 //-------------------------------------------------------------------------
37 void genSetRegToIcon(regNumber reg, ssize_t val, var_types type = TYP_INT, insFlags flags = INS_FLAGS_DONT_CARE);
39 regNumber genGetRegSetToIcon(ssize_t val, regMaskTP regBest = 0, var_types type = TYP_INT);
40 void genDecRegBy(regNumber reg, ssize_t ival, GenTree* tree);
41 void genIncRegBy(regNumber reg, ssize_t ival, GenTree* tree, var_types dstType = TYP_INT, bool ovfl = false);
43 void genMulRegBy(regNumber reg, ssize_t ival, GenTree* tree, var_types dstType = TYP_INT, bool ovfl = false);
45 //-------------------------------------------------------------------------
47 bool genRegTrashable(regNumber reg, GenTree* tree);
50 // Prolog functions and data (there are a few exceptions for more generally used things)
53 regMaskTP genPInvokeMethodProlog(regMaskTP initRegs);
55 void genPInvokeMethodEpilog();
57 regNumber genPInvokeCallProlog(LclVarDsc* varDsc,
59 CORINFO_METHOD_HANDLE methodToken,
60 BasicBlock* returnLabel);
62 void genPInvokeCallEpilog(LclVarDsc* varDsc, regMaskTP retVal);
64 regNumber genLclHeap(GenTree* size);
66 void genDyingVars(VARSET_VALARG_TP beforeSet, VARSET_VALARG_TP afterSet);
68 bool genContainsVarDeath(GenTree* from, GenTree* to, unsigned varNum);
71 GenTree* tree, regMaskTP needReg, RegSet::ExactReg mustReg, RegSet::KeepReg keepReg, bool freeOnly = false);
73 void genCompIntoFreeReg(GenTree* tree, regMaskTP needReg, RegSet::KeepReg keepReg);
75 void genReleaseReg(GenTree* tree);
77 void genRecoverReg(GenTree* tree, regMaskTP needReg, RegSet::KeepReg keepReg);
79 void genMoveRegPairHalf(GenTree* tree, regNumber dst, regNumber src, int off = 0);
81 void genMoveRegPair(GenTree* tree, regMaskTP needReg, regPairNo newPair);
83 void genComputeRegPair(
84 GenTree* tree, regPairNo needRegPair, regMaskTP avoidReg, RegSet::KeepReg keepReg, bool freeOnly = false);
86 void genCompIntoFreeRegPair(GenTree* tree, regMaskTP avoidReg, RegSet::KeepReg keepReg);
88 void genComputeAddressable(GenTree* tree,
90 RegSet::KeepReg keptReg,
92 RegSet::KeepReg keepReg,
93 bool freeOnly = false);
95 void genReleaseRegPair(GenTree* tree);
97 void genRecoverRegPair(GenTree* tree, regPairNo regPair, RegSet::KeepReg keepReg);
99 void genEvalIntoFreeRegPair(GenTree* tree, regPairNo regPair, regMaskTP avoidReg);
101 void genMakeRegPairAvailable(regPairNo regPair);
103 bool genMakeIndAddrMode(GenTree* addr,
107 RegSet::KeepReg keepReg,
108 regMaskTP* useMaskPtr,
109 bool deferOp = false);
111 regMaskTP genMakeRvalueAddressable(
112 GenTree* tree, regMaskTP needReg, RegSet::KeepReg keepReg, bool forLoadStore, bool smallOK = false);
114 regMaskTP genMakeAddressable(
115 GenTree* tree, regMaskTP needReg, RegSet::KeepReg keepReg, bool smallOK = false, bool deferOK = false);
117 regMaskTP genMakeAddrArrElem(GenTree* arrElem, GenTree* tree, regMaskTP needReg, RegSet::KeepReg keepReg);
119 regMaskTP genMakeAddressable2(GenTree* tree,
121 RegSet::KeepReg keepReg,
123 bool smallOK = false,
124 bool deferOK = false,
125 bool evalSideEffs = false);
127 bool genStillAddressable(GenTree* tree);
129 regMaskTP genRestoreAddrMode(GenTree* addr, GenTree* tree, bool lockPhase);
131 regMaskTP genRestAddressable(GenTree* tree, regMaskTP addrReg, regMaskTP lockMask);
133 regMaskTP genKeepAddressable(GenTree* tree, regMaskTP addrReg, regMaskTP avoidMask = RBM_NONE);
135 void genDoneAddressable(GenTree* tree, regMaskTP addrReg, RegSet::KeepReg keptReg);
137 GenTree* genMakeAddrOrFPstk(GenTree* tree, regMaskTP* regMaskPtr, bool roundResult);
139 void genEmitGSCookieCheck(bool pushReg);
141 void genEvalSideEffects(GenTree* tree);
143 void genCondJump(GenTree* cond, BasicBlock* destTrue = NULL, BasicBlock* destFalse = NULL, bool bStackFPFixup = true);
145 emitJumpKind genCondSetFlags(GenTree* cond);
147 void genJCC(genTreeOps cmp, BasicBlock* block, var_types type);
149 void genJccLongHi(genTreeOps cmp, BasicBlock* jumpTrue, BasicBlock* jumpFalse, bool unsOper = false);
151 void genJccLongLo(genTreeOps cmp, BasicBlock* jumpTrue, BasicBlock* jumpFalse);
153 void genCondJumpLng(GenTree* cond, BasicBlock* jumpTrue, BasicBlock* jumpFalse, bool bFPTransition = false);
155 bool genUse_fcomip();
157 void genTableSwitch(regNumber reg, unsigned jumpCnt, BasicBlock** jumpTab);
159 regMaskTP WriteBarrier(GenTree* tgt, GenTree* assignVal, regMaskTP addrReg);
161 void genCodeForTreeConst(GenTree* tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE);
163 void genCodeForTreeLeaf(GenTree* tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE);
165 // If "tree" is a comma node, generates code for the left comma arguments,
166 // in order, returning the first right argument in the list that is not
168 GenTree* genCodeForCommaTree(GenTree* tree);
170 void genCodeForTreeLeaf_GT_JMP(GenTree* tree);
172 static Compiler::fgWalkPreFn fgIsVarAssignedTo;
174 void genCodeForQmark(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
176 bool genCodeForQmarkWithCMOV(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
178 #ifdef _TARGET_XARCH_
179 void genCodeForMultEAX(GenTree* tree);
182 void genCodeForMult64(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
185 void genCodeForTreeSmpBinArithLogOp(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
187 void genCodeForTreeSmpBinArithLogAsgOp(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
189 void genCodeForUnsignedMod(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
191 void genCodeForSignedMod(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
193 void genCodeForUnsignedDiv(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
195 void genCodeForSignedDiv(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
197 void genCodeForGeneralDivide(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
199 void genCodeForAsgShift(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
201 void genCodeForShift(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
203 void genCodeForRelop(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
205 void genCodeForCopyObj(GenTree* tree, regMaskTP destReg);
207 void genCodeForBlkOp(GenTree* tree, regMaskTP destReg);
209 void genCodeForTreeSmpOp(GenTree* tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE);
211 regNumber genIntegerCast(GenTree* tree, regMaskTP needReg, regMaskTP bestReg);
213 void genCodeForNumericCast(GenTree* tree, regMaskTP destReg, regMaskTP bestReg);
215 void genCodeForTreeSmpOp_GT_ADDR(GenTree* tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE);
217 void genCodeForTreeSmpOpAsg(GenTree* tree);
219 void genCodeForTreeSmpOpAsg_DONE_ASSG(GenTree* tree, regMaskTP addrReg, regNumber reg, bool ovfl);
221 void genCodeForTreeSpecialOp(GenTree* tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE);
223 void genCodeForTree(GenTree* tree, regMaskTP destReg, regMaskTP bestReg = RBM_NONE);
225 void genCodeForTree_DONE_LIFE(GenTree* tree, regNumber reg)
227 /* We've computed the value of 'tree' into 'reg' */
229 assert(reg != 0xFEEFFAAFu);
230 assert(!IsUninitialized(reg));
232 genMarkTreeInReg(tree, reg);
235 void genCodeForTree_DONE_LIFE(GenTree* tree, regPairNo regPair)
237 /* We've computed the value of 'tree' into 'regPair' */
239 genMarkTreeInRegPair(tree, regPair);
242 void genCodeForTree_DONE(GenTree* tree, regNumber reg)
244 /* Check whether this subtree has freed up any variables */
248 genCodeForTree_DONE_LIFE(tree, reg);
251 void genCodeForTree_REG_VAR1(GenTree* tree)
253 /* Value is already in a register */
255 regNumber reg = tree->gtRegNum;
257 gcInfo.gcMarkRegPtrVal(reg, tree->TypeGet());
259 genCodeForTree_DONE(tree, reg);
262 void genCodeForTreeLng(GenTree* tree, regMaskTP needReg, regMaskTP avoidReg);
264 regPairNo genCodeForLongModInt(GenTree* tree, regMaskTP needReg);
266 unsigned genRegCountForLiveIntEnregVars(GenTree* tree);
269 void genStoreFromFltRetRegs(GenTree* tree);
270 void genLoadIntoFltRetRegs(GenTree* tree);
271 void genLdStFltRetRegsPromotedVar(LclVarDsc* varDsc, bool isLoadIntoFltReg);
274 #if CPU_HAS_FP_SUPPORT
275 void genRoundFpExpression(GenTree* op, var_types type = TYP_UNDEF);
276 void genCodeForTreeFlt(GenTree* tree, regMaskTP needReg = RBM_ALLFLOAT, regMaskTP bestReg = RBM_NONE);
282 void genCodeForJumpTable(GenTree* tree);
283 void genCodeForSwitchTable(GenTree* tree);
284 void genCodeForSwitch(GenTree* tree);
286 size_t genPushArgList(GenTreeCall* call);
289 // We are generating code for a promoted struct local variable. Fill the next slot (register or
290 // 4-byte stack slot) with one or more field variables of the promoted struct local -- or 2 such slots
291 // if the next field is a 64-bit value.
292 // The arguments are:
293 // "arg" is the current argument node.
295 // "curArgTabEntry" arg table entry pointer for "arg".
297 // "promotedStructLocalVarDesc" describes the struct local being copied, assumed non-NULL.
299 // "fieldSize" is somewhat misnamed; it must be the element in the struct's GC layout describing the next slot
300 // of the struct -- it will be EA_4BYTE, EA_GCREF, or EA_BYREF.
302 // "*pNextPromotedStructFieldVar" must be the the local variable number of the next field variable to copy;
303 // this location will be updated by the call to reflect the bytes that are copied.
305 // "*pBytesOfNextSlotOfCurPromotedStruct" must be the number of bytes within the struct local at which the next
306 // slot to be copied starts. This location will be updated by the call to reflect the bytes that are copied.
308 // "*pCurRegNum" must be the current argument register number, and will be updated if argument registers are filled.
310 // "argOffset" must be the offset of the next slot to be filled in the outgoing argument area, if the argument is to
312 // put in the outgoing arg area of the stack (or else should be INT_MAX if the next slot to be filled is a
314 // (Strictly speaking, after the addition of "argOffsetOfFirstStackSlot", this arg is redundant, and is only used
315 // in assertions, and could be removed.)
317 // "fieldOffsetOfFirstStackSlot" must be the offset within the promoted struct local of the first slot that should be
318 // copied to the outgoing argument area -- non-zero only in the case of a struct that spans registers and stack
321 // "argOffsetOfFirstStackSlot" must be the 4-byte-aligned offset of the first offset in the outgoing argument area
323 // contain part of the struct. (Explicit alignment may mean it doesn't actually contain part of the struct.)
325 // "*deadFieldVarRegs" is an out parameter, the set of registers containing promoted field variables that become dead
327 // this (implicit) use.
329 // "*pRegTmp" -- if a temporary register is needed, and this is not REG_STK, uses that register. Otherwise, if it is
331 // allocates a register, uses it, and sets "*pRegTmp" to the allocated register.
333 // Returns "true" iff it filled two slots with an 8-byte value.
334 bool genFillSlotFromPromotedStruct(GenTree* arg,
335 fgArgTabEntry* curArgTabEntry,
336 LclVarDsc* promotedStructLocalVarDesc,
338 unsigned* pNextPromotedStructFieldVar, // IN/OUT
339 unsigned* pBytesOfNextSlotOfCurPromotedStruct, // IN/OUT
340 regNumber* pCurRegNum, // IN/OUT
342 int fieldOffsetOfFirstStackSlot,
343 int argOffsetOfFirstStackSlot,
344 regMaskTP* deadFieldVarRegs, // OUT
345 regNumber* pRegTmp); // IN/OUT
347 #endif // _TARGET_ARM_
348 // Requires that "curr" is a cpblk. If the RHS is a promoted struct local,
349 // then returns a regMaskTP representing the set of registers holding
350 // fieldVars of the RHS that go dead with this use (as determined by the live set
352 regMaskTP genFindDeadFieldRegs(GenTree* cpBlk);
354 void SetupLateArgs(GenTreeCall* call);
357 void PushMkRefAnyArg(GenTree* mkRefAnyTree, fgArgTabEntry* curArgTabEntry, regMaskTP regNeedMask);
358 #endif // _TARGET_ARM_
360 regMaskTP genLoadIndirectCallTarget(GenTreeCall* call);
362 regMaskTP genCodeForCall(GenTreeCall* call, bool valUsed);
364 GenTree* genGetAddrModeBase(GenTree* tree);
366 GenTree* genIsAddrMode(GenTree* tree, GenTree** indxPtr);
369 bool genIsLocalLastUse(GenTree* tree);
371 bool genIsRegCandidateLocal(GenTree* tree);
373 //=========================================================================
375 //=========================================================================
377 #if FEATURE_STACK_FP_X87
379 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
380 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
384 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
385 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
388 bool StackFPIsSameAsFloat(double d);
389 bool FlatFPSameRegisters(FlatFPStateX87* pState, regMaskTP mask);
391 // FlatFPStateX87_ functions are the actual verbs to do stuff
392 // like doing a transition, loading register, etc. It's also
393 // responsible for emitting the x87 code to do so. We keep
394 // them in Compiler because we don't want to store a pointer to the
396 void FlatFPX87_Kill(FlatFPStateX87* pState, unsigned iVirtual);
397 void FlatFPX87_PushVirtual(FlatFPStateX87* pState, unsigned iRegister, bool bEmitCode = true);
398 unsigned FlatFPX87_Pop(FlatFPStateX87* pState, bool bEmitCode = true);
399 unsigned FlatFPX87_Top(FlatFPStateX87* pState, bool bEmitCode = true);
400 void FlatFPX87_Unload(FlatFPStateX87* pState, unsigned iVirtual, bool bEmitCode = true);
403 // Codegen functions. This is the API that codegen will use
404 regMaskTP genPushArgumentStackFP(GenTree* arg);
405 void genRoundFpExpressionStackFP(GenTree* op, var_types type = TYP_UNDEF);
406 void genCodeForTreeStackFP_Const(GenTree* tree);
407 void genCodeForTreeStackFP_Leaf(GenTree* tree);
408 void genCodeForTreeStackFP_SmpOp(GenTree* tree);
409 void genCodeForTreeStackFP_Special(GenTree* tree);
410 void genCodeForTreeStackFP_Cast(GenTree* tree);
411 void genCodeForTreeStackFP(GenTree* tree);
412 void genCondJumpFltStackFP(GenTree* cond, BasicBlock* jumpTrue, BasicBlock* jumpFalse, bool bDoTransition = true);
413 void genCondJumpFloat(GenTree* cond, BasicBlock* jumpTrue, BasicBlock* jumpFalse);
414 void genCondJumpLngStackFP(GenTree* cond, BasicBlock* jumpTrue, BasicBlock* jumpFalse);
416 void genFloatConst(GenTree* tree, RegSet::RegisterPreference* pref);
417 void genFloatLeaf(GenTree* tree, RegSet::RegisterPreference* pref);
418 void genFloatSimple(GenTree* tree, RegSet::RegisterPreference* pref);
419 void genFloatMath(GenTree* tree, RegSet::RegisterPreference* pref);
420 void genFloatCheckFinite(GenTree* tree, RegSet::RegisterPreference* pref);
421 void genLoadFloat(GenTree* tree, regNumber reg);
422 void genFloatAssign(GenTree* tree);
423 void genFloatArith(GenTree* tree, RegSet::RegisterPreference* pref);
424 void genFloatAsgArith(GenTree* tree);
426 regNumber genAssignArithFloat(genTreeOps oper, GenTree* dst, regNumber dstreg, GenTree* src, regNumber srcreg);
428 GenTree* genMakeAddressableFloat(GenTree* tree,
429 regMaskTP* regMaskIntPtr,
430 regMaskTP* regMaskFltPtr,
431 bool bCollapseConstantDoubles = true);
433 void genCodeForTreeFloat(GenTree* tree, RegSet::RegisterPreference* pref = NULL);
435 void genCodeForTreeFloat(GenTree* tree, regMaskTP needReg, regMaskTP bestReg);
437 regNumber genArithmFloat(
438 genTreeOps oper, GenTree* dst, regNumber dstreg, GenTree* src, regNumber srcreg, bool bReverse);
439 void genCodeForTreeCastFloat(GenTree* tree, RegSet::RegisterPreference* pref);
440 void genCodeForTreeCastToFloat(GenTree* tree, RegSet::RegisterPreference* pref);
441 void genCodeForTreeCastFromFloat(GenTree* tree, RegSet::RegisterPreference* pref);
442 void genKeepAddressableFloat(GenTree* tree, regMaskTP* regMaskIntPtr, regMaskTP* regMaskFltPtr);
443 void genDoneAddressableFloat(GenTree* tree, regMaskTP addrRegInt, regMaskTP addrRegFlt, RegSet::KeepReg keptReg);
444 void genComputeAddressableFloat(GenTree* tree,
445 regMaskTP addrRegInt,
446 regMaskTP addrRegFlt,
447 RegSet::KeepReg keptReg,
449 RegSet::KeepReg keepReg,
450 bool freeOnly = false);
451 void genRoundFloatExpression(GenTree* op, var_types type);
453 #if FEATURE_STACK_FP_X87
454 // Assumes then block will be generated before else block.
455 struct QmarkStateStackFP
457 FlatFPStateX87 stackState;
460 void genQMarkRegVarTransition(GenTree* nextNode, VARSET_VALARG_TP liveset);
461 void genQMarkBeforeElseStackFP(QmarkStateStackFP* pState, VARSET_VALARG_TP varsetCond, GenTree* nextNode);
462 void genQMarkAfterElseBlockStackFP(QmarkStateStackFP* pState, VARSET_VALARG_TP varsetCond, GenTree* nextNode);
463 void genQMarkAfterThenBlockStackFP(QmarkStateStackFP* pState);
467 GenTree* genMakeAddressableStackFP(GenTree* tree,
468 regMaskTP* regMaskIntPtr,
469 regMaskTP* regMaskFltPtr,
470 bool bCollapseConstantDoubles = true);
471 void genKeepAddressableStackFP(GenTree* tree, regMaskTP* regMaskIntPtr, regMaskTP* regMaskFltPtr);
472 void genDoneAddressableStackFP(GenTree* tree, regMaskTP addrRegInt, regMaskTP addrRegFlt, RegSet::KeepReg keptReg);
474 void genCodeForTreeStackFP_Asg(GenTree* tree);
475 void genCodeForTreeStackFP_AsgArithm(GenTree* tree);
476 void genCodeForTreeStackFP_Arithm(GenTree* tree);
477 void genCodeForTreeStackFP_DONE(GenTree* tree, regNumber reg);
478 void genCodeForTreeFloat_DONE(GenTree* tree, regNumber reg);
480 void genSetupStateStackFP(BasicBlock* block);
481 regMaskTP genRegMaskFromLivenessStackFP(VARSET_VALARG_TP varset);
483 // bReverse means make op1 addressable and codegen for op2.
484 // If op1 or op2 are comma expressions, will do code-gen for their non-last comma parts,
485 // and set op1 and op2 to the remaining non-comma expressions.
486 void genSetupForOpStackFP(
487 GenTree*& op1, GenTree*& op2, bool bReverse, bool bMakeOp1Addressable, bool bOp1ReadOnly, bool bOp2ReadOnly);
489 #if FEATURE_STACK_FP_X87
492 bool ConsistentAfterStatementStackFP();
496 void SpillTempsStackFP(regMaskTP canSpillMask);
497 void SpillForCallStackFP();
498 void UnspillRegVarsStackFp();
500 // Transition API. Takes care of the stack matching of basicblock boundaries
501 void genCodeForPrologStackFP();
502 void genCodeForEndBlockTransitionStackFP(BasicBlock* block);
504 void genCodeForBBTransitionStackFP(BasicBlock* pDst);
505 void genCodeForTransitionStackFP(FlatFPStateX87* pSrc, FlatFPStateX87* pDst);
506 void genCodeForTransitionFromMask(FlatFPStateX87* pSrc, regMaskTP mask, bool bEmitCode = true);
507 BasicBlock* genTransitionBlockStackFP(FlatFPStateX87* pState, BasicBlock* pFrom, BasicBlock* pTarget);
509 // This is the API codegen will use to emit virtual fp code. In theory, nobody above this API
510 // should know about x87 instructions.
512 int genNumberTemps();
513 void genDiscardStackFP(GenTree* tree);
514 void genRegRenameWithMasks(regNumber dstReg, regNumber srcReg);
515 void genRegVarBirthStackFP(GenTree* tree);
516 void genRegVarBirthStackFP(LclVarDsc* varDsc);
517 void genRegVarDeathStackFP(GenTree* tree);
518 void genRegVarDeathStackFP(LclVarDsc* varDsc);
519 void genLoadStackFP(GenTree* tree, regNumber reg);
520 void genMovStackFP(GenTree* dst, regNumber dstreg, GenTree* src, regNumber srcreg);
521 bool genCompInsStackFP(GenTree* tos, GenTree* other);
522 regNumber genArithmStackFP(
523 genTreeOps oper, GenTree* dst, regNumber dstreg, GenTree* src, regNumber srcreg, bool bReverse);
524 regNumber genAsgArithmStackFP(genTreeOps oper, GenTree* dst, regNumber dstreg, GenTree* src, regNumber srcreg);
525 void genCondJmpInsStackFP(emitJumpKind jumpKind,
526 BasicBlock* jumpTrue,
527 BasicBlock* jumpFalse,
528 bool bDoTransition = true);
529 void genTableSwitchStackFP(regNumber reg, unsigned jumpCnt, BasicBlock** jumpTab);
531 void JitDumpFPState();
532 #else // !FEATURE_STACK_FP_X87
533 void SpillForCallRegisterFP(regMaskTP noSpillMask);
534 #endif // !FEATURE_STACK_FP_X87
536 // When bOnlyNoMemAccess = true, the load will be generated only for constant loading that doesn't
537 // involve memory accesses, (ie: fldz for positive zero, or fld1 for 1). Will return true the function
539 bool genConstantLoadStackFP(GenTree* tree, bool bOnlyNoMemAccess = false);
540 void genEndOfStatement();
542 #if FEATURE_STACK_FP_X87
543 struct genRegVarDiesInSubTreeData
548 static Compiler::fgWalkPreFn genRegVarDiesInSubTreeWorker;
549 bool genRegVarDiesInSubTree(GenTree* tree, regNumber reg);
550 #endif // FEATURE_STACK_FP_X87
553 void UnspillFloat(RegSet::SpillDsc* spillDsc);
554 void UnspillFloat(GenTree* tree);
555 void UnspillFloat(LclVarDsc* varDsc);
556 void UnspillFloatMachineDep(RegSet::SpillDsc* spillDsc);
557 void UnspillFloatMachineDep(RegSet::SpillDsc* spillDsc, bool useSameReg);
558 void RemoveSpillDsc(RegSet::SpillDsc* spillDsc);
561 struct genLivenessSet
565 regMaskSmall maskVars;
566 regMaskSmall gcRefRegs;
567 regMaskSmall byRefRegs;
569 genLivenessSet() : liveSet(VarSetOps::UninitVal()), varPtrSet(VarSetOps::UninitVal())
574 void saveLiveness(genLivenessSet* ls);
575 void restoreLiveness(genLivenessSet* ls);
576 void checkLiveness(genLivenessSet* ls);
577 void unspillLiveness(genLivenessSet* ls);
579 //-------------------------------------------------------------------------
581 // If we know that the flags register is set to a value that corresponds
582 // to the current value of a register or variable, the following values
583 // record that information.
586 emitLocation genFlagsEqLoc;
587 regNumber genFlagsEqReg;
588 unsigned genFlagsEqVar;
590 void genFlagsEqualToNone();
591 void genFlagsEqualToReg(GenTree* tree, regNumber reg);
592 void genFlagsEqualToVar(GenTree* tree, unsigned var);
593 bool genFlagsAreReg(regNumber reg);
594 bool genFlagsAreVar(unsigned var);
596 #endif // LEGACY_BACKEND
598 #endif // _CODEGENCLASSIC_H_