/*****************************************************************************
*
+ * emitIns_valid_imm_for_ldst_offset() returns true when the immediate 'imm'
+ * can be encoded as the offset in a ldr/str instruction.
+ */
+/*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(int imm, emitAttr size)
+{
+ if ((imm & 0x0fff) == imm)
+ return true; // encodable using IF_T2_K1
+ if (unsigned_abs(imm) <= 0x0ff)
+ return true; // encodable using IF_T2_H0
+ return false;
+}
+
+/*****************************************************************************
+ *
* Add an instruction with no operands.
*/
}
}
}
- else
+ else // no Index
{
- // TODO check offset is valid for encoding
- emitIns_R_R_I(ins, attr, dataReg, memBase->gtRegNum, offset);
+ if (emitIns_valid_imm_for_ldst_offset(offset, attr))
+ {
+ // Then load/store dataReg from/to [memBase + offset]
+ emitIns_R_R_I(ins, attr, dataReg, memBase->gtRegNum, offset);
+ }
+ else
+ {
+ // We require a tmpReg to hold the offset
+ regMaskTP tmpRegMask = indir->gtRsvdRegs;
+ regNumber tmpReg = genRegNumFromMask(tmpRegMask);
+ noway_assert(tmpReg != REG_NA);
+
+ // First load/store tmpReg with the large offset constant
+ codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
+
+ // Then load/store dataReg from/to [memBase + tmpReg]
+ emitIns_R_R_R(ins, attr, dataReg, memBase->gtRegNum, tmpReg);
+ }
}
}
else
static bool emitIns_valid_imm_for_add(int imm, insFlags flags);
static bool emitIns_valid_imm_for_cmp(int imm, insFlags flags);
static bool emitIns_valid_imm_for_add_sp(int imm);
+static bool emitIns_valid_imm_for_ldst_offset(int imm, emitAttr size);
void emitIns(instruction ins);
if (index != nullptr && !modifiedSources)
{
info->srcCount++;
-
-#ifdef _TARGET_ARM_
- info->internalIntCount++;
-#endif // _TARGET_ARM_
}
-#ifdef _TARGET_ARM64_
-
- // On ARM64 we may need a single internal register
+ // On ARM we may need a single internal register
// (when both conditions are true then we still only need a single internal register)
if ((index != nullptr) && (cns != 0))
{
- // ARM64 does not support both Index and offset so we need an internal register
+ // ARM does not support both Index and offset so we need an internal register
info->internalIntCount = 1;
}
else if (!emitter::emitIns_valid_imm_for_ldst_offset(cns, emitTypeSize(indirTree)))
// This offset can't be contained in the ldr/str instruction, so we need an internal register
info->internalIntCount = 1;
}
-
-#endif // _TARGET_ARM64_
}
//------------------------------------------------------------------------