From: Tilmann Scheller Date: Mon, 30 Sep 2013 16:11:48 +0000 (+0000) Subject: [ARM] Assembler: ARM LDRD with writeback requires the base register to be different... X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=9724873c317d2b170cfea87cdf2a402fcd7c6c7d;p=oota-llvm.git [ARM] Assembler: ARM LDRD with writeback requires the base register to be different from the destination registers. See ARM ARM A8.8.72. Violating this constraint results in unpredictable behavior. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191678 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 6d6255f2cc2..d360a24114e 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -5343,25 +5343,40 @@ validateInstruction(MCInst &Inst, Inst.getOpcode() != ARM::t2Bcc) return Error(Loc, "predicated instructions must be in IT block"); - switch (Inst.getOpcode()) { + const unsigned Opcode = Inst.getOpcode(); + switch (Opcode) { case ARM::LDRD: case ARM::LDRD_PRE: case ARM::LDRD_POST: { - unsigned RtReg = Inst.getOperand(0).getReg(); + const unsigned RtReg = Inst.getOperand(0).getReg(); + // Rt can't be R14. if (RtReg == ARM::LR) return Error(Operands[3]->getStartLoc(), "Rt can't be R14"); - unsigned Rt = MRI->getEncodingValue(RtReg); + + const unsigned Rt = MRI->getEncodingValue(RtReg); // Rt must be even-numbered. if ((Rt & 1) == 1) return Error(Operands[3]->getStartLoc(), "Rt must be even-numbered"); + // Rt2 must be Rt + 1. - unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg()); + const unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg()); if (Rt2 != Rt + 1) return Error(Operands[3]->getStartLoc(), "destination operands must be sequential"); + + if (Opcode == ARM::LDRD_PRE || Opcode == ARM::LDRD_POST) { + const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(3).getReg()); + // For addressing modes with writeback, the base register needs to be + // different from the destination registers. + if (Rn == Rt || Rn == Rt2) + return Error(Operands[3]->getStartLoc(), + "base register needs to be different from destination " + "registers"); + } + return false; } case ARM::t2LDRDi8: diff --git a/test/MC/ARM/arm-ldrd.s b/test/MC/ARM/arm-ldrd.s index d62193aeba8..d4c608c760f 100644 --- a/test/MC/ARM/arm-ldrd.s +++ b/test/MC/ARM/arm-ldrd.s @@ -3,6 +3,7 @@ // RUN: grep "error: Rt must be even-numbered" %t | count 7 // RUN: grep "error: Rt can't be R14" %t | count 7 // RUN: grep "error: destination operands must be sequential" %t | count 7 +// RUN: grep "error: base register needs to be different from destination registers" %t | count 4 // rdar://14479793 ldrd r1, r2, [pc, #0] @@ -26,3 +27,8 @@ ldrd r0, r3, [r4, r5] ldrd r1, r2, [r3], r4 ldrd lr, pc, [r3], r4 ldrd r0, r3, [r4], r5 + +ldrd r0, r1, [r0], #4 +ldrd r0, r1, [r1], #4 +ldrd r0, r1, [r0, #4]! +ldrd r0, r1, [r1, #4]!