aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp122
-rw-r--r--test/MC/ARM/ldr-pseudo-cond-darwin.s55
-rw-r--r--test/MC/ARM/ldr-pseudo-cond.s55
-rw-r--r--test/MC/ARM/ldr-pseudo-darwin.s101
-rw-r--r--test/MC/ARM/ldr-pseudo.s101
5 files changed, 410 insertions, 24 deletions
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 58033619fd4..92442b3a92d 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -257,6 +257,9 @@ class ARMAsmParser : public MCTargetAsmParser {
bool hasThumb() const {
return getSTI().getFeatureBits()[ARM::HasV4TOps];
}
+ bool hasThumb2() const {
+ return getSTI().getFeatureBits()[ARM::FeatureThumb2];
+ }
bool hasV6Ops() const {
return getSTI().getFeatureBits()[ARM::HasV6Ops];
}
@@ -5248,7 +5251,6 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
S = Parser.getTok().getLoc();
if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
return Error(S, "unexpected token in operand");
-
Parser.Lex(); // Eat '='
const MCExpr *SubExprVal;
if (getParser().parseExpression(SubExprVal))
@@ -6869,33 +6871,121 @@ bool ARMAsmParser::processInstruction(MCInst &Inst,
case ARM::t2LDRSHpcrel:
Inst.setOpcode(ARM::t2LDRSHpci);
return true;
- case ARM::LDRConstPool:
+ case ARM::LDRConstPool: {
+ // Pseudo instruction ldr rt, =immediate is converted to a
+ // MOV rt, immediate if immediate is known and representable
+ // otherwise we create a constant pool entry that we load from.
+ MCInst TmpInst;
+ const ARMOperand &PoolOperand =
+ static_cast<ARMOperand &>(*Operands[3]);
+ const MCExpr *SubExprVal = PoolOperand.getConstantPoolImm();
+ if (isa<MCConstantExpr>(SubExprVal)) {
+ int64_t Value =
+ (int64_t) (cast<MCConstantExpr>(SubExprVal))->getValue();
+
+ if (ARM_AM::getSOImmVal((uint32_t)Value) != -1) {
+ int64_t ModImmValue = ARM_AM::getSOImmVal((uint32_t)Value);
+ TmpInst.setOpcode(ARM::MOVi);
+ TmpInst.addOperand(Inst.getOperand(0)); // Rt
+ TmpInst.addOperand(MCOperand::createImm(ModImmValue)); // mod imm
+ TmpInst.addOperand(Inst.getOperand(2)); // CondCode
+ TmpInst.addOperand(Inst.getOperand(3)); // CondCode
+ TmpInst.addOperand(MCOperand::createReg(0)); // S
+ Inst = TmpInst;
+ return true;
+ }
+ else if (ARM_AM::getSOImmVal(~(uint32_t)Value) != -1) {
+ int64_t ModImmValue = ARM_AM::getSOImmVal(~(uint32_t)Value);
+ TmpInst.setOpcode(ARM::MVNi);
+ TmpInst.addOperand(Inst.getOperand(0)); // Rt
+ TmpInst.addOperand(MCOperand::createImm(ModImmValue)); // mod imm
+ TmpInst.addOperand(Inst.getOperand(2)); // CondCode
+ TmpInst.addOperand(Inst.getOperand(3)); // CondCode
+ TmpInst.addOperand(MCOperand::createReg(0)); // S
+ Inst = TmpInst;
+ return true;
+ }
+ else if (hasV8MBaseline() &&
+ Value >=0 && Value < 65536) {
+ TmpInst.setOpcode(ARM::MOVi16);
+ TmpInst.addOperand(Inst.getOperand(0)); // Rt
+ TmpInst.addOperand(MCOperand::createImm(Value)); // Immediate
+ TmpInst.addOperand(Inst.getOperand(2)); // CondCode
+ TmpInst.addOperand(Inst.getOperand(3)); // CondCode
+ Inst = TmpInst;
+ return true;
+ }
+ }
+ // No use of MOV, create constant pool entry
+ TmpInst.setOpcode(ARM::LDRi12);
+ const MCExpr *CPLoc =
+ getTargetStreamer().addConstantPoolEntry(SubExprVal,
+ PoolOperand.getStartLoc());
+ TmpInst.addOperand(Inst.getOperand(0)); // Rt
+ TmpInst.addOperand(MCOperand::createExpr(CPLoc)); // offset to constpool
+ TmpInst.addOperand(MCOperand::createImm(0)); // unused offset
+ TmpInst.addOperand(Inst.getOperand(2)); // CondCode
+ TmpInst.addOperand(Inst.getOperand(3)); // CondCode
+ Inst = TmpInst;
+ return true;
+ }
case ARM::tLDRConstPool:
case ARM::t2LDRConstPool: {
- // Handle the pseudo instruction for ldr rn,=
- // For now we always create the constant pool entry and load from it
- // FIXME: Use a MOV or MVN when the immediate will fit
+ // Thumb variant of pseudo instruction ldr rt, =immediate
MCInst TmpInst;
- if (Inst.getOpcode() == ARM::LDRConstPool)
- TmpInst.setOpcode(ARM::LDRi12);
- else if (Inst.getOpcode() == ARM::tLDRConstPool)
+ const ARMOperand &PoolOperand =
+ static_cast<ARMOperand &>(*Operands[3]);
+ const MCExpr *SubExprVal = PoolOperand.getConstantPoolImm();
+ if (isa<MCConstantExpr>(SubExprVal)) {
+ int64_t Value =
+ (int64_t) (cast<MCConstantExpr>(SubExprVal))->getValue();
+ if (hasThumb2() &&
+ ARM_AM::getT2SOImmVal((uint32_t)Value) != -1) {
+ TmpInst.setOpcode(ARM::t2MOVi);
+ TmpInst.addOperand(Inst.getOperand(0)); // Rt
+ TmpInst.addOperand(MCOperand::createImm(Value)); // mod imm
+ TmpInst.addOperand(Inst.getOperand(2)); // CondCode
+ TmpInst.addOperand(Inst.getOperand(3)); // CondCode
+ TmpInst.addOperand(MCOperand::createReg(0)); // S
+ Inst = TmpInst;
+ return true;
+ }
+ else if (hasThumb2() &&
+ ARM_AM::getT2SOImmVal(~(uint32_t)Value) != -1) {
+ TmpInst.setOpcode(ARM::t2MVNi);
+ TmpInst.addOperand(Inst.getOperand(0)); // Rt
+ TmpInst.addOperand(MCOperand::createImm(~Value)); // mod imm
+ TmpInst.addOperand(Inst.getOperand(2)); // CondCode
+ TmpInst.addOperand(Inst.getOperand(3)); // CondCode
+ TmpInst.addOperand(MCOperand::createReg(0)); // S
+ Inst = TmpInst;
+ return true;
+ }
+ else if (hasV8MBaseline() &&
+ Value >=0 && Value < 65536) {
+ TmpInst.setOpcode(ARM::t2MOVi16);
+ TmpInst.addOperand(Inst.getOperand(0)); // Rt
+ TmpInst.addOperand(MCOperand::createImm(Value)); // Immediate
+ TmpInst.addOperand(Inst.getOperand(2)); // CondCode
+ TmpInst.addOperand(Inst.getOperand(3)); // CondCode
+ Inst = TmpInst;
+ return true;
+ }
+ }
+ // No use of MOV, create constant pool entry
+ if (Inst.getOpcode() == ARM::tLDRConstPool)
TmpInst.setOpcode(ARM::tLDRpci);
else if (Inst.getOpcode() == ARM::t2LDRConstPool)
TmpInst.setOpcode(ARM::t2LDRpci);
- const ARMOperand &PoolOperand =
- static_cast<ARMOperand &>(*Operands[3]);
- const MCExpr *PoolExpr = PoolOperand.getConstantPoolImm();
const MCExpr *CPLoc =
- getTargetStreamer().addConstantPoolEntry(PoolExpr,
+ getTargetStreamer().addConstantPoolEntry(SubExprVal,
PoolOperand.getStartLoc());
TmpInst.addOperand(Inst.getOperand(0)); // Rt
- TmpInst.addOperand(MCOperand::createExpr(CPLoc)); // Offset to pool
- if (Inst.getOpcode() == ARM::LDRConstPool)
- TmpInst.addOperand(MCOperand::createImm(0)); // ARM uses two operands
+ TmpInst.addOperand(MCOperand::createExpr(CPLoc)); // Immediate
TmpInst.addOperand(Inst.getOperand(2)); // CondCode
TmpInst.addOperand(Inst.getOperand(3)); // CondCode
Inst = TmpInst;
- return false;
+ return true;
}
break;
// Handle NEON VST complex aliases.
diff --git a/test/MC/ARM/ldr-pseudo-cond-darwin.s b/test/MC/ARM/ldr-pseudo-cond-darwin.s
new file mode 100644
index 00000000000..542b060d1e2
--- /dev/null
+++ b/test/MC/ARM/ldr-pseudo-cond-darwin.s
@@ -0,0 +1,55 @@
+@RUN: llvm-mc -triple armv7-base-apple-darwin %s | FileCheck --check-prefix=CHECK-ARM --check-prefix=CHECK %s
+@RUN: llvm-mc -triple thumbv7-base-apple-darwin %s | FileCheck --check-prefix=CHECK-THUMB2 --check-prefix=CHECK %s
+
+@
+@ Check that ldr to constant pool correctly transfers the condition codes
+@
+@ simple test
+.section __TEXT,a,regular,pure_instructions
+@ CHECK-LABEL: f0:
+f0:
+ it eq
+ ldreq r0, =0x10002
+@ CHECK: ldreq r0, Ltmp0
+
+@ loading multiple constants
+.section __TEXT,b,regular,pure_instructions
+@ CHECK-LABEL: f1:
+f1:
+ ite eq
+ ldreq r0, =0x10003
+@ CHECK: ldreq r0, Ltmp1
+ ldrne r0, =0x10004
+@ CHECK: ldrne r0, Ltmp2
+
+@ transformation to mov
+.section __TEXT,d,regular,pure_instructions
+@ CHECK-LABEL: f2:
+f2:
+@ Can use the narrow Thumb mov as it does not set flags in an IT block
+ it eq
+ ldreq r1, =0x1
+@ CHECK: moveq r1, #1
+
+@ Must use the wide Thumb mov if the constant can't be represented
+ ite eq
+ ldreq r2, = 0x1f000000
+@ CHECK-ARM moveq r2, #520093696
+@ CHECK-THUMB2 moveq.w r2, #520093696
+ ldrne r3, = 0x00001234
+@ CHECK movwne r2, #4660
+
+@
+@ Constant Pools
+@
+@ CHECK: .section __TEXT,a,regular,pure_instructions
+@ CHECK: .p2align 2
+@ CHECK: Ltmp0:
+@ CHECK: .long 65538
+
+@ CHECK: .section __TEXT,b,regular,pure_instructions
+@ CHECK: .p2align 2
+@ CHECK: Ltmp1:
+@ CHECK: .long 65539
+@ CHECK: Ltmp2:
+@ CHECK: .long 65540
diff --git a/test/MC/ARM/ldr-pseudo-cond.s b/test/MC/ARM/ldr-pseudo-cond.s
new file mode 100644
index 00000000000..f8d17f6c46b
--- /dev/null
+++ b/test/MC/ARM/ldr-pseudo-cond.s
@@ -0,0 +1,55 @@
+@RUN: llvm-mc -triple armv7-unknown-linux-gnueabi %s | FileCheck --check-prefix=CHECK-ARM --check-prefix=CHECK %s
+@RUN: llvm-mc -triple thumbv7-unknown-linux-gnueabi %s | FileCheck --check-prefix=CHECK-THUMB2 --check-prefix=CHECK %s
+
+@
+@ Check that ldr to constant pool correctly transfers the condition codes
+@
+@ simple test
+.section a,"ax",%progbits
+@ CHECK-LABEL: f0:
+f0:
+ it eq
+ ldreq r0, =0x10002
+@ CHECK: ldreq r0, .Ltmp[[TMP0:[0-9]+]]
+
+@ loading multiple constants
+.section b,"ax",%progbits
+@ CHECK-LABEL: f1:
+f1:
+ ite eq
+ ldreq r0, =0x10003
+@ CHECK: ldreq r0, .Ltmp[[TMP1:[0-9]+]]
+ ldrne r0, =0x10004
+@ CHECK: ldrne r0, .Ltmp[[TMP2:[0-9]+]]
+
+@ transformation to mov
+.section c, "ax", %progbits
+@ CHECK-LABEL: f2:
+f2:
+@ Can use the narrow Thumb mov as it does not set flags in an IT block
+ it eq
+ ldreq r1, =0x1
+@ CHECK: moveq r1, #1
+
+@ Must use the wide Thumb mov if the constant can't be represented
+ ite eq
+ ldreq r2, = 0x1f000000
+@ CHECK-ARM moveq r2, #520093696
+@ CHECK-THUMB2 moveq.w r2, #520093696
+ ldrne r3, = 0x00001234
+@ CHECK movwne r2, #4660
+
+@
+@ Constant Pools
+@
+@ CHECK: .section a,"ax",%progbits
+@ CHECK: .p2align 2
+@ CHECK: .Ltmp[[TMP0]]
+@ CHECK: .long 65538
+
+@ CHECK: .section b,"ax",%progbits
+@ CHECK: .p2align 2
+@ CHECK: .Ltmp[[TMP1]]
+@ CHECK: .long 65539
+@ CHECK: .Ltmp[[TMP2]]
+@ CHECK: .long 65540
diff --git a/test/MC/ARM/ldr-pseudo-darwin.s b/test/MC/ARM/ldr-pseudo-darwin.s
index 2395e1ad2c9..4972cf389e0 100644
--- a/test/MC/ARM/ldr-pseudo-darwin.s
+++ b/test/MC/ARM/ldr-pseudo-darwin.s
@@ -4,10 +4,11 @@
@ between darwin and linux. Any tests added here should have a matching
@ test added there.
-@RUN: llvm-mc -triple armv7-apple-darwin %s | FileCheck %s
-@RUN: llvm-mc -triple thumbv5-apple-darwin %s | FileCheck %s
-@RUN: llvm-mc -triple thumbv7-apple-darwin %s | FileCheck %s
-
+@RUN: llvm-mc -triple armv7-base-apple-darwin %s | FileCheck --check-prefix=CHECK-ARM --check-prefix=CHECK %s
+@RUN: llvm-mc -triple armv5-base-apple-darwin %s | FileCheck --check-prefix=CHECK-ARMV5 --check-prefix=CHECK %s
+@RUN: llvm-mc -triple thumbv5-base-apple-darwin %s | FileCheck --check-prefix=CHECK-THUMB --check-prefix=CHECK %s
+@RUN: llvm-mc -triple thumbv7-base-apple-darwin %s | FileCheck --check-prefix=CHECK-THUMB2 --check-prefix=CHECK %s
+@RUN: llvm-mc -triple thumbv8m.base-base-apple-darwin %s | FileCheck --check-prefix=CHECK-BASELINE --check-prefix=CHECK %s
@
@ Check that large constants are converted to ldr from constant pool
@
@@ -152,6 +153,98 @@ f15:
@ CHECK: ldr r0, Ltmp15
adds r0, r0, #1
+@ transformation to mov
+.section __TEXT,m,regular,pure_instructions
+@ CHECK-LABEL: f16:
+f16:
+
+@ Representable in ARM, and Thumb with support mov.w or movw
+ ldr r1, =0x1
+@ CHECK-ARM: mov r1, #1
+@ CHECK-ARMV5: mov r1, #1
+@ CHECK-THUMB: ldr r1, Ltmp16
+@ CHECK-THUMB2: mov.w r1, #1
+@ CHECK-BASELINE: movw r1, #1
+
+@ Immediate is representable in A1 and T2 modified immediate only not movw
+ ldr r2, =0x120000
+@ CHECK-ARM: mov r2, #1179648
+@ CHECK-ARMV5: mov r2, #1179648
+@ CHECK-THUMB: ldr r2, Ltmp17
+@ CHECK-THUMB2: mov.w r2, #1179648
+@ CHECK-BASELINE: ldr r2, Ltmp16
+
+@ Immediate can be represented only with movw instruction
+ ldr r3, =0x1234
+@ CHECK-ARM: movw r3, #4660
+@ CHECK-ARMV5: ldr r3, Ltmp16
+@ CHECK-THUMB: ldr r3, Ltmp18
+@ CHECK-THUMB2: movw r3, #4660
+@ CHECK-BASELINE: movw r3, #4660
+
+@ Immediate can be represented only with T2 modified immediate
+ ldr r4, =0xabababab
+@ CHECK-ARM: ldr r4, Ltmp16
+@ CHECK-ARMV5: ldr r4, Ltmp17
+@ CHECK-THUMB: ldr r4, Ltmp19
+@ CHECK-THUMB2: mov.w r4, #2880154539
+@ CHECK-BASELINE: ldr r4, Ltmp17
+
+@ Immediate can be represented only with A1 modified immediate
+ ldr r5, =0x1000000b
+@ CHECK-ARM: mov r5, #268435467
+@ CHECK-ARMV5: mov r5, #268435467
+@ CHECK-THUMB: ldr r5, Ltmp20
+@ CHECK-THUMB2: ldr r5, Ltmp16
+@ CHECK-BASELINE: ldr r5, Ltmp18
+
+@ Negative numbers can be used with MVN or in Thumb2 with modified immediate
+ ldr r6, =-1
+@ CHECK-ARM: mvn r6, #0
+@ CHECK-ARMV5: mvn r6, #0
+@ CHECK-THUMB: ldr r6, Ltmp21
+@ CHECK-THUMB2: mov.w r6, #-1
+@ CHECK-BASELINE: ldr r6, Ltmp19
+ ldr r7, =-0x100
+@ CHECK-ARM: mvn r7, #255
+@ CHECK-ARMV5: mvn r7, #255
+@ CHECK-THUMB: ldr r7, Ltmp22
+@ CHECK-THUMB2: mvn r7, #255
+@ CHECK-BASELINE: ldr r7, Ltmp20
+
+@ Constant expressions can be used
+ .equ expr, 0x10 + 0x10
+ ldr r0, = expr
+@ CHECK-ARM: mov r0, #32
+@ CHECK-ARMV5: mov r0, #32
+@ CHECK-THUMB: ldr r0, Ltmp23
+@ CHECK-THUMB2: mov.w r0, #32
+@ CHECK-BASELINE: movw r0, #32
+ ldr r1, = expr - 0x10
+@ CHECK-ARM: mov r1, #16
+@ CHECK-ARMV5: mov r1, #16
+@ CHECK-THUMB: ldr r1, Ltmp24
+@ CHECK-THUMB2: mov.w r1, #16
+@ CHECK-BASELINE: movw r1, #16
+
+@ usage of translation in macro
+.macro usemov_in_a_macro
+ ldr r2, =0x3
+ ldr r3, =expr
+.endm
+@ CHECK-LABEL: f17:
+f17:
+ usemov_in_a_macro
+@ CHECK-ARM: mov r2, #3
+@ CHECK-ARM: mov r3, #32
+@ CHECK-ARMV5: mov r2, #3
+@ CHECK-ARMV5: mov r3, #32
+@ CHECK-THUMB: ldr r2, Ltmp25
+@ CHECK-THUMB: ldr r3, Ltmp26
+@ CHECK-THUMB2: mov.w r2, #3
+@ CHECK-THUMB2: mov.w r3, #32
+@ CHECK-BASELINE: movw r2, #3
+@ CHECK-BASELINE: movw r3, #32
@
@ Constant Pools
@
diff --git a/test/MC/ARM/ldr-pseudo.s b/test/MC/ARM/ldr-pseudo.s
index 57bf6e77329..2358c483295 100644
--- a/test/MC/ARM/ldr-pseudo.s
+++ b/test/MC/ARM/ldr-pseudo.s
@@ -4,10 +4,11 @@
@ between darwin and linux. Any tests added here should have a matching
@ test added there.
-@RUN: llvm-mc -triple armv7-unknown-linux-gnueabi %s | FileCheck %s
-@RUN: llvm-mc -triple thumbv5-unknown-linux-gnueabi %s | FileCheck %s
-@RUN: llvm-mc -triple thumbv7-unknown-linux-gnueabi %s | FileCheck %s
-
+@RUN: llvm-mc -triple armv7-unknown-linux-gnueabi %s | FileCheck --check-prefix=CHECK-ARM --check-prefix=CHECK %s
+@RUN: llvm-mc -triple armv5-unknown-linux-gnueabi %s | FileCheck --check-prefix=CHECK-ARMV5 --check-prefix=CHECK %s
+@RUN: llvm-mc -triple thumbv5-unknown-linux-gnueabi %s | FileCheck --check-prefix=CHECK-THUMB --check-prefix=CHECK %s
+@RUN: llvm-mc -triple thumbv7-unknown-linux-gnueabi %s | FileCheck --check-prefix=CHECK-THUMB2 --check-prefix=CHECK %s
+@RUN: llvm-mc -triple thumbv8m.base-unknown-linux-gnueabi %s | FileCheck --check-prefix=CHECK-BASELINE --check-prefix=CHECK %s
@
@ Check that large constants are converted to ldr from constant pool
@
@@ -152,6 +153,98 @@ f15:
@ CHECK: ldr r0, .Ltmp[[TMP15:[0-9]+]]
adds r0, r0, #1
+@ transformation to mov
+.section m, "ax", %progbits
+@ CHECK-LABEL: f16:
+f16:
+
+@ Representable in ARM, and Thumb with support mov.w or movw
+ ldr r1, =0x1
+@ CHECK-ARM: mov r1, #1
+@ CHECK-ARMV5: mov r1, #1
+@ CHECK-THUMB: ldr r1, .Ltmp[[TMP16:[0-9]+]]
+@ CHECK-THUMB2: mov.w r1, #1
+@ CHECK-BASELINE: movw r1, #1
+
+@ Immediate is representable in A1 and T2 modified immediate only not movw
+ ldr r2, =0x120000
+@ CHECK-ARM: mov r2, #1179648
+@ CHECK-ARMV5: mov r2, #1179648
+@ CHECK-THUMB: ldr r2, .Ltmp[[TMP17:[0-9]+]]
+@ CHECK-THUMB2: mov.w r2, #1179648
+@ CHECK-BASELINE: ldr r2, .Ltmp[[TMP16:[0-9]+]]
+
+@ Immediate can be represented only with movw instruction
+ ldr r3, =0x1234
+@ CHECK-ARM: movw r3, #4660
+@ CHECK-ARMV5: ldr r3, .Ltmp[[TMP16:[0-9]+]]
+@ CHECK-THUMB: ldr r3, .Ltmp[[TMP18:[0-9]+]]
+@ CHECK-THUMB2: movw r3, #4660
+@ CHECK-BASELINE: movw r3, #4660
+
+@ Immediate can be represented only with T2 modified immediate
+ ldr r4, =0xabababab
+@ CHECK-ARM: ldr r4, .Ltmp[[TMP16:[0-9]+]]
+@ CHECK-ARMV5: ldr r4, .Ltmp[[TMP17:[0-9]+]]
+@ CHECK-THUMB: ldr r4, .Ltmp[[TMP19:[0-9]+]]
+@ CHECK-THUMB2: mov.w r4, #2880154539
+@ CHECK-BASELINE: ldr r4, .Ltmp[[TMP17:[0-9]+]]
+
+@ Immediate can be represented only with A1 modified immediate
+ ldr r5, =0x1000000b
+@ CHECK-ARM: mov r5, #268435467
+@ CHECK-ARMV5: mov r5, #268435467
+@ CHECK-THUMB: ldr r5, .Ltmp[[TMP20:[0-9]+]]
+@ CHECK-THUMB2: ldr r5, .Ltmp[[TMP16:[0-9]+]]
+@ CHECK-BASELINE: ldr r5, .Ltmp[[TMP18:[0-9]+]]
+
+@ Negative numbers can be used with MVN or in Thumb2 with modified immediate
+ ldr r6, =-1
+@ CHECK-ARM: mvn r6, #0
+@ CHECK-ARMV5: mvn r6, #0
+@ CHECK-THUMB: ldr r6, .Ltmp[[TMP21:[0-9]+]]
+@ CHECK-THUMB2: mov.w r6, #-1
+@ CHECK-BASELINE: ldr r6, .Ltmp[[TMP19:[0-9]+]]
+ ldr r7, =-0x100
+@ CHECK-ARM: mvn r7, #255
+@ CHECK-ARMV5: mvn r7, #255
+@ CHECK-THUMB: ldr r7, .Ltmp[[TMP22:[0-9]+]]
+@ CHECK-THUMB2: mvn r7, #255
+@ CHECK-BASELINE: ldr r7, .Ltmp[[TMP20:[0-9]+]]
+
+@ Constant expressions can be used
+ .equ expr, 0x10 + 0x10
+ ldr r0, = expr
+@ CHECK-ARM: mov r0, #32
+@ CHECK-ARMV5: mov r0, #32
+@ CHECK-THUMB: ldr r0, .Ltmp[[TMP23:[0-9]+]]
+@ CHECK-THUMB2: mov.w r0, #32
+@ CHECK-BASELINE: movw r0, #32
+ ldr r1, = expr - 0x10
+@ CHECK-ARM: mov r1, #16
+@ CHECK-ARMV5: mov r1, #16
+@ CHECK-THUMB: ldr r1, .Ltmp[[TMP24:[0-9]+]]
+@ CHECK-THUMB2: mov.w r1, #16
+@ CHECK-BASELINE: movw r1, #16
+
+@ usage of translation in macro
+.macro usemov_in_a_macro
+ ldr r2, =0x3
+ ldr r3, =expr
+.endm
+@ CHECK-LABEL: f17:
+f17:
+ usemov_in_a_macro
+@ CHECK-ARM: mov r2, #3
+@ CHECK-ARM: mov r3, #32
+@ CHECK-ARMV5: mov r2, #3
+@ CHECK-ARMV5: mov r3, #32
+@ CHECK-THUMB: ldr r2, .Ltmp[[TMP25:[0-9]+]]
+@ CHECK-THUMB: ldr r3, .Ltmp[[TMP26:[0-9]+]]
+@ CHECK-THUMB2: mov.w r2, #3
+@ CHECK-THUMB2: mov.w r3, #32
+@ CHECK-BASELINE: movw r2, #3
+@ CHECK-BASELINE: movw r3, #32
@
@ Constant Pools
@