ARM assembly parsing and encoding for extend instructions.

Assembly parser handling for extend instruction rotate operands. Add tests
for the sign extend instructions.

llvm-svn: 136252
This commit is contained in:
Jim Grosbach 2011-07-27 20:15:40 +00:00
parent 9d155aa061
commit 833b9d3353
4 changed files with 229 additions and 0 deletions

View File

@ -397,11 +397,16 @@ def rot_imm_XFORM: SDNodeXForm<imm, [{
case 24: return CurDAG->getTargetConstant(3, MVT::i32); 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), [{ def rot_imm : Operand<i32>, PatLeaf<(i32 imm), [{
int32_t v = N->getZExtValue(); int32_t v = N->getZExtValue();
return v == 8 || v == 16 || v == 24; }], return v == 8 || v == 16 || v == 24; }],
rot_imm_XFORM> { rot_imm_XFORM> {
let PrintMethod = "printRotImmOperand"; let PrintMethod = "printRotImmOperand";
let ParserMatchClass = RotImmAsmOperand;
} }
// shift_imm: An integer that encodes a shift amount and the type of shift // shift_imm: An integer that encodes a shift amount and the type of shift

View File

@ -124,6 +124,7 @@ class ARMAsmParser : public MCTargetAsmParser {
} }
OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&); OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&); OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
// Asm Match Converter Methods // Asm Match Converter Methods
bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode, bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
@ -187,6 +188,7 @@ class ARMOperand : public MCParsedAsmOperand {
ShiftedRegister, ShiftedRegister,
ShiftedImmediate, ShiftedImmediate,
ShifterImmediate, ShifterImmediate,
RotateImmediate,
Token Token
} Kind; } Kind;
@ -260,6 +262,9 @@ class ARMOperand : public MCParsedAsmOperand {
unsigned SrcReg; unsigned SrcReg;
unsigned ShiftImm; unsigned ShiftImm;
} RegShiftedImm; } RegShiftedImm;
struct {
unsigned Imm;
} RotImm;
}; };
ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
@ -312,6 +317,9 @@ public:
case ShiftedImmediate: case ShiftedImmediate:
RegShiftedImm = o.RegShiftedImm; RegShiftedImm = o.RegShiftedImm;
break; break;
case RotateImmediate:
RotImm = o.RotImm;
break;
} }
} }
@ -531,6 +539,7 @@ public:
bool isShifterImm() const { return Kind == ShifterImmediate; } bool isShifterImm() const { return Kind == ShifterImmediate; }
bool isRegShiftedReg() const { return Kind == ShiftedRegister; } bool isRegShiftedReg() const { return Kind == ShiftedRegister; }
bool isRegShiftedImm() const { return Kind == ShiftedImmediate; } bool isRegShiftedImm() const { return Kind == ShiftedImmediate; }
bool isRotImm() const { return Kind == RotateImmediate; }
bool isMemMode2() const { bool isMemMode2() const {
if (getMemAddrMode() != ARMII::AddrMode2) if (getMemAddrMode() != ARMII::AddrMode2)
return false; return false;
@ -701,6 +710,12 @@ public:
addRegListOperands(Inst, N); 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 { void addImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!"); assert(N == 1 && "Invalid number of operands!");
addExpr(Inst, getImm()); addExpr(Inst, getImm());
@ -1008,6 +1023,14 @@ public:
return Op; 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 * static ARMOperand *
CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs, CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
SMLoc StartLoc, SMLoc EndLoc) { SMLoc StartLoc, SMLoc EndLoc) {
@ -1183,6 +1206,9 @@ void ARMOperand::print(raw_ostream &OS) const {
<< ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm) << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
<< ">"; << ">";
break; break;
case RotateImmediate:
OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
break;
case RegisterList: case RegisterList:
case DPRRegisterList: case DPRRegisterList:
case SPRRegisterList: { case SPRRegisterList: {
@ -1810,6 +1836,58 @@ parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_Success; 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. /// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
/// Needed here because the Asm Gen Matcher can't handle properly tied operands /// Needed here because the Asm Gen Matcher can't handle properly tied operands
/// when they refer multiple MIOperands inside a single one. /// when they refer multiple MIOperands inside a single one.

View File

@ -1802,3 +1802,115 @@ _func:
@ CHECK: swp r1, r2, [r3] @ encoding: [0x92,0x10,0x03,0xe1] @ CHECK: swp r1, r2, [r3] @ encoding: [0x92,0x10,0x03,0xe1]
@ CHECK: swp r4, r4, [r6] @ encoding: [0x94,0x40,0x06,0xe1] @ CHECK: swp r4, r4, [r6] @ encoding: [0x94,0x40,0x06,0xe1]
@ CHECK: swpb r5, r1, [r9] @ encoding: [0x91,0x50,0x49,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]

View File

@ -238,3 +238,37 @@
@ CHECK-ERRORS: error: source operands must be sequential @ CHECK-ERRORS: error: source operands must be sequential
@ CHECK-ERRORS: strexd r6, r5, r3, [r8] @ CHECK-ERRORS: strexd r6, r5, r3, [r8]
@ CHECK-ERRORS: ^ @ 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: ^