blob: 66abf99dda052de02c43df28f3c74c18747f0a65 [file] [log] [blame]
Chris Lattnerfd603822009-10-19 19:56:26 +00001//===-- ARMInstPrinter.cpp - Convert ARM MCInst to assembly syntax --------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This class prints an ARM MCInst to a .s file.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "asm-printer"
Chris Lattner413ae252009-10-20 00:42:49 +000015#include "ARM.h" // FIXME: FACTOR ENUMS BETTER.
Chris Lattnerfd603822009-10-19 19:56:26 +000016#include "ARMInstPrinter.h"
Chris Lattner61d35c22009-10-19 21:21:39 +000017#include "ARMAddressingModes.h"
Chris Lattnerfd603822009-10-19 19:56:26 +000018#include "llvm/MC/MCInst.h"
Chris Lattner61d35c22009-10-19 21:21:39 +000019#include "llvm/MC/MCAsmInfo.h"
Chris Lattner6f997762009-10-19 21:53:00 +000020#include "llvm/MC/MCExpr.h"
21#include "llvm/Support/raw_ostream.h"
Chris Lattnerfd603822009-10-19 19:56:26 +000022using namespace llvm;
23
24// Include the auto-generated portion of the assembly writer.
25#define MachineInstr MCInst
26#define ARMAsmPrinter ARMInstPrinter // FIXME: REMOVE.
Chris Lattnerfd603822009-10-19 19:56:26 +000027#include "ARMGenAsmWriter.inc"
28#undef MachineInstr
29#undef ARMAsmPrinter
30
Bob Wilson49d9dc42010-03-16 16:59:47 +000031void ARMInstPrinter::printInst(const MCInst *MI) { printInstruction(MI); }
Chris Lattnerfd603822009-10-19 19:56:26 +000032
Chris Lattner8bc86cb2009-10-19 20:59:55 +000033void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
34 const char *Modifier) {
Chris Lattner8bc86cb2009-10-19 20:59:55 +000035 const MCOperand &Op = MI->getOperand(OpNo);
36 if (Op.isReg()) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +000037 unsigned Reg = Op.getReg();
38 if (Modifier && strcmp(Modifier, "dregpair") == 0) {
39 // FIXME: Breaks e.g. ARM/vmul.ll.
40 assert(0);
41 /*
42 unsigned DRegLo = TRI->getSubReg(Reg, 5); // arm_dsubreg_0
43 unsigned DRegHi = TRI->getSubReg(Reg, 6); // arm_dsubreg_1
44 O << '{'
45 << getRegisterName(DRegLo) << ',' << getRegisterName(DRegHi)
46 << '}';*/
47 } else if (Modifier && strcmp(Modifier, "lane") == 0) {
48 assert(0);
49 /*
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) << ']';
54 */
55 } else {
56 O << getRegisterName(Reg);
57 }
Chris Lattner8bc86cb2009-10-19 20:59:55 +000058 } else if (Op.isImm()) {
Bob Wilson49d9dc42010-03-16 16:59:47 +000059 assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
Chris Lattner8bc86cb2009-10-19 20:59:55 +000060 O << '#' << Op.getImm();
61 } else {
Chris Lattnerbf16faa2009-10-20 06:15:28 +000062 assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
Chris Lattner8bc86cb2009-10-19 20:59:55 +000063 assert(Op.isExpr() && "unknown operand kind in printOperand");
Chris Lattner8cb9a3b2010-01-18 00:37:40 +000064 O << *Op.getExpr();
Chris Lattner8bc86cb2009-10-19 20:59:55 +000065 }
66}
Chris Lattner61d35c22009-10-19 21:21:39 +000067
68static 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!");
73
74 unsigned Imm = ARM_AM::getSOImmValImm(V);
75 unsigned Rot = ARM_AM::getSOImmValRot(V);
76
77 // Print low-level immediate formation info, per
78 // A5.1.3: "Data-processing operands - Immediate".
79 if (Rot) {
80 O << "#" << Imm << ", " << Rot;
81 // Pretty printed version.
82 if (VerboseAsm)
83 O << ' ' << MAI->getCommentString()
84 << ' ' << (int)ARM_AM::rotr32(Imm, Rot);
85 } else {
86 O << "#" << Imm;
87 }
88}
89
90
91/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
92/// immediate in bits 0-7.
93void 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);
97}
Chris Lattner084f87d2009-10-19 21:57:05 +000098
Chris Lattner017d9472009-10-20 00:40:56 +000099/// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov'
100/// followed by an 'orr' to materialize.
101void ARMInstPrinter::printSOImm2PartOperand(const MCInst *MI, unsigned OpNum) {
102 // FIXME: REMOVE this method.
103 abort();
104}
105
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:
108// REG 0 0 - e.g. R5
109// REG REG 0,SH_OPC - e.g. R5, ROR R3
110// REG 0 IMM,SH_OPC - e.g. R5, LSL #3
111void 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);
115
116 O << getRegisterName(MO1.getReg());
117
118 // Print the shift opc.
119 O << ", "
120 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()))
121 << ' ';
122
123 if (MO2.getReg()) {
124 O << getRegisterName(MO2.getReg());
125 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
126 } else {
127 O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
128 }
129}
Chris Lattner084f87d2009-10-19 21:57:05 +0000130
131
132void 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);
136
137 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
138 printOperand(MI, Op);
139 return;
140 }
141
142 O << "[" << getRegisterName(MO1.getReg());
143
144 if (!MO2.getReg()) {
Bob Wilson49d9dc42010-03-16 16:59:47 +0000145 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
Chris Lattner084f87d2009-10-19 21:57:05 +0000146 O << ", #"
Bob Wilson49d9dc42010-03-16 16:59:47 +0000147 << (char)ARM_AM::getAM2Op(MO3.getImm())
148 << ARM_AM::getAM2Offset(MO3.getImm());
Chris Lattner084f87d2009-10-19 21:57:05 +0000149 O << "]";
150 return;
151 }
152
153 O << ", "
Bob Wilson49d9dc42010-03-16 16:59:47 +0000154 << (char)ARM_AM::getAM2Op(MO3.getImm())
155 << getRegisterName(MO2.getReg());
Chris Lattner084f87d2009-10-19 21:57:05 +0000156
157 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
158 O << ", "
159 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
160 << " #" << ShImm;
161 O << "]";
162}
Chris Lattnere306d8d2009-10-19 22:09:23 +0000163
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000164void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
165 unsigned OpNum) {
166 const MCOperand &MO1 = MI->getOperand(OpNum);
167 const MCOperand &MO2 = MI->getOperand(OpNum+1);
168
169 if (!MO1.getReg()) {
170 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
171 assert(ImmOffs && "Malformed indexed load / store!");
Bob Wilson49d9dc42010-03-16 16:59:47 +0000172 O << '#' << (char)ARM_AM::getAM2Op(MO2.getImm()) << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000173 return;
174 }
175
Bob Wilson49d9dc42010-03-16 16:59:47 +0000176 O << (char)ARM_AM::getAM2Op(MO2.getImm()) << getRegisterName(MO1.getReg());
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000177
178 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
179 O << ", "
180 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
181 << " #" << ShImm;
182}
183
184void 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);
188
189 O << '[' << getRegisterName(MO1.getReg());
190
191 if (MO2.getReg()) {
192 O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm())
193 << getRegisterName(MO2.getReg()) << ']';
194 return;
195 }
196
197 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
198 O << ", #"
Bob Wilson49d9dc42010-03-16 16:59:47 +0000199 << (char)ARM_AM::getAM3Op(MO3.getImm())
200 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000201 O << ']';
202}
203
204void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
205 unsigned OpNum) {
206 const MCOperand &MO1 = MI->getOperand(OpNum);
207 const MCOperand &MO2 = MI->getOperand(OpNum+1);
208
209 if (MO1.getReg()) {
210 O << (char)ARM_AM::getAM3Op(MO2.getImm())
211 << getRegisterName(MO1.getReg());
212 return;
213 }
214
215 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
216 assert(ImmOffs && "Malformed indexed load / store!");
Bob Wilson49d9dc42010-03-16 16:59:47 +0000217 O << "#"
218 << (char)ARM_AM::getAM3Op(MO2.getImm())
219 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000220}
221
Chris Lattnere306d8d2009-10-19 22:09:23 +0000222
223void ARMInstPrinter::printAddrMode4Operand(const MCInst *MI, unsigned OpNum,
224 const char *Modifier) {
Chris Lattnere306d8d2009-10-19 22:09:23 +0000225 const MCOperand &MO2 = MI->getOperand(OpNum+1);
226 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
Chris Lattner306d14f2009-10-19 23:31:43 +0000227 if (Modifier && strcmp(Modifier, "submode") == 0) {
Bob Wilsonea7f22c2010-03-16 16:19:07 +0000228 O << ARM_AM::getAMSubModeStr(Mode);
Chris Lattner306d14f2009-10-19 23:31:43 +0000229 } else if (Modifier && strcmp(Modifier, "wide") == 0) {
Chris Lattnere306d8d2009-10-19 22:09:23 +0000230 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
231 if (Mode == ARM_AM::ia)
232 O << ".w";
233 } else {
234 printOperand(MI, OpNum);
Chris Lattnere306d8d2009-10-19 22:09:23 +0000235 }
236}
237
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000238void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
239 const char *Modifier) {
240 const MCOperand &MO1 = MI->getOperand(OpNum);
241 const MCOperand &MO2 = MI->getOperand(OpNum+1);
242
243 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
244 printOperand(MI, OpNum);
245 return;
246 }
247
248 if (Modifier && strcmp(Modifier, "submode") == 0) {
249 ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm());
Jim Grosbache5165492009-11-09 00:11:35 +0000250 O << ARM_AM::getAMSubModeStr(Mode);
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000251 return;
252 } else if (Modifier && strcmp(Modifier, "base") == 0) {
253 // Used for FSTM{D|S} and LSTM{D|S} operations.
254 O << getRegisterName(MO1.getReg());
255 if (ARM_AM::getAM5WBFlag(MO2.getImm()))
256 O << "!";
257 return;
258 }
259
260 O << "[" << getRegisterName(MO1.getReg());
261
262 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
263 O << ", #"
Bob Wilson49d9dc42010-03-16 16:59:47 +0000264 << (char)ARM_AM::getAM5Op(MO2.getImm())
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000265 << ImmOffs*4;
266 }
267 O << "]";
268}
269
Chris Lattner235e2f62009-10-20 06:22:33 +0000270void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum) {
271 const MCOperand &MO1 = MI->getOperand(OpNum);
272 const MCOperand &MO2 = MI->getOperand(OpNum+1);
273 const MCOperand &MO3 = MI->getOperand(OpNum+2);
274
275 // FIXME: No support yet for specifying alignment.
276 O << '[' << getRegisterName(MO1.getReg()) << ']';
277
278 if (ARM_AM::getAM6WBFlag(MO3.getImm())) {
279 if (MO2.getReg() == 0)
280 O << '!';
281 else
282 O << ", " << getRegisterName(MO2.getReg());
283 }
284}
285
286void ARMInstPrinter::printAddrModePCOperand(const MCInst *MI, unsigned OpNum,
287 const char *Modifier) {
288 assert(0 && "FIXME: Implement printAddrModePCOperand");
289}
290
291void ARMInstPrinter::printBitfieldInvMaskImmOperand (const MCInst *MI,
292 unsigned OpNum) {
293 const MCOperand &MO = MI->getOperand(OpNum);
294 uint32_t v = ~MO.getImm();
295 int32_t lsb = CountTrailingZeros_32(v);
296 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
297 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
298 O << '#' << lsb << ", #" << width;
299}
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000300
Chris Lattnere306d8d2009-10-19 22:09:23 +0000301void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum) {
302 O << "{";
Bob Wilson49d9dc42010-03-16 16:59:47 +0000303 // Always skip the first operand, it's the optional (and implicit writeback).
304 for (unsigned i = OpNum+1, e = MI->getNumOperands(); i != e; ++i) {
305 if (i != OpNum+1) O << ", ";
Chris Lattnere306d8d2009-10-19 22:09:23 +0000306 O << getRegisterName(MI->getOperand(i).getReg());
307 }
308 O << "}";
309}
Chris Lattner4d152222009-10-19 22:23:04 +0000310
Chris Lattner413ae252009-10-20 00:42:49 +0000311void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum) {
312 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
313 if (CC != ARMCC::AL)
314 O << ARMCondCodeToString(CC);
315}
316
Johnny Chen9d3acaa2010-03-02 17:57:15 +0000317void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
318 unsigned OpNum) {
319 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
320 O << ARMCondCodeToString(CC);
321}
322
Chris Lattner233917c2009-10-20 00:46:11 +0000323void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum){
Daniel Dunbara7cc6522009-10-20 22:10:05 +0000324 if (MI->getOperand(OpNum).getReg()) {
325 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
326 "Expect ARM CPSR register!");
Chris Lattner233917c2009-10-20 00:46:11 +0000327 O << 's';
328 }
329}
330
331
Chris Lattner4d152222009-10-19 22:23:04 +0000332
Chris Lattnera70e6442009-10-19 22:33:05 +0000333void ARMInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNum,
334 const char *Modifier) {
335 // FIXME: remove this.
336 abort();
337}
Chris Lattner4d152222009-10-19 22:23:04 +0000338
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000339void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum) {
340 O << MI->getOperand(OpNum).getImm();
341}
342
343
Chris Lattner4d152222009-10-19 22:23:04 +0000344void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum) {
345 // FIXME: remove this.
346 abort();
347}
Evan Cheng2ef9c8a2009-11-19 06:57:41 +0000348
349void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum) {
Johnny Chen541ba7d2010-01-25 22:13:10 +0000350 O << "#" << MI->getOperand(OpNum).getImm() * 4;
Evan Cheng2ef9c8a2009-11-19 06:57:41 +0000351}