diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 91 |
1 files changed, 76 insertions, 15 deletions
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index e2f7dfb17f9..e9860764962 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -164,7 +164,10 @@ class ARMAsmParser : public MCTargetAsmParser { // according to count of instructions in block. // ~0U if no active IT block. } ITState; - bool inITBlock() { return ITState.CurPosition != ~0U;} + bool inITBlock() { return ITState.CurPosition != ~0U; } + bool lastInITBlock() { + return ITState.CurPosition == 4 - countTrailingZeros(ITState.Mask); + } void forwardITPosition() { if (!inITBlock()) return; // 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); } + bool validatetLDMRegList(MCInst Inst, const OperandVector &Operands, + unsigned ListNo, bool IsPop = false); + bool validatetSTMRegList(MCInst Inst, const OperandVector &Operands, + unsigned ListNo); + int tryParseRegister(); bool tryParseRegisterWithWriteBack(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. bool ARMAsmParser::validateInstruction(MCInst &Inst, const OperandVector &Operands) { @@ -6194,9 +6246,9 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, return Error(Operands[3]->getStartLoc(), "writeback operator '!' not allowed when base register " "in register list"); - if (listContainsReg(Inst, 3 + HasWritebackToken, ARM::SP)) - return Error(Operands[3 + HasWritebackToken]->getStartLoc(), - "SP not allowed in register list"); + + if (validatetLDMRegList(Inst, Operands, 3)) + return true; break; } case ARM::LDMIA_UPD: @@ -6213,13 +6265,14 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, break; case ARM::t2LDMIA: case ARM::t2LDMDB: + if (validatetLDMRegList(Inst, Operands, 3)) + return true; + break; case ARM::t2STMIA: - case ARM::t2STMDB: { - if (listContainsReg(Inst, 3, ARM::SP)) - return Error(Operands.back()->getStartLoc(), - "SP not allowed in register list"); + case ARM::t2STMDB: + if (validatetSTMRegList(Inst, Operands, 3)) + return true; break; - } case ARM::t2LDMIA_UPD: case ARM::t2LDMDB_UPD: case ARM::t2STMIA_UPD: @@ -6228,9 +6281,13 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, return Error(Operands.back()->getStartLoc(), "writeback register not allowed in register list"); - if (listContainsReg(Inst, 4, ARM::SP)) - return Error(Operands.back()->getStartLoc(), - "SP not allowed in register list"); + if (Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) { + if (validatetLDMRegList(Inst, Operands, 4)) + return true; + } else { + if (validatetSTMRegList(Inst, Operands, 4)) + return true; + } break; } case ARM::sysLDMIA_UPD: @@ -6275,6 +6332,8 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, !isThumbTwo()) return Error(Operands[2]->getStartLoc(), "registers must be in range r0-r7 or pc"); + if (validatetLDMRegList(Inst, Operands, 2, /*IsPop=*/true)) + return true; break; } case ARM::tPUSH: { @@ -6283,6 +6342,8 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, !isThumbTwo()) return Error(Operands[2]->getStartLoc(), "registers must be in range r0-r7 or lr"); + if (validatetSTMRegList(Inst, Operands, 2)) + return true; break; } case ARM::tSTMIA_UPD: { @@ -6299,9 +6360,9 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, return Error(Operands[4]->getStartLoc(), "writeback operator '!' not allowed when base register " "in register list"); - if (listContainsReg(Inst, 4, ARM::SP) && !inITBlock()) - return Error(Operands.back()->getStartLoc(), - "SP not allowed in register list"); + + if (validatetSTMRegList(Inst, Operands, 4)) + return true; break; } case ARM::tADDrSP: { |

