mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-03 14:21:30 +00:00 
			
		
		
		
	[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
This commit is contained in:
		@@ -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:
 | 
			
		||||
 
 | 
			
		||||
@@ -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]!
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user