mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-04 05:17:07 +00:00 
			
		
		
		
	ARM: improve instruction validation for thumb mode
The ARM Architecture Reference Manual states the following:
  LDM{,IA,DB}:
    The SP cannot be in the list.
    The PC can be in the list.
    If the PC is in the list:
      • the LR must not be in the list
      • the instruction must be either outside any IT block, or the last
        instruction in an IT block.
  POP:
    The PC can be in the list.
    If the PC is in the list:
      • the LR must not be in the list
      • the instruction must be either outside any IT block, or the last
        instruction in an IT block.
  PUSH:
    The SP and PC can be in the list in ARM instructions, but not in Thumb
    instructions.
  STM:{,IA,DB}:
    The SP and PC can be in the list in ARM instructions, but not in Thumb
    instructions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224502 91177308-0d34-0410-b5e6-96231b3b80d8
			
			
This commit is contained in:
		@@ -164,7 +164,10 @@ class ARMAsmParser : public MCTargetAsmParser {
 | 
				
			|||||||
                              // according to count of instructions in block.
 | 
					                              // according to count of instructions in block.
 | 
				
			||||||
                              // ~0U if no active IT block.
 | 
					                              // ~0U if no active IT block.
 | 
				
			||||||
  } ITState;
 | 
					  } ITState;
 | 
				
			||||||
  bool inITBlock() { return ITState.CurPosition != ~0U;}
 | 
					  bool inITBlock() { return ITState.CurPosition != ~0U; }
 | 
				
			||||||
 | 
					  bool lastInITBlock() {
 | 
				
			||||||
 | 
					    return ITState.CurPosition == 4 - countTrailingZeros(ITState.Mask);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  void forwardITPosition() {
 | 
					  void forwardITPosition() {
 | 
				
			||||||
    if (!inITBlock()) return;
 | 
					    if (!inITBlock()) return;
 | 
				
			||||||
    // Move to the next instruction in the IT block, if there is one. If not,
 | 
					    // Move to the next instruction in the IT block, if there is one. If not,
 | 
				
			||||||
@@ -186,6 +189,11 @@ class ARMAsmParser : public MCTargetAsmParser {
 | 
				
			|||||||
    return getParser().Error(L, Msg, Ranges);
 | 
					    return getParser().Error(L, Msg, Ranges);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool validatetLDMRegList(MCInst Inst, const OperandVector &Operands,
 | 
				
			||||||
 | 
					                           unsigned ListNo, bool IsPop = false);
 | 
				
			||||||
 | 
					  bool validatetSTMRegList(MCInst Inst, const OperandVector &Operands,
 | 
				
			||||||
 | 
					                           unsigned ListNo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int tryParseRegister();
 | 
					  int tryParseRegister();
 | 
				
			||||||
  bool tryParseRegisterWithWriteBack(OperandVector &);
 | 
					  bool tryParseRegisterWithWriteBack(OperandVector &);
 | 
				
			||||||
  int tryParseShiftRegister(OperandVector &);
 | 
					  int tryParseShiftRegister(OperandVector &);
 | 
				
			||||||
@@ -6011,6 +6019,50 @@ static bool instIsBreakpoint(const MCInst &Inst) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ARMAsmParser::validatetLDMRegList(MCInst Inst,
 | 
				
			||||||
 | 
					                                       const OperandVector &Operands,
 | 
				
			||||||
 | 
					                                       unsigned ListNo, bool IsPop) {
 | 
				
			||||||
 | 
					  const ARMOperand &Op = static_cast<const ARMOperand &>(*Operands[ListNo]);
 | 
				
			||||||
 | 
					  bool HasWritebackToken = Op.isToken() && Op.getToken() == "!";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool ListContainsSP = listContainsReg(Inst, ListNo, ARM::SP);
 | 
				
			||||||
 | 
					  bool ListContainsLR = listContainsReg(Inst, ListNo, ARM::LR);
 | 
				
			||||||
 | 
					  bool ListContainsPC = listContainsReg(Inst, ListNo, ARM::PC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!IsPop && ListContainsSP)
 | 
				
			||||||
 | 
					    return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(),
 | 
				
			||||||
 | 
					                 "SP may not be in the register list");
 | 
				
			||||||
 | 
					  else if (ListContainsPC && ListContainsLR)
 | 
				
			||||||
 | 
					    return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(),
 | 
				
			||||||
 | 
					                 "PC and LR may not be in the register list simultaneously");
 | 
				
			||||||
 | 
					  else if (inITBlock() && !lastInITBlock() && ListContainsPC)
 | 
				
			||||||
 | 
					    return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(),
 | 
				
			||||||
 | 
					                 "instruction must be outside of IT block or the last "
 | 
				
			||||||
 | 
					                 "instruction in an IT block");
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool ARMAsmParser::validatetSTMRegList(MCInst Inst,
 | 
				
			||||||
 | 
					                                       const OperandVector &Operands,
 | 
				
			||||||
 | 
					                                       unsigned ListNo) {
 | 
				
			||||||
 | 
					  const ARMOperand &Op = static_cast<const ARMOperand &>(*Operands[ListNo]);
 | 
				
			||||||
 | 
					  bool HasWritebackToken = Op.isToken() && Op.getToken() == "!";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool ListContainsSP = listContainsReg(Inst, ListNo, ARM::SP);
 | 
				
			||||||
 | 
					  bool ListContainsPC = listContainsReg(Inst, ListNo, ARM::PC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (ListContainsSP && ListContainsPC)
 | 
				
			||||||
 | 
					    return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(),
 | 
				
			||||||
 | 
					                 "SP and PC may not be in the register list");
 | 
				
			||||||
 | 
					  else if (ListContainsSP)
 | 
				
			||||||
 | 
					    return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(),
 | 
				
			||||||
 | 
					                 "SP may not be in the register list");
 | 
				
			||||||
 | 
					  else if (ListContainsPC)
 | 
				
			||||||
 | 
					    return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(),
 | 
				
			||||||
 | 
					                 "PC may not be in the register list");
 | 
				
			||||||
 | 
					  return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FIXME: We would really like to be able to tablegen'erate this.
 | 
					// FIXME: We would really like to be able to tablegen'erate this.
 | 
				
			||||||
bool ARMAsmParser::validateInstruction(MCInst &Inst,
 | 
					bool ARMAsmParser::validateInstruction(MCInst &Inst,
 | 
				
			||||||
                                       const OperandVector &Operands) {
 | 
					                                       const OperandVector &Operands) {
 | 
				
			||||||
@@ -6194,9 +6246,9 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
 | 
				
			|||||||
      return Error(Operands[3]->getStartLoc(),
 | 
					      return Error(Operands[3]->getStartLoc(),
 | 
				
			||||||
                   "writeback operator '!' not allowed when base register "
 | 
					                   "writeback operator '!' not allowed when base register "
 | 
				
			||||||
                   "in register list");
 | 
					                   "in register list");
 | 
				
			||||||
    if (listContainsReg(Inst, 3 + HasWritebackToken, ARM::SP))
 | 
					
 | 
				
			||||||
      return Error(Operands[3 + HasWritebackToken]->getStartLoc(),
 | 
					    if (validatetLDMRegList(Inst, Operands, 3))
 | 
				
			||||||
                   "SP not allowed in register list");
 | 
					      return true;
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case ARM::LDMIA_UPD:
 | 
					  case ARM::LDMIA_UPD:
 | 
				
			||||||
@@ -6213,13 +6265,14 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
 | 
				
			|||||||
    break;
 | 
					    break;
 | 
				
			||||||
  case ARM::t2LDMIA:
 | 
					  case ARM::t2LDMIA:
 | 
				
			||||||
  case ARM::t2LDMDB:
 | 
					  case ARM::t2LDMDB:
 | 
				
			||||||
  case ARM::t2STMIA:
 | 
					    if (validatetLDMRegList(Inst, Operands, 3))
 | 
				
			||||||
  case ARM::t2STMDB: {
 | 
					      return true;
 | 
				
			||||||
    if (listContainsReg(Inst, 3, ARM::SP))
 | 
					    break;
 | 
				
			||||||
      return Error(Operands.back()->getStartLoc(),
 | 
					  case ARM::t2STMIA:
 | 
				
			||||||
                   "SP not allowed in register list");
 | 
					  case ARM::t2STMDB:
 | 
				
			||||||
 | 
					    if (validatetSTMRegList(Inst, Operands, 3))
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  case ARM::t2LDMIA_UPD:
 | 
					  case ARM::t2LDMIA_UPD:
 | 
				
			||||||
  case ARM::t2LDMDB_UPD:
 | 
					  case ARM::t2LDMDB_UPD:
 | 
				
			||||||
  case ARM::t2STMIA_UPD:
 | 
					  case ARM::t2STMIA_UPD:
 | 
				
			||||||
@@ -6228,9 +6281,13 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
 | 
				
			|||||||
      return Error(Operands.back()->getStartLoc(),
 | 
					      return Error(Operands.back()->getStartLoc(),
 | 
				
			||||||
                   "writeback register not allowed in register list");
 | 
					                   "writeback register not allowed in register list");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (listContainsReg(Inst, 4, ARM::SP))
 | 
					    if (Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) {
 | 
				
			||||||
      return Error(Operands.back()->getStartLoc(),
 | 
					      if (validatetLDMRegList(Inst, Operands, 4))
 | 
				
			||||||
                   "SP not allowed in register list");
 | 
					        return true;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      if (validatetSTMRegList(Inst, Operands, 4))
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case ARM::sysLDMIA_UPD:
 | 
					  case ARM::sysLDMIA_UPD:
 | 
				
			||||||
@@ -6275,6 +6332,8 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
 | 
				
			|||||||
        !isThumbTwo())
 | 
					        !isThumbTwo())
 | 
				
			||||||
      return Error(Operands[2]->getStartLoc(),
 | 
					      return Error(Operands[2]->getStartLoc(),
 | 
				
			||||||
                   "registers must be in range r0-r7 or pc");
 | 
					                   "registers must be in range r0-r7 or pc");
 | 
				
			||||||
 | 
					    if (validatetLDMRegList(Inst, Operands, 2, /*IsPop=*/true))
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case ARM::tPUSH: {
 | 
					  case ARM::tPUSH: {
 | 
				
			||||||
@@ -6283,6 +6342,8 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
 | 
				
			|||||||
        !isThumbTwo())
 | 
					        !isThumbTwo())
 | 
				
			||||||
      return Error(Operands[2]->getStartLoc(),
 | 
					      return Error(Operands[2]->getStartLoc(),
 | 
				
			||||||
                   "registers must be in range r0-r7 or lr");
 | 
					                   "registers must be in range r0-r7 or lr");
 | 
				
			||||||
 | 
					    if (validatetSTMRegList(Inst, Operands, 2))
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case ARM::tSTMIA_UPD: {
 | 
					  case ARM::tSTMIA_UPD: {
 | 
				
			||||||
@@ -6299,9 +6360,9 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
 | 
				
			|||||||
      return Error(Operands[4]->getStartLoc(),
 | 
					      return Error(Operands[4]->getStartLoc(),
 | 
				
			||||||
                   "writeback operator '!' not allowed when base register "
 | 
					                   "writeback operator '!' not allowed when base register "
 | 
				
			||||||
                   "in register list");
 | 
					                   "in register list");
 | 
				
			||||||
    if (listContainsReg(Inst, 4, ARM::SP) && !inITBlock())
 | 
					
 | 
				
			||||||
      return Error(Operands.back()->getStartLoc(),
 | 
					    if (validatetSTMRegList(Inst, Operands, 4))
 | 
				
			||||||
                   "SP not allowed in register list");
 | 
					      return true;
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  case ARM::tADDrSP: {
 | 
					  case ARM::tADDrSP: {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -83,25 +83,25 @@ error: invalid operand for instruction
 | 
				
			|||||||
@ CHECK-ERRORS-V8: error: writeback register not allowed in register list
 | 
					@ CHECK-ERRORS-V8: error: writeback register not allowed in register list
 | 
				
			||||||
@ CHECK-ERRORS-V8:         ldmdb r2!, {r2, r3, r4}
 | 
					@ CHECK-ERRORS-V8:         ldmdb r2!, {r2, r3, r4}
 | 
				
			||||||
@ CHECK-ERRORS-V8:                 ^
 | 
					@ CHECK-ERRORS-V8:                 ^
 | 
				
			||||||
@ CHECK-ERRORS-V7M: error: SP not allowed in register list
 | 
					@ CHECK-ERRORS-V7M: error: SP may not be in the register list
 | 
				
			||||||
@ CHECK-ERRORS-V7M:         ldm r0, {r2, sp}
 | 
					@ CHECK-ERRORS-V7M:         ldm r0, {r2, sp}
 | 
				
			||||||
@ CHECK-ERRORS-V7M:                 ^
 | 
					@ CHECK-ERRORS-V7M:                 ^
 | 
				
			||||||
@ CHECK-ERRORS-V7M: error: SP not allowed in register list
 | 
					@ CHECK-ERRORS-V7M: error: SP may not be in the register list
 | 
				
			||||||
@ CHECK-ERRORS-V7M:         ldmia r0, {r2-r3, sp}
 | 
					@ CHECK-ERRORS-V7M:         ldmia r0, {r2-r3, sp}
 | 
				
			||||||
@ CHECK-ERRORS-V7M:                   ^
 | 
					@ CHECK-ERRORS-V7M:                   ^
 | 
				
			||||||
@ CHECK-ERRORS-V7M: error: SP not allowed in register list
 | 
					@ CHECK-ERRORS-V7M: error: SP may not be in the register list
 | 
				
			||||||
@ CHECK-ERRORS-V7M:         ldmia r0!, {r2-r3, sp}
 | 
					@ CHECK-ERRORS-V7M:         ldmia r0!, {r2-r3, sp}
 | 
				
			||||||
@ CHECK-ERRORS-V7M:                    ^
 | 
					@ CHECK-ERRORS-V7M:                    ^
 | 
				
			||||||
@ CHECK-ERRORS-V7M: error: SP not allowed in register list
 | 
					@ CHECK-ERRORS-V7M: error: SP may not be in the register list
 | 
				
			||||||
@ CHECK-ERRORS-V7M:         ldmfd r2, {r1, r3-r6, sp}
 | 
					@ CHECK-ERRORS-V7M:         ldmfd r2, {r1, r3-r6, sp}
 | 
				
			||||||
@ CHECK-ERRORS-V7M:                   ^
 | 
					@ CHECK-ERRORS-V7M:                   ^
 | 
				
			||||||
@ CHECK-ERRORS-V7M: error: SP not allowed in register list
 | 
					@ CHECK-ERRORS-V7M: error: SP may not be in the register list
 | 
				
			||||||
@ CHECK-ERRORS-V7M:         ldmfd r2!, {r1, r3-r6, sp}
 | 
					@ CHECK-ERRORS-V7M:         ldmfd r2!, {r1, r3-r6, sp}
 | 
				
			||||||
@ CHECK-ERRORS-V7M:                    ^
 | 
					@ CHECK-ERRORS-V7M:                    ^
 | 
				
			||||||
@ CHECK-ERRORS-V7M: error: SP not allowed in register list
 | 
					@ CHECK-ERRORS-V7M: error: SP may not be in the register list
 | 
				
			||||||
@ CHECK-ERRORS-V7M:         ldmdb r1, {r2, r3, sp}
 | 
					@ CHECK-ERRORS-V7M:         ldmdb r1, {r2, r3, sp}
 | 
				
			||||||
@ CHECK-ERRORS-V7M:                   ^
 | 
					@ CHECK-ERRORS-V7M:                   ^
 | 
				
			||||||
@ CHECK-ERRORS-V7M: error: SP not allowed in register list
 | 
					@ CHECK-ERRORS-V7M: error: SP may not be in the register list
 | 
				
			||||||
@ CHECK-ERRORS-V7M:         ldmdb r1!, {r2, r3, sp}
 | 
					@ CHECK-ERRORS-V7M:         ldmdb r1!, {r2, r3, sp}
 | 
				
			||||||
@ CHECK-ERRORS-V7M:                    ^
 | 
					@ CHECK-ERRORS-V7M:                    ^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -137,16 +137,16 @@ error: invalid operand for instruction
 | 
				
			|||||||
@ CHECK-ERRORS-V8: error: writeback register not allowed in register list
 | 
					@ CHECK-ERRORS-V8: error: writeback register not allowed in register list
 | 
				
			||||||
@ CHECK-ERRORS-V8:         stmdb r2!, {r0, r2}
 | 
					@ CHECK-ERRORS-V8:         stmdb r2!, {r0, r2}
 | 
				
			||||||
@ CHECK-ERRORS-V8:                  ^
 | 
					@ CHECK-ERRORS-V8:                  ^
 | 
				
			||||||
@ CHECK-ERRORS-V7M: error: SP not allowed in register list
 | 
					@ CHECK-ERRORS-V7M: error: SP may not be in the register list
 | 
				
			||||||
@ CHECK-ERRORS-V7M:         stm r1!, {r2, sp}
 | 
					@ CHECK-ERRORS-V7M:         stm r1!, {r2, sp}
 | 
				
			||||||
@ CHECK-ERRORS-V7M:                  ^
 | 
					@ CHECK-ERRORS-V7M:                  ^
 | 
				
			||||||
@ CHECK-ERRORS-V7M: error: SP not allowed in register list
 | 
					@ CHECK-ERRORS-V7M: error: SP may not be in the register list
 | 
				
			||||||
@ CHECK-ERRORS-V7M:         stmia r4!, {r0-r3, sp}
 | 
					@ CHECK-ERRORS-V7M:         stmia r4!, {r0-r3, sp}
 | 
				
			||||||
@ CHECK-ERRORS-V7M:                    ^
 | 
					@ CHECK-ERRORS-V7M:                    ^
 | 
				
			||||||
@ CHECK-ERRORS-V7M: error: SP not allowed in register list
 | 
					@ CHECK-ERRORS-V7M: error: SP may not be in the register list
 | 
				
			||||||
@ CHECK-ERRORS-V7M:         stmdb r1, {r2, r3, sp}
 | 
					@ CHECK-ERRORS-V7M:         stmdb r1, {r2, r3, sp}
 | 
				
			||||||
@ CHECK-ERRORS-V7M:                   ^
 | 
					@ CHECK-ERRORS-V7M:                   ^
 | 
				
			||||||
@ CHECK-ERRORS-V7M: error: SP not allowed in register list
 | 
					@ CHECK-ERRORS-V7M: error: SP may not be in the register list
 | 
				
			||||||
@ CHECK-ERRORS-V7M:         stmdb r1!, {r2, r3, sp}
 | 
					@ CHECK-ERRORS-V7M:         stmdb r1!, {r2, r3, sp}
 | 
				
			||||||
@ CHECK-ERRORS-V7M:                    ^
 | 
					@ CHECK-ERRORS-V7M:                    ^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										86
									
								
								test/MC/ARM/thumb-load-store-multiple.s
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								test/MC/ARM/thumb-load-store-multiple.s
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
				
			|||||||
 | 
					@ RUN: not llvm-mc -triple thumbv7-eabi -filetype asm -o /dev/null %s 2>&1 \
 | 
				
			||||||
 | 
					@ RUN:     | FileCheck %s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.syntax unified
 | 
				
			||||||
 | 
						.thumb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.global ldm
 | 
				
			||||||
 | 
						.type ldm,%function
 | 
				
			||||||
 | 
					ldb:
 | 
				
			||||||
 | 
						ldm r0!, {r1, sp}
 | 
				
			||||||
 | 
					@ CHECK: error: SP may not be in the register list
 | 
				
			||||||
 | 
					@ CHECK: ldm r0!, {r1, sp}
 | 
				
			||||||
 | 
					@ CHECK:          ^
 | 
				
			||||||
 | 
						ldm r0!, {lr, pc}
 | 
				
			||||||
 | 
					@ CHECK: error: PC and LR may not be in the register list simultaneously
 | 
				
			||||||
 | 
					@ CHECK: ldm r0!, {lr, pc}
 | 
				
			||||||
 | 
					@ CHECK:          ^
 | 
				
			||||||
 | 
						itt eq
 | 
				
			||||||
 | 
						ldmeq r0!, {r1, pc}
 | 
				
			||||||
 | 
						ldmeq r0!, {r2, lr}
 | 
				
			||||||
 | 
					@ CHECK: error: instruction must be outside of IT block or the last instruction in an IT block
 | 
				
			||||||
 | 
					@ CHECK: ldmeq r0!, {r1, pc}
 | 
				
			||||||
 | 
					@ CHECK:            ^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.global ldmdb
 | 
				
			||||||
 | 
						.type ldmdb,%function
 | 
				
			||||||
 | 
					ldmdb:
 | 
				
			||||||
 | 
						ldmdb r0!, {r1, sp}
 | 
				
			||||||
 | 
					@ CHECK: error: SP may not be in the register list
 | 
				
			||||||
 | 
						ldm r0!, {lr, pc}
 | 
				
			||||||
 | 
					@ error: PC and LR may not be in the register list simultaneously
 | 
				
			||||||
 | 
						itt eq
 | 
				
			||||||
 | 
						ldmeq r0!, {r1, pc}
 | 
				
			||||||
 | 
						ldmeq r0!, {r2, lr}
 | 
				
			||||||
 | 
					@ CHECK: error: instruction must be outside of IT block or the last instruction in an IT block
 | 
				
			||||||
 | 
					@ CHECK: ldmeq r0!, {r1, pc}
 | 
				
			||||||
 | 
					@ CHECK:            ^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.global stm
 | 
				
			||||||
 | 
						.type stm,%function
 | 
				
			||||||
 | 
					stm:
 | 
				
			||||||
 | 
						stm r0!, {r1, sp}
 | 
				
			||||||
 | 
					@ CHECK: error: SP may not be in the register list
 | 
				
			||||||
 | 
						stm r0!, {r2, pc}
 | 
				
			||||||
 | 
					@ CHECK: error: PC may not be in the register list
 | 
				
			||||||
 | 
						stm r0!, {sp, pc}
 | 
				
			||||||
 | 
					@ CHECK: error: SP and PC may not be in the register list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.global stmdb
 | 
				
			||||||
 | 
						.type stmdb,%function
 | 
				
			||||||
 | 
					stmdb:
 | 
				
			||||||
 | 
						stmdb r0!, {r1, sp}
 | 
				
			||||||
 | 
					@ CHECK: error: SP may not be in the register list
 | 
				
			||||||
 | 
						stmdb r0!, {r2, pc}
 | 
				
			||||||
 | 
					@ CHECK: error: PC may not be in the register list
 | 
				
			||||||
 | 
						stmdb r0!, {sp, pc}
 | 
				
			||||||
 | 
					@ CHECK: error: SP and PC may not be in the register list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.global push
 | 
				
			||||||
 | 
						.type push,%function
 | 
				
			||||||
 | 
					push:
 | 
				
			||||||
 | 
						push {sp}
 | 
				
			||||||
 | 
					@ CHECK: error: SP may not be in the register list
 | 
				
			||||||
 | 
						push {pc}
 | 
				
			||||||
 | 
					@ CHECK: error: PC may not be in the register list
 | 
				
			||||||
 | 
						push {sp,pc}
 | 
				
			||||||
 | 
					@ CHECK: error: SP and PC may not be in the register list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.global pop
 | 
				
			||||||
 | 
						.type pop,%function
 | 
				
			||||||
 | 
					pop:
 | 
				
			||||||
 | 
						pop {sp}
 | 
				
			||||||
 | 
					@ CHECK-NOT: error: SP may not be in the register list
 | 
				
			||||||
 | 
						pop {sp, pc}
 | 
				
			||||||
 | 
					@ CHECK-NOT: error: SP may not be in the register list
 | 
				
			||||||
 | 
						pop {lr, pc}
 | 
				
			||||||
 | 
					@ CHECK: error: PC and LR may not be in the register list simultaneously
 | 
				
			||||||
 | 
					@ CHECK: pop {lr, pc}
 | 
				
			||||||
 | 
					@ CHECK:     ^
 | 
				
			||||||
 | 
						itt eq
 | 
				
			||||||
 | 
						popeq {r1, pc}
 | 
				
			||||||
 | 
						popeq {r2, lr}
 | 
				
			||||||
 | 
					@ CHECK: error: instruction must be outside of IT block or the last instruction in an IT block
 | 
				
			||||||
 | 
					@ CHECK: popeq {r1, pc}
 | 
				
			||||||
 | 
					@ CHECK:     ^
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -554,11 +554,11 @@ pushge {r1, r3, r7}
 | 
				
			|||||||
@ PUSH, encoding T2 (32-bit)
 | 
					@ PUSH, encoding T2 (32-bit)
 | 
				
			||||||
@ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
 | 
					@ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
 | 
				
			||||||
it ge
 | 
					it ge
 | 
				
			||||||
pushge {r1, r13, r7}
 | 
					pushge {r1, r3, r7}
 | 
				
			||||||
@ PUSH, encoding T3 (32-bit)
 | 
					@ PUSH, encoding T3 (32-bit)
 | 
				
			||||||
@ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
 | 
					@ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
 | 
				
			||||||
it ge
 | 
					it ge
 | 
				
			||||||
pushge {r13}
 | 
					pushge {r3}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ REV, encoding T1
 | 
					@ REV, encoding T1
 | 
				
			||||||
@ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
 | 
					@ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
 | 
				
			||||||
@@ -614,9 +614,10 @@ stmge r1!, {r2, r3}
 | 
				
			|||||||
@ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
 | 
					@ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
 | 
				
			||||||
it ge
 | 
					it ge
 | 
				
			||||||
stmge r1, {r2, r3}
 | 
					stmge r1, {r2, r3}
 | 
				
			||||||
 | 
					@ STM, encoding T3 (32-bit)
 | 
				
			||||||
@ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
 | 
					@ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
 | 
				
			||||||
it ge
 | 
					it ge
 | 
				
			||||||
stmge r1!, {r2, r13}
 | 
					stmge r1!, {r2, r3}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ LDM, encoding T1
 | 
					@ LDM, encoding T1
 | 
				
			||||||
@ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
 | 
					@ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user