1
//===-- ARMInstPrinter.cpp - Convert ARM MCInst to assembly syntax --------===//
3
// The LLVM Compiler Infrastructure
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
8
//===----------------------------------------------------------------------===//
10
// This class prints an ARM MCInst to a .s file.
12
//===----------------------------------------------------------------------===//
14
#define DEBUG_TYPE "asm-printer"
15
#include "ARM.h" // FIXME: FACTOR ENUMS BETTER.
16
#include "ARMInstPrinter.h"
17
#include "ARMAddressingModes.h"
18
#include "llvm/MC/MCInst.h"
19
#include "llvm/MC/MCAsmInfo.h"
20
#include "llvm/MC/MCExpr.h"
21
#include "llvm/Support/raw_ostream.h"
24
// Include the auto-generated portion of the assembly writer.
25
#define MachineInstr MCInst
26
#define ARMAsmPrinter ARMInstPrinter // FIXME: REMOVE.
27
#include "ARMGenAsmWriter.inc"
31
void ARMInstPrinter::printInst(const MCInst *MI) { printInstruction(MI); }
33
void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
34
const char *Modifier) {
35
const MCOperand &Op = MI->getOperand(OpNo);
37
unsigned Reg = Op.getReg();
38
if (Modifier && strcmp(Modifier, "dregpair") == 0) {
39
// FIXME: Breaks e.g. ARM/vmul.ll.
42
unsigned DRegLo = TRI->getSubReg(Reg, 5); // arm_dsubreg_0
43
unsigned DRegHi = TRI->getSubReg(Reg, 6); // arm_dsubreg_1
45
<< getRegisterName(DRegLo) << ',' << getRegisterName(DRegHi)
47
} else if (Modifier && strcmp(Modifier, "lane") == 0) {
50
unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg);
51
unsigned DReg = TRI->getMatchingSuperReg(Reg, RegNum & 1 ? 2 : 1,
52
&ARM::DPR_VFP2RegClass);
53
O << getRegisterName(DReg) << '[' << (RegNum & 1) << ']';
56
O << getRegisterName(Reg);
58
} else if (Op.isImm()) {
59
assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
60
O << '#' << Op.getImm();
62
assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
63
assert(Op.isExpr() && "unknown operand kind in printOperand");
68
static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm,
69
const MCAsmInfo *MAI) {
70
// Break it up into two parts that make up a shifter immediate.
71
V = ARM_AM::getSOImmVal(V);
72
assert(V != -1 && "Not a valid so_imm value!");
74
unsigned Imm = ARM_AM::getSOImmValImm(V);
75
unsigned Rot = ARM_AM::getSOImmValRot(V);
77
// Print low-level immediate formation info, per
78
// A5.1.3: "Data-processing operands - Immediate".
80
O << "#" << Imm << ", " << Rot;
81
// Pretty printed version.
83
O << ' ' << MAI->getCommentString()
84
<< ' ' << (int)ARM_AM::rotr32(Imm, Rot);
91
/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
92
/// immediate in bits 0-7.
93
void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum) {
94
const MCOperand &MO = MI->getOperand(OpNum);
95
assert(MO.isImm() && "Not a valid so_imm value!");
96
printSOImm(O, MO.getImm(), VerboseAsm, &MAI);
99
/// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov'
100
/// followed by an 'orr' to materialize.
101
void ARMInstPrinter::printSOImm2PartOperand(const MCInst *MI, unsigned OpNum) {
102
// FIXME: REMOVE this method.
106
// so_reg is a 4-operand unit corresponding to register forms of the A5.1
107
// "Addressing Mode 1 - Data-processing operands" forms. This includes:
109
// REG REG 0,SH_OPC - e.g. R5, ROR R3
110
// REG 0 IMM,SH_OPC - e.g. R5, LSL #3
111
void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum) {
112
const MCOperand &MO1 = MI->getOperand(OpNum);
113
const MCOperand &MO2 = MI->getOperand(OpNum+1);
114
const MCOperand &MO3 = MI->getOperand(OpNum+2);
116
O << getRegisterName(MO1.getReg());
118
// Print the shift opc.
120
<< ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()))
124
O << getRegisterName(MO2.getReg());
125
assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
127
O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
132
void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op) {
133
const MCOperand &MO1 = MI->getOperand(Op);
134
const MCOperand &MO2 = MI->getOperand(Op+1);
135
const MCOperand &MO3 = MI->getOperand(Op+2);
137
if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
138
printOperand(MI, Op);
142
O << "[" << getRegisterName(MO1.getReg());
145
if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
147
<< (char)ARM_AM::getAM2Op(MO3.getImm())
148
<< ARM_AM::getAM2Offset(MO3.getImm());
154
<< (char)ARM_AM::getAM2Op(MO3.getImm())
155
<< getRegisterName(MO2.getReg());
157
if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
159
<< ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
164
void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
166
const MCOperand &MO1 = MI->getOperand(OpNum);
167
const MCOperand &MO2 = MI->getOperand(OpNum+1);
170
unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
171
assert(ImmOffs && "Malformed indexed load / store!");
172
O << '#' << (char)ARM_AM::getAM2Op(MO2.getImm()) << ImmOffs;
176
O << (char)ARM_AM::getAM2Op(MO2.getImm()) << getRegisterName(MO1.getReg());
178
if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
180
<< ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
184
void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum) {
185
const MCOperand &MO1 = MI->getOperand(OpNum);
186
const MCOperand &MO2 = MI->getOperand(OpNum+1);
187
const MCOperand &MO3 = MI->getOperand(OpNum+2);
189
O << '[' << getRegisterName(MO1.getReg());
192
O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm())
193
<< getRegisterName(MO2.getReg()) << ']';
197
if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
199
<< (char)ARM_AM::getAM3Op(MO3.getImm())
204
void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
206
const MCOperand &MO1 = MI->getOperand(OpNum);
207
const MCOperand &MO2 = MI->getOperand(OpNum+1);
210
O << (char)ARM_AM::getAM3Op(MO2.getImm())
211
<< getRegisterName(MO1.getReg());
215
unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
216
assert(ImmOffs && "Malformed indexed load / store!");
218
<< (char)ARM_AM::getAM3Op(MO2.getImm())
223
void ARMInstPrinter::printAddrMode4Operand(const MCInst *MI, unsigned OpNum,
224
const char *Modifier) {
225
const MCOperand &MO1 = MI->getOperand(OpNum);
226
const MCOperand &MO2 = MI->getOperand(OpNum+1);
227
ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
228
if (Modifier && strcmp(Modifier, "submode") == 0) {
229
if (MO1.getReg() == ARM::SP) {
231
bool isLDM = (MI->getOpcode() == ARM::LDM ||
232
MI->getOpcode() == ARM::LDM_RET ||
233
MI->getOpcode() == ARM::t2LDM ||
234
MI->getOpcode() == ARM::t2LDM_RET);
235
O << ARM_AM::getAMSubModeAltStr(Mode, isLDM);
237
O << ARM_AM::getAMSubModeStr(Mode);
238
} else if (Modifier && strcmp(Modifier, "wide") == 0) {
239
ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
240
if (Mode == ARM_AM::ia)
243
printOperand(MI, OpNum);
244
if (ARM_AM::getAM4WBFlag(MO2.getImm()))
249
void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
250
const char *Modifier) {
251
const MCOperand &MO1 = MI->getOperand(OpNum);
252
const MCOperand &MO2 = MI->getOperand(OpNum+1);
254
if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
255
printOperand(MI, OpNum);
259
if (Modifier && strcmp(Modifier, "submode") == 0) {
260
ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm());
261
O << ARM_AM::getAMSubModeStr(Mode);
263
} else if (Modifier && strcmp(Modifier, "base") == 0) {
264
// Used for FSTM{D|S} and LSTM{D|S} operations.
265
O << getRegisterName(MO1.getReg());
266
if (ARM_AM::getAM5WBFlag(MO2.getImm()))
271
O << "[" << getRegisterName(MO1.getReg());
273
if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
275
<< (char)ARM_AM::getAM5Op(MO2.getImm())
281
void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum) {
282
const MCOperand &MO1 = MI->getOperand(OpNum);
283
const MCOperand &MO2 = MI->getOperand(OpNum+1);
284
const MCOperand &MO3 = MI->getOperand(OpNum+2);
286
// FIXME: No support yet for specifying alignment.
287
O << '[' << getRegisterName(MO1.getReg()) << ']';
289
if (ARM_AM::getAM6WBFlag(MO3.getImm())) {
290
if (MO2.getReg() == 0)
293
O << ", " << getRegisterName(MO2.getReg());
297
void ARMInstPrinter::printAddrModePCOperand(const MCInst *MI, unsigned OpNum,
298
const char *Modifier) {
299
assert(0 && "FIXME: Implement printAddrModePCOperand");
302
void ARMInstPrinter::printBitfieldInvMaskImmOperand (const MCInst *MI,
304
const MCOperand &MO = MI->getOperand(OpNum);
305
uint32_t v = ~MO.getImm();
306
int32_t lsb = CountTrailingZeros_32(v);
307
int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
308
assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
309
O << '#' << lsb << ", #" << width;
312
void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum) {
314
// Always skip the first operand, it's the optional (and implicit writeback).
315
for (unsigned i = OpNum+1, e = MI->getNumOperands(); i != e; ++i) {
316
if (i != OpNum+1) O << ", ";
317
O << getRegisterName(MI->getOperand(i).getReg());
322
void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum) {
323
ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
325
O << ARMCondCodeToString(CC);
328
void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
330
ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
331
O << ARMCondCodeToString(CC);
334
void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum){
335
if (MI->getOperand(OpNum).getReg()) {
336
assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
337
"Expect ARM CPSR register!");
344
void ARMInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNum,
345
const char *Modifier) {
346
// FIXME: remove this.
350
void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum) {
351
O << MI->getOperand(OpNum).getImm();
355
void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum) {
356
// FIXME: remove this.
360
void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum) {
361
O << "#" << MI->getOperand(OpNum).getImm() * 4;