@@ -3510,11 +3510,22 @@ void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
35103510 NYI (" emitIns_S" );
35113511}
35123512
3513- /* ****************************************************************************
3514- *
3515- * Add an instruction referencing a register and a stack-based local variable.
3516- */
3517- void emitter::emitIns_R_S (instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
3513+ // -------------------------------------------------------------------------------------
3514+ // emitIns_R_S: Add an instruction referencing a register and a stack-based local variable.
3515+ //
3516+ // Arguments:
3517+ // ins - The instruction to add.
3518+ // attr - Oeration size.
3519+ // varx - The variable to generate offset for.
3520+ // offs - The offset of variable or field in stack.
3521+ // pBaseReg - The base register that is used while calculating the offset. For example, if the offset
3522+ // with "stack pointer" can't be encoded in instruction, "frame pointer" can be used to get
3523+ // the offset of the field. In such case, pBaseReg will store the "fp".
3524+ //
3525+ // Return Value:
3526+ // The pBaseReg that holds the base register that was used to calculate the offset.
3527+ //
3528+ void emitter::emitIns_R_S (instruction ins, emitAttr attr, regNumber reg1, int varx, int offs, regNumber* pBaseReg)
35183529{
35193530 if (ins == INS_mov)
35203531 {
@@ -3547,6 +3558,7 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
35473558 insFormat fmt = IF_NONE;
35483559 insFlags sf = INS_FLAGS_NOT_SET;
35493560 regNumber reg2;
3561+ regNumber baseRegUsed;
35503562
35513563 /* Figure out the variable's frame position */
35523564 int base;
@@ -3555,6 +3567,10 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
35553567
35563568 base = emitComp->lvaFrameAddress (varx, emitComp->funCurrentFunc ()->funKind != FUNC_ROOT, ®2, offs,
35573569 CodeGen::instIsFP (ins));
3570+ if (pBaseReg != nullptr )
3571+ {
3572+ *pBaseReg = reg2;
3573+ }
35583574
35593575 disp = base + offs;
35603576 undisp = unsigned_abs (disp);
@@ -3575,8 +3591,8 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
35753591 else
35763592 {
35773593 regNumber rsvdReg = codeGen->rsGetRsvdReg ();
3578- emitIns_genStackOffset (rsvdReg, varx, offs, /* isFloatUsage */ true );
3579- emitIns_R_R (INS_add, EA_4BYTE, rsvdReg, reg2 );
3594+ emitIns_genStackOffset (rsvdReg, varx, offs, /* isFloatUsage */ true , &baseRegUsed );
3595+ emitIns_R_R (INS_add, EA_4BYTE, rsvdReg, baseRegUsed );
35803596 emitIns_R_R_I (ins, attr, reg1, rsvdReg, 0 );
35813597 return ;
35823598 }
@@ -3599,8 +3615,11 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
35993615 {
36003616 // Load disp into a register
36013617 regNumber rsvdReg = codeGen->rsGetRsvdReg ();
3602- emitIns_genStackOffset (rsvdReg, varx, offs, /* isFloatUsage */ false );
3618+ emitIns_genStackOffset (rsvdReg, varx, offs, /* isFloatUsage */ false , &baseRegUsed );
36033619 fmt = IF_T2_E0;
3620+
3621+ // Ensure the baseReg calculated is correct.
3622+ assert (baseRegUsed == reg2);
36043623 }
36053624 }
36063625 else if (ins == INS_add)
@@ -3625,7 +3644,10 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
36253644 {
36263645 // Load disp into a register
36273646 regNumber rsvdReg = codeGen->rsGetRsvdReg ();
3628- emitIns_genStackOffset (rsvdReg, varx, offs, /* isFloatUsage */ false );
3647+ emitIns_genStackOffset (rsvdReg, varx, offs, /* isFloatUsage */ false , &baseRegUsed);
3648+
3649+ // Ensure the baseReg calculated is correct.
3650+ assert (baseRegUsed == reg2);
36293651 emitIns_R_R_R (ins, attr, reg1, reg2, rsvdReg);
36303652 return ;
36313653 }
@@ -3662,8 +3684,24 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
36623684 appendToCurIG (id);
36633685}
36643686
3665- // generate the offset of &varx + offs into a register
3666- void emitter::emitIns_genStackOffset (regNumber r, int varx, int offs, bool isFloatUsage)
3687+ // -------------------------------------------------------------------------------------
3688+ // emitIns_genStackOffset: Generate the offset of &varx + offs into a register
3689+ //
3690+ // Arguments:
3691+ // r - Register in which offset calculation result is stored.
3692+ // varx - The variable to generate offset for.
3693+ // offs - The offset of variable or field in stack.
3694+ // isFloatUsage - True if the instruction being generated is a floating point instruction. This requires using
3695+ // floating-point offset restrictions. Note that a variable can be non-float, e.g., struct, but
3696+ // accessed as a float local field.
3697+ // pBaseReg - The base register that is used while calculating the offset. For example, if the offset with
3698+ // "stack pointer" can't be encoded in instruction, "frame pointer" can be used to get the offset
3699+ // of the field. In such case, pBaseReg will store the "fp".
3700+ //
3701+ // Return Value:
3702+ // The pBaseReg that holds the base register that was used to calculate the offset.
3703+ //
3704+ void emitter::emitIns_genStackOffset (regNumber r, int varx, int offs, bool isFloatUsage, regNumber* pBaseReg)
36673705{
36683706 regNumber regBase;
36693707 int base;
@@ -3673,11 +3711,13 @@ void emitter::emitIns_genStackOffset(regNumber r, int varx, int offs, bool isFlo
36733711 emitComp->lvaFrameAddress (varx, emitComp->funCurrentFunc ()->funKind != FUNC_ROOT, ®Base, offs, isFloatUsage);
36743712 disp = base + offs;
36753713
3676- emitIns_R_S (INS_movw, EA_4BYTE, r, varx, offs);
3714+ emitIns_R_S (INS_movw, EA_4BYTE, r, varx, offs, pBaseReg );
36773715
36783716 if ((disp & 0xffff ) != disp)
36793717 {
3680- emitIns_R_S (INS_movt, EA_4BYTE, r, varx, offs);
3718+ regNumber regBaseUsedInMovT;
3719+ emitIns_R_S (INS_movt, EA_4BYTE, r, varx, offs, ®BaseUsedInMovT);
3720+ assert (*pBaseReg == regBaseUsedInMovT);
36813721 }
36823722}
36833723
@@ -3708,6 +3748,7 @@ void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int va
37083748 insFormat fmt = IF_NONE;
37093749 insFlags sf = INS_FLAGS_NOT_SET;
37103750 regNumber reg2;
3751+ regNumber baseRegUsed;
37113752
37123753 /* Figure out the variable's frame position */
37133754 int base;
@@ -3736,7 +3777,10 @@ void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int va
37363777 else
37373778 {
37383779 regNumber rsvdReg = codeGen->rsGetRsvdReg ();
3739- emitIns_genStackOffset (rsvdReg, varx, offs, /* isFloatUsage */ true );
3780+ emitIns_genStackOffset (rsvdReg, varx, offs, /* isFloatUsage */ true , &baseRegUsed);
3781+
3782+ // Ensure the baseReg calculated is correct.
3783+ assert (baseRegUsed == reg2);
37403784 emitIns_R_R (INS_add, EA_4BYTE, rsvdReg, reg2);
37413785 emitIns_R_R_I (ins, attr, reg1, rsvdReg, 0 );
37423786 return ;
@@ -3758,8 +3802,11 @@ void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int va
37583802 {
37593803 // Load disp into a register
37603804 regNumber rsvdReg = codeGen->rsGetRsvdReg ();
3761- emitIns_genStackOffset (rsvdReg, varx, offs, /* isFloatUsage */ false );
3805+ emitIns_genStackOffset (rsvdReg, varx, offs, /* isFloatUsage */ false , &baseRegUsed );
37623806 fmt = IF_T2_E0;
3807+
3808+ // Ensure the baseReg calculated is correct.
3809+ assert (baseRegUsed == reg2);
37633810 }
37643811 assert ((fmt == IF_T1_J2) || (fmt == IF_T2_E0) || (fmt == IF_T2_H0) || (fmt == IF_T2_VLDST) || (fmt == IF_T2_K1));
37653812 assert (sf != INS_FLAGS_DONT_CARE);
0 commit comments