Initial ARM/Thumb disassembler check-in. It consists of a tablgen backend
(RISCDisassemblerEmitter) which emits the decoder functions for ARM and Thumb,
and the disassembler core which invokes the decoder function and builds up the
MCInst based on the decoded Opcode.
Added sub-formats to the NeonI/NeonXI instructions to further refine the NEONFrm
instructions to help disassembly.
We also changed the output of the addressing modes to omit the '+' from the
assembler syntax #+/-<imm> or +/-<Rm>. See, for example, A8.6.57/58/60.
And modified test cases to not expect '+' in +reg or #+num. For example,
; CHECK: ldr.w r9, [r7, #28]
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98637 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
index 4a4437e..ea299a0 100644
--- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
+++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
@@ -120,7 +120,7 @@
void printT2AddrModeImm8Operand(const MachineInstr *MI, int OpNum);
void printT2AddrModeImm8s4Operand(const MachineInstr *MI, int OpNum);
void printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, int OpNum);
- void printT2AddrModeImm8s4OffsetOperand(const MachineInstr *MI, int OpNum) {}
+ void printT2AddrModeImm8s4OffsetOperand(const MachineInstr *MI, int OpNum);
void printT2AddrModeSoRegOperand(const MachineInstr *MI, int OpNum);
void printCPSOptionOperand(const MachineInstr *MI, int OpNum) {}
@@ -431,16 +431,16 @@
O << "[" << getRegisterName(MO1.getReg());
if (!MO2.getReg()) {
- if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
+ if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
O << ", #"
- << (char)ARM_AM::getAM2Op(MO3.getImm())
+ << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
<< ARM_AM::getAM2Offset(MO3.getImm());
O << "]";
return;
}
O << ", "
- << (char)ARM_AM::getAM2Op(MO3.getImm())
+ << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
<< getRegisterName(MO2.getReg());
if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
@@ -458,12 +458,12 @@
unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
assert(ImmOffs && "Malformed indexed load / store!");
O << "#"
- << (char)ARM_AM::getAM2Op(MO2.getImm())
+ << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
<< ImmOffs;
return;
}
- O << (char)ARM_AM::getAM2Op(MO2.getImm())
+ O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
<< getRegisterName(MO1.getReg());
if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
@@ -490,7 +490,7 @@
if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
O << ", #"
- << (char)ARM_AM::getAM3Op(MO3.getImm())
+ << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
<< ImmOffs;
O << "]";
}
@@ -508,7 +508,7 @@
unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
assert(ImmOffs && "Malformed indexed load / store!");
O << "#"
- << (char)ARM_AM::getAM3Op(MO2.getImm())
+ << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
<< ImmOffs;
}
@@ -558,7 +558,7 @@
if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
O << ", #"
- << (char)ARM_AM::getAM5Op(MO2.getImm())
+ << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
<< ImmOffs*4;
}
O << "]";
@@ -594,7 +594,7 @@
const MachineOperand &MO1 = MI->getOperand(Op);
assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
- O << "[pc, +" << getRegisterName(MO1.getReg()) << "]";
+ O << "[pc, " << getRegisterName(MO1.getReg()) << "]";
}
void
@@ -617,10 +617,11 @@
ARMAsmPrinter::printThumbITMask(const MachineInstr *MI, int Op) {
// (3 - the number of trailing zeros) is the number of then / else.
unsigned Mask = MI->getOperand(Op).getImm();
+ unsigned CondBit0 = Mask >> 4 & 1;
unsigned NumTZ = CountTrailingZeros_32(Mask);
assert(NumTZ <= 3 && "Invalid IT mask!");
for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
- bool T = (Mask & (1 << Pos)) == 0;
+ bool T = ((Mask >> Pos) & 1) == CondBit0;
if (T)
O << 't';
else
@@ -652,7 +653,7 @@
if (MO3.getReg())
O << ", " << getRegisterName(MO3.getReg());
else if (unsigned ImmOffs = MO2.getImm())
- O << ", #+" << ImmOffs * Scale;
+ O << ", #" << ImmOffs * Scale;
O << "]";
}
@@ -674,7 +675,7 @@
const MachineOperand &MO2 = MI->getOperand(Op+1);
O << "[" << getRegisterName(MO1.getReg());
if (unsigned ImmOffs = MO2.getImm())
- O << ", #+" << ImmOffs*4;
+ O << ", #" << ImmOffs*4;
O << "]";
}
@@ -710,7 +711,7 @@
unsigned OffImm = MO2.getImm();
if (OffImm) // Don't print +0.
- O << ", #+" << OffImm;
+ O << ", #" << OffImm;
O << "]";
}
@@ -726,7 +727,7 @@
if (OffImm < 0)
O << ", #-" << -OffImm;
else if (OffImm > 0)
- O << ", #+" << OffImm;
+ O << ", #" << OffImm;
O << "]";
}
@@ -742,7 +743,7 @@
if (OffImm < 0)
O << ", #-" << -OffImm * 4;
else if (OffImm > 0)
- O << ", #+" << OffImm * 4;
+ O << ", #" << OffImm * 4;
O << "]";
}
@@ -754,7 +755,18 @@
if (OffImm < 0)
O << "#-" << -OffImm;
else if (OffImm > 0)
- O << "#+" << OffImm;
+ O << "#" << OffImm;
+}
+
+void ARMAsmPrinter::printT2AddrModeImm8s4OffsetOperand(const MachineInstr *MI,
+ int OpNum) {
+ const MachineOperand &MO1 = MI->getOperand(OpNum);
+ int32_t OffImm = (int32_t)MO1.getImm() / 4;
+ // Don't print +0.
+ if (OffImm < 0)
+ O << "#-" << -OffImm * 4;
+ else if (OffImm > 0)
+ O << "#" << OffImm * 4;
}
void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr *MI,
diff --git a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp
index d4b213a..f8235c9 100644
--- a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp
+++ b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp
@@ -28,7 +28,165 @@
#undef MachineInstr
#undef ARMAsmPrinter
-void ARMInstPrinter::printInst(const MCInst *MI) { printInstruction(MI); }
+static unsigned NextReg(unsigned Reg) {
+ switch (Reg) {
+ case ARM::D0:
+ return ARM::D1;
+ case ARM::D1:
+ return ARM::D2;
+ case ARM::D2:
+ return ARM::D3;
+ case ARM::D3:
+ return ARM::D4;
+ case ARM::D4:
+ return ARM::D5;
+ case ARM::D5:
+ return ARM::D6;
+ case ARM::D6:
+ return ARM::D7;
+ case ARM::D7:
+ return ARM::D8;
+ case ARM::D8:
+ return ARM::D9;
+ case ARM::D9:
+ return ARM::D10;
+ case ARM::D10:
+ return ARM::D11;
+ case ARM::D11:
+ return ARM::D12;
+ case ARM::D12:
+ return ARM::D13;
+ case ARM::D13:
+ return ARM::D14;
+ case ARM::D14:
+ return ARM::D15;
+ case ARM::D15:
+ return ARM::D16;
+ case ARM::D16:
+ return ARM::D17;
+ case ARM::D17:
+ return ARM::D18;
+ case ARM::D18:
+ return ARM::D19;
+ case ARM::D19:
+ return ARM::D20;
+ case ARM::D20:
+ return ARM::D21;
+ case ARM::D21:
+ return ARM::D22;
+ case ARM::D22:
+ return ARM::D23;
+ case ARM::D23:
+ return ARM::D24;
+ case ARM::D24:
+ return ARM::D25;
+ case ARM::D25:
+ return ARM::D26;
+ case ARM::D26:
+ return ARM::D27;
+ case ARM::D27:
+ return ARM::D28;
+ case ARM::D28:
+ return ARM::D29;
+ case ARM::D29:
+ return ARM::D30;
+ case ARM::D30:
+ return ARM::D31;
+
+ default:
+ assert(0 && "Unexpected register enum");
+ }
+}
+
+void ARMInstPrinter::printInst(const MCInst *MI) {
+ // Check for MOVs and print canonical forms, instead.
+ if (MI->getOpcode() == ARM::MOVs) {
+ const MCOperand &Dst = MI->getOperand(0);
+ const MCOperand &MO1 = MI->getOperand(1);
+ const MCOperand &MO2 = MI->getOperand(2);
+ const MCOperand &MO3 = MI->getOperand(3);
+
+ O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
+ printSBitModifierOperand(MI, 6);
+ printPredicateOperand(MI, 4);
+
+ O << '\t' << getRegisterName(Dst.getReg())
+ << ", " << getRegisterName(MO1.getReg());
+
+ if (ARM_AM::getSORegShOp(MO3.getImm()) == ARM_AM::rrx)
+ return;
+
+ O << ", ";
+
+ if (MO2.getReg()) {
+ O << getRegisterName(MO2.getReg());
+ assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
+ } else {
+ O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
+ }
+ return;
+ }
+
+ // A8.6.123 PUSH
+ if ((MI->getOpcode() == ARM::STM || MI->getOpcode() == ARM::t2STM_UPD) &&
+ MI->getOperand(0).getReg() == ARM::SP) {
+ const unsigned IdxOffset = MI->getOpcode() == ARM::STM ? 0 : 1;
+ const MCOperand &MO1 = MI->getOperand(IdxOffset + 1);
+ if (ARM_AM::getAM4WBFlag(MO1.getImm()) &&
+ ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) {
+ O << '\t' << "push";
+ printPredicateOperand(MI, IdxOffset + 2);
+ O << '\t';
+ printRegisterList(MI, IdxOffset + 4);
+ return;
+ }
+ }
+
+ // A8.6.122 POP
+ if ((MI->getOpcode() == ARM::LDM || MI->getOpcode() == ARM::t2LDM_UPD) &&
+ MI->getOperand(0).getReg() == ARM::SP) {
+ const unsigned IdxOffset = MI->getOpcode() == ARM::LDM ? 0 : 1;
+ const MCOperand &MO1 = MI->getOperand(IdxOffset + 1);
+ if (ARM_AM::getAM4WBFlag(MO1.getImm()) &&
+ ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) {
+ O << '\t' << "pop";
+ printPredicateOperand(MI, IdxOffset + 2);
+ O << '\t';
+ printRegisterList(MI, IdxOffset + 4);
+ return;
+ }
+ }
+
+ // A8.6.355 VPUSH
+ if ((MI->getOpcode() == ARM::VSTMS || MI->getOpcode() == ARM::VSTMD) &&
+ MI->getOperand(0).getReg() == ARM::SP) {
+ const MCOperand &MO1 = MI->getOperand(1);
+ if (ARM_AM::getAM5WBFlag(MO1.getImm()) &&
+ ARM_AM::getAM5SubMode(MO1.getImm()) == ARM_AM::db) {
+ O << '\t' << "vpush";
+ printPredicateOperand(MI, 2);
+ O << '\t';
+ printRegisterList(MI, 4);
+ return;
+ }
+ }
+
+ // A8.6.354 VPOP
+ if ((MI->getOpcode() == ARM::VLDMS || MI->getOpcode() == ARM::VLDMD) &&
+ MI->getOperand(0).getReg() == ARM::SP) {
+ const MCOperand &MO1 = MI->getOperand(1);
+ if (ARM_AM::getAM5WBFlag(MO1.getImm()) &&
+ ARM_AM::getAM5SubMode(MO1.getImm()) == ARM_AM::ia) {
+ O << '\t' << "vpop";
+ printPredicateOperand(MI, 2);
+ O << '\t';
+ printRegisterList(MI, 4);
+ return;
+ }
+ }
+
+ printInstruction(MI);
+ }
void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
const char *Modifier) {
@@ -36,6 +194,9 @@
if (Op.isReg()) {
unsigned Reg = Op.getReg();
if (Modifier && strcmp(Modifier, "dregpair") == 0) {
+ O << '{' << getRegisterName(Reg) << ", "
+ << getRegisterName(NextReg(Reg)) << '}';
+#if 0
// FIXME: Breaks e.g. ARM/vmul.ll.
assert(0);
/*
@@ -44,6 +205,7 @@
O << '{'
<< getRegisterName(DRegLo) << ',' << getRegisterName(DRegHi)
<< '}';*/
+#endif
} else if (Modifier && strcmp(Modifier, "lane") == 0) {
assert(0);
/*
@@ -56,7 +218,9 @@
O << getRegisterName(Reg);
}
} else if (Op.isImm()) {
- assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
+ bool isCallOp = Modifier && !strcmp(Modifier, "call");
+ assert(isCallOp ||
+ ((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"));
O << '#' << Op.getImm();
} else {
assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
@@ -142,17 +306,17 @@
O << "[" << getRegisterName(MO1.getReg());
if (!MO2.getReg()) {
- if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
+ if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
O << ", #"
- << (char)ARM_AM::getAM2Op(MO3.getImm())
- << ARM_AM::getAM2Offset(MO3.getImm());
+ << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
+ << ARM_AM::getAM2Offset(MO3.getImm());
O << "]";
return;
}
O << ", "
- << (char)ARM_AM::getAM2Op(MO3.getImm())
- << getRegisterName(MO2.getReg());
+ << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
+ << getRegisterName(MO2.getReg());
if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
O << ", "
@@ -169,11 +333,14 @@
if (!MO1.getReg()) {
unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
assert(ImmOffs && "Malformed indexed load / store!");
- O << '#' << (char)ARM_AM::getAM2Op(MO2.getImm()) << ImmOffs;
+ O << '#'
+ << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
+ << ImmOffs;
return;
}
- O << (char)ARM_AM::getAM2Op(MO2.getImm()) << getRegisterName(MO1.getReg());
+ O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
+ << getRegisterName(MO1.getReg());
if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
O << ", "
@@ -196,8 +363,8 @@
if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
O << ", #"
- << (char)ARM_AM::getAM3Op(MO3.getImm())
- << ImmOffs;
+ << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
+ << ImmOffs;
O << ']';
}
@@ -214,9 +381,9 @@
unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
assert(ImmOffs && "Malformed indexed load / store!");
- O << "#"
- << (char)ARM_AM::getAM3Op(MO2.getImm())
- << ImmOffs;
+ O << '#'
+ << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
+ << ImmOffs;
}
@@ -264,7 +431,7 @@
if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
O << ", #"
- << (char)ARM_AM::getAM5Op(MO2.getImm())
+ << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
<< ImmOffs*4;
}
O << "]";
@@ -303,14 +470,56 @@
void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum) {
O << "{";
- // Always skip the first operand, it's the optional (and implicit writeback).
- for (unsigned i = OpNum+1, e = MI->getNumOperands(); i != e; ++i) {
- if (i != OpNum+1) O << ", ";
+ for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
+ if (i != OpNum) O << ", ";
O << getRegisterName(MI->getOperand(i).getReg());
}
O << "}";
}
+void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum) {
+ const MCOperand &Op = MI->getOperand(OpNum);
+ unsigned option = Op.getImm();
+ unsigned mode = option & 31;
+ bool changemode = option >> 5 & 1;
+ unsigned AIF = option >> 6 & 7;
+ unsigned imod = option >> 9 & 3;
+ if (imod == 2)
+ O << "ie";
+ else if (imod == 3)
+ O << "id";
+ O << '\t';
+ if (imod > 1) {
+ if (AIF & 4) O << 'a';
+ if (AIF & 2) O << 'i';
+ if (AIF & 1) O << 'f';
+ if (AIF > 0 && changemode) O << ", ";
+ }
+ if (changemode)
+ O << '#' << mode;
+}
+
+void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum) {
+ const MCOperand &Op = MI->getOperand(OpNum);
+ unsigned Mask = Op.getImm();
+ if (Mask) {
+ O << '_';
+ if (Mask & 8) O << 'f';
+ if (Mask & 4) O << 's';
+ if (Mask & 2) O << 'x';
+ if (Mask & 1) O << 'c';
+ }
+}
+
+void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum){
+ const MCOperand &Op = MI->getOperand(OpNum);
+ O << '#';
+ if (Op.getImm() < 0)
+ O << '-' << (-Op.getImm() - 1);
+ else
+ O << Op.getImm();
+}
+
void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum) {
ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
if (CC != ARMCC::AL)
@@ -352,3 +561,191 @@
void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum) {
O << "#" << MI->getOperand(OpNum).getImm() * 4;
}
+
+void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum) {
+ // (3 - the number of trailing zeros) is the number of then / else.
+ unsigned Mask = MI->getOperand(OpNum).getImm();
+ unsigned CondBit0 = Mask >> 4 & 1;
+ unsigned NumTZ = CountTrailingZeros_32(Mask);
+ assert(NumTZ <= 3 && "Invalid IT mask!");
+ for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
+ bool T = ((Mask >> Pos) & 1) == CondBit0;
+ if (T)
+ O << 't';
+ else
+ O << 'e';
+ }
+}
+
+void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op)
+{
+ const MCOperand &MO1 = MI->getOperand(Op);
+ const MCOperand &MO2 = MI->getOperand(Op+1);
+ O << "[" << getRegisterName(MO1.getReg());
+ O << ", " << getRegisterName(MO2.getReg()) << "]";
+}
+
+void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op,
+ unsigned Scale) {
+ const MCOperand &MO1 = MI->getOperand(Op);
+ const MCOperand &MO2 = MI->getOperand(Op+1);
+ const MCOperand &MO3 = MI->getOperand(Op+2);
+
+ if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
+ printOperand(MI, Op);
+ return;
+ }
+
+ O << "[" << getRegisterName(MO1.getReg());
+ if (MO3.getReg())
+ O << ", " << getRegisterName(MO3.getReg());
+ else if (unsigned ImmOffs = MO2.getImm())
+ O << ", #" << ImmOffs * Scale;
+ O << "]";
+}
+
+void ARMInstPrinter::printThumbAddrModeS1Operand(const MCInst *MI, unsigned Op)
+{
+ printThumbAddrModeRI5Operand(MI, Op, 1);
+}
+
+void ARMInstPrinter::printThumbAddrModeS2Operand(const MCInst *MI, unsigned Op)
+{
+ printThumbAddrModeRI5Operand(MI, Op, 2);
+}
+
+void ARMInstPrinter::printThumbAddrModeS4Operand(const MCInst *MI, unsigned Op)
+{
+ printThumbAddrModeRI5Operand(MI, Op, 4);
+}
+
+void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI,unsigned Op) {
+ const MCOperand &MO1 = MI->getOperand(Op);
+ const MCOperand &MO2 = MI->getOperand(Op+1);
+ O << "[" << getRegisterName(MO1.getReg());
+ if (unsigned ImmOffs = MO2.getImm())
+ O << ", #" << ImmOffs*4;
+ O << "]";
+}
+
+void ARMInstPrinter::printTBAddrMode(const MCInst *MI, unsigned OpNum) {
+ O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg());
+ if (MI->getOpcode() == ARM::t2TBH)
+ O << ", lsl #1";
+ O << ']';
+}
+
+// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
+// register with shift forms.
+// REG 0 0 - e.g. R5
+// REG IMM, SH_OPC - e.g. R5, LSL #3
+void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum) {
+ const MCOperand &MO1 = MI->getOperand(OpNum);
+ const MCOperand &MO2 = MI->getOperand(OpNum+1);
+
+ unsigned Reg = MO1.getReg();
+ O << getRegisterName(Reg);
+
+ // Print the shift opc.
+ O << ", "
+ << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()))
+ << " ";
+
+ assert(MO2.isImm() && "Not a valid t2_so_reg value!");
+ O << "#" << ARM_AM::getSORegOffset(MO2.getImm());
+}
+
+void ARMInstPrinter::printT2AddrModeImm12Operand(const MCInst *MI,
+ unsigned OpNum) {
+ const MCOperand &MO1 = MI->getOperand(OpNum);
+ const MCOperand &MO2 = MI->getOperand(OpNum+1);
+
+ O << "[" << getRegisterName(MO1.getReg());
+
+ unsigned OffImm = MO2.getImm();
+ if (OffImm) // Don't print +0.
+ O << ", #" << OffImm;
+ O << "]";
+}
+
+void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
+ unsigned OpNum) {
+ const MCOperand &MO1 = MI->getOperand(OpNum);
+ const MCOperand &MO2 = MI->getOperand(OpNum+1);
+
+ O << "[" << getRegisterName(MO1.getReg());
+
+ int32_t OffImm = (int32_t)MO2.getImm();
+ // Don't print +0.
+ if (OffImm < 0)
+ O << ", #-" << -OffImm;
+ else if (OffImm > 0)
+ O << ", #" << OffImm;
+ O << "]";
+}
+
+void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
+ unsigned OpNum) {
+ const MCOperand &MO1 = MI->getOperand(OpNum);
+ const MCOperand &MO2 = MI->getOperand(OpNum+1);
+
+ O << "[" << getRegisterName(MO1.getReg());
+
+ int32_t OffImm = (int32_t)MO2.getImm() / 4;
+ // Don't print +0.
+ if (OffImm < 0)
+ O << ", #-" << -OffImm * 4;
+ else if (OffImm > 0)
+ O << ", #" << OffImm * 4;
+ O << "]";
+}
+
+void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
+ unsigned OpNum) {
+ const MCOperand &MO1 = MI->getOperand(OpNum);
+ int32_t OffImm = (int32_t)MO1.getImm();
+ // Don't print +0.
+ if (OffImm < 0)
+ O << "#-" << -OffImm;
+ else if (OffImm > 0)
+ O << "#" << OffImm;
+}
+
+void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
+ unsigned OpNum) {
+ const MCOperand &MO1 = MI->getOperand(OpNum);
+ int32_t OffImm = (int32_t)MO1.getImm() / 4;
+ // Don't print +0.
+ if (OffImm < 0)
+ O << "#-" << -OffImm * 4;
+ else if (OffImm > 0)
+ O << "#" << OffImm * 4;
+}
+
+void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
+ unsigned OpNum) {
+ const MCOperand &MO1 = MI->getOperand(OpNum);
+ const MCOperand &MO2 = MI->getOperand(OpNum+1);
+ const MCOperand &MO3 = MI->getOperand(OpNum+2);
+
+ O << "[" << getRegisterName(MO1.getReg());
+
+ assert(MO2.getReg() && "Invalid so_reg load / store address!");
+ O << ", " << getRegisterName(MO2.getReg());
+
+ unsigned ShAmt = MO3.getImm();
+ if (ShAmt) {
+ assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
+ O << ", lsl #" << ShAmt;
+ }
+ O << "]";
+}
+
+void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum) {
+ O << '#' << MI->getOperand(OpNum).getImm();
+}
+
+void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum) {
+ O << '#' << MI->getOperand(OpNum).getImm();
+}
+
diff --git a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h
index 9a3cbc3..ceb641d 100644
--- a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h
+++ b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h
@@ -54,26 +54,26 @@
void printBitfieldInvMaskImmOperand(const MCInst *MI, unsigned OpNum);
void printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum);
- void printThumbITMask(const MCInst *MI, unsigned OpNum) {}
- void printThumbAddrModeRROperand(const MCInst *MI, unsigned OpNum) {}
+ void printThumbITMask(const MCInst *MI, unsigned OpNum);
+ void printThumbAddrModeRROperand(const MCInst *MI, unsigned OpNum);
void printThumbAddrModeRI5Operand(const MCInst *MI, unsigned OpNum,
- unsigned Scale) {}
- void printThumbAddrModeS1Operand(const MCInst *MI, unsigned OpNum) {}
- void printThumbAddrModeS2Operand(const MCInst *MI, unsigned OpNum) {}
- void printThumbAddrModeS4Operand(const MCInst *MI, unsigned OpNum) {}
- void printThumbAddrModeSPOperand(const MCInst *MI, unsigned OpNum) {}
+ unsigned Scale);
+ void printThumbAddrModeS1Operand(const MCInst *MI, unsigned OpNum);
+ void printThumbAddrModeS2Operand(const MCInst *MI, unsigned OpNum);
+ void printThumbAddrModeS4Operand(const MCInst *MI, unsigned OpNum);
+ void printThumbAddrModeSPOperand(const MCInst *MI, unsigned OpNum);
- void printT2SOOperand(const MCInst *MI, unsigned OpNum) {}
- void printT2AddrModeImm12Operand(const MCInst *MI, unsigned OpNum) {}
- void printT2AddrModeImm8Operand(const MCInst *MI, unsigned OpNum) {}
- void printT2AddrModeImm8s4Operand(const MCInst *MI, unsigned OpNum) {}
- void printT2AddrModeImm8OffsetOperand(const MCInst *MI, unsigned OpNum) {}
- void printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, unsigned OpNum) {}
- void printT2AddrModeSoRegOperand(const MCInst *MI, unsigned OpNum) {}
+ void printT2SOOperand(const MCInst *MI, unsigned OpNum);
+ void printT2AddrModeImm12Operand(const MCInst *MI, unsigned OpNum);
+ void printT2AddrModeImm8Operand(const MCInst *MI, unsigned OpNum);
+ void printT2AddrModeImm8s4Operand(const MCInst *MI, unsigned OpNum);
+ void printT2AddrModeImm8OffsetOperand(const MCInst *MI, unsigned OpNum);
+ void printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, unsigned OpNum);
+ void printT2AddrModeSoRegOperand(const MCInst *MI, unsigned OpNum);
- void printCPSOptionOperand(const MCInst *MI, unsigned OpNum) {}
- void printMSRMaskOperand(const MCInst *MI, unsigned OpNum) {}
- void printNegZeroOperand(const MCInst *MI, unsigned OpNum) {}
+ void printCPSOptionOperand(const MCInst *MI, unsigned OpNum);
+ void printMSRMaskOperand(const MCInst *MI, unsigned OpNum);
+ void printNegZeroOperand(const MCInst *MI, unsigned OpNum);
void printPredicateOperand(const MCInst *MI, unsigned OpNum);
void printMandatoryPredicateOperand(const MCInst *MI, unsigned OpNum);
void printSBitModifierOperand(const MCInst *MI, unsigned OpNum);
@@ -82,10 +82,10 @@
const char *Modifier);
void printJTBlockOperand(const MCInst *MI, unsigned OpNum) {}
void printJT2BlockOperand(const MCInst *MI, unsigned OpNum) {}
- void printTBAddrMode(const MCInst *MI, unsigned OpNum) {}
+ void printTBAddrMode(const MCInst *MI, unsigned OpNum);
void printNoHashImmediate(const MCInst *MI, unsigned OpNum);
- void printVFPf32ImmOperand(const MCInst *MI, int OpNum) {}
- void printVFPf64ImmOperand(const MCInst *MI, int OpNum) {}
+ void printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum);
+ void printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum);
void printHex8ImmOperand(const MCInst *MI, int OpNum) {}
void printHex16ImmOperand(const MCInst *MI, int OpNum) {}
void printHex32ImmOperand(const MCInst *MI, int OpNum) {}