summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve MacLean, Qualcomm Datacenter Technologies, Inc <sdmaclea@qti.qualcomm.com>2017-05-01 19:10:37 +0000
committerSteve MacLean, Qualcomm Datacenter Technologies, Inc <sdmaclea@qti.qualcomm.com>2017-05-08 16:23:46 +0000
commit16ca06c4b68502b39c105367f27a8f62368959d4 (patch)
treec0726741f850682fd48230679ecba9bce542c1fb
parent494f00cb881cc68426718b32a62464d4c7c48007 (diff)
downloadcoreclr-16ca06c4b68502b39c105367f27a8f62368959d4.tar.gz
coreclr-16ca06c4b68502b39c105367f27a8f62368959d4.tar.bz2
coreclr-16ca06c4b68502b39c105367f27a8f62368959d4.zip
[Arm64] Add emitIns_R_R_S_S
-rw-r--r--src/jit/codegenarm64.cpp4
-rw-r--r--src/jit/codegenarmarch.cpp29
-rw-r--r--src/jit/emitarm64.cpp95
-rw-r--r--src/jit/emitarm64.h3
4 files changed, 104 insertions, 27 deletions
diff --git a/src/jit/codegenarm64.cpp b/src/jit/codegenarm64.cpp
index 0e536cd445..88240409e6 100644
--- a/src/jit/codegenarm64.cpp
+++ b/src/jit/codegenarm64.cpp
@@ -2597,9 +2597,7 @@ void CodeGen::genCodeForLoadPairOffset(regNumber dst, regNumber dst2, GenTree* b
if (base->gtOper == GT_LCL_FLD_ADDR)
offset += base->gtLclFld.gtLclOffs;
- // TODO-ARM64-CQ: Implement support for using a ldp instruction with a varNum (see emitIns_R_S)
- emit->emitIns_R_S(INS_ldr, EA_8BYTE, dst, base->gtLclVarCommon.gtLclNum, offset);
- emit->emitIns_R_S(INS_ldr, EA_8BYTE, dst2, base->gtLclVarCommon.gtLclNum, offset + REGSIZE_BYTES);
+ emit->emitIns_R_R_S_S(INS_ldp, EA_8BYTE, EA_8BYTE, dst, dst2, base->gtLclVarCommon.gtLclNum, offset);
}
else
{
diff --git a/src/jit/codegenarmarch.cpp b/src/jit/codegenarmarch.cpp
index 61b9309bb9..d71a0b776e 100644
--- a/src/jit/codegenarmarch.cpp
+++ b/src/jit/codegenarmarch.cpp
@@ -686,28 +686,9 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode)
noway_assert(structSize <= MAX_PASS_MULTIREG_BYTES);
- // For a 16-byte structSize with GC pointers we will use two ldr and two str instructions
- // ldr x2, [x0]
- // ldr x3, [x0, #8]
- // str x2, [sp, #16]
- // str x3, [sp, #24]
- //
- // For a 16-byte structSize with no GC pointers we will use a ldp and two str instructions
- // ldp x2, x3, [x0]
- // str x2, [sp, #16]
- // str x3, [sp, #24]
- //
- // For a 32-byte structSize with no GC pointers we will use two ldp and four str instructions
- // ldp x2, x3, [x0]
- // str x2, [sp, #16]
- // str x3, [sp, #24]
+ // For a >= 16-byte structSize we will generate a ldp and stp instruction each loop
// ldp x2, x3, [x0]
- // str x2, [sp, #32]
- // str x3, [sp, #40]
- //
- // Note that when loading from a varNode we currently can't use the ldp instruction
- // TODO-ARM64-CQ: Implement support for using a ldp instruction with a varNum (see emitIns_R_S)
- //
+ // stp x2, x3, [sp, #16]
int remainingSize = structSize;
unsigned structOffset = 0;
@@ -720,9 +701,9 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode)
if (varNode != nullptr)
{
- // Load from our varNumImp source, currently we can't use a ldp instruction to do this
- emit->emitIns_R_S(ins_Load(type0), emitTypeSize(type0), loReg, varNumInp, 0);
- emit->emitIns_R_S(ins_Load(type1), emitTypeSize(type1), hiReg, varNumInp, TARGET_POINTER_SIZE);
+ // Load from our varNumImp source
+ emit->emitIns_R_R_S_S(INS_ldp, emitTypeSize(type0), emitTypeSize(type1), loReg, hiReg, varNumInp,
+ 0);
}
else
{
diff --git a/src/jit/emitarm64.cpp b/src/jit/emitarm64.cpp
index c979c240a4..d398b2f833 100644
--- a/src/jit/emitarm64.cpp
+++ b/src/jit/emitarm64.cpp
@@ -6110,6 +6110,101 @@ void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int va
/*****************************************************************************
*
+ * Add an instruction referencing two register and consectutive stack-based local variable slots.
+ */
+void emitter::emitIns_R_R_S_S(
+ instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
+{
+ assert((ins == INS_ldp) || (ins == INS_ldnp));
+ assert(EA_8BYTE == EA_SIZE(attr1));
+ assert(EA_8BYTE == EA_SIZE(attr2));
+ assert(isGeneralRegisterOrZR(reg1));
+ assert(isGeneralRegisterOrZR(reg2));
+ assert(offs >= 0);
+
+ emitAttr size = EA_SIZE(attr1);
+ insFormat fmt = IF_LS_3B;
+ int disp = 0;
+ const unsigned scale = 3;
+
+ /* Figure out the variable's frame position */
+ int base;
+ bool FPbased;
+
+ base = emitComp->lvaFrameAddress(varx, &FPbased);
+ disp = base + offs;
+
+ // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
+ regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
+ reg3 = encodingSPtoZR(reg3);
+
+ bool useRegForAdr = true;
+ ssize_t imm = disp;
+ ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
+ if (imm == 0)
+ {
+ useRegForAdr = false;
+ }
+ else
+ {
+ if ((imm & mask) == 0)
+ {
+ ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
+
+ if ((immShift >= -64) && (immShift <= 63))
+ {
+ fmt = IF_LS_3C;
+ useRegForAdr = false;
+ imm = immShift;
+ }
+ }
+ }
+
+ if (useRegForAdr)
+ {
+ regNumber rsvd = codeGen->rsGetRsvdReg();
+ emitIns_R_R_Imm(INS_add, EA_8BYTE, rsvd, reg3, imm);
+ reg3 = rsvd;
+ imm = 0;
+ }
+
+ assert(fmt != IF_NONE);
+
+ instrDesc* id = emitNewInstrCns(attr1, imm);
+
+ id->idIns(ins);
+ id->idInsFmt(fmt);
+ id->idInsOpt(INS_OPTS_NONE);
+
+ if (EA_IS_GCREF(attr2))
+ {
+ /* A special value indicates a GCref pointer value */
+
+ id->idGCrefReg2(GCT_GCREF);
+ }
+ else if (EA_IS_BYREF(attr2))
+ {
+ /* A special value indicates a Byref pointer value */
+
+ id->idGCrefReg2(GCT_BYREF);
+ }
+
+ id->idReg1(reg1);
+ id->idReg2(reg2);
+ id->idReg3(reg3);
+ id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
+ id->idSetIsLclVar();
+
+#ifdef DEBUG
+ id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
+#endif
+
+ dispIns(id);
+ appendToCurIG(id);
+}
+
+/*****************************************************************************
+ *
* Add an instruction referencing a stack-based local variable and a register
*/
void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
diff --git a/src/jit/emitarm64.h b/src/jit/emitarm64.h
index 87caa22638..09158fb796 100644
--- a/src/jit/emitarm64.h
+++ b/src/jit/emitarm64.h
@@ -763,6 +763,9 @@ void emitIns_S_S_R_R(
void emitIns_R_S(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs);
+void emitIns_R_R_S_S(
+ instruction ins, emitAttr attr, emitAttr attr2, regNumber ireg, regNumber ireg2, int varx, int offs);
+
void emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val);
void emitIns_R_C(