diff options
author | Roland Levillain <rpl@google.com> | 2015-04-07 13:54:49 +0100 |
---|---|---|
committer | Roland Levillain <rpl@google.com> | 2015-04-07 13:54:49 +0100 |
commit | 4af147eb3296a26eea566f53a7f687194638d46b (patch) | |
tree | 1152dedc18b1b2f4c3f3d2d118720f8054b76f3d /compiler/utils | |
parent | c5a5ac641eb4b32fa6737c390813ce78c66a12d3 (diff) | |
download | android_art-4af147eb3296a26eea566f53a7f687194638d46b.tar.gz android_art-4af147eb3296a26eea566f53a7f687194638d46b.tar.bz2 android_art-4af147eb3296a26eea566f53a7f687194638d46b.zip |
Exercise art::arm::Thumb2Assembler::StoreToOffset for word pairs.
- Augment compiler/utils/arm/assembler_thumb2_test.cc.
- Ensure art::arm::Thumb2Assembler::StoreToOffset properly
handles IP as (implicit) second source register.
- Remove the parity constraint on the first source register
for art::arm::Thumb2Assembler::ldrd and
art::arm::Thumb2Assembler::strd (as they are not required
by the Thumb-2 encoding).
- Introduce additional versions of
art::arm::Thumb2Assembler::ldrd and
art::arm::Thumb2Assembler::strd accepting a second source
register, which is not necessarily the one following the
first source register, as it is allowed by the Thumb-2
encoding.
Change-Id: I7dba168437a96a5cbb117058e9c547fb1ff5c295
Diffstat (limited to 'compiler/utils')
-rw-r--r-- | compiler/utils/arm/assembler_thumb2.cc | 32 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_thumb2.h | 8 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_thumb2_test.cc | 55 |
3 files changed, 85 insertions, 10 deletions
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc index a894319c99..602e67232d 100644 --- a/compiler/utils/arm/assembler_thumb2.cc +++ b/compiler/utils/arm/assembler_thumb2.cc @@ -373,24 +373,34 @@ void Thumb2Assembler::ldrsh(Register rd, const Address& ad, Condition cond) { void Thumb2Assembler::ldrd(Register rd, const Address& ad, Condition cond) { + ldrd(rd, Register(rd + 1), ad, cond); +} + + +void Thumb2Assembler::ldrd(Register rd, Register rd2, const Address& ad, Condition cond) { CheckCondition(cond); - CHECK_EQ(rd % 2, 0); + // Encoding T1. // This is different from other loads. The encoding is like ARM. int32_t encoding = B31 | B30 | B29 | B27 | B22 | B20 | static_cast<int32_t>(rd) << 12 | - (static_cast<int32_t>(rd) + 1) << 8 | + static_cast<int32_t>(rd2) << 8 | ad.encodingThumbLdrdStrd(); Emit32(encoding); } void Thumb2Assembler::strd(Register rd, const Address& ad, Condition cond) { + strd(rd, Register(rd + 1), ad, cond); +} + + +void Thumb2Assembler::strd(Register rd, Register rd2, const Address& ad, Condition cond) { CheckCondition(cond); - CHECK_EQ(rd % 2, 0); + // Encoding T1. // This is different from other loads. The encoding is like ARM. int32_t encoding = B31 | B30 | B29 | B27 | B22 | static_cast<int32_t>(rd) << 12 | - (static_cast<int32_t>(rd) + 1) << 8 | + static_cast<int32_t>(rd2) << 8 | ad.encodingThumbLdrdStrd(); Emit32(encoding); } @@ -2614,14 +2624,16 @@ void Thumb2Assembler::StoreToOffset(StoreOperandType type, Register tmp_reg = kNoRegister; if (!Address::CanHoldStoreOffsetThumb(type, offset)) { CHECK_NE(base, IP); - if (reg != IP) { + if (reg != IP && + (type != kStoreWordPair || reg + 1 != IP)) { tmp_reg = IP; } else { - // Be careful not to use IP twice (for `reg` and to build the - // Address object used by the store instruction(s) below). - // Instead, save R5 on the stack (or R6 if R5 is not available), - // use it as secondary temporary register, and restore it after - // the store instruction has been emitted. + // Be careful not to use IP twice (for `reg` (or `reg` + 1 in + // the case of a word-pair store)) and to build the Address + // object used by the store instruction(s) below). Instead, + // save R5 on the stack (or R6 if R5 is not available), use it + // as secondary temporary register, and restore it after the + // store instruction has been emitted. tmp_reg = base != R5 ? R5 : R6; Push(tmp_reg); if (base == SP) { diff --git a/compiler/utils/arm/assembler_thumb2.h b/compiler/utils/arm/assembler_thumb2.h index 81dd13894f..e33c240dbf 100644 --- a/compiler/utils/arm/assembler_thumb2.h +++ b/compiler/utils/arm/assembler_thumb2.h @@ -135,9 +135,17 @@ class Thumb2Assembler FINAL : public ArmAssembler { void ldrsb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; void ldrsh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; + // Load/store register dual instructions using registers `rd` and `rd` + 1. void ldrd(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; void strd(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; + // Load/store register dual instructions using registers `rd` and `rd2`. + // Note that contrary to the ARM A1 encoding, the Thumb-2 T1 encoding + // does not require `rd` to be even, nor `rd2' to be equal to `rd` + 1. + void ldrd(Register rd, Register rd2, const Address& ad, Condition cond); + void strd(Register rd, Register rd2, const Address& ad, Condition cond); + + void ldm(BlockAddressMode am, Register base, RegList regs, Condition cond = AL) OVERRIDE; void stm(BlockAddressMode am, Register base, diff --git a/compiler/utils/arm/assembler_thumb2_test.cc b/compiler/utils/arm/assembler_thumb2_test.cc index 62e0b90e73..5f5561a499 100644 --- a/compiler/utils/arm/assembler_thumb2_test.cc +++ b/compiler/utils/arm/assembler_thumb2_test.cc @@ -291,4 +291,59 @@ TEST_F(AssemblerThumb2Test, StoreWordToNonThumbOffset) { DriverStr(expected, "StoreWordToNonThumbOffset"); } +TEST_F(AssemblerThumb2Test, StoreWordPairToThumbOffset) { + arm::StoreOperandType type = arm::kStoreWordPair; + int32_t offset = 1020; + ASSERT_TRUE(arm::Address::CanHoldStoreOffsetThumb(type, offset)); + + __ StoreToOffset(type, arm::R0, arm::SP, offset); + // We cannot use IP (i.e. R12) as first source register, as it would + // force us to use SP (i.e. R13) as second source register, which + // would have an "unpredictable" effect according to the ARMv7 + // specification (the T1 encoding describes the result as + // UNPREDICTABLE when of the source registers is R13). + // + // So we use (R11, IP) (e.g. (R11, R12)) as source registers in the + // following instructions. + __ StoreToOffset(type, arm::R11, arm::SP, offset); + __ StoreToOffset(type, arm::R11, arm::R5, offset); + + const char* expected = + "strd r0, r1, [sp, #1020]\n" + "strd r11, ip, [sp, #1020]\n" + "strd r11, ip, [r5, #1020]\n"; + DriverStr(expected, "StoreWordPairToThumbOffset"); +} + +TEST_F(AssemblerThumb2Test, StoreWordPairToNonThumbOffset) { + arm::StoreOperandType type = arm::kStoreWordPair; + int32_t offset = 1024; + ASSERT_FALSE(arm::Address::CanHoldStoreOffsetThumb(type, offset)); + + __ StoreToOffset(type, arm::R0, arm::SP, offset); + // Same comment as in AssemblerThumb2Test.StoreWordPairToThumbOffset + // regarding the use of (R11, IP) (e.g. (R11, R12)) as source + // registers in the following instructions. + __ StoreToOffset(type, arm::R11, arm::SP, offset); + __ StoreToOffset(type, arm::R11, arm::R5, offset); + + const char* expected = + "mov ip, #1024\n" // LoadImmediate(ip, 1024) + "add ip, ip, sp\n" + "strd r0, r1, [ip, #0]\n" + + "str r5, [sp, #-4]!\n" // Push(r5) + "movw r5, #1028\n" // LoadImmediate(r5, 1024 + kRegisterSize) + "add r5, r5, sp\n" + "strd r11, ip, [r5, #0]\n" + "ldr r5, [sp], #4\n" // Pop(r5) + + "str r6, [sp, #-4]!\n" // Push(r6) + "mov r6, #1024\n" // LoadImmediate(r6, 1024) + "add r6, r6, r5\n" + "strd r11, ip, [r6, #0]\n" + "ldr r6, [sp], #4\n"; // Pop(r6) + DriverStr(expected, "StoreWordPairToNonThumbOffset"); +} + } // namespace art |