diff options
Diffstat (limited to 'llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
-rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 111 |
1 files changed, 104 insertions, 7 deletions
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 089a08c405f..fd7e7734ad6 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -98,6 +98,8 @@ class ARMAsmParser : public TargetAsmParser { SmallVectorImpl<MCParsedAsmOperand*>&); OperandMatchResultTy tryParseMemBarrierOptOperand( SmallVectorImpl<MCParsedAsmOperand*> &); + OperandMatchResultTy tryParseProcIFlagsOperand( + SmallVectorImpl<MCParsedAsmOperand*> &); public: ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM) @@ -126,6 +128,7 @@ class ARMOperand : public MCParsedAsmOperand { Immediate, MemBarrierOpt, Memory, + ProcIFlags, Register, RegisterList, DPRRegisterList, @@ -150,6 +153,10 @@ class ARMOperand : public MCParsedAsmOperand { } Cop; struct { + ARM_PROC::IFlags Val; + } IFlags; + + struct { const char *Data; unsigned Length; } Tok; @@ -215,6 +222,8 @@ public: case Memory: Mem = o.Mem; break; + case ProcIFlags: + IFlags = o.IFlags; } } @@ -259,6 +268,11 @@ public: return MBOpt.Val; } + ARM_PROC::IFlags getProcIFlags() const { + assert(Kind == ProcIFlags && "Invalid access!"); + return IFlags.Val; + } + /// @name Memory Operand Accessors /// @{ @@ -333,6 +347,7 @@ public: uint64_t Value = CE->getValue(); return ((Value & 0x3) == 0 && Value <= 124); } + bool isProcIFlags() const { return Kind == ProcIFlags; } void addExpr(MCInst &Inst, const MCExpr *Expr) const { // Add as immediates when possible. Null MCExpr = 0. @@ -433,6 +448,11 @@ public: Inst.addOperand(MCOperand::CreateImm(CE->getValue())); } + void addProcIFlagsOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags()))); + } + virtual void dump(raw_ostream &OS) const; static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) { @@ -556,6 +576,14 @@ public: Op->EndLoc = S; return Op; } + + static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) { + ARMOperand *Op = new ARMOperand(ProcIFlags); + Op->IFlags.Val = IFlags; + Op->StartLoc = S; + Op->EndLoc = S; + return Op; + } }; } // end anonymous namespace. @@ -604,6 +632,15 @@ void ARMOperand::dump(raw_ostream &OS) const { OS << " (writeback)"; OS << ">"; break; + case ProcIFlags: { + OS << "<ARM_PROC::"; + unsigned IFlags = getProcIFlags(); + for (int i=2; i >= 0; --i) + if (IFlags & (1 << i)) + OS << ARM_PROC::IFlagsToString(1 << i); + OS << ">"; + break; + } case Register: OS << "<register " << getReg() << ">"; break; @@ -885,6 +922,35 @@ tryParseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { return MatchOperand_Success; } +/// ParseProcIFlagsOperand - Try to parse iflags from CPS instruction. +ARMAsmParser::OperandMatchResultTy ARMAsmParser:: +tryParseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + SMLoc S = Parser.getTok().getLoc(); + const AsmToken &Tok = Parser.getTok(); + assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); + StringRef IFlagsStr = Tok.getString(); + + unsigned IFlags = 0; + for (int i = 0, e = IFlagsStr.size(); i != e; ++i) { + unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1)) + .Case("a", ARM_PROC::A) + .Case("i", ARM_PROC::I) + .Case("f", ARM_PROC::F) + .Default(~0U); + + // If some specific iflag is already set, it means that some letter is + // present more than once, this is not acceptable. + if (Flag == ~0U || (IFlags & Flag)) + return MatchOperand_NoMatch; + + IFlags |= Flag; + } + + Parser.Lex(); // Eat identifier token. + Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S)); + return MatchOperand_Success; +} + /// Parse an ARM memory expression, return false if successful else return true /// or an error. The first token must be a '[' when called. /// @@ -1254,11 +1320,13 @@ ARMAsmParser::ApplyPrefixToExpr(const MCExpr *E, /// setting letters to form a canonical mnemonic and flags. // // FIXME: Would be nice to autogen this. -static StringRef SplitMnemonicAndCC(StringRef Mnemonic, - unsigned &PredicationCode, - bool &CarrySetting) { +static StringRef SplitMnemonic(StringRef Mnemonic, + unsigned &PredicationCode, + bool &CarrySetting, + unsigned &ProcessorIMod) { PredicationCode = ARMCC::AL; CarrySetting = false; + ProcessorIMod = 0; // Ignore some mnemonics we know aren't predicated forms. // @@ -1312,6 +1380,21 @@ static StringRef SplitMnemonicAndCC(StringRef Mnemonic, CarrySetting = true; } + // The "cps" instruction can have a interrupt mode operand which is glued into + // the mnemonic. Check if this is the case, split it and parse the imod op + if (Mnemonic.startswith("cps")) { + // Split out any imod code. + unsigned IMod = + StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2)) + .Case("ie", ARM_PROC::IE) + .Case("id", ARM_PROC::ID) + .Default(~0U); + if (IMod != ~0U) { + Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2); + ProcessorIMod = IMod; + } + } + return Mnemonic; } @@ -1342,7 +1425,7 @@ GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet, Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" || Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" || Mnemonic == "dsb" || Mnemonic == "movs" || Mnemonic == "isb" || - Mnemonic == "clrex") { + Mnemonic == "clrex" || Mnemonic.startswith("cps")) { CanAcceptPredicationCode = false; } else { CanAcceptPredicationCode = true; @@ -1363,8 +1446,10 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc, // Split out the predication code and carry setting flag from the mnemonic. unsigned PredicationCode; + unsigned ProcessorIMod; bool CarrySetting; - Head = SplitMnemonicAndCC(Head, PredicationCode, CarrySetting); + Head = SplitMnemonic(Head, PredicationCode, CarrySetting, + ProcessorIMod); Operands.push_back(ARMOperand::CreateToken(Head, NameLoc)); @@ -1404,13 +1489,25 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc, // FIXME: Issue a nice error. } + // Add the processor imod operand, if necessary. + if (ProcessorIMod) { + Operands.push_back(ARMOperand::CreateImm( + MCConstantExpr::Create(ProcessorIMod, getContext()), + NameLoc, NameLoc)); + } else { + // This mnemonic can't ever accept a imod, but the user wrote + // one (or misspelled another mnemonic). + + // FIXME: Issue a nice error. + } + // Add the remaining tokens in the mnemonic. while (Next != StringRef::npos) { Start = Next; Next = Name.find('.', Start + 1); - Head = Name.slice(Start, Next); + StringRef ExtraToken = Name.slice(Start, Next); - Operands.push_back(ARMOperand::CreateToken(Head, NameLoc)); + Operands.push_back(ARMOperand::CreateToken(ExtraToken, NameLoc)); } // Read the remaining operands. |