diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 4587ed200dd..a074bc5a747 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -135,6 +135,10 @@ class ARMAsmParser : public MCTargetAsmParser { bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode, const SmallVectorImpl &); + + bool validateInstruction(MCInst &Inst, + const SmallVectorImpl &Ops); + public: ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser) : MCTargetAsmParser(), STI(_STI), Parser(_Parser) { @@ -147,7 +151,7 @@ public: // Implementation of the MCTargetAsmParser interface: bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); bool ParseInstruction(StringRef Name, SMLoc NameLoc, - SmallVectorImpl &Operands); + SmallVectorImpl &Operands); bool ParseDirective(AsmToken DirectiveID); bool MatchAndEmitInstruction(SMLoc IDLoc, @@ -2499,6 +2503,35 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc, return false; } +// Validate context-sensitive operand constraints. +// FIXME: We would really like to be able to tablegen'erate this. +bool ARMAsmParser:: +validateInstruction(MCInst &Inst, + const SmallVectorImpl &Operands) { + switch (Inst.getOpcode()) { + case ARM::LDREXD: { + // Rt2 must be Rt + 1. + unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg()); + unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg()); + if (Rt2 != Rt + 1) + return Error(Operands[3]->getStartLoc(), + "destination operands must be sequential"); + return false; + } + case ARM::STREXD: { + // Rt2 must be Rt + 1. + unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg()); + unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg()); + if (Rt2 != Rt + 1) + return Error(Operands[4]->getStartLoc(), + "source operands must be sequential"); + return false; + } + } + + return false; +} + bool ARMAsmParser:: MatchAndEmitInstruction(SMLoc IDLoc, SmallVectorImpl &Operands, @@ -2509,6 +2542,11 @@ MatchAndEmitInstruction(SMLoc IDLoc, MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo); switch (MatchResult) { case Match_Success: + // Context sensitive operand constraints aren't handled by the matcher, + // so check them here. + if (validateInstruction(Inst, Operands)) + return true; + Out.EmitInstruction(Inst); return false; case Match_MissingFeature: diff --git a/test/MC/ARM/diagnostics.s b/test/MC/ARM/diagnostics.s index 0c51887c7a2..c8ca0593e7b 100644 --- a/test/MC/ARM/diagnostics.s +++ b/test/MC/ARM/diagnostics.s @@ -226,3 +226,15 @@ @ CHECK-ERRORS: error: invalid operand for instruction @ CHECK-ERRORS: svc #0x1000000 @ CHECK-ERRORS: ^ + + + @ Out of order Rt/Rt2 operands for ldrexd/strexd + ldrexd r4, r3, [r8] + strexd r6, r5, r3, [r8] + +@ CHECK-ERRORS: error: destination operands must be sequential +@ CHECK-ERRORS: ldrexd r4, r3, [r8] +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: source operands must be sequential +@ CHECK-ERRORS: strexd r6, r5, r3, [r8] +@ CHECK-ERRORS: ^