summaryrefslogtreecommitdiffstats
path: root/compiler
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2014-06-18 17:45:32 -0700
committerAndreas Gampe <agampe@google.com>2014-06-18 17:45:32 -0700
commit9f975bfe091e9592a1b6b5b46d224ec04b1183b6 (patch)
tree72a26568539aef4d0199bdb7a8e40d4c38262ecb /compiler
parent0c29909cbde112bc9c04da4ce81421e1a0b39f36 (diff)
downloadart-9f975bfe091e9592a1b6b5b46d224ec04b1183b6.zip
art-9f975bfe091e9592a1b6b5b46d224ec04b1183b6.tar.gz
art-9f975bfe091e9592a1b6b5b46d224ec04b1183b6.tar.bz2
ART: Change rrr add and sub for ARM64
OpRegRegImm will fall back to loading a constant into a register and then doing the operation with three registers. That is, for example, the case when we allocate large stack frames. However, the currently chosen operations are add/sub shifted, which does *not* allow to specify SP (x31 will be interpreted as xzr). Switch to add/sub extended. There won't be a practical difference, as we do not call with anything other than 0 shift. Change-Id: I2b78df9f044d2963e3e890777c855b339952f9f4
Diffstat (limited to 'compiler')
-rw-r--r--compiler/dex/quick/arm64/arm64_lir.h6
-rw-r--r--compiler/dex/quick/arm64/assemble_arm64.cc8
-rw-r--r--compiler/dex/quick/arm64/utility_arm64.cc14
3 files changed, 23 insertions, 5 deletions
diff --git a/compiler/dex/quick/arm64/arm64_lir.h b/compiler/dex/quick/arm64/arm64_lir.h
index c1ce03d..3a6012e 100644
--- a/compiler/dex/quick/arm64/arm64_lir.h
+++ b/compiler/dex/quick/arm64/arm64_lir.h
@@ -219,7 +219,8 @@ enum ArmOpcode {
kA64First = 0,
kA64Adc3rrr = kA64First, // adc [00011010000] rm[20-16] [000000] rn[9-5] rd[4-0].
kA64Add4RRdT, // add [s001000100] imm_12[21-10] rn[9-5] rd[4-0].
- kA64Add4rrro, // add [00001011000] rm[20-16] option[15-13] imm_3[12-10] rn[9-5] rd[4-0].
+ kA64Add4rrro, // add [00001011000] rm[20-16] imm_6[15-10] rn[9-5] rd[4-0].
+ kA64Add4rrre, // add [00001011001] rm[20-16] option[15-13] imm_3[12-10] rn[9-5] rd[4-0].
kA64Adr2xd, // adr [0] immlo[30-29] [10000] immhi[23-5] rd[4-0].
kA64And3Rrl, // and [00010010] N[22] imm_r[21-16] imm_s[15-10] rn[9-5] rd[4-0].
kA64And4rrro, // and [00001010] shift[23-22] [N=0] rm[20-16] imm_6[15-10] rn[9-5] rd[4-0].
@@ -328,7 +329,8 @@ enum ArmOpcode {
kA64Stxr3wrX, // stxr[11001000000] rs[20-16] [011111] rn[9-5] rt[4-0].
kA64Stlxr3wrX, // stlxr[11001000000] rs[20-16] [111111] rn[9-5] rt[4-0].
kA64Sub4RRdT, // sub [s101000100] imm_12[21-10] rn[9-5] rd[4-0].
- kA64Sub4rrro, // sub [s1001011000] rm[20-16] option[15-13] imm_3[12-10] rn[9-5] rd[4-0].
+ kA64Sub4rrro, // sub [s1001011000] rm[20-16] imm_6[15-10] rn[9-5] rd[4-0].
+ kA64Sub4rrre, // sub [s1001011001] rm[20-16] option[15-13] imm_3[12-10] rn[9-5] rd[4-0].
kA64Subs3rRd, // subs[s111000100] imm_12[21-10] rn[9-5] rd[4-0].
kA64Tst3rro, // tst alias of "ands rzr, arg1, arg2, arg3".
kA64Ubfm4rrdd, // ubfm[s10100110] N[22] imm_r[21-16] imm_s[15-10] rn[9-5] rd[4-0].
diff --git a/compiler/dex/quick/arm64/assemble_arm64.cc b/compiler/dex/quick/arm64/assemble_arm64.cc
index c5bd005..fe3bd6a 100644
--- a/compiler/dex/quick/arm64/assemble_arm64.cc
+++ b/compiler/dex/quick/arm64/assemble_arm64.cc
@@ -115,6 +115,10 @@ const ArmEncodingMap Arm64Mir2Lir::EncodingMap[kA64Last] = {
kFmtRegR, 4, 0, kFmtRegR, 9, 5, kFmtRegR, 20, 16,
kFmtShift, -1, -1, IS_QUAD_OP | REG_DEF0_USE1,
"add", "!0r, !1r, !2r!3o", kFixupNone),
+ ENCODING_MAP(WIDE(kA64Add4rrre), SF_VARIANTS(0x0b200000),
+ kFmtRegROrSp, 4, 0, kFmtRegROrSp, 9, 5, kFmtRegR, 20, 16,
+ kFmtExtend, -1, -1, IS_QUAD_OP | REG_DEF0_USE12,
+ "add", "!0r, !1r, !2r!3o", kFixupNone),
// Note: adr is binary, but declared as tertiary. The third argument is used while doing the
// fixups and contains information to identify the adr label.
ENCODING_MAP(kA64Adr2xd, NO_VARIANTS(0x10000000),
@@ -558,6 +562,10 @@ const ArmEncodingMap Arm64Mir2Lir::EncodingMap[kA64Last] = {
kFmtRegR, 4, 0, kFmtRegR, 9, 5, kFmtRegR, 20, 16,
kFmtShift, -1, -1, IS_QUAD_OP | REG_DEF0_USE12,
"sub", "!0r, !1r, !2r!3o", kFixupNone),
+ ENCODING_MAP(WIDE(kA64Sub4rrre), SF_VARIANTS(0x4b200000),
+ kFmtRegROrSp, 4, 0, kFmtRegROrSp, 9, 5, kFmtRegR, 20, 16,
+ kFmtExtend, -1, -1, IS_QUAD_OP | REG_DEF0_USE12,
+ "sub", "!0r, !1r, !2r!3o", kFixupNone),
ENCODING_MAP(WIDE(kA64Subs3rRd), SF_VARIANTS(0x71000000),
kFmtRegR, 4, 0, kFmtRegROrSp, 9, 5, kFmtBitBlt, 21, 10,
kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
diff --git a/compiler/dex/quick/arm64/utility_arm64.cc b/compiler/dex/quick/arm64/utility_arm64.cc
index 2254b8b..9b32a46 100644
--- a/compiler/dex/quick/arm64/utility_arm64.cc
+++ b/compiler/dex/quick/arm64/utility_arm64.cc
@@ -660,6 +660,7 @@ LIR* Arm64Mir2Lir::OpRegRegImm64(OpKind op, RegStorage r_dest, RegStorage r_src1
int32_t log_imm = -1;
bool is_wide = r_dest.Is64Bit();
ArmOpcode wide = (is_wide) ? WIDE(0) : UNWIDE(0);
+ int info = 0;
switch (op) {
case kOpLsl: {
@@ -692,7 +693,14 @@ LIR* Arm64Mir2Lir::OpRegRegImm64(OpKind op, RegStorage r_dest, RegStorage r_src1
return NewLIR4(opcode | wide, r_dest.GetReg(), r_src1.GetReg(), abs_value >> 12, 1);
} else {
log_imm = -1;
- alt_opcode = (neg) ? kA64Add4rrro : kA64Sub4rrro;
+ alt_opcode = (neg) ? kA64Add4rrre : kA64Sub4rrre;
+ // To make it correct, we need:
+ // 23..21 = 001 = extend
+ // 15..13 = 01x = LSL/UXTW/X / x defines wide or not
+ // 12..10 = 000 = no shift (in case of SP)
+ // => info = 00101x000
+ // => =0x 0 5 (0/8)
+ info = (is_wide ? 8 : 0) | 0x50;
}
break;
// case kOpRsub:
@@ -734,7 +742,7 @@ LIR* Arm64Mir2Lir::OpRegRegImm64(OpKind op, RegStorage r_dest, RegStorage r_src1
if (log_imm >= 0) {
return NewLIR3(opcode | wide, r_dest.GetReg(), r_src1.GetReg(), log_imm);
} else {
- RegStorage r_scratch = AllocTemp();
+ RegStorage r_scratch;
if (IS_WIDE(wide)) {
r_scratch = AllocTempWide();
LoadConstantWide(r_scratch, value);
@@ -743,7 +751,7 @@ LIR* Arm64Mir2Lir::OpRegRegImm64(OpKind op, RegStorage r_dest, RegStorage r_src1
LoadConstant(r_scratch, value);
}
if (EncodingMap[alt_opcode].flags & IS_QUAD_OP)
- res = NewLIR4(alt_opcode | wide, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg(), 0);
+ res = NewLIR4(alt_opcode | wide, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg(), info);
else
res = NewLIR3(alt_opcode | wide, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg());
FreeTemp(r_scratch);