diff options
author | Andreas Gampe <agampe@google.com> | 2014-06-18 17:45:32 -0700 |
---|---|---|
committer | Andreas Gampe <agampe@google.com> | 2014-06-18 17:45:32 -0700 |
commit | 9f975bfe091e9592a1b6b5b46d224ec04b1183b6 (patch) | |
tree | 72a26568539aef4d0199bdb7a8e40d4c38262ecb /compiler | |
parent | 0c29909cbde112bc9c04da4ce81421e1a0b39f36 (diff) | |
download | art-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.h | 6 | ||||
-rw-r--r-- | compiler/dex/quick/arm64/assemble_arm64.cc | 8 | ||||
-rw-r--r-- | compiler/dex/quick/arm64/utility_arm64.cc | 14 |
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); |