diff options
-rw-r--r-- | src/jit/emitarm.cpp | 36 | ||||
-rw-r--r-- | src/jit/emitarm.h | 1 | ||||
-rw-r--r-- | src/jit/lsraarmarch.cpp | 12 |
3 files changed, 36 insertions, 13 deletions
diff --git a/src/jit/emitarm.cpp b/src/jit/emitarm.cpp index ebefa27fb8..53ee88b3a2 100644 --- a/src/jit/emitarm.cpp +++ b/src/jit/emitarm.cpp @@ -1422,6 +1422,20 @@ DONE: /***************************************************************************** * + * 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. */ @@ -7608,10 +7622,26 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR } } } - 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 diff --git a/src/jit/emitarm.h b/src/jit/emitarm.h index 4ec189385c..d7c8d4d0ef 100644 --- a/src/jit/emitarm.h +++ b/src/jit/emitarm.h @@ -243,6 +243,7 @@ static bool emitIns_valid_imm_for_small_mov(regNumber reg, int imm, insFlags fla 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); diff --git a/src/jit/lsraarmarch.cpp b/src/jit/lsraarmarch.cpp index 11fc490954..7d999d880f 100644 --- a/src/jit/lsraarmarch.cpp +++ b/src/jit/lsraarmarch.cpp @@ -291,19 +291,13 @@ void Lowering::TreeNodeInfoInitIndir(GenTreePtr indirTree) 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))) @@ -311,8 +305,6 @@ void Lowering::TreeNodeInfoInitIndir(GenTreePtr indirTree) // This offset can't be contained in the ldr/str instruction, so we need an internal register info->internalIntCount = 1; } - -#endif // _TARGET_ARM64_ } //------------------------------------------------------------------------ |