blob: f080fa81e941d93996b8909dc52897da20be3531 [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"
Jim Grosbachd8be4102010-09-15 19:27:50 +000015#include "ARMBaseInfo.h"
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"
Johnny Chenc7b65912010-04-16 22:40:20 +000021#include "llvm/ADT/StringExtras.h"
Chris Lattner6f997762009-10-19 21:53:00 +000022#include "llvm/Support/raw_ostream.h"
Chris Lattnerfd603822009-10-19 19:56:26 +000023using namespace llvm;
24
Chris Lattner6274ec42010-10-28 21:37:33 +000025#define GET_INSTRUCTION_NAME
Chris Lattnerfd603822009-10-19 19:56:26 +000026#include "ARMGenAsmWriter.inc"
Chris Lattnerfd603822009-10-19 19:56:26 +000027
Chris Lattner6274ec42010-10-28 21:37:33 +000028StringRef ARMInstPrinter::getOpcodeName(unsigned Opcode) const {
29 return getInstructionName(Opcode);
30}
31
Anton Korobeynikov57caad72011-03-05 18:43:32 +000032StringRef ARMInstPrinter::getRegName(unsigned RegNo) const {
33 return getRegisterName(RegNo);
34}
Chris Lattner6274ec42010-10-28 21:37:33 +000035
Chris Lattnerd3740872010-04-04 05:04:31 +000036void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
Bill Wendling04863d02010-11-13 10:40:19 +000037 unsigned Opcode = MI->getOpcode();
38
Johnny Chen9e088762010-03-17 17:52:21 +000039 // Check for MOVs and print canonical forms, instead.
Bill Wendling04863d02010-11-13 10:40:19 +000040 if (Opcode == ARM::MOVs) {
Jim Grosbache6be85e2010-09-17 22:36:38 +000041 // FIXME: Thumb variants?
Johnny Chen9e088762010-03-17 17:52:21 +000042 const MCOperand &Dst = MI->getOperand(0);
43 const MCOperand &MO1 = MI->getOperand(1);
44 const MCOperand &MO2 = MI->getOperand(2);
45 const MCOperand &MO3 = MI->getOperand(3);
46
47 O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
Chris Lattner35c33bd2010-04-04 04:47:45 +000048 printSBitModifierOperand(MI, 6, O);
49 printPredicateOperand(MI, 4, O);
Johnny Chen9e088762010-03-17 17:52:21 +000050
51 O << '\t' << getRegisterName(Dst.getReg())
52 << ", " << getRegisterName(MO1.getReg());
53
54 if (ARM_AM::getSORegShOp(MO3.getImm()) == ARM_AM::rrx)
55 return;
56
57 O << ", ";
58
59 if (MO2.getReg()) {
60 O << getRegisterName(MO2.getReg());
61 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
62 } else {
63 O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
64 }
65 return;
66 }
67
68 // A8.6.123 PUSH
Bill Wendling73fe34a2010-11-16 01:16:36 +000069 if ((Opcode == ARM::STMDB_UPD || Opcode == ARM::t2STMDB_UPD) &&
Johnny Chen9e088762010-03-17 17:52:21 +000070 MI->getOperand(0).getReg() == ARM::SP) {
Bill Wendling73fe34a2010-11-16 01:16:36 +000071 O << '\t' << "push";
72 printPredicateOperand(MI, 2, O);
Jim Grosbach41ad0c42010-12-03 20:33:01 +000073 if (Opcode == ARM::t2STMDB_UPD)
74 O << ".w";
Bill Wendling73fe34a2010-11-16 01:16:36 +000075 O << '\t';
76 printRegisterList(MI, 4, O);
77 return;
Johnny Chen9e088762010-03-17 17:52:21 +000078 }
79
80 // A8.6.122 POP
Bill Wendling73fe34a2010-11-16 01:16:36 +000081 if ((Opcode == ARM::LDMIA_UPD || Opcode == ARM::t2LDMIA_UPD) &&
Johnny Chen9e088762010-03-17 17:52:21 +000082 MI->getOperand(0).getReg() == ARM::SP) {
Bill Wendling73fe34a2010-11-16 01:16:36 +000083 O << '\t' << "pop";
84 printPredicateOperand(MI, 2, O);
Jim Grosbach41ad0c42010-12-03 20:33:01 +000085 if (Opcode == ARM::t2LDMIA_UPD)
86 O << ".w";
Bill Wendling73fe34a2010-11-16 01:16:36 +000087 O << '\t';
88 printRegisterList(MI, 4, O);
89 return;
Johnny Chen9e088762010-03-17 17:52:21 +000090 }
91
92 // A8.6.355 VPUSH
Bill Wendling73fe34a2010-11-16 01:16:36 +000093 if ((Opcode == ARM::VSTMSDB_UPD || Opcode == ARM::VSTMDDB_UPD) &&
Johnny Chen9e088762010-03-17 17:52:21 +000094 MI->getOperand(0).getReg() == ARM::SP) {
Bill Wendling73fe34a2010-11-16 01:16:36 +000095 O << '\t' << "vpush";
96 printPredicateOperand(MI, 2, O);
97 O << '\t';
98 printRegisterList(MI, 4, O);
99 return;
Johnny Chen9e088762010-03-17 17:52:21 +0000100 }
101
102 // A8.6.354 VPOP
Bill Wendling73fe34a2010-11-16 01:16:36 +0000103 if ((Opcode == ARM::VLDMSIA_UPD || Opcode == ARM::VLDMDIA_UPD) &&
Johnny Chen9e088762010-03-17 17:52:21 +0000104 MI->getOperand(0).getReg() == ARM::SP) {
Bill Wendling73fe34a2010-11-16 01:16:36 +0000105 O << '\t' << "vpop";
106 printPredicateOperand(MI, 2, O);
107 O << '\t';
108 printRegisterList(MI, 4, O);
109 return;
Johnny Chen9e088762010-03-17 17:52:21 +0000110 }
111
Chris Lattner35c33bd2010-04-04 04:47:45 +0000112 printInstruction(MI, O);
Bill Wendling04863d02010-11-13 10:40:19 +0000113}
Chris Lattnerfd603822009-10-19 19:56:26 +0000114
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000115void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
Jim Grosbach0a2287b2010-11-03 01:11:15 +0000116 raw_ostream &O) {
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000117 const MCOperand &Op = MI->getOperand(OpNo);
118 if (Op.isReg()) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000119 unsigned Reg = Op.getReg();
Jim Grosbach35636282010-10-06 21:22:32 +0000120 O << getRegisterName(Reg);
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000121 } else if (Op.isImm()) {
122 O << '#' << Op.getImm();
123 } else {
124 assert(Op.isExpr() && "unknown operand kind in printOperand");
Chris Lattner8cb9a3b2010-01-18 00:37:40 +0000125 O << *Op.getExpr();
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000126 }
127}
Chris Lattner61d35c22009-10-19 21:21:39 +0000128
Jim Grosbach74d7e6c2010-09-17 21:33:25 +0000129static void printSOImm(raw_ostream &O, int64_t V, raw_ostream *CommentStream,
Chris Lattner61d35c22009-10-19 21:21:39 +0000130 const MCAsmInfo *MAI) {
131 // Break it up into two parts that make up a shifter immediate.
Bob Wilsonb123b8b2010-04-13 02:11:48 +0000132 V = ARM_AM::getSOImmVal(V);
Chris Lattner61d35c22009-10-19 21:21:39 +0000133 assert(V != -1 && "Not a valid so_imm value!");
Jim Grosbach15d78982010-09-14 22:27:15 +0000134
Chris Lattner61d35c22009-10-19 21:21:39 +0000135 unsigned Imm = ARM_AM::getSOImmValImm(V);
136 unsigned Rot = ARM_AM::getSOImmValRot(V);
Jim Grosbach15d78982010-09-14 22:27:15 +0000137
Chris Lattner61d35c22009-10-19 21:21:39 +0000138 // Print low-level immediate formation info, per
139 // A5.1.3: "Data-processing operands - Immediate".
140 if (Rot) {
141 O << "#" << Imm << ", " << Rot;
142 // Pretty printed version.
Jim Grosbach74d7e6c2010-09-17 21:33:25 +0000143 if (CommentStream)
144 *CommentStream << (int)ARM_AM::rotr32(Imm, Rot) << "\n";
Chris Lattner61d35c22009-10-19 21:21:39 +0000145 } else {
146 O << "#" << Imm;
147 }
148}
149
150
151/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
152/// immediate in bits 0-7.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000153void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum,
154 raw_ostream &O) {
Chris Lattner61d35c22009-10-19 21:21:39 +0000155 const MCOperand &MO = MI->getOperand(OpNum);
156 assert(MO.isImm() && "Not a valid so_imm value!");
Jim Grosbach74d7e6c2010-09-17 21:33:25 +0000157 printSOImm(O, MO.getImm(), CommentStream, &MAI);
Chris Lattner61d35c22009-10-19 21:21:39 +0000158}
Chris Lattner084f87d2009-10-19 21:57:05 +0000159
Chris Lattner017d9472009-10-20 00:40:56 +0000160// so_reg is a 4-operand unit corresponding to register forms of the A5.1
161// "Addressing Mode 1 - Data-processing operands" forms. This includes:
162// REG 0 0 - e.g. R5
163// REG REG 0,SH_OPC - e.g. R5, ROR R3
164// REG 0 IMM,SH_OPC - e.g. R5, LSL #3
Chris Lattner35c33bd2010-04-04 04:47:45 +0000165void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum,
166 raw_ostream &O) {
Chris Lattner017d9472009-10-20 00:40:56 +0000167 const MCOperand &MO1 = MI->getOperand(OpNum);
168 const MCOperand &MO2 = MI->getOperand(OpNum+1);
169 const MCOperand &MO3 = MI->getOperand(OpNum+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000170
Chris Lattner017d9472009-10-20 00:40:56 +0000171 O << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000172
Chris Lattner017d9472009-10-20 00:40:56 +0000173 // Print the shift opc.
Bob Wilson1d9125a2010-08-05 00:34:42 +0000174 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
175 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
Chris Lattner017d9472009-10-20 00:40:56 +0000176 if (MO2.getReg()) {
Bob Wilson1d9125a2010-08-05 00:34:42 +0000177 O << ' ' << getRegisterName(MO2.getReg());
Chris Lattner017d9472009-10-20 00:40:56 +0000178 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
Bob Wilson1d9125a2010-08-05 00:34:42 +0000179 } else if (ShOpc != ARM_AM::rrx) {
180 O << " #" << ARM_AM::getSORegOffset(MO3.getImm());
Chris Lattner017d9472009-10-20 00:40:56 +0000181 }
182}
Chris Lattner084f87d2009-10-19 21:57:05 +0000183
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000184//===--------------------------------------------------------------------===//
185// Addressing Mode #2
186//===--------------------------------------------------------------------===//
187
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000188void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
189 raw_ostream &O) {
Chris Lattner084f87d2009-10-19 21:57:05 +0000190 const MCOperand &MO1 = MI->getOperand(Op);
191 const MCOperand &MO2 = MI->getOperand(Op+1);
192 const MCOperand &MO3 = MI->getOperand(Op+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000193
Chris Lattner084f87d2009-10-19 21:57:05 +0000194 O << "[" << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000195
Chris Lattner084f87d2009-10-19 21:57:05 +0000196 if (!MO2.getReg()) {
Johnny Chen9e088762010-03-17 17:52:21 +0000197 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
Chris Lattner084f87d2009-10-19 21:57:05 +0000198 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000199 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
200 << ARM_AM::getAM2Offset(MO3.getImm());
Chris Lattner084f87d2009-10-19 21:57:05 +0000201 O << "]";
202 return;
203 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000204
Chris Lattner084f87d2009-10-19 21:57:05 +0000205 O << ", "
Johnny Chen9e088762010-03-17 17:52:21 +0000206 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
207 << getRegisterName(MO2.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000208
Chris Lattner084f87d2009-10-19 21:57:05 +0000209 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
210 O << ", "
211 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
212 << " #" << ShImm;
213 O << "]";
Jim Grosbach15d78982010-09-14 22:27:15 +0000214}
Chris Lattnere306d8d2009-10-19 22:09:23 +0000215
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000216void ARMInstPrinter::printAM2PostIndexOp(const MCInst *MI, unsigned Op,
217 raw_ostream &O) {
218 const MCOperand &MO1 = MI->getOperand(Op);
219 const MCOperand &MO2 = MI->getOperand(Op+1);
220 const MCOperand &MO3 = MI->getOperand(Op+2);
221
222 O << "[" << getRegisterName(MO1.getReg()) << "], ";
223
224 if (!MO2.getReg()) {
225 unsigned ImmOffs = ARM_AM::getAM2Offset(MO3.getImm());
226 O << '#'
227 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
228 << ImmOffs;
229 return;
230 }
231
232 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
233 << getRegisterName(MO2.getReg());
234
235 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
236 O << ", "
237 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
238 << " #" << ShImm;
239}
240
241void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
242 raw_ostream &O) {
243 const MCOperand &MO1 = MI->getOperand(Op);
244
245 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
246 printOperand(MI, Op, O);
247 return;
248 }
249
250 const MCOperand &MO3 = MI->getOperand(Op+2);
251 unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm());
252
253 if (IdxMode == ARMII::IndexModePost) {
254 printAM2PostIndexOp(MI, Op, O);
255 return;
256 }
257 printAM2PreOrOffsetIndexOp(MI, Op, O);
258}
259
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000260void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000261 unsigned OpNum,
262 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000263 const MCOperand &MO1 = MI->getOperand(OpNum);
264 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000265
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000266 if (!MO1.getReg()) {
267 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000268 O << '#'
269 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
270 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000271 return;
272 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000273
Johnny Chen9e088762010-03-17 17:52:21 +0000274 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
275 << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000276
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000277 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
278 O << ", "
279 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
280 << " #" << ShImm;
281}
282
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000283//===--------------------------------------------------------------------===//
284// Addressing Mode #3
285//===--------------------------------------------------------------------===//
286
287void ARMInstPrinter::printAM3PostIndexOp(const MCInst *MI, unsigned Op,
288 raw_ostream &O) {
289 const MCOperand &MO1 = MI->getOperand(Op);
290 const MCOperand &MO2 = MI->getOperand(Op+1);
291 const MCOperand &MO3 = MI->getOperand(Op+2);
292
293 O << "[" << getRegisterName(MO1.getReg()) << "], ";
294
295 if (MO2.getReg()) {
296 O << (char)ARM_AM::getAM3Op(MO3.getImm())
297 << getRegisterName(MO2.getReg());
298 return;
299 }
300
301 unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm());
302 O << '#'
303 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
304 << ImmOffs;
305}
306
307void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
308 raw_ostream &O) {
309 const MCOperand &MO1 = MI->getOperand(Op);
310 const MCOperand &MO2 = MI->getOperand(Op+1);
311 const MCOperand &MO3 = MI->getOperand(Op+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000312
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000313 O << '[' << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000314
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000315 if (MO2.getReg()) {
316 O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm())
317 << getRegisterName(MO2.getReg()) << ']';
318 return;
319 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000320
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000321 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
322 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000323 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
324 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000325 O << ']';
326}
327
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000328void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op,
329 raw_ostream &O) {
330 const MCOperand &MO3 = MI->getOperand(Op+2);
331 unsigned IdxMode = ARM_AM::getAM3IdxMode(MO3.getImm());
332
333 if (IdxMode == ARMII::IndexModePost) {
334 printAM3PostIndexOp(MI, Op, O);
335 return;
336 }
337 printAM3PreOrOffsetIndexOp(MI, Op, O);
338}
339
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000340void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000341 unsigned OpNum,
342 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000343 const MCOperand &MO1 = MI->getOperand(OpNum);
344 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000345
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000346 if (MO1.getReg()) {
347 O << (char)ARM_AM::getAM3Op(MO2.getImm())
348 << getRegisterName(MO1.getReg());
349 return;
350 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000351
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000352 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000353 O << '#'
354 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
355 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000356}
357
Jim Grosbache6913602010-11-03 01:01:43 +0000358void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,
Jim Grosbach0a2287b2010-11-03 01:11:15 +0000359 raw_ostream &O) {
Jim Grosbache6913602010-11-03 01:01:43 +0000360 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(OpNum)
361 .getImm());
362 O << ARM_AM::getAMSubModeStr(Mode);
Chris Lattnere306d8d2009-10-19 22:09:23 +0000363}
364
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000365void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
Jim Grosbach0a2287b2010-11-03 01:11:15 +0000366 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000367 const MCOperand &MO1 = MI->getOperand(OpNum);
368 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000369
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000370 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000371 printOperand(MI, OpNum, O);
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000372 return;
373 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000374
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000375 O << "[" << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000376
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000377 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
378 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000379 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000380 << ImmOffs * 4;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000381 }
382 O << "]";
383}
384
Chris Lattner35c33bd2010-04-04 04:47:45 +0000385void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
386 raw_ostream &O) {
Chris Lattner235e2f62009-10-20 06:22:33 +0000387 const MCOperand &MO1 = MI->getOperand(OpNum);
388 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000389
Bob Wilson226036e2010-03-20 22:13:40 +0000390 O << "[" << getRegisterName(MO1.getReg());
391 if (MO2.getImm()) {
392 // FIXME: Both darwin as and GNU as violate ARM docs here.
Bob Wilson273ff312010-07-14 23:54:43 +0000393 O << ", :" << (MO2.getImm() << 3);
Chris Lattner235e2f62009-10-20 06:22:33 +0000394 }
Bob Wilson226036e2010-03-20 22:13:40 +0000395 O << "]";
396}
397
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +0000398void ARMInstPrinter::printAddrMode7Operand(const MCInst *MI, unsigned OpNum,
399 raw_ostream &O) {
400 const MCOperand &MO1 = MI->getOperand(OpNum);
401 O << "[" << getRegisterName(MO1.getReg()) << "]";
402}
403
Bob Wilson226036e2010-03-20 22:13:40 +0000404void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000405 unsigned OpNum,
406 raw_ostream &O) {
Bob Wilson226036e2010-03-20 22:13:40 +0000407 const MCOperand &MO = MI->getOperand(OpNum);
408 if (MO.getReg() == 0)
409 O << "!";
410 else
411 O << ", " << getRegisterName(MO.getReg());
Chris Lattner235e2f62009-10-20 06:22:33 +0000412}
413
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000414void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
415 unsigned OpNum,
416 raw_ostream &O) {
Chris Lattner235e2f62009-10-20 06:22:33 +0000417 const MCOperand &MO = MI->getOperand(OpNum);
418 uint32_t v = ~MO.getImm();
419 int32_t lsb = CountTrailingZeros_32(v);
420 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
421 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
422 O << '#' << lsb << ", #" << width;
423}
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000424
Johnny Chen1adc40c2010-08-12 20:46:17 +0000425void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
426 raw_ostream &O) {
427 unsigned val = MI->getOperand(OpNum).getImm();
428 O << ARM_MB::MemBOptToString(val);
429}
430
Bob Wilson22f5dc72010-08-16 18:27:34 +0000431void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000432 raw_ostream &O) {
433 unsigned ShiftOp = MI->getOperand(OpNum).getImm();
434 ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp);
435 switch (Opc) {
436 case ARM_AM::no_shift:
437 return;
438 case ARM_AM::lsl:
439 O << ", lsl #";
440 break;
441 case ARM_AM::asr:
442 O << ", asr #";
443 break;
444 default:
Bob Wilson22f5dc72010-08-16 18:27:34 +0000445 assert(0 && "unexpected shift opcode for shift immediate operand");
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000446 }
447 O << ARM_AM::getSORegOffset(ShiftOp);
448}
449
Chris Lattner35c33bd2010-04-04 04:47:45 +0000450void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
451 raw_ostream &O) {
Chris Lattnere306d8d2009-10-19 22:09:23 +0000452 O << "{";
Johnny Chen9e088762010-03-17 17:52:21 +0000453 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
454 if (i != OpNum) O << ", ";
Chris Lattnere306d8d2009-10-19 22:09:23 +0000455 O << getRegisterName(MI->getOperand(i).getReg());
456 }
457 O << "}";
458}
Chris Lattner4d152222009-10-19 22:23:04 +0000459
Jim Grosbachb3af5de2010-10-13 21:00:04 +0000460void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum,
461 raw_ostream &O) {
462 const MCOperand &Op = MI->getOperand(OpNum);
463 if (Op.getImm())
464 O << "be";
465 else
466 O << "le";
467}
468
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000469void ARMInstPrinter::printCPSIMod(const MCInst *MI, unsigned OpNum,
470 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000471 const MCOperand &Op = MI->getOperand(OpNum);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000472 O << ARM_PROC::IModToString(Op.getImm());
473}
474
475void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum,
476 raw_ostream &O) {
477 const MCOperand &Op = MI->getOperand(OpNum);
478 unsigned IFlags = Op.getImm();
479 for (int i=2; i >= 0; --i)
480 if (IFlags & (1 << i))
481 O << ARM_PROC::IFlagsToString(1 << i);
Johnny Chen9e088762010-03-17 17:52:21 +0000482}
483
Chris Lattner35c33bd2010-04-04 04:47:45 +0000484void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
485 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000486 const MCOperand &Op = MI->getOperand(OpNum);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000487 unsigned SpecRegRBit = Op.getImm() >> 4;
488 unsigned Mask = Op.getImm() & 0xf;
489
490 if (SpecRegRBit)
491 O << "spsr";
492 else
493 O << "cpsr";
494
Johnny Chen9e088762010-03-17 17:52:21 +0000495 if (Mask) {
496 O << '_';
497 if (Mask & 8) O << 'f';
498 if (Mask & 4) O << 's';
499 if (Mask & 2) O << 'x';
500 if (Mask & 1) O << 'c';
501 }
502}
503
Chris Lattner35c33bd2010-04-04 04:47:45 +0000504void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
505 raw_ostream &O) {
Chris Lattner413ae252009-10-20 00:42:49 +0000506 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
507 if (CC != ARMCC::AL)
508 O << ARMCondCodeToString(CC);
509}
510
Jim Grosbach15d78982010-09-14 22:27:15 +0000511void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000512 unsigned OpNum,
513 raw_ostream &O) {
Johnny Chen9d3acaa2010-03-02 17:57:15 +0000514 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
515 O << ARMCondCodeToString(CC);
516}
517
Chris Lattner35c33bd2010-04-04 04:47:45 +0000518void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
519 raw_ostream &O) {
Daniel Dunbara7cc6522009-10-20 22:10:05 +0000520 if (MI->getOperand(OpNum).getReg()) {
521 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
522 "Expect ARM CPSR register!");
Chris Lattner233917c2009-10-20 00:46:11 +0000523 O << 's';
524 }
525}
526
Chris Lattner35c33bd2010-04-04 04:47:45 +0000527void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
528 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000529 O << MI->getOperand(OpNum).getImm();
530}
531
Owen Andersone4e5e2a2011-01-13 21:46:02 +0000532void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum,
533 raw_ostream &O) {
534 O << "p" << MI->getOperand(OpNum).getImm();
535}
536
537void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum,
538 raw_ostream &O) {
539 O << "c" << MI->getOperand(OpNum).getImm();
540}
541
Chris Lattner35c33bd2010-04-04 04:47:45 +0000542void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
543 raw_ostream &O) {
Jim Grosbachd30cfde2010-09-18 00:04:53 +0000544 llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
Chris Lattner4d152222009-10-19 22:23:04 +0000545}
Evan Cheng2ef9c8a2009-11-19 06:57:41 +0000546
Chris Lattner35c33bd2010-04-04 04:47:45 +0000547void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
548 raw_ostream &O) {
Johnny Chen541ba7d2010-01-25 22:13:10 +0000549 O << "#" << MI->getOperand(OpNum).getImm() * 4;
Evan Cheng2ef9c8a2009-11-19 06:57:41 +0000550}
Johnny Chen9e088762010-03-17 17:52:21 +0000551
Chris Lattner35c33bd2010-04-04 04:47:45 +0000552void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
553 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000554 // (3 - the number of trailing zeros) is the number of then / else.
555 unsigned Mask = MI->getOperand(OpNum).getImm();
556 unsigned CondBit0 = Mask >> 4 & 1;
557 unsigned NumTZ = CountTrailingZeros_32(Mask);
558 assert(NumTZ <= 3 && "Invalid IT mask!");
559 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
560 bool T = ((Mask >> Pos) & 1) == CondBit0;
561 if (T)
562 O << 't';
563 else
564 O << 'e';
565 }
566}
567
Chris Lattner35c33bd2010-04-04 04:47:45 +0000568void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
569 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000570 const MCOperand &MO1 = MI->getOperand(Op);
Bill Wendlingf4caf692010-12-14 03:36:38 +0000571 const MCOperand &MO2 = MI->getOperand(Op + 1);
Johnny Chen9e088762010-03-17 17:52:21 +0000572
573 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000574 printOperand(MI, Op, O);
Johnny Chen9e088762010-03-17 17:52:21 +0000575 return;
576 }
577
578 O << "[" << getRegisterName(MO1.getReg());
Bill Wendlingf4caf692010-12-14 03:36:38 +0000579 if (unsigned RegNum = MO2.getReg())
580 O << ", " << getRegisterName(RegNum);
581 O << "]";
582}
583
584void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI,
585 unsigned Op,
586 raw_ostream &O,
587 unsigned Scale) {
588 const MCOperand &MO1 = MI->getOperand(Op);
589 const MCOperand &MO2 = MI->getOperand(Op + 1);
590
591 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
592 printOperand(MI, Op, O);
593 return;
594 }
595
596 O << "[" << getRegisterName(MO1.getReg());
597 if (unsigned ImmOffs = MO2.getImm())
Johnny Chen9e088762010-03-17 17:52:21 +0000598 O << ", #" << ImmOffs * Scale;
599 O << "]";
600}
601
Bill Wendlingf4caf692010-12-14 03:36:38 +0000602void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI,
603 unsigned Op,
604 raw_ostream &O) {
605 printThumbAddrModeImm5SOperand(MI, Op, O, 1);
Johnny Chen9e088762010-03-17 17:52:21 +0000606}
607
Bill Wendlingf4caf692010-12-14 03:36:38 +0000608void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI,
609 unsigned Op,
610 raw_ostream &O) {
611 printThumbAddrModeImm5SOperand(MI, Op, O, 2);
Johnny Chen9e088762010-03-17 17:52:21 +0000612}
613
Bill Wendlingf4caf692010-12-14 03:36:38 +0000614void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI,
615 unsigned Op,
616 raw_ostream &O) {
617 printThumbAddrModeImm5SOperand(MI, Op, O, 4);
Johnny Chen9e088762010-03-17 17:52:21 +0000618}
619
Chris Lattner35c33bd2010-04-04 04:47:45 +0000620void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
621 raw_ostream &O) {
Bill Wendlingf4caf692010-12-14 03:36:38 +0000622 printThumbAddrModeImm5SOperand(MI, Op, O, 4);
Johnny Chen9e088762010-03-17 17:52:21 +0000623}
624
Johnny Chen9e088762010-03-17 17:52:21 +0000625// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
626// register with shift forms.
627// REG 0 0 - e.g. R5
628// REG IMM, SH_OPC - e.g. R5, LSL #3
Chris Lattner35c33bd2010-04-04 04:47:45 +0000629void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
630 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000631 const MCOperand &MO1 = MI->getOperand(OpNum);
632 const MCOperand &MO2 = MI->getOperand(OpNum+1);
633
634 unsigned Reg = MO1.getReg();
635 O << getRegisterName(Reg);
636
637 // Print the shift opc.
Johnny Chen9e088762010-03-17 17:52:21 +0000638 assert(MO2.isImm() && "Not a valid t2_so_reg value!");
Bob Wilson1d9125a2010-08-05 00:34:42 +0000639 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm());
640 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
641 if (ShOpc != ARM_AM::rrx)
642 O << " #" << ARM_AM::getSORegOffset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000643}
644
Jim Grosbach458f2dc2010-10-25 20:00:01 +0000645void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
646 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000647 const MCOperand &MO1 = MI->getOperand(OpNum);
648 const MCOperand &MO2 = MI->getOperand(OpNum+1);
649
Jim Grosbach3e556122010-10-26 22:37:02 +0000650 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
651 printOperand(MI, OpNum, O);
652 return;
653 }
654
Johnny Chen9e088762010-03-17 17:52:21 +0000655 O << "[" << getRegisterName(MO1.getReg());
656
Jim Grosbach77aee8e2010-10-27 01:19:41 +0000657 int32_t OffImm = (int32_t)MO2.getImm();
Jim Grosbachab682a22010-10-28 18:34:10 +0000658 bool isSub = OffImm < 0;
659 // Special value for #-0. All others are normal.
660 if (OffImm == INT32_MIN)
661 OffImm = 0;
662 if (isSub)
Jim Grosbach77aee8e2010-10-27 01:19:41 +0000663 O << ", #-" << -OffImm;
664 else if (OffImm > 0)
Johnny Chen9e088762010-03-17 17:52:21 +0000665 O << ", #" << OffImm;
666 O << "]";
667}
668
669void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000670 unsigned OpNum,
671 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000672 const MCOperand &MO1 = MI->getOperand(OpNum);
673 const MCOperand &MO2 = MI->getOperand(OpNum+1);
674
675 O << "[" << getRegisterName(MO1.getReg());
676
677 int32_t OffImm = (int32_t)MO2.getImm();
678 // Don't print +0.
679 if (OffImm < 0)
680 O << ", #-" << -OffImm;
681 else if (OffImm > 0)
682 O << ", #" << OffImm;
683 O << "]";
684}
685
686void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000687 unsigned OpNum,
688 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000689 const MCOperand &MO1 = MI->getOperand(OpNum);
690 const MCOperand &MO2 = MI->getOperand(OpNum+1);
691
692 O << "[" << getRegisterName(MO1.getReg());
693
694 int32_t OffImm = (int32_t)MO2.getImm() / 4;
695 // Don't print +0.
696 if (OffImm < 0)
697 O << ", #-" << -OffImm * 4;
698 else if (OffImm > 0)
699 O << ", #" << OffImm * 4;
700 O << "]";
701}
702
703void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000704 unsigned OpNum,
705 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000706 const MCOperand &MO1 = MI->getOperand(OpNum);
707 int32_t OffImm = (int32_t)MO1.getImm();
708 // Don't print +0.
709 if (OffImm < 0)
710 O << "#-" << -OffImm;
711 else if (OffImm > 0)
712 O << "#" << OffImm;
713}
714
715void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000716 unsigned OpNum,
717 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000718 const MCOperand &MO1 = MI->getOperand(OpNum);
719 int32_t OffImm = (int32_t)MO1.getImm() / 4;
720 // Don't print +0.
721 if (OffImm < 0)
722 O << "#-" << -OffImm * 4;
723 else if (OffImm > 0)
724 O << "#" << OffImm * 4;
725}
726
727void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000728 unsigned OpNum,
729 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000730 const MCOperand &MO1 = MI->getOperand(OpNum);
731 const MCOperand &MO2 = MI->getOperand(OpNum+1);
732 const MCOperand &MO3 = MI->getOperand(OpNum+2);
733
734 O << "[" << getRegisterName(MO1.getReg());
735
736 assert(MO2.getReg() && "Invalid so_reg load / store address!");
737 O << ", " << getRegisterName(MO2.getReg());
738
739 unsigned ShAmt = MO3.getImm();
740 if (ShAmt) {
741 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
742 O << ", lsl #" << ShAmt;
743 }
744 O << "]";
745}
746
Chris Lattner35c33bd2010-04-04 04:47:45 +0000747void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum,
748 raw_ostream &O) {
Bill Wendling8cb415e2011-01-26 20:57:43 +0000749 const MCOperand &MO = MI->getOperand(OpNum);
750 O << '#';
751 if (MO.isFPImm()) {
752 O << (float)MO.getFPImm();
753 } else {
754 union {
755 uint32_t I;
756 float F;
757 } FPUnion;
758
759 FPUnion.I = MO.getImm();
760 O << FPUnion.F;
761 }
Johnny Chen9e088762010-03-17 17:52:21 +0000762}
763
Chris Lattner35c33bd2010-04-04 04:47:45 +0000764void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum,
765 raw_ostream &O) {
Bill Wendling8cb415e2011-01-26 20:57:43 +0000766 const MCOperand &MO = MI->getOperand(OpNum);
767 O << '#';
768 if (MO.isFPImm()) {
769 O << MO.getFPImm();
770 } else {
771 // We expect the binary encoding of a floating point number here.
772 union {
773 uint64_t I;
774 double D;
775 } FPUnion;
776
777 FPUnion.I = MO.getImm();
778 O << FPUnion.D;
779 }
Johnny Chen9e088762010-03-17 17:52:21 +0000780}
781
Bob Wilson1a913ed2010-06-11 21:34:50 +0000782void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
783 raw_ostream &O) {
Bob Wilson6dce00c2010-07-13 04:44:34 +0000784 unsigned EncodedImm = MI->getOperand(OpNum).getImm();
785 unsigned EltBits;
786 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
Bob Wilson1a913ed2010-06-11 21:34:50 +0000787 O << "#0x" << utohexstr(Val);
Johnny Chenc7b65912010-04-16 22:40:20 +0000788}