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 | 483995875f0e23402921e41baced835ee9c913c9 (patch) | |
| tree | de48953203152c7205b61b8a6715b9a8cae7a849 /llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | |
| parent | a5542112d731218b5da6e99cac248fd7ea118bf9 (diff) | |
| download | bcm5719-llvm-483995875f0e23402921e41baced835ee9c913c9.tar.gz bcm5719-llvm-483995875f0e23402921e41baced835ee9c913c9.zip | |
ARM parsing and encoding for the <option> form of LDC/STC instructions.
llvm-svn: 141786
Diffstat (limited to 'llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
| -rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 71 | 
1 files changed, 66 insertions, 5 deletions
| diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index afb6e5684dd..3ce086a0491 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/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. | 

