aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Grosbach <grosbach@apple.com>2011-07-27 20:15:40 +0000
committerJim Grosbach <grosbach@apple.com>2011-07-27 20:15:40 +0000
commit7e1547ebf726a40e7ed3dbe89a77e1b946a8e2d0 (patch)
treeaf95f5c13d8cb00d5b562d61c484323e7baca50c
parente511186183d49fb9c4ebefe746ca65e5d9275ff4 (diff)
ARM assembly parsing and encoding for extend instructions.
Assembly parser handling for extend instruction rotate operands. Add tests for the sign extend instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136252 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td5
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp78
-rw-r--r--test/MC/ARM/basic-arm-instructions.s112
-rw-r--r--test/MC/ARM/diagnostics.s34
4 files changed, 229 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.
diff --git a/test/MC/ARM/basic-arm-instructions.s b/test/MC/ARM/basic-arm-instructions.s
index 0cd59346d0..8232d1d108 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 c8ca0593e7..e086128f42 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: ^