diff options
author | Tilmann Scheller <tilmann.scheller@googlemail.com> | 2013-09-30 16:11:48 +0000 |
---|---|---|
committer | Tilmann Scheller <tilmann.scheller@googlemail.com> | 2013-09-30 16:11:48 +0000 |
commit | 9724873c317d2b170cfea87cdf2a402fcd7c6c7d (patch) | |
tree | be6d0f82e9e4c6788a6b6551b7d2f5b43f4ca280 /lib/Target/ARM | |
parent | 7373265e1a2042032dfa48f1d0accca4e5b68fe1 (diff) | |
download | llvm-9724873c317d2b170cfea87cdf2a402fcd7c6c7d.tar.gz llvm-9724873c317d2b170cfea87cdf2a402fcd7c6c7d.tar.bz2 llvm-9724873c317d2b170cfea87cdf2a402fcd7c6c7d.tar.xz |
[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
Diffstat (limited to 'lib/Target/ARM')
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 6d6255f2cc..d360a24114 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: |