blob: b2f2f023650cc6acd63a969796ab4c69931343ce [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
Rafael Espindolacde4ce42011-06-02 02:34:55 +000032void ARMInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
33 OS << getRegisterName(RegNo);
Anton Korobeynikov57caad72011-03-05 18:43:32 +000034}
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
Chris Lattner017d9472009-10-20 00:40:56 +0000129// so_reg is a 4-operand unit corresponding to register forms of the A5.1
130// "Addressing Mode 1 - Data-processing operands" forms. This includes:
131// REG 0 0 - e.g. R5
132// REG REG 0,SH_OPC - e.g. R5, ROR R3
133// REG 0 IMM,SH_OPC - e.g. R5, LSL #3
Chris Lattner35c33bd2010-04-04 04:47:45 +0000134void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum,
135 raw_ostream &O) {
Chris Lattner017d9472009-10-20 00:40:56 +0000136 const MCOperand &MO1 = MI->getOperand(OpNum);
137 const MCOperand &MO2 = MI->getOperand(OpNum+1);
138 const MCOperand &MO3 = MI->getOperand(OpNum+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000139
Chris Lattner017d9472009-10-20 00:40:56 +0000140 O << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000141
Chris Lattner017d9472009-10-20 00:40:56 +0000142 // Print the shift opc.
Bob Wilson1d9125a2010-08-05 00:34:42 +0000143 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
144 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
Chris Lattner017d9472009-10-20 00:40:56 +0000145 if (MO2.getReg()) {
Bob Wilson1d9125a2010-08-05 00:34:42 +0000146 O << ' ' << getRegisterName(MO2.getReg());
Chris Lattner017d9472009-10-20 00:40:56 +0000147 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
Bob Wilson1d9125a2010-08-05 00:34:42 +0000148 } else if (ShOpc != ARM_AM::rrx) {
149 O << " #" << ARM_AM::getSORegOffset(MO3.getImm());
Chris Lattner017d9472009-10-20 00:40:56 +0000150 }
151}
Chris Lattner084f87d2009-10-19 21:57:05 +0000152
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000153//===--------------------------------------------------------------------===//
154// Addressing Mode #2
155//===--------------------------------------------------------------------===//
156
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000157void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
158 raw_ostream &O) {
Chris Lattner084f87d2009-10-19 21:57:05 +0000159 const MCOperand &MO1 = MI->getOperand(Op);
160 const MCOperand &MO2 = MI->getOperand(Op+1);
161 const MCOperand &MO3 = MI->getOperand(Op+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000162
Chris Lattner084f87d2009-10-19 21:57:05 +0000163 O << "[" << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000164
Chris Lattner084f87d2009-10-19 21:57:05 +0000165 if (!MO2.getReg()) {
Johnny Chen9e088762010-03-17 17:52:21 +0000166 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
Chris Lattner084f87d2009-10-19 21:57:05 +0000167 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000168 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
169 << ARM_AM::getAM2Offset(MO3.getImm());
Chris Lattner084f87d2009-10-19 21:57:05 +0000170 O << "]";
171 return;
172 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000173
Chris Lattner084f87d2009-10-19 21:57:05 +0000174 O << ", "
Johnny Chen9e088762010-03-17 17:52:21 +0000175 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
176 << getRegisterName(MO2.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000177
Chris Lattner084f87d2009-10-19 21:57:05 +0000178 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
179 O << ", "
180 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
181 << " #" << ShImm;
182 O << "]";
Jim Grosbach15d78982010-09-14 22:27:15 +0000183}
Chris Lattnere306d8d2009-10-19 22:09:23 +0000184
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000185void ARMInstPrinter::printAM2PostIndexOp(const MCInst *MI, unsigned Op,
186 raw_ostream &O) {
187 const MCOperand &MO1 = MI->getOperand(Op);
188 const MCOperand &MO2 = MI->getOperand(Op+1);
189 const MCOperand &MO3 = MI->getOperand(Op+2);
190
191 O << "[" << getRegisterName(MO1.getReg()) << "], ";
192
193 if (!MO2.getReg()) {
194 unsigned ImmOffs = ARM_AM::getAM2Offset(MO3.getImm());
195 O << '#'
196 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
197 << ImmOffs;
198 return;
199 }
200
201 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
202 << getRegisterName(MO2.getReg());
203
204 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
205 O << ", "
206 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
207 << " #" << ShImm;
208}
209
210void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
211 raw_ostream &O) {
212 const MCOperand &MO1 = MI->getOperand(Op);
213
214 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
215 printOperand(MI, Op, O);
216 return;
217 }
218
219 const MCOperand &MO3 = MI->getOperand(Op+2);
220 unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm());
221
222 if (IdxMode == ARMII::IndexModePost) {
223 printAM2PostIndexOp(MI, Op, O);
224 return;
225 }
226 printAM2PreOrOffsetIndexOp(MI, Op, O);
227}
228
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000229void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000230 unsigned OpNum,
231 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000232 const MCOperand &MO1 = MI->getOperand(OpNum);
233 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000234
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000235 if (!MO1.getReg()) {
236 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000237 O << '#'
238 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
239 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000240 return;
241 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000242
Johnny Chen9e088762010-03-17 17:52:21 +0000243 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
244 << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000245
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000246 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
247 O << ", "
248 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
249 << " #" << ShImm;
250}
251
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000252//===--------------------------------------------------------------------===//
253// Addressing Mode #3
254//===--------------------------------------------------------------------===//
255
256void ARMInstPrinter::printAM3PostIndexOp(const MCInst *MI, unsigned Op,
257 raw_ostream &O) {
258 const MCOperand &MO1 = MI->getOperand(Op);
259 const MCOperand &MO2 = MI->getOperand(Op+1);
260 const MCOperand &MO3 = MI->getOperand(Op+2);
261
262 O << "[" << getRegisterName(MO1.getReg()) << "], ";
263
264 if (MO2.getReg()) {
265 O << (char)ARM_AM::getAM3Op(MO3.getImm())
266 << getRegisterName(MO2.getReg());
267 return;
268 }
269
270 unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm());
271 O << '#'
272 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
273 << ImmOffs;
274}
275
276void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
277 raw_ostream &O) {
278 const MCOperand &MO1 = MI->getOperand(Op);
279 const MCOperand &MO2 = MI->getOperand(Op+1);
280 const MCOperand &MO3 = MI->getOperand(Op+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000281
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000282 O << '[' << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000283
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000284 if (MO2.getReg()) {
285 O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm())
286 << getRegisterName(MO2.getReg()) << ']';
287 return;
288 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000289
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000290 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
291 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000292 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
293 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000294 O << ']';
295}
296
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000297void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op,
298 raw_ostream &O) {
299 const MCOperand &MO3 = MI->getOperand(Op+2);
300 unsigned IdxMode = ARM_AM::getAM3IdxMode(MO3.getImm());
301
302 if (IdxMode == ARMII::IndexModePost) {
303 printAM3PostIndexOp(MI, Op, O);
304 return;
305 }
306 printAM3PreOrOffsetIndexOp(MI, Op, O);
307}
308
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000309void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000310 unsigned OpNum,
311 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000312 const MCOperand &MO1 = MI->getOperand(OpNum);
313 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000314
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000315 if (MO1.getReg()) {
316 O << (char)ARM_AM::getAM3Op(MO2.getImm())
317 << getRegisterName(MO1.getReg());
318 return;
319 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000320
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000321 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000322 O << '#'
323 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
324 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000325}
326
Jim Grosbache6913602010-11-03 01:01:43 +0000327void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,
Jim Grosbach0a2287b2010-11-03 01:11:15 +0000328 raw_ostream &O) {
Jim Grosbache6913602010-11-03 01:01:43 +0000329 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(OpNum)
330 .getImm());
331 O << ARM_AM::getAMSubModeStr(Mode);
Chris Lattnere306d8d2009-10-19 22:09:23 +0000332}
333
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000334void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
Jim Grosbach0a2287b2010-11-03 01:11:15 +0000335 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000336 const MCOperand &MO1 = MI->getOperand(OpNum);
337 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000338
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000339 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000340 printOperand(MI, OpNum, O);
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000341 return;
342 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000343
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000344 O << "[" << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000345
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000346 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
347 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000348 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000349 << ImmOffs * 4;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000350 }
351 O << "]";
352}
353
Chris Lattner35c33bd2010-04-04 04:47:45 +0000354void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
355 raw_ostream &O) {
Chris Lattner235e2f62009-10-20 06:22:33 +0000356 const MCOperand &MO1 = MI->getOperand(OpNum);
357 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000358
Bob Wilson226036e2010-03-20 22:13:40 +0000359 O << "[" << getRegisterName(MO1.getReg());
360 if (MO2.getImm()) {
361 // FIXME: Both darwin as and GNU as violate ARM docs here.
Bob Wilson273ff312010-07-14 23:54:43 +0000362 O << ", :" << (MO2.getImm() << 3);
Chris Lattner235e2f62009-10-20 06:22:33 +0000363 }
Bob Wilson226036e2010-03-20 22:13:40 +0000364 O << "]";
365}
366
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +0000367void ARMInstPrinter::printAddrMode7Operand(const MCInst *MI, unsigned OpNum,
368 raw_ostream &O) {
369 const MCOperand &MO1 = MI->getOperand(OpNum);
370 O << "[" << getRegisterName(MO1.getReg()) << "]";
371}
372
Bob Wilson226036e2010-03-20 22:13:40 +0000373void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000374 unsigned OpNum,
375 raw_ostream &O) {
Bob Wilson226036e2010-03-20 22:13:40 +0000376 const MCOperand &MO = MI->getOperand(OpNum);
377 if (MO.getReg() == 0)
378 O << "!";
379 else
380 O << ", " << getRegisterName(MO.getReg());
Chris Lattner235e2f62009-10-20 06:22:33 +0000381}
382
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000383void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
384 unsigned OpNum,
385 raw_ostream &O) {
Chris Lattner235e2f62009-10-20 06:22:33 +0000386 const MCOperand &MO = MI->getOperand(OpNum);
387 uint32_t v = ~MO.getImm();
388 int32_t lsb = CountTrailingZeros_32(v);
389 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
390 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
391 O << '#' << lsb << ", #" << width;
392}
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000393
Johnny Chen1adc40c2010-08-12 20:46:17 +0000394void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
395 raw_ostream &O) {
396 unsigned val = MI->getOperand(OpNum).getImm();
397 O << ARM_MB::MemBOptToString(val);
398}
399
Bob Wilson22f5dc72010-08-16 18:27:34 +0000400void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000401 raw_ostream &O) {
402 unsigned ShiftOp = MI->getOperand(OpNum).getImm();
403 ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp);
404 switch (Opc) {
405 case ARM_AM::no_shift:
406 return;
407 case ARM_AM::lsl:
408 O << ", lsl #";
409 break;
410 case ARM_AM::asr:
411 O << ", asr #";
412 break;
413 default:
Bob Wilson22f5dc72010-08-16 18:27:34 +0000414 assert(0 && "unexpected shift opcode for shift immediate operand");
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000415 }
416 O << ARM_AM::getSORegOffset(ShiftOp);
417}
418
Chris Lattner35c33bd2010-04-04 04:47:45 +0000419void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
420 raw_ostream &O) {
Chris Lattnere306d8d2009-10-19 22:09:23 +0000421 O << "{";
Johnny Chen9e088762010-03-17 17:52:21 +0000422 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
423 if (i != OpNum) O << ", ";
Chris Lattnere306d8d2009-10-19 22:09:23 +0000424 O << getRegisterName(MI->getOperand(i).getReg());
425 }
426 O << "}";
427}
Chris Lattner4d152222009-10-19 22:23:04 +0000428
Jim Grosbachb3af5de2010-10-13 21:00:04 +0000429void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum,
430 raw_ostream &O) {
431 const MCOperand &Op = MI->getOperand(OpNum);
432 if (Op.getImm())
433 O << "be";
434 else
435 O << "le";
436}
437
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000438void ARMInstPrinter::printCPSIMod(const MCInst *MI, unsigned OpNum,
439 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000440 const MCOperand &Op = MI->getOperand(OpNum);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000441 O << ARM_PROC::IModToString(Op.getImm());
442}
443
444void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum,
445 raw_ostream &O) {
446 const MCOperand &Op = MI->getOperand(OpNum);
447 unsigned IFlags = Op.getImm();
448 for (int i=2; i >= 0; --i)
449 if (IFlags & (1 << i))
450 O << ARM_PROC::IFlagsToString(1 << i);
Johnny Chen9e088762010-03-17 17:52:21 +0000451}
452
Chris Lattner35c33bd2010-04-04 04:47:45 +0000453void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
454 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000455 const MCOperand &Op = MI->getOperand(OpNum);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000456 unsigned SpecRegRBit = Op.getImm() >> 4;
457 unsigned Mask = Op.getImm() & 0xf;
458
459 if (SpecRegRBit)
460 O << "spsr";
461 else
462 O << "cpsr";
463
Johnny Chen9e088762010-03-17 17:52:21 +0000464 if (Mask) {
465 O << '_';
466 if (Mask & 8) O << 'f';
467 if (Mask & 4) O << 's';
468 if (Mask & 2) O << 'x';
469 if (Mask & 1) O << 'c';
470 }
471}
472
Chris Lattner35c33bd2010-04-04 04:47:45 +0000473void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
474 raw_ostream &O) {
Chris Lattner413ae252009-10-20 00:42:49 +0000475 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
476 if (CC != ARMCC::AL)
477 O << ARMCondCodeToString(CC);
478}
479
Jim Grosbach15d78982010-09-14 22:27:15 +0000480void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000481 unsigned OpNum,
482 raw_ostream &O) {
Johnny Chen9d3acaa2010-03-02 17:57:15 +0000483 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
484 O << ARMCondCodeToString(CC);
485}
486
Chris Lattner35c33bd2010-04-04 04:47:45 +0000487void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
488 raw_ostream &O) {
Daniel Dunbara7cc6522009-10-20 22:10:05 +0000489 if (MI->getOperand(OpNum).getReg()) {
490 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
491 "Expect ARM CPSR register!");
Chris Lattner233917c2009-10-20 00:46:11 +0000492 O << 's';
493 }
494}
495
Chris Lattner35c33bd2010-04-04 04:47:45 +0000496void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
497 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000498 O << MI->getOperand(OpNum).getImm();
499}
500
Owen Andersone4e5e2a2011-01-13 21:46:02 +0000501void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum,
502 raw_ostream &O) {
503 O << "p" << MI->getOperand(OpNum).getImm();
504}
505
506void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum,
507 raw_ostream &O) {
508 O << "c" << MI->getOperand(OpNum).getImm();
509}
510
Chris Lattner35c33bd2010-04-04 04:47:45 +0000511void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
512 raw_ostream &O) {
Jim Grosbachd30cfde2010-09-18 00:04:53 +0000513 llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
Chris Lattner4d152222009-10-19 22:23:04 +0000514}
Evan Cheng2ef9c8a2009-11-19 06:57:41 +0000515
Chris Lattner35c33bd2010-04-04 04:47:45 +0000516void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
517 raw_ostream &O) {
Johnny Chen541ba7d2010-01-25 22:13:10 +0000518 O << "#" << MI->getOperand(OpNum).getImm() * 4;
Evan Cheng2ef9c8a2009-11-19 06:57:41 +0000519}
Johnny Chen9e088762010-03-17 17:52:21 +0000520
Chris Lattner35c33bd2010-04-04 04:47:45 +0000521void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
522 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000523 // (3 - the number of trailing zeros) is the number of then / else.
524 unsigned Mask = MI->getOperand(OpNum).getImm();
525 unsigned CondBit0 = Mask >> 4 & 1;
526 unsigned NumTZ = CountTrailingZeros_32(Mask);
527 assert(NumTZ <= 3 && "Invalid IT mask!");
528 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
529 bool T = ((Mask >> Pos) & 1) == CondBit0;
530 if (T)
531 O << 't';
532 else
533 O << 'e';
534 }
535}
536
Chris Lattner35c33bd2010-04-04 04:47:45 +0000537void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
538 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000539 const MCOperand &MO1 = MI->getOperand(Op);
Bill Wendlingf4caf692010-12-14 03:36:38 +0000540 const MCOperand &MO2 = MI->getOperand(Op + 1);
Johnny Chen9e088762010-03-17 17:52:21 +0000541
542 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000543 printOperand(MI, Op, O);
Johnny Chen9e088762010-03-17 17:52:21 +0000544 return;
545 }
546
547 O << "[" << getRegisterName(MO1.getReg());
Bill Wendlingf4caf692010-12-14 03:36:38 +0000548 if (unsigned RegNum = MO2.getReg())
549 O << ", " << getRegisterName(RegNum);
550 O << "]";
551}
552
553void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI,
554 unsigned Op,
555 raw_ostream &O,
556 unsigned Scale) {
557 const MCOperand &MO1 = MI->getOperand(Op);
558 const MCOperand &MO2 = MI->getOperand(Op + 1);
559
560 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
561 printOperand(MI, Op, O);
562 return;
563 }
564
565 O << "[" << getRegisterName(MO1.getReg());
566 if (unsigned ImmOffs = MO2.getImm())
Johnny Chen9e088762010-03-17 17:52:21 +0000567 O << ", #" << ImmOffs * Scale;
568 O << "]";
569}
570
Bill Wendlingf4caf692010-12-14 03:36:38 +0000571void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI,
572 unsigned Op,
573 raw_ostream &O) {
574 printThumbAddrModeImm5SOperand(MI, Op, O, 1);
Johnny Chen9e088762010-03-17 17:52:21 +0000575}
576
Bill Wendlingf4caf692010-12-14 03:36:38 +0000577void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI,
578 unsigned Op,
579 raw_ostream &O) {
580 printThumbAddrModeImm5SOperand(MI, Op, O, 2);
Johnny Chen9e088762010-03-17 17:52:21 +0000581}
582
Bill Wendlingf4caf692010-12-14 03:36:38 +0000583void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI,
584 unsigned Op,
585 raw_ostream &O) {
586 printThumbAddrModeImm5SOperand(MI, Op, O, 4);
Johnny Chen9e088762010-03-17 17:52:21 +0000587}
588
Chris Lattner35c33bd2010-04-04 04:47:45 +0000589void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
590 raw_ostream &O) {
Bill Wendlingf4caf692010-12-14 03:36:38 +0000591 printThumbAddrModeImm5SOperand(MI, Op, O, 4);
Johnny Chen9e088762010-03-17 17:52:21 +0000592}
593
Johnny Chen9e088762010-03-17 17:52:21 +0000594// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
595// register with shift forms.
596// REG 0 0 - e.g. R5
597// REG IMM, SH_OPC - e.g. R5, LSL #3
Chris Lattner35c33bd2010-04-04 04:47:45 +0000598void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
599 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000600 const MCOperand &MO1 = MI->getOperand(OpNum);
601 const MCOperand &MO2 = MI->getOperand(OpNum+1);
602
603 unsigned Reg = MO1.getReg();
604 O << getRegisterName(Reg);
605
606 // Print the shift opc.
Johnny Chen9e088762010-03-17 17:52:21 +0000607 assert(MO2.isImm() && "Not a valid t2_so_reg value!");
Bob Wilson1d9125a2010-08-05 00:34:42 +0000608 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm());
609 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
610 if (ShOpc != ARM_AM::rrx)
611 O << " #" << ARM_AM::getSORegOffset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000612}
613
Jim Grosbach458f2dc2010-10-25 20:00:01 +0000614void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
615 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000616 const MCOperand &MO1 = MI->getOperand(OpNum);
617 const MCOperand &MO2 = MI->getOperand(OpNum+1);
618
Jim Grosbach3e556122010-10-26 22:37:02 +0000619 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
620 printOperand(MI, OpNum, O);
621 return;
622 }
623
Johnny Chen9e088762010-03-17 17:52:21 +0000624 O << "[" << getRegisterName(MO1.getReg());
625
Jim Grosbach77aee8e2010-10-27 01:19:41 +0000626 int32_t OffImm = (int32_t)MO2.getImm();
Jim Grosbachab682a22010-10-28 18:34:10 +0000627 bool isSub = OffImm < 0;
628 // Special value for #-0. All others are normal.
629 if (OffImm == INT32_MIN)
630 OffImm = 0;
631 if (isSub)
Jim Grosbach77aee8e2010-10-27 01:19:41 +0000632 O << ", #-" << -OffImm;
633 else if (OffImm > 0)
Johnny Chen9e088762010-03-17 17:52:21 +0000634 O << ", #" << OffImm;
635 O << "]";
636}
637
638void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000639 unsigned OpNum,
640 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000641 const MCOperand &MO1 = MI->getOperand(OpNum);
642 const MCOperand &MO2 = MI->getOperand(OpNum+1);
643
644 O << "[" << getRegisterName(MO1.getReg());
645
646 int32_t OffImm = (int32_t)MO2.getImm();
647 // Don't print +0.
648 if (OffImm < 0)
649 O << ", #-" << -OffImm;
650 else if (OffImm > 0)
651 O << ", #" << OffImm;
652 O << "]";
653}
654
655void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000656 unsigned OpNum,
657 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000658 const MCOperand &MO1 = MI->getOperand(OpNum);
659 const MCOperand &MO2 = MI->getOperand(OpNum+1);
660
661 O << "[" << getRegisterName(MO1.getReg());
662
663 int32_t OffImm = (int32_t)MO2.getImm() / 4;
664 // Don't print +0.
665 if (OffImm < 0)
666 O << ", #-" << -OffImm * 4;
667 else if (OffImm > 0)
668 O << ", #" << OffImm * 4;
669 O << "]";
670}
671
672void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000673 unsigned OpNum,
674 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000675 const MCOperand &MO1 = MI->getOperand(OpNum);
676 int32_t OffImm = (int32_t)MO1.getImm();
677 // Don't print +0.
678 if (OffImm < 0)
679 O << "#-" << -OffImm;
680 else if (OffImm > 0)
681 O << "#" << OffImm;
682}
683
684void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000685 unsigned OpNum,
686 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000687 const MCOperand &MO1 = MI->getOperand(OpNum);
688 int32_t OffImm = (int32_t)MO1.getImm() / 4;
689 // Don't print +0.
690 if (OffImm < 0)
691 O << "#-" << -OffImm * 4;
692 else if (OffImm > 0)
693 O << "#" << OffImm * 4;
694}
695
696void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000697 unsigned OpNum,
698 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000699 const MCOperand &MO1 = MI->getOperand(OpNum);
700 const MCOperand &MO2 = MI->getOperand(OpNum+1);
701 const MCOperand &MO3 = MI->getOperand(OpNum+2);
702
703 O << "[" << getRegisterName(MO1.getReg());
704
705 assert(MO2.getReg() && "Invalid so_reg load / store address!");
706 O << ", " << getRegisterName(MO2.getReg());
707
708 unsigned ShAmt = MO3.getImm();
709 if (ShAmt) {
710 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
711 O << ", lsl #" << ShAmt;
712 }
713 O << "]";
714}
715
Chris Lattner35c33bd2010-04-04 04:47:45 +0000716void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum,
717 raw_ostream &O) {
Bill Wendling8cb415e2011-01-26 20:57:43 +0000718 const MCOperand &MO = MI->getOperand(OpNum);
719 O << '#';
720 if (MO.isFPImm()) {
721 O << (float)MO.getFPImm();
722 } else {
723 union {
724 uint32_t I;
725 float F;
726 } FPUnion;
727
728 FPUnion.I = MO.getImm();
729 O << FPUnion.F;
730 }
Johnny Chen9e088762010-03-17 17:52:21 +0000731}
732
Chris Lattner35c33bd2010-04-04 04:47:45 +0000733void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum,
734 raw_ostream &O) {
Bill Wendling8cb415e2011-01-26 20:57:43 +0000735 const MCOperand &MO = MI->getOperand(OpNum);
736 O << '#';
737 if (MO.isFPImm()) {
738 O << MO.getFPImm();
739 } else {
740 // We expect the binary encoding of a floating point number here.
741 union {
742 uint64_t I;
743 double D;
744 } FPUnion;
745
746 FPUnion.I = MO.getImm();
747 O << FPUnion.D;
748 }
Johnny Chen9e088762010-03-17 17:52:21 +0000749}
750
Bob Wilson1a913ed2010-06-11 21:34:50 +0000751void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
752 raw_ostream &O) {
Bob Wilson6dce00c2010-07-13 04:44:34 +0000753 unsigned EncodedImm = MI->getOperand(OpNum).getImm();
754 unsigned EltBits;
755 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
Bob Wilson1a913ed2010-06-11 21:34:50 +0000756 O << "#0x" << utohexstr(Val);
Johnny Chenc7b65912010-04-16 22:40:20 +0000757}