aboutsummaryrefslogtreecommitdiffstats
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)
downloadexternal_llvm-93b3eff62322803a520e183fdc294bffd6d99bfa.tar.gz
external_llvm-93b3eff62322803a520e183fdc294bffd6d99bfa.tar.bz2
external_llvm-93b3eff62322803a520e183fdc294bffd6d99bfa.zip
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