diff options
author | Jim Grosbach <grosbach@apple.com> | 2011-10-12 17:34:41 +0000 |
---|---|---|
committer | Jim Grosbach <grosbach@apple.com> | 2011-10-12 17:34:41 +0000 |
commit | 9b8f2a0b365ea62a5fef80bbaab3cf0252db2fcf (patch) | |
tree | b5eb114960ac0ae3c4be79ff11cf15cf256dd6be /lib/Target/ARM/AsmParser/ARMAsmParser.cpp | |
parent | 01208d56e8341c17bb7dbeaf6c081fdffe523786 (diff) |
ARM parsing and encoding for the <option> form of LDC/STC instructions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141786 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 71 |
1 files changed, 66 insertions, 5 deletions
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index afb6e5684d..3ce086a049 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -138,6 +138,8 @@ class ARMAsmParser : public MCTargetAsmParser { SmallVectorImpl<MCParsedAsmOperand*>&); OperandMatchResultTy parseCoprocRegOperand( SmallVectorImpl<MCParsedAsmOperand*>&); + OperandMatchResultTy parseCoprocOptionOperand( + SmallVectorImpl<MCParsedAsmOperand*>&); OperandMatchResultTy parseMemBarrierOptOperand( SmallVectorImpl<MCParsedAsmOperand*>&); OperandMatchResultTy parseProcIFlagsOperand( @@ -247,6 +249,7 @@ class ARMOperand : public MCParsedAsmOperand { k_ITCondMask, k_CoprocNum, k_CoprocReg, + k_CoprocOption, k_Immediate, k_FPImmediate, k_MemBarrierOpt, @@ -280,6 +283,10 @@ class ARMOperand : public MCParsedAsmOperand { } Cop; struct { + unsigned Val; + } CoprocOption; + + struct { unsigned Mask:4; } ITMask; @@ -390,6 +397,9 @@ public: case k_CoprocReg: Cop = o.Cop; break; + case k_CoprocOption: + CoprocOption = o.CoprocOption; + break; case k_Immediate: Imm = o.Imm; break; @@ -495,6 +505,7 @@ public: bool isCoprocNum() const { return Kind == k_CoprocNum; } bool isCoprocReg() const { return Kind == k_CoprocReg; } + bool isCoprocOption() const { return Kind == k_CoprocOption; } bool isCondCode() const { return Kind == k_CondCode; } bool isCCOut() const { return Kind == k_CCOut; } bool isITMask() const { return Kind == k_ITCondMask; } @@ -924,6 +935,16 @@ public: Inst.addOperand(MCOperand::CreateImm(getCoproc())); } + void addCoprocRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateImm(getCoproc())); + } + + void addCoprocOptionOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val)); + } + void addITMaskOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateImm(ITMask.Mask)); @@ -934,11 +955,6 @@ public: Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode()))); } - void addCoprocRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getCoproc())); - } - void addCCOutOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateReg(getReg())); @@ -1453,6 +1469,14 @@ public: return Op; } + static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) { + ARMOperand *Op = new ARMOperand(k_CoprocOption); + Op->Cop.Val = Val; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) { ARMOperand *Op = new ARMOperand(k_CCOut); Op->Reg.RegNum = RegNum; @@ -1668,6 +1692,9 @@ void ARMOperand::print(raw_ostream &OS) const { case k_CoprocReg: OS << "<coprocessor register: " << getCoproc() << ">"; break; + case k_CoprocOption: + OS << "<coprocessor option: " << CoprocOption.Val << ">"; + break; case k_MSRMask: OS << "<mask: " << getMSRMask() << ">"; break; @@ -2088,6 +2115,40 @@ parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { return MatchOperand_Success; } +/// parseCoprocOptionOperand - Try to parse an coprocessor option operand. +/// coproc_option : '{' imm0_255 '}' +ARMAsmParser::OperandMatchResultTy ARMAsmParser:: +parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + SMLoc S = Parser.getTok().getLoc(); + + // If this isn't a '{', this isn't a coprocessor immediate operand. + if (Parser.getTok().isNot(AsmToken::LCurly)) + return MatchOperand_NoMatch; + Parser.Lex(); // Eat the '{' + + const MCExpr *Expr; + SMLoc Loc = Parser.getTok().getLoc(); + if (getParser().ParseExpression(Expr)) { + Error(Loc, "illegal expression"); + return MatchOperand_ParseFail; + } + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr); + if (!CE || CE->getValue() < 0 || CE->getValue() > 255) { + Error(Loc, "coprocessor option must be an immediate in range [0, 255]"); + return MatchOperand_ParseFail; + } + int Val = CE->getValue(); + + // Check for and consume the closing '}' + if (Parser.getTok().isNot(AsmToken::RCurly)) + return MatchOperand_ParseFail; + SMLoc E = Parser.getTok().getLoc(); + Parser.Lex(); // Eat the '}' + + Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E)); + return MatchOperand_Success; +} + // For register list parsing, we need to map from raw GPR register numbering // to the enumeration values. The enumeration values aren't sorted by // register number due to our using "sp", "lr" and "pc" as canonical names. |