[llvm-commits] [llvm] r135049 - in /llvm/trunk: lib/Target/ARM/ARMInstrInfo.td lib/Target/ARM/AsmParser/ARMAsmParser.cpp lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp test/MC/ARM/basic-arm-instructions.s
Jim Grosbach
grosbach at apple.com
Wed Jul 13 10:50:29 PDT 2011
Author: grosbach
Date: Wed Jul 13 12:50:29 2011
New Revision: 135049
URL: http://llvm.org/viewvc/llvm-project?rev=135049&view=rev
Log:
Flesh out ARM Parser support for shifted-register operands.
Now works for parsing register shifted register and register shifted
immediate arithmetic instructions, including the 'rrx' rotate with extend.
Modified:
llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
llvm/trunk/test/MC/ARM/basic-arm-instructions.s
Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=135049&r1=135048&r2=135049&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Wed Jul 13 12:50:29 2011
@@ -412,14 +412,20 @@
let ParserMatchClass = ShifterAsmOperand;
}
+def ShiftedRegAsmOperand : AsmOperandClass {
+ let Name = "ShiftedReg";
+}
+
// shifter_operand operands: so_reg and so_imm.
def so_reg : Operand<i32>, // reg reg imm
ComplexPattern<i32, 3, "SelectShifterOperandReg",
[shl,srl,sra,rotr]> {
let EncoderMethod = "getSORegOpValue";
let PrintMethod = "printSORegOperand";
+ let ParserMatchClass = ShiftedRegAsmOperand;
let MIOperandInfo = (ops GPR, GPR, shift_imm);
}
+// FIXME: Does this need to be distinct from so_reg?
def shift_so_reg : Operand<i32>, // reg reg imm
ComplexPattern<i32, 3, "SelectShiftShifterOperandReg",
[shl,srl,sra,rotr]> {
Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=135049&r1=135048&r2=135049&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Wed Jul 13 12:50:29 2011
@@ -164,6 +164,7 @@
RegisterList,
DPRRegisterList,
SPRRegisterList,
+ ShiftedRegister,
Shifter,
Token
} Kind;
@@ -225,8 +226,14 @@
struct {
ARM_AM::ShiftOpc ShiftTy;
- unsigned RegNum;
+ unsigned Imm;
} Shift;
+ struct {
+ ARM_AM::ShiftOpc ShiftTy;
+ unsigned SrcReg;
+ unsigned ShiftReg;
+ unsigned ShiftImm;
+ } ShiftedReg;
};
ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
@@ -273,6 +280,9 @@
case Shifter:
Shift = o.Shift;
break;
+ case ShiftedRegister:
+ ShiftedReg = o.ShiftedReg;
+ break;
}
}
@@ -392,6 +402,7 @@
bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; }
bool isMemory() const { return Kind == Memory; }
bool isShifter() const { return Kind == Shifter; }
+ bool isShiftedReg() const { return Kind == ShiftedRegister; }
bool isMemMode2() const {
if (getMemAddrMode() != ARMII::AddrMode2)
return false;
@@ -522,6 +533,18 @@
Inst.addOperand(MCOperand::CreateReg(getReg()));
}
+ void addShiftedRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 3 && "Invalid number of operands!");
+ assert(isShiftedReg() && "addShiftedRegOperands() on non ShiftedReg!");
+ assert((ShiftedReg.ShiftReg == 0 ||
+ ARM_AM::getSORegOffset(ShiftedReg.ShiftImm) == 0) &&
+ "Invalid shifted register operand!");
+ Inst.addOperand(MCOperand::CreateReg(ShiftedReg.SrcReg));
+ Inst.addOperand(MCOperand::CreateReg(ShiftedReg.ShiftReg));
+ Inst.addOperand(MCOperand::CreateImm(
+ ARM_AM::getSORegOpc(ShiftedReg.ShiftTy, ShiftedReg.ShiftImm)));
+ }
+
void addShifterOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateImm(
@@ -743,6 +766,21 @@
return Op;
}
+ static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
+ unsigned SrcReg,
+ unsigned ShiftReg,
+ unsigned ShiftImm,
+ SMLoc S, SMLoc E) {
+ ARMOperand *Op = new ARMOperand(ShiftedRegister);
+ Op->ShiftedReg.ShiftTy = ShTy;
+ Op->ShiftedReg.SrcReg = SrcReg;
+ Op->ShiftedReg.ShiftReg = ShiftReg;
+ Op->ShiftedReg.ShiftImm = ShiftImm;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
static ARMOperand *CreateShifter(ARM_AM::ShiftOpc ShTy,
SMLoc S, SMLoc E) {
ARMOperand *Op = new ARMOperand(Shifter);
@@ -907,7 +945,15 @@
OS << "<register " << getReg() << ">";
break;
case Shifter:
- OS << "<shifter " << getShiftOpcStr(Shift.ShiftTy) << ">";
+ OS << "<shifter " << ARM_AM::getShiftOpcStr(Shift.ShiftTy) << ">";
+ break;
+ case ShiftedRegister:
+ OS << "<so_reg"
+ << ShiftedReg.SrcReg
+ << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(ShiftedReg.ShiftImm))
+ << ", " << ShiftedReg.ShiftReg << ", "
+ << ARM_AM::getSORegOffset(ShiftedReg.ShiftImm)
+ << ">";
break;
case RegisterList:
case DPRRegisterList:
@@ -994,13 +1040,56 @@
if (ShiftTy == ARM_AM::no_shift)
return true;
- Parser.Lex(); // Eat shift-type operand;
- int RegNum = TryParseRegister();
- if (RegNum == -1)
- return Error(Parser.getTok().getLoc(), "register expected");
+ Parser.Lex(); // Eat the operator.
+
+ // The source register for the shift has already been added to the
+ // operand list, so we need to pop it off and combine it into the shifted
+ // register operand instead.
+ ARMOperand *PrevOp = (ARMOperand*)Operands.pop_back_val();
+ if (!PrevOp->isReg())
+ return Error(PrevOp->getStartLoc(), "shift must be of a register");
+ int SrcReg = PrevOp->getReg();
+ int64_t Imm = 0;
+ int ShiftReg = 0;
+ if (ShiftTy == ARM_AM::rrx) {
+ // RRX Doesn't have an explicit shift amount. The encoder expects
+ // the shift register to be the same as the source register. Seems odd,
+ // but OK.
+ ShiftReg = SrcReg;
+ } else {
+ // Figure out if this is shifted by a constant or a register (for non-RRX).
+ if (Parser.getTok().is(AsmToken::Hash)) {
+ Parser.Lex(); // Eat hash.
+ SMLoc ImmLoc = Parser.getTok().getLoc();
+ const MCExpr *ShiftExpr = 0;
+ if (getParser().ParseExpression(ShiftExpr))
+ return Error(ImmLoc, "invalid immediate shift value");
+ // The expression must be evaluatable as an immediate.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
+ if (!CE)
+ return Error(ImmLoc, "invalid immediate shift value");
+ // Range check the immediate.
+ // lsl, ror: 0 <= imm <= 31
+ // lsr, asr: 0 <= imm <= 32
+ Imm = CE->getValue();
+ if (Imm < 0 ||
+ ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
+ ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
+ return Error(ImmLoc, "immediate shift value out of range");
+ }
+ } else if (Parser.getTok().is(AsmToken::Identifier)) {
+ ShiftReg = TryParseRegister();
+ SMLoc L = Parser.getTok().getLoc();
+ if (ShiftReg == -1)
+ return Error (L, "expected immediate or register in shift operand");
+ } else
+ return Error (Parser.getTok().getLoc(),
+ "expected immediate or register in shift operand");
+ }
+
- Operands.push_back(ARMOperand::CreateReg(RegNum,S, Parser.getTok().getLoc()));
- Operands.push_back(ARMOperand::CreateShifter(ShiftTy,
+ Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
+ ShiftReg, Imm,
S, Parser.getTok().getLoc()));
return false;
Modified: llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp?rev=135049&r1=135048&r2=135049&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp (original)
+++ llvm/trunk/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp Wed Jul 13 12:50:29 2011
@@ -142,6 +142,8 @@
// Print the shift opc.
ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
+ if (ShOpc == ARM_AM::rrx)
+ return;
if (MO2.getReg()) {
O << ' ' << getRegisterName(MO2.getReg());
assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
Modified: llvm/trunk/test/MC/ARM/basic-arm-instructions.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/basic-arm-instructions.s?rev=135049&r1=135048&r2=135049&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/basic-arm-instructions.s (original)
+++ llvm/trunk/test/MC/ARM/basic-arm-instructions.s Wed Jul 13 12:50:29 2011
@@ -1,6 +1,13 @@
@ RUN: llvm-mc -triple=armv7-apple-darwin -show-encoding < %s | FileCheck %s
.syntax unified
.globl _func
+
+@ Check that the assembler can handle the documented syntax from the ARM ARM.
+@ For complex constructs like shifter operands, check more thoroughly for them
+@ once then spot check that following instructions accept the form generally.
+@ This gives us good coverage while keeping the overall size of the test
+@ more reasonable.
+
_func:
@ CHECK: _func
@@ -31,3 +38,44 @@
@ CHECK: adcs r1, r2, #3840 @ encoding: [0x0f,0x1c,0xb2,0xe2]
@ CHECK: adcseq r1, r2, #3840 @ encoding: [0x0f,0x1c,0xb2,0x02]
@ CHECK: adceq r1, r2, #3840 @ encoding: [0x0f,0x1c,0xa2,0x02]
+
+@ ADC (register)
+ adc r4, r5, r6
+ @ Constant shifts
+ adc r4, r5, r6, lsl #1
+ adc r4, r5, r6, lsl #31
+ adc r4, r5, r6, lsr #1
+ adc r4, r5, r6, lsr #31
+ adc r4, r5, r6, lsr #32
+ adc r4, r5, r6, asr #1
+ adc r4, r5, r6, asr #31
+ adc r4, r5, r6, asr #32
+ adc r4, r5, r6, ror #1
+ adc r4, r5, r6, ror #31
+
+ @ Register shifts
+ adc r6, r7, r8, lsl r9
+ adc r6, r7, r8, lsr r9
+ adc r6, r7, r8, asr r9
+ adc r6, r7, r8, ror r9
+ adc r4, r5, r6, rrx
+
+@ CHECK: adc r4, r5, r6 @ encoding: [0x06,0x40,0xa5,0xe0]
+
+@ CHECK: adc r4, r5, r6, lsl #1 @ encoding: [0x86,0x40,0xa5,0xe0]
+@ CHECK: adc r4, r5, r6, lsl #31 @ encoding: [0x86,0x4f,0xa5,0xe0]
+@ CHECK: adc r4, r5, r6, lsr #1 @ encoding: [0xa6,0x40,0xa5,0xe0]
+@ CHECK: adc r4, r5, r6, lsr #31 @ encoding: [0xa6,0x4f,0xa5,0xe0]
+@ CHECK: adc r4, r5, r6, lsr #32 @ encoding: [0x26,0x40,0xa5,0xe0]
+@ CHECK: adc r4, r5, r6, asr #1 @ encoding: [0xc6,0x40,0xa5,0xe0]
+@ CHECK: adc r4, r5, r6, asr #31 @ encoding: [0xc6,0x4f,0xa5,0xe0]
+@ CHECK: adc r4, r5, r6, asr #32 @ encoding: [0x46,0x40,0xa5,0xe0]
+@ CHECK: adc r4, r5, r6, ror #1 @ encoding: [0xe6,0x40,0xa5,0xe0]
+@ CHECK: adc r4, r5, r6, ror #31 @ encoding: [0xe6,0x4f,0xa5,0xe0]
+
+@ CHECK: adc r6, r7, r8, lsl r9 @ encoding: [0x18,0x69,0xa7,0xe0]
+@ CHECK: adc r6, r7, r8, lsr r9 @ encoding: [0x38,0x69,0xa7,0xe0]
+@ CHECK: adc r6, r7, r8, asr r9 @ encoding: [0x58,0x69,0xa7,0xe0]
+@ CHECK: adc r6, r7, r8, ror r9 @ encoding: [0x78,0x69,0xa7,0xe0]
+@ CHECK: adc r4, r5, r6, rrx @ encoding: [0x66,0x40,0xa5,0xe0]
+
More information about the llvm-commits
mailing list