diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 5 | ||||
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 78 |
2 files changed, 83 insertions, 0 deletions
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 6527e72642..1061fbdbb3 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -397,11 +397,16 @@ def rot_imm_XFORM: SDNodeXForm<imm, [{ case 24: return CurDAG->getTargetConstant(3, MVT::i32); } }]>; +def RotImmAsmOperand : AsmOperandClass { + let Name = "RotImm"; + let ParserMethod = "parseRotImm"; +} def rot_imm : Operand<i32>, PatLeaf<(i32 imm), [{ int32_t v = N->getZExtValue(); return v == 8 || v == 16 || v == 24; }], rot_imm_XFORM> { let PrintMethod = "printRotImmOperand"; + let ParserMatchClass = RotImmAsmOperand; } // shift_imm: An integer that encodes a shift amount and the type of shift diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index b2c14a1c9b..a2df19f8f4 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -124,6 +124,7 @@ class ARMAsmParser : public MCTargetAsmParser { } OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&); OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&); + OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&); // Asm Match Converter Methods bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode, @@ -187,6 +188,7 @@ class ARMOperand : public MCParsedAsmOperand { ShiftedRegister, ShiftedImmediate, ShifterImmediate, + RotateImmediate, Token } Kind; @@ -260,6 +262,9 @@ class ARMOperand : public MCParsedAsmOperand { unsigned SrcReg; unsigned ShiftImm; } RegShiftedImm; + struct { + unsigned Imm; + } RotImm; }; ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} @@ -312,6 +317,9 @@ public: case ShiftedImmediate: RegShiftedImm = o.RegShiftedImm; break; + case RotateImmediate: + RotImm = o.RotImm; + break; } } @@ -531,6 +539,7 @@ public: bool isShifterImm() const { return Kind == ShifterImmediate; } bool isRegShiftedReg() const { return Kind == ShiftedRegister; } bool isRegShiftedImm() const { return Kind == ShiftedImmediate; } + bool isRotImm() const { return Kind == RotateImmediate; } bool isMemMode2() const { if (getMemAddrMode() != ARMII::AddrMode2) return false; @@ -701,6 +710,12 @@ public: addRegListOperands(Inst, N); } + void addRotImmOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + // Encoded as val>>3. The printer handles display as 8, 16, 24. + Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3)); + } + void addImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); addExpr(Inst, getImm()); @@ -1008,6 +1023,14 @@ public: return Op; } + static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) { + ARMOperand *Op = new ARMOperand(RotateImmediate); + Op->RotImm.Imm = Imm; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + static ARMOperand * CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs, SMLoc StartLoc, SMLoc EndLoc) { @@ -1183,6 +1206,9 @@ void ARMOperand::print(raw_ostream &OS) const { << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm) << ">"; break; + case RotateImmediate: + OS << "<ror " << " #" << (RotImm.Imm * 8) << ">"; + break; case RegisterList: case DPRRegisterList: case SPRRegisterList: { @@ -1810,6 +1836,58 @@ parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { return MatchOperand_Success; } +/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family +/// of instructions. Legal values are: +/// ror #n 'n' in {0, 8, 16, 24} +ARMAsmParser::OperandMatchResultTy ARMAsmParser:: +parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + const AsmToken &Tok = Parser.getTok(); + SMLoc S = Tok.getLoc(); + if (Tok.isNot(AsmToken::Identifier)) { + Error(S, "rotate operator 'ror' expected"); + return MatchOperand_ParseFail; + } + StringRef ShiftName = Tok.getString(); + if (ShiftName != "ror" && ShiftName != "ROR") { + Error(S, "rotate operator 'ror' expected"); + return MatchOperand_ParseFail; + } + Parser.Lex(); // Eat the operator. + + // A '#' and a rotate amount. + if (Parser.getTok().isNot(AsmToken::Hash)) { + Error(Parser.getTok().getLoc(), "'#' expected"); + return MatchOperand_ParseFail; + } + Parser.Lex(); // Eat hash token. + + const MCExpr *ShiftAmount; + SMLoc E = Parser.getTok().getLoc(); + if (getParser().ParseExpression(ShiftAmount)) { + Error(E, "malformed rotate expression"); + return MatchOperand_ParseFail; + } + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount); + if (!CE) { + Error(E, "rotate amount must be an immediate"); + return MatchOperand_ParseFail; + } + + int64_t Val = CE->getValue(); + // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension) + // normally, zero is represented in asm by omitting the rotate operand + // entirely. + if (Val != 8 && Val != 16 && Val != 24 && Val != 0) { + Error(E, "'ror' rotate amount must be 8, 16, or 24"); + return MatchOperand_ParseFail; + } + + E = Parser.getTok().getLoc(); + Operands.push_back(ARMOperand::CreateRotImm(Val, S, E)); + + return MatchOperand_Success; +} + /// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst. /// Needed here because the Asm Gen Matcher can't handle properly tied operands /// when they refer multiple MIOperands inside a single one. |