aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Grosbach <grosbach@apple.com>2011-08-18 21:50:53 +0000
committerJim Grosbach <grosbach@apple.com>2011-08-18 21:50:53 +0000
commit93b3eff62322803a520e183fdc294bffd6d99bfa (patch)
tree4cd6de7ba49f9322993c3f4ca1c4f30c6fa27920
parentb48ef3a3ec7f527b0c76e7fbb37bbaac63b7c6aa (diff)
Thumb assembly parsing and encoding for LDM instruction.
Fix base register type and canonicallize to the "ldm" spelling rather than "ldmia." Add diagnostics for incorrect writeback token and out-of-range registers. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137986 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMInstrThumb.td11
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp23
-rw-r--r--lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp4
-rw-r--r--test/CodeGen/Thumb2/thumb2-ldm.ll2
-rw-r--r--test/MC/ARM/basic-thumb-instructions.s12
-rw-r--r--test/MC/ARM/thumb-diagnostics.s10
-rw-r--r--test/MC/Disassembler/ARM/thumb-tests.txt10
7 files changed, 61 insertions, 11 deletions
diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td
index 2b047279d2..199691f6c3 100644
--- a/lib/Target/ARM/ARMInstrThumb.td
+++ b/lib/Target/ARM/ARMInstrThumb.td
@@ -683,8 +683,8 @@ multiclass thumb_ldst_mult<string asm, InstrItinClass itin,
InstrItinClass itin_upd, bits<6> T1Enc,
bit L_bit, string baseOpc> {
def IA :
- T1I<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
- itin, !strconcat(asm, "ia${p}\t$Rn, $regs"), []>,
+ T1I<(outs), (ins tGPR:$Rn, pred:$p, reglist:$regs, variable_ops),
+ itin, !strconcat(asm, "${p}\t$Rn, $regs"), []>,
T1Encoding<T1Enc> {
bits<3> Rn;
bits<8> regs;
@@ -696,7 +696,7 @@ multiclass thumb_ldst_mult<string asm, InstrItinClass itin,
InstTemplate<AddrModeNone, 0, IndexModeNone, Pseudo, GenericDomain,
"$Rn = $wb", itin_upd>,
PseudoInstExpansion<(!cast<Instruction>(!strconcat(baseOpc, "IA"))
- GPR:$Rn, pred:$p, reglist:$regs)> {
+ tGPR:$Rn, pred:$p, reglist:$regs)> {
let Size = 2;
let OutOperandList = (outs GPR:$wb);
let InOperandList = (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops);
@@ -720,6 +720,11 @@ defm tSTM : thumb_ldst_mult<"stm", IIC_iStore_m, IIC_iStore_mu,
} // neverHasSideEffects
+def : InstAlias<"ldm${p} $Rn!, $regs",
+ (tLDMIA tGPR:$Rn, pred:$p, reglist:$regs)>,
+ Requires<[IsThumb, IsThumb1Only]>;
+
+
let mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in
def tPOP : T1I<(outs), (ins pred:$p, reglist:$regs, variable_ops),
IIC_iPop,
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 44c7a0a8d6..6977545511 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -2988,6 +2988,29 @@ validateInstruction(MCInst &Inst,
"bitfield width must be in range [1,32-lsb]");
return false;
}
+ case ARM::tLDMIA: {
+ // Thumb LDM instructions are writeback iff the base register is not
+ // in the register list.
+ unsigned Rn = Inst.getOperand(0).getReg();
+ bool doesWriteback = true;
+ for (unsigned i = 3; i < Inst.getNumOperands(); ++i) {
+ unsigned Reg = Inst.getOperand(i).getReg();
+ if (Reg == Rn)
+ doesWriteback = false;
+ // Anything other than a low register isn't legal here.
+ if (getARMRegisterNumbering(Reg) > 7)
+ return Error(Operands[4]->getStartLoc(),
+ "registers must be in range r0-r7");
+ }
+ // If we should have writeback, then there should be a '!' token.
+ if (doesWriteback &&
+ (!static_cast<ARMOperand*>(Operands[3])->isToken() ||
+ static_cast<ARMOperand*>(Operands[3])->getToken() != "!"))
+ return Error(Operands[2]->getStartLoc(),
+ "writeback operator '!' expected");
+
+ break;
+ }
}
return false;
diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
index 961b0576b0..1999ee7a6f 100644
--- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
+++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
@@ -155,9 +155,9 @@ void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
}
if (Opcode == ARM::tLDMIA)
- O << "\tldmia";
+ O << "\tldm";
else if (Opcode == ARM::tSTMIA)
- O << "\tstmia";
+ O << "\tstm";
else
llvm_unreachable("Unknown opcode!");
diff --git a/test/CodeGen/Thumb2/thumb2-ldm.ll b/test/CodeGen/Thumb2/thumb2-ldm.ll
index c5f7e84c89..4f2b7c18f9 100644
--- a/test/CodeGen/Thumb2/thumb2-ldm.ll
+++ b/test/CodeGen/Thumb2/thumb2-ldm.ll
@@ -15,7 +15,7 @@ define i32 @t1() {
define i32 @t2() {
; CHECK: t2:
; CHECK: push {r7, lr}
-; CHECK: ldmia
+; CHECK: ldm
; CHECK: pop {r7, pc}
%tmp = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 2) ; <i32> [#uses=1]
%tmp3 = load i32* getelementptr ([0 x i32]* @X, i32 0, i32 3) ; <i32> [#uses=1]
diff --git a/test/MC/ARM/basic-thumb-instructions.s b/test/MC/ARM/basic-thumb-instructions.s
index e315a9fe50..fd0b620a66 100644
--- a/test/MC/ARM/basic-thumb-instructions.s
+++ b/test/MC/ARM/basic-thumb-instructions.s
@@ -162,3 +162,15 @@ _func:
eors r4, r5
@ CHECK: eors r4, r5 @ encoding: [0x6c,0x40]
+
+
+@------------------------------------------------------------------------------
+@ LDM
+@------------------------------------------------------------------------------
+ ldm r3, {r0, r1, r2, r3, r4, r5, r6, r7}
+ ldm r2!, {r1, r3, r4, r5, r7}
+ ldm r1, {r1}
+
+@ CHECK: ldm r3, {r0, r1, r2, r3, r4, r5, r6, r7} @ encoding: [0xff,0xcb]
+@ CHECK: ldm r2!, {r1, r3, r4, r5, r7} @ encoding: [0xba,0xca]
+@ CHECK: ldm r1, {r1} @ encoding: [0x02,0xc9]
diff --git a/test/MC/ARM/thumb-diagnostics.s b/test/MC/ARM/thumb-diagnostics.s
index 99d85fedfa..d067b2be6c 100644
--- a/test/MC/ARM/thumb-diagnostics.s
+++ b/test/MC/ARM/thumb-diagnostics.s
@@ -39,3 +39,13 @@ error: invalid operand for instruction
error: invalid operand for instruction
bkpt #-1
^
+
+@ Invalid writeback and register lists for LDM
+ ldm r2!, {r5, r8}
+ ldm r2, {r5, r7}
+@ CHECK-ERRORS: error: registers must be in range r0-r7
+@ CHECK-ERRORS: ldm r2!, {r5, r8}
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: writeback operator '!' expected
+@ CHECK-ERRORS: ldm r2, {r5, r7}
+@ CHECK-ERRORS: ^
diff --git a/test/MC/Disassembler/ARM/thumb-tests.txt b/test/MC/Disassembler/ARM/thumb-tests.txt
index 3b578eca07..b9490c760f 100644
--- a/test/MC/Disassembler/ARM/thumb-tests.txt
+++ b/test/MC/Disassembler/ARM/thumb-tests.txt
@@ -27,7 +27,7 @@
# CHECK: cmn.w r0, #31
0x10 0xf1 0x1f 0x0f
-# CHECK: ldmia r0!, {r1}
+# CHECK: ldm r0!, {r1}
0x02 0xc8
# CHECK: ldr r5, #432
@@ -112,7 +112,7 @@
# CHECK: lsleq r1, r0, #28
0x01 0x07
-# CHECK: stmiane r0!, {r1, r2, r3}
+# CHECK: stmne r0!, {r1, r2, r3}
0x0e 0xc0
# IT block end
@@ -146,13 +146,13 @@
# CHECK: stmdb.w sp, {r0, r2, r3, r8, r11, lr}
0x0d 0xe9 0x0d 0x49
-# CHECK: stmia r5!, {r0, r1, r2, r3, r4}
+# CHECK: stm r5!, {r0, r1, r2, r3, r4}
0x1f 0xc5
-# CHECK: ldmia r5, {r0, r1, r2, r3, r4, r5}
+# CHECK: ldm r5, {r0, r1, r2, r3, r4, r5}
0x3f 0xcd
-# CHECK: ldmia r5!, {r0, r1, r2, r3, r4}
+# CHECK: ldm r5!, {r0, r1, r2, r3, r4}
0x1f 0xcd
# CHECK: addw r0, pc, #1050