forked from OSchip/llvm-project
[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. llvm-svn: 191678
This commit is contained in:
parent
66eb921a82
commit
255722beb8
|
@ -5343,25 +5343,40 @@ validateInstruction(MCInst &Inst,
|
||||||
Inst.getOpcode() != ARM::t2Bcc)
|
Inst.getOpcode() != ARM::t2Bcc)
|
||||||
return Error(Loc, "predicated instructions must be in IT block");
|
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:
|
||||||
case ARM::LDRD_PRE:
|
case ARM::LDRD_PRE:
|
||||||
case ARM::LDRD_POST: {
|
case ARM::LDRD_POST: {
|
||||||
unsigned RtReg = Inst.getOperand(0).getReg();
|
const unsigned RtReg = Inst.getOperand(0).getReg();
|
||||||
|
|
||||||
// Rt can't be R14.
|
// Rt can't be R14.
|
||||||
if (RtReg == ARM::LR)
|
if (RtReg == ARM::LR)
|
||||||
return Error(Operands[3]->getStartLoc(),
|
return Error(Operands[3]->getStartLoc(),
|
||||||
"Rt can't be R14");
|
"Rt can't be R14");
|
||||||
unsigned Rt = MRI->getEncodingValue(RtReg);
|
|
||||||
|
const unsigned Rt = MRI->getEncodingValue(RtReg);
|
||||||
// Rt must be even-numbered.
|
// Rt must be even-numbered.
|
||||||
if ((Rt & 1) == 1)
|
if ((Rt & 1) == 1)
|
||||||
return Error(Operands[3]->getStartLoc(),
|
return Error(Operands[3]->getStartLoc(),
|
||||||
"Rt must be even-numbered");
|
"Rt must be even-numbered");
|
||||||
|
|
||||||
// Rt2 must be Rt + 1.
|
// 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)
|
if (Rt2 != Rt + 1)
|
||||||
return Error(Operands[3]->getStartLoc(),
|
return Error(Operands[3]->getStartLoc(),
|
||||||
"destination operands must be sequential");
|
"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;
|
return false;
|
||||||
}
|
}
|
||||||
case ARM::t2LDRDi8:
|
case ARM::t2LDRDi8:
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// RUN: grep "error: Rt must be even-numbered" %t | count 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: Rt can't be R14" %t | count 7
|
||||||
// RUN: grep "error: destination operands must be sequential" %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
|
// rdar://14479793
|
||||||
|
|
||||||
ldrd r1, r2, [pc, #0]
|
ldrd r1, r2, [pc, #0]
|
||||||
|
@ -26,3 +27,8 @@ ldrd r0, r3, [r4, r5]
|
||||||
ldrd r1, r2, [r3], r4
|
ldrd r1, r2, [r3], r4
|
||||||
ldrd lr, pc, [r3], r4
|
ldrd lr, pc, [r3], r4
|
||||||
ldrd r0, r3, [r4], r5
|
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]!
|
||||||
|
|
Loading…
Reference in New Issue