summaryrefslogtreecommitdiffstats
path: root/compiler/utils
diff options
context:
space:
mode:
authorRoland Levillain <rpl@google.com>2015-04-07 13:54:49 +0100
committerRoland Levillain <rpl@google.com>2015-04-07 13:54:49 +0100
commit4af147eb3296a26eea566f53a7f687194638d46b (patch)
tree1152dedc18b1b2f4c3f3d2d118720f8054b76f3d /compiler/utils
parentc5a5ac641eb4b32fa6737c390813ce78c66a12d3 (diff)
downloadandroid_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.cc32
-rw-r--r--compiler/utils/arm/assembler_thumb2.h8
-rw-r--r--compiler/utils/arm/assembler_thumb2_test.cc55
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