diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 6527e72642f..1061fbdbb33 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -397,11 +397,16 @@ def rot_imm_XFORM: SDNodeXFormgetTargetConstant(3, MVT::i32); } }]>; +def RotImmAsmOperand : AsmOperandClass { + let Name = "RotImm"; + let ParserMethod = "parseRotImm"; +} def rot_imm : Operand, 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 b2c14a1c9b0..a2df19f8f49 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&); OperandMatchResultTy parseShifterImm(SmallVectorImpl&); + OperandMatchResultTy parseRotImm(SmallVectorImpl&); // 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 > &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 << ""; + break; case RegisterList: case DPRRegisterList: case SPRRegisterList: { @@ -1810,6 +1836,58 @@ parseShifterImm(SmallVectorImpl &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 &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(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. diff --git a/test/MC/ARM/basic-arm-instructions.s b/test/MC/ARM/basic-arm-instructions.s index 0cd59346d0f..8232d1d108a 100644 --- a/test/MC/ARM/basic-arm-instructions.s +++ b/test/MC/ARM/basic-arm-instructions.s @@ -1802,3 +1802,115 @@ _func: @ CHECK: swp r1, r2, [r3] @ encoding: [0x92,0x10,0x03,0xe1] @ CHECK: swp r4, r4, [r6] @ encoding: [0x94,0x40,0x06,0xe1] @ CHECK: swpb r5, r1, [r9] @ encoding: [0x91,0x50,0x49,0xe1] + + +@------------------------------------------------------------------------------ +@ SXTAB +@------------------------------------------------------------------------------ + sxtab r2, r3, r4 + sxtab r4, r5, r6, ror #0 + sxtablt r6, r2, r9, ror #8 + sxtab r5, r1, r4, ror #16 + sxtab r7, r8, r3, ror #24 + +@ CHECK: sxtab r2, r3, r4 @ encoding: [0x74,0x20,0xa3,0xe6] +@ CHECK: sxtab r4, r5, r6 @ encoding: [0x76,0x40,0xa5,0xe6] +@ CHECK: sxtablt r6, r2, r9, ror #8 + @ encoding: [0x79,0x64,0xa2,0xb6] +@ CHECK: sxtab r5, r1, r4, ror #16 + @ encoding: [0x74,0x58,0xa1,0xe6] +@ CHECK: sxtab r7, r8, r3, ror #24 + @ encoding: [0x73,0x7c,0xa8,0xe6] + + +@------------------------------------------------------------------------------ +@ SXTAB16 +@------------------------------------------------------------------------------ + sxtab16ge r0, r1, r4 + sxtab16 r6, r2, r7, ror #0 + sxtab16 r3, r5, r8, ror #8 + sxtab16 r3, r2, r1, ror #16 + sxtab16eq r1, r2, r3, ror #24 + +@ CHECK: sxtab16ge r0, r1, r4 @ encoding: [0x74,0x00,0x81,0xa6] +@ CHECK: sxtab16 r6, r2, r7 @ encoding: [0x77,0x60,0x82,0xe6] +@ CHECK: sxtab16 r3, r5, r8, ror #8 + @ encoding: [0x78,0x34,0x85,0xe6] +@ CHECK: sxtab16 r3, r2, r1, ror #16 + @ encoding: [0x71,0x38,0x82,0xe6] +@ CHECK: sxtab16eq r1, r2, r3, ror #24 + @ encoding: [0x73,0x1c,0x82,0x06] + +@------------------------------------------------------------------------------ +@ SXTAH +@------------------------------------------------------------------------------ + sxtah r1, r3, r9 + sxtahhi r6, r1, r6, ror #0 + sxtah r3, r8, r3, ror #8 + sxtahlo r2, r2, r4, ror #16 + sxtah r9, r3, r3, ror #24 + +@ CHECK: sxtah r1, r3, r9 @ encoding: [0x79,0x10,0xb3,0xe6] +@ CHECK: sxtahhi r6, r1, r6 @ encoding: [0x76,0x60,0xb1,0x86] +@ CHECK: sxtah r3, r8, r3, ror #8 + @ encoding: [0x73,0x34,0xb8,0xe6] +@ CHECK: sxtahlo r2, r2, r4, ror #16 + @ encoding: [0x74,0x28,0xb2,0x36] +@ CHECK: sxtah r9, r3, r3, ror #24 + @ encoding: [0x73,0x9c,0xb3,0xe6] + +@------------------------------------------------------------------------------ +@ SXTB +@------------------------------------------------------------------------------ + sxtbge r2, r4 + sxtb r5, r6, ror #0 + sxtb r6, r9, ror #8 + sxtbcc r5, r1, ror #16 + sxtb r8, r3, ror #24 + +@ CHECK: sxtbge r2, r4 @ encoding: [0x74,0x20,0xaf,0xa6] +@ CHECK: sxtb r5, r6 @ encoding: [0x76,0x50,0xaf,0xe6] +@ CHECK: sxtb r6, r9, ror #8 + @ encoding: [0x79,0x64,0xaf,0xe6] +@ CHECK: sxtblo r5, r1, ror #16 + @ encoding: [0x71,0x58,0xaf,0x36] +@ CHECK: sxtb r8, r3, ror #24 + @ encoding: [0x73,0x8c,0xaf,0xe6] + + +@------------------------------------------------------------------------------ +@ SXTB16 +@------------------------------------------------------------------------------ + sxtb16 r1, r4 + sxtb16 r6, r7, ror #0 + sxtb16cs r3, r5, ror #8 + sxtb16 r3, r1, ror #16 + sxtb16ge r2, r3, ror #24 + +@ CHECK: sxtb16 r1, r4 @ encoding: [0x74,0x10,0x8f,0xe6] +@ CHECK: sxtb16 r6, r7 @ encoding: [0x77,0x60,0x8f,0xe6] +@ CHECK: sxtb16hs r3, r5, ror #8 + @ encoding: [0x75,0x34,0x8f,0x26] +@ CHECK: sxtb16 r3, r1, ror #16 + @ encoding: [0x71,0x38,0x8f,0xe6] +@ CHECK: sxtb16ge r2, r3, ror #24 + @ encoding: [0x73,0x2c,0x8f,0xa6] + + +@------------------------------------------------------------------------------ +@ SXTH +@------------------------------------------------------------------------------ + sxthne r3, r9 + sxth r1, r6, ror #0 + sxth r3, r8, ror #8 + sxthle r2, r2, ror #16 + sxth r9, r3, ror #24 + +@ CHECK: sxthne r3, r9 @ encoding: [0x79,0x30,0xbf,0x16] +@ CHECK: sxth r1, r6 @ encoding: [0x76,0x10,0xbf,0xe6] +@ CHECK: sxth r3, r8, ror #8 + @ encoding: [0x78,0x34,0xbf,0xe6] +@ CHECK: sxthle r2, r2, ror #16 + @ encoding: [0x72,0x28,0xbf,0xd6] +@ CHECK: sxth r9, r3, ror #24 + @ encoding: [0x73,0x9c,0xbf,0xe6] diff --git a/test/MC/ARM/diagnostics.s b/test/MC/ARM/diagnostics.s index c8ca0593e7b..e086128f420 100644 --- a/test/MC/ARM/diagnostics.s +++ b/test/MC/ARM/diagnostics.s @@ -238,3 +238,37 @@ @ CHECK-ERRORS: error: source operands must be sequential @ CHECK-ERRORS: strexd r6, r5, r3, [r8] @ CHECK-ERRORS: ^ + + @ Illegal rotate operators for extend instructions + sxtb r8, r3, #8 + sxtb r8, r3, ror 24 + sxtb r8, r3, ror #8 - + sxtab r3, r8, r3, ror #(fred - wilma) + sxtab r7, r8, r3, ror #25 + sxtah r9, r3, r3, ror #-8 + sxtb16ge r2, r3, lsr #24 + +@ CHECK-ERRORS: error: rotate operator 'ror' expected +@ CHECK-ERRORS: sxtb r8, r3, #8 +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: '#' expected +@ CHECK-ERRORS: sxtb r8, r3, ror 24 +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: unknown token in expression +@ CHECK-ERRORS: sxtb r8, r3, ror #8 - +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: malformed rotate expression +@ CHECK-ERRORS: sxtb r8, r3, ror #8 - +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: rotate amount must be an immediate +@ CHECK-ERRORS: sxtab r3, r8, r3, ror #(fred - wilma) +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: 'ror' rotate amount must be 8, 16, or 24 +@ CHECK-ERRORS: sxtab r7, r8, r3, ror #25 +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: 'ror' rotate amount must be 8, 16, or 24 +@ CHECK-ERRORS: sxtah r9, r3, r3, ror #-8 +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: rotate operator 'ror' expected +@ CHECK-ERRORS: sxtb16ge r2, r3, lsr #24 +@ CHECK-ERRORS: ^