ARM: Fix shifted register offset mem address mode for load signed.
For example 'ldrsh r0, [sp, r1, LSL #2]' previously
was assembled as 'ldrh'.
Test: New test in assembler_thumb2_test.cc .
Change-Id: I1d30724f0c2745b131876bffefdc0a780d76f6a1
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc
index 8747dad..353c729 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -2456,6 +2456,9 @@
} else if (!byte) {
encoding |= B22;
}
+ if (load && is_signed && (byte || half)) {
+ encoding |= B24;
+ }
Emit32(encoding);
} else {
// 16 bit register offset.
diff --git a/compiler/utils/arm/assembler_thumb2_test.cc b/compiler/utils/arm/assembler_thumb2_test.cc
index f3fa72c..abb09f7 100644
--- a/compiler/utils/arm/assembler_thumb2_test.cc
+++ b/compiler/utils/arm/assembler_thumb2_test.cc
@@ -1450,4 +1450,23 @@
DriverStr(expected, "vpaddl");
}
+TEST_F(AssemblerThumb2Test, LoadFromShiftedRegOffset) {
+ arm::Address mem_address(arm::R0, arm::R1, arm::Shift::LSL, 2);
+
+ __ ldrsb(arm::R2, mem_address);
+ __ ldrb(arm::R2, mem_address);
+ __ ldrsh(arm::R2, mem_address);
+ __ ldrh(arm::R2, mem_address);
+ __ ldr(arm::R2, mem_address);
+
+ std::string expected =
+ "ldrsb r2, [r0, r1, LSL #2]\n"
+ "ldrb r2, [r0, r1, LSL #2]\n"
+ "ldrsh r2, [r0, r1, LSL #2]\n"
+ "ldrh r2, [r0, r1, LSL #2]\n"
+ "ldr r2, [r0, r1, LSL #2]\n";
+
+ DriverStr(expected, "LoadFromShiftedRegOffset");
+}
+
} // namespace art