diff options
| -rw-r--r-- | llvm/lib/Target/ARM/ARMInstrInfo.td | 16 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 71 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.h | 1 | ||||
| -rw-r--r-- | llvm/test/MC/ARM/basic-arm-instructions.s | 4 | ||||
| -rw-r--r-- | llvm/test/MC/ARM/diagnostics.s | 10 | ||||
| -rw-r--r-- | llvm/utils/TableGen/EDEmitter.cpp | 1 | 
7 files changed, 99 insertions, 9 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td index d43da911e22..2cf0f09ffc6 100644 --- a/llvm/lib/Target/ARM/ARMInstrInfo.td +++ b/llvm/lib/Target/ARM/ARMInstrInfo.td @@ -842,6 +842,14 @@ def c_imm : Operand<i32> {    let PrintMethod = "printCImmediate";    let ParserMatchClass = CoprocRegAsmOperand;  } +def CoprocOptionAsmOperand : AsmOperandClass { +  let Name = "CoprocOption"; +  let ParserMethod = "parseCoprocOptionOperand"; +} +def coproc_option_imm : Operand<i32> { +  let PrintMethod = "printCoprocOptionImm"; +  let ParserMatchClass = CoprocOptionAsmOperand; +}  //===----------------------------------------------------------------------===// @@ -4312,8 +4320,8 @@ multiclass LdStCop<bit load, bit Dbit, string asm> {    }    def _OPTION : ACI<(outs),                      (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr, -                         nohash_imm:$option), -      asm, "\t$cop, $CRd, $addr, \\{$option\\}"> { +                         coproc_option_imm:$option), +      asm, "\t$cop, $CRd, $addr, $option"> {      bits<8> option;      bits<4> addr;      bits<4> cop; @@ -4383,8 +4391,8 @@ multiclass LdSt2Cop<bit load, bit Dbit, string asm> {    }    def _OPTION : ACInoP<(outs),                         (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr, -                            nohash_imm:$option), -      asm, "\t$cop, $CRd, $addr, \\{$option\\}"> { +                            coproc_option_imm:$option), +      asm, "\t$cop, $CRd, $addr, $option"> {      bits<8> option;      bits<4> addr;      bits<4> cop; 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. diff --git a/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index 81608922842..ccdac3ebeb4 100644 --- a/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -719,6 +719,11 @@ void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum,    O << "c" << MI->getOperand(OpNum).getImm();  } +void ARMInstPrinter::printCoprocOptionImm(const MCInst *MI, unsigned OpNum, +                                          raw_ostream &O) { +  O << "{" << MI->getOperand(OpNum).getImm() << "}"; +} +  void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,                                    raw_ostream &O) {    llvm_unreachable("Unhandled PC-relative pseudo-instruction!"); diff --git a/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.h b/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.h index 61b26e67924..5c2173fcde6 100644 --- a/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.h +++ b/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.h @@ -120,6 +120,7 @@ public:    void printNoHashImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O);    void printPImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O);    void printCImmediate(const MCInst *MI, unsigned OpNum, raw_ostream &O); +  void printCoprocOptionImm(const MCInst *MI, unsigned OpNum, raw_ostream &O);    void printFPImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);    void printNEONModImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);    void printImmPlusOneOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); diff --git a/llvm/test/MC/ARM/basic-arm-instructions.s b/llvm/test/MC/ARM/basic-arm-instructions.s index 04054e95c0e..8b4c0536c95 100644 --- a/llvm/test/MC/ARM/basic-arm-instructions.s +++ b/llvm/test/MC/ARM/basic-arm-instructions.s @@ -684,6 +684,8 @@ Lforward:          ldcleq p6, c14, [r10], #16          ldclhi p7, c15, [r11], #-72 +        ldc2 p2, c8, [r1], { 25 } +  @ CHECK: ldc2	p0, c8, [r1, #4]        @ encoding: [0x01,0x80,0x91,0xfd]  @ CHECK: ldc2	p1, c7, [r2]            @ encoding: [0x00,0x71,0x92,0xfd]  @ CHECK: ldc2	p2, c6, [r3, #-224]     @ encoding: [0x38,0x62,0x13,0xfd] @@ -723,6 +725,8 @@ Lforward:  @ CHECK: ldcleq	p6, c14, [r10], #16     @ encoding: [0x04,0xe6,0xfa,0x0c]  @ CHECK: ldclhi	p7, c15, [r11], #-72    @ encoding: [0x12,0xf7,0x7b,0x8c] +@ CHECK: ldc2	p2, c8, [r1], {25}      @ encoding: [0x19,0x82,0x91,0xfc] +  @------------------------------------------------------------------------------  @ LDM* diff --git a/llvm/test/MC/ARM/diagnostics.s b/llvm/test/MC/ARM/diagnostics.s index 41dde080522..f722dd7c070 100644 --- a/llvm/test/MC/ARM/diagnostics.s +++ b/llvm/test/MC/ARM/diagnostics.s @@ -305,3 +305,13 @@  @ CHECK-ERRORS:         vpush {s0, s3}  @ CHECK-ERRORS:                    ^ +        @ Out of range coprocessor option immediate. +        ldc2 p2, c8, [r1], { 256 } +        ldc2 p2, c8, [r1], { -1 } + +@ CHECK-ERRORS: error: coprocessor option must be an immediate in range [0, 255] +@ CHECK-ERRORS:         ldc2 p2, c8, [r1], { 256 } +@ CHECK-ERRORS:                              ^ +@ CHECK-ERRORS: error: coprocessor option must be an immediate in range [0, 255] +@ CHECK-ERRORS:         ldc2 p2, c8, [r1], { -1 } +@ CHECK-ERRORS:                              ^ diff --git a/llvm/utils/TableGen/EDEmitter.cpp b/llvm/utils/TableGen/EDEmitter.cpp index a38f0066d98..abef70e3189 100644 --- a/llvm/utils/TableGen/EDEmitter.cpp +++ b/llvm/utils/TableGen/EDEmitter.cpp @@ -581,6 +581,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,    IMM("nohash_imm");    IMM("p_imm");    IMM("c_imm"); +  IMM("coproc_option_imm");    IMM("imod_op");    IMM("iflags_op");    IMM("cpinst_operand");  | 

