diff options
Diffstat (limited to 'lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 543340f8e4..9d28a1cd09 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -114,10 +114,16 @@ class ARMAsmParser : public MCTargetAsmParser { bool hasV6Ops() const { return STI.getFeatureBits() & ARM::HasV6Ops; } + bool hasV7Ops() const { + return STI.getFeatureBits() & ARM::HasV7Ops; + } void SwitchMode() { unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb)); setAvailableFeatures(FB); } + bool isMClass() const { + return STI.getFeatureBits() & ARM::FeatureMClass; + } /// @name Auto-generated Match Functions /// { @@ -2076,6 +2082,37 @@ parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); StringRef Mask = Tok.getString(); + if (isMClass()) { + // See ARMv6-M 10.1.1 + unsigned FlagsVal = StringSwitch<unsigned>(Mask) + .Case("apsr", 0) + .Case("iapsr", 1) + .Case("eapsr", 2) + .Case("xpsr", 3) + .Case("ipsr", 5) + .Case("epsr", 6) + .Case("iepsr", 7) + .Case("msp", 8) + .Case("psp", 9) + .Case("primask", 16) + .Case("basepri", 17) + .Case("basepri_max", 18) + .Case("faultmask", 19) + .Case("control", 20) + .Default(~0U); + + if (FlagsVal == ~0U) + return MatchOperand_NoMatch; + + if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19) + // basepri, basepri_max and faultmask only valid for V7m. + return MatchOperand_NoMatch; + + Parser.Lex(); // Eat identifier token. + Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S)); + return MatchOperand_Success; + } + // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf" size_t Start = 0, Next = Mask.find('_'); StringRef Flags = ""; |