blob: 0e1f8b38351c4bbb5c21f4f0ceb90435a54626f1 [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
25// Include the auto-generated portion of the assembly writer.
26#define MachineInstr MCInst
27#define ARMAsmPrinter ARMInstPrinter // FIXME: REMOVE.
Chris Lattnerfd603822009-10-19 19:56:26 +000028#include "ARMGenAsmWriter.inc"
29#undef MachineInstr
30#undef ARMAsmPrinter
31
Jim Grosbach05ae0c62010-09-14 23:54:06 +000032// Get the constituent sub-regs for a dregpair from a Q register.
33static std::pair<unsigned, unsigned> GetDRegPair(unsigned QReg) {
34 switch (QReg) {
Daniel Dunbar6b7c2cf2010-03-19 03:18:23 +000035 default:
36 assert(0 && "Unexpected register enum");
Jim Grosbach05ae0c62010-09-14 23:54:06 +000037 case ARM::Q0: return std::pair<unsigned, unsigned>(ARM::D0, ARM::D1);
38 case ARM::Q1: return std::pair<unsigned, unsigned>(ARM::D2, ARM::D3);
39 case ARM::Q2: return std::pair<unsigned, unsigned>(ARM::D4, ARM::D5);
40 case ARM::Q3: return std::pair<unsigned, unsigned>(ARM::D6, ARM::D7);
41 case ARM::Q4: return std::pair<unsigned, unsigned>(ARM::D8, ARM::D9);
42 case ARM::Q5: return std::pair<unsigned, unsigned>(ARM::D10, ARM::D11);
43 case ARM::Q6: return std::pair<unsigned, unsigned>(ARM::D12, ARM::D13);
44 case ARM::Q7: return std::pair<unsigned, unsigned>(ARM::D14, ARM::D15);
45 case ARM::Q8: return std::pair<unsigned, unsigned>(ARM::D16, ARM::D17);
46 case ARM::Q9: return std::pair<unsigned, unsigned>(ARM::D18, ARM::D19);
47 case ARM::Q10: return std::pair<unsigned, unsigned>(ARM::D20, ARM::D21);
48 case ARM::Q11: return std::pair<unsigned, unsigned>(ARM::D22, ARM::D23);
49 case ARM::Q12: return std::pair<unsigned, unsigned>(ARM::D24, ARM::D25);
50 case ARM::Q13: return std::pair<unsigned, unsigned>(ARM::D26, ARM::D27);
51 case ARM::Q14: return std::pair<unsigned, unsigned>(ARM::D28, ARM::D29);
52 case ARM::Q15: return std::pair<unsigned, unsigned>(ARM::D30, ARM::D31);
Johnny Chen9e088762010-03-17 17:52:21 +000053 }
54}
55
Chris Lattnerd3740872010-04-04 05:04:31 +000056void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +000057 // Check for MOVs and print canonical forms, instead.
58 if (MI->getOpcode() == ARM::MOVs) {
59 const MCOperand &Dst = MI->getOperand(0);
60 const MCOperand &MO1 = MI->getOperand(1);
61 const MCOperand &MO2 = MI->getOperand(2);
62 const MCOperand &MO3 = MI->getOperand(3);
63
64 O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
Chris Lattner35c33bd2010-04-04 04:47:45 +000065 printSBitModifierOperand(MI, 6, O);
66 printPredicateOperand(MI, 4, O);
Johnny Chen9e088762010-03-17 17:52:21 +000067
68 O << '\t' << getRegisterName(Dst.getReg())
69 << ", " << getRegisterName(MO1.getReg());
70
71 if (ARM_AM::getSORegShOp(MO3.getImm()) == ARM_AM::rrx)
72 return;
73
74 O << ", ";
75
76 if (MO2.getReg()) {
77 O << getRegisterName(MO2.getReg());
78 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
79 } else {
80 O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
81 }
82 return;
83 }
84
85 // A8.6.123 PUSH
86 if ((MI->getOpcode() == ARM::STM_UPD || MI->getOpcode() == ARM::t2STM_UPD) &&
87 MI->getOperand(0).getReg() == ARM::SP) {
88 const MCOperand &MO1 = MI->getOperand(2);
89 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) {
90 O << '\t' << "push";
Chris Lattner35c33bd2010-04-04 04:47:45 +000091 printPredicateOperand(MI, 3, O);
Johnny Chen9e088762010-03-17 17:52:21 +000092 O << '\t';
Chris Lattner35c33bd2010-04-04 04:47:45 +000093 printRegisterList(MI, 5, O);
Johnny Chen9e088762010-03-17 17:52:21 +000094 return;
95 }
96 }
97
98 // A8.6.122 POP
99 if ((MI->getOpcode() == ARM::LDM_UPD || MI->getOpcode() == ARM::t2LDM_UPD) &&
100 MI->getOperand(0).getReg() == ARM::SP) {
101 const MCOperand &MO1 = MI->getOperand(2);
102 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) {
103 O << '\t' << "pop";
Chris Lattner35c33bd2010-04-04 04:47:45 +0000104 printPredicateOperand(MI, 3, O);
Johnny Chen9e088762010-03-17 17:52:21 +0000105 O << '\t';
Chris Lattner35c33bd2010-04-04 04:47:45 +0000106 printRegisterList(MI, 5, O);
Johnny Chen9e088762010-03-17 17:52:21 +0000107 return;
108 }
109 }
110
111 // A8.6.355 VPUSH
112 if ((MI->getOpcode() == ARM::VSTMS_UPD || MI->getOpcode() ==ARM::VSTMD_UPD) &&
113 MI->getOperand(0).getReg() == ARM::SP) {
114 const MCOperand &MO1 = MI->getOperand(2);
Bob Wilsond4bfd542010-08-27 23:18:17 +0000115 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) {
Johnny Chen9e088762010-03-17 17:52:21 +0000116 O << '\t' << "vpush";
Chris Lattner35c33bd2010-04-04 04:47:45 +0000117 printPredicateOperand(MI, 3, O);
Johnny Chen9e088762010-03-17 17:52:21 +0000118 O << '\t';
Chris Lattner35c33bd2010-04-04 04:47:45 +0000119 printRegisterList(MI, 5, O);
Johnny Chen9e088762010-03-17 17:52:21 +0000120 return;
121 }
122 }
123
124 // A8.6.354 VPOP
125 if ((MI->getOpcode() == ARM::VLDMS_UPD || MI->getOpcode() ==ARM::VLDMD_UPD) &&
126 MI->getOperand(0).getReg() == ARM::SP) {
127 const MCOperand &MO1 = MI->getOperand(2);
Bob Wilsond4bfd542010-08-27 23:18:17 +0000128 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) {
Johnny Chen9e088762010-03-17 17:52:21 +0000129 O << '\t' << "vpop";
Chris Lattner35c33bd2010-04-04 04:47:45 +0000130 printPredicateOperand(MI, 3, O);
Johnny Chen9e088762010-03-17 17:52:21 +0000131 O << '\t';
Chris Lattner35c33bd2010-04-04 04:47:45 +0000132 printRegisterList(MI, 5, O);
Johnny Chen9e088762010-03-17 17:52:21 +0000133 return;
134 }
135 }
136
Chris Lattner35c33bd2010-04-04 04:47:45 +0000137 printInstruction(MI, O);
Johnny Chen9e088762010-03-17 17:52:21 +0000138 }
Chris Lattnerfd603822009-10-19 19:56:26 +0000139
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000140void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000141 raw_ostream &O, const char *Modifier) {
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000142 const MCOperand &Op = MI->getOperand(OpNo);
143 if (Op.isReg()) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000144 unsigned Reg = Op.getReg();
145 if (Modifier && strcmp(Modifier, "dregpair") == 0) {
Jim Grosbach05ae0c62010-09-14 23:54:06 +0000146 std::pair<unsigned, unsigned> dregpair = GetDRegPair(Reg);
147 O << '{' << getRegisterName(dregpair.first) << ", "
148 << getRegisterName(dregpair.second) << '}';
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000149 } else if (Modifier && strcmp(Modifier, "lane") == 0) {
Jim Grosbach05ae0c62010-09-14 23:54:06 +0000150 // FIXME
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000151 assert(0);
152 /*
153 unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg);
154 unsigned DReg = TRI->getMatchingSuperReg(Reg, RegNum & 1 ? 2 : 1,
155 &ARM::DPR_VFP2RegClass);
156 O << getRegisterName(DReg) << '[' << (RegNum & 1) << ']';
157 */
158 } else {
159 O << getRegisterName(Reg);
160 }
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000161 } else if (Op.isImm()) {
Daniel Dunbar6b7c2cf2010-03-19 03:18:23 +0000162 assert((Modifier && !strcmp(Modifier, "call")) ||
Johnny Chen9e088762010-03-17 17:52:21 +0000163 ((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"));
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000164 O << '#' << Op.getImm();
165 } else {
Rafael Espindola18c10212010-05-12 05:16:34 +0000166 if (Modifier && Modifier[0] != 0 && strcmp(Modifier, "call") != 0)
167 llvm_unreachable("Unsupported modifier");
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000168 assert(Op.isExpr() && "unknown operand kind in printOperand");
Chris Lattner8cb9a3b2010-01-18 00:37:40 +0000169 O << *Op.getExpr();
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000170 }
171}
Chris Lattner61d35c22009-10-19 21:21:39 +0000172
173static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm,
174 const MCAsmInfo *MAI) {
175 // Break it up into two parts that make up a shifter immediate.
Bob Wilsonb123b8b2010-04-13 02:11:48 +0000176 V = ARM_AM::getSOImmVal(V);
Chris Lattner61d35c22009-10-19 21:21:39 +0000177 assert(V != -1 && "Not a valid so_imm value!");
Jim Grosbach15d78982010-09-14 22:27:15 +0000178
Chris Lattner61d35c22009-10-19 21:21:39 +0000179 unsigned Imm = ARM_AM::getSOImmValImm(V);
180 unsigned Rot = ARM_AM::getSOImmValRot(V);
Jim Grosbach15d78982010-09-14 22:27:15 +0000181
Chris Lattner61d35c22009-10-19 21:21:39 +0000182 // Print low-level immediate formation info, per
183 // A5.1.3: "Data-processing operands - Immediate".
184 if (Rot) {
185 O << "#" << Imm << ", " << Rot;
186 // Pretty printed version.
187 if (VerboseAsm)
188 O << ' ' << MAI->getCommentString()
189 << ' ' << (int)ARM_AM::rotr32(Imm, Rot);
190 } else {
191 O << "#" << Imm;
192 }
193}
194
195
196/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
197/// immediate in bits 0-7.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000198void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum,
199 raw_ostream &O) {
Chris Lattner61d35c22009-10-19 21:21:39 +0000200 const MCOperand &MO = MI->getOperand(OpNum);
201 assert(MO.isImm() && "Not a valid so_imm value!");
202 printSOImm(O, MO.getImm(), VerboseAsm, &MAI);
203}
Chris Lattner084f87d2009-10-19 21:57:05 +0000204
Chris Lattner017d9472009-10-20 00:40:56 +0000205/// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov'
206/// followed by an 'orr' to materialize.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000207void ARMInstPrinter::printSOImm2PartOperand(const MCInst *MI, unsigned OpNum,
208 raw_ostream &O) {
Chris Lattner017d9472009-10-20 00:40:56 +0000209 // FIXME: REMOVE this method.
210 abort();
211}
212
213// so_reg is a 4-operand unit corresponding to register forms of the A5.1
214// "Addressing Mode 1 - Data-processing operands" forms. This includes:
215// REG 0 0 - e.g. R5
216// REG REG 0,SH_OPC - e.g. R5, ROR R3
217// REG 0 IMM,SH_OPC - e.g. R5, LSL #3
Chris Lattner35c33bd2010-04-04 04:47:45 +0000218void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum,
219 raw_ostream &O) {
Chris Lattner017d9472009-10-20 00:40:56 +0000220 const MCOperand &MO1 = MI->getOperand(OpNum);
221 const MCOperand &MO2 = MI->getOperand(OpNum+1);
222 const MCOperand &MO3 = MI->getOperand(OpNum+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000223
Chris Lattner017d9472009-10-20 00:40:56 +0000224 O << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000225
Chris Lattner017d9472009-10-20 00:40:56 +0000226 // Print the shift opc.
Bob Wilson1d9125a2010-08-05 00:34:42 +0000227 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
228 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
Chris Lattner017d9472009-10-20 00:40:56 +0000229 if (MO2.getReg()) {
Bob Wilson1d9125a2010-08-05 00:34:42 +0000230 O << ' ' << getRegisterName(MO2.getReg());
Chris Lattner017d9472009-10-20 00:40:56 +0000231 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
Bob Wilson1d9125a2010-08-05 00:34:42 +0000232 } else if (ShOpc != ARM_AM::rrx) {
233 O << " #" << ARM_AM::getSORegOffset(MO3.getImm());
Chris Lattner017d9472009-10-20 00:40:56 +0000234 }
235}
Chris Lattner084f87d2009-10-19 21:57:05 +0000236
237
Chris Lattner35c33bd2010-04-04 04:47:45 +0000238void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
239 raw_ostream &O) {
Chris Lattner084f87d2009-10-19 21:57:05 +0000240 const MCOperand &MO1 = MI->getOperand(Op);
241 const MCOperand &MO2 = MI->getOperand(Op+1);
242 const MCOperand &MO3 = MI->getOperand(Op+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000243
Chris Lattner084f87d2009-10-19 21:57:05 +0000244 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000245 printOperand(MI, Op, O);
Chris Lattner084f87d2009-10-19 21:57:05 +0000246 return;
247 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000248
Chris Lattner084f87d2009-10-19 21:57:05 +0000249 O << "[" << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000250
Chris Lattner084f87d2009-10-19 21:57:05 +0000251 if (!MO2.getReg()) {
Johnny Chen9e088762010-03-17 17:52:21 +0000252 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
Chris Lattner084f87d2009-10-19 21:57:05 +0000253 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000254 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
255 << ARM_AM::getAM2Offset(MO3.getImm());
Chris Lattner084f87d2009-10-19 21:57:05 +0000256 O << "]";
257 return;
258 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000259
Chris Lattner084f87d2009-10-19 21:57:05 +0000260 O << ", "
Johnny Chen9e088762010-03-17 17:52:21 +0000261 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
262 << getRegisterName(MO2.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000263
Chris Lattner084f87d2009-10-19 21:57:05 +0000264 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
265 O << ", "
266 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
267 << " #" << ShImm;
268 O << "]";
Jim Grosbach15d78982010-09-14 22:27:15 +0000269}
Chris Lattnere306d8d2009-10-19 22:09:23 +0000270
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000271void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000272 unsigned OpNum,
273 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000274 const MCOperand &MO1 = MI->getOperand(OpNum);
275 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000276
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000277 if (!MO1.getReg()) {
278 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000279 O << '#'
280 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
281 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000282 return;
283 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000284
Johnny Chen9e088762010-03-17 17:52:21 +0000285 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
286 << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000287
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000288 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
289 O << ", "
290 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
291 << " #" << ShImm;
292}
293
Chris Lattner35c33bd2010-04-04 04:47:45 +0000294void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum,
295 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000296 const MCOperand &MO1 = MI->getOperand(OpNum);
297 const MCOperand &MO2 = MI->getOperand(OpNum+1);
298 const MCOperand &MO3 = MI->getOperand(OpNum+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000299
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000300 O << '[' << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000301
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000302 if (MO2.getReg()) {
303 O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm())
304 << getRegisterName(MO2.getReg()) << ']';
305 return;
306 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000307
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000308 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
309 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000310 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
311 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000312 O << ']';
313}
314
315void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000316 unsigned OpNum,
317 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000318 const MCOperand &MO1 = MI->getOperand(OpNum);
319 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000320
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000321 if (MO1.getReg()) {
322 O << (char)ARM_AM::getAM3Op(MO2.getImm())
323 << getRegisterName(MO1.getReg());
324 return;
325 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000326
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000327 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000328 O << '#'
329 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
330 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000331}
332
Chris Lattnere306d8d2009-10-19 22:09:23 +0000333
334void ARMInstPrinter::printAddrMode4Operand(const MCInst *MI, unsigned OpNum,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000335 raw_ostream &O,
Chris Lattnere306d8d2009-10-19 22:09:23 +0000336 const char *Modifier) {
Chris Lattnere306d8d2009-10-19 22:09:23 +0000337 const MCOperand &MO2 = MI->getOperand(OpNum+1);
338 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
Chris Lattner306d14f2009-10-19 23:31:43 +0000339 if (Modifier && strcmp(Modifier, "submode") == 0) {
Bob Wilsonea7f22c2010-03-16 16:19:07 +0000340 O << ARM_AM::getAMSubModeStr(Mode);
Chris Lattner306d14f2009-10-19 23:31:43 +0000341 } else if (Modifier && strcmp(Modifier, "wide") == 0) {
Chris Lattnere306d8d2009-10-19 22:09:23 +0000342 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
343 if (Mode == ARM_AM::ia)
344 O << ".w";
345 } else {
Chris Lattner35c33bd2010-04-04 04:47:45 +0000346 printOperand(MI, OpNum, O);
Chris Lattnere306d8d2009-10-19 22:09:23 +0000347 }
348}
349
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000350void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000351 raw_ostream &O,
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000352 const char *Modifier) {
353 const MCOperand &MO1 = MI->getOperand(OpNum);
354 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000355
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000356 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000357 printOperand(MI, OpNum, O);
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000358 return;
359 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000360
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000361 O << "[" << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000362
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000363 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
364 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000365 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000366 << ImmOffs*4;
367 }
368 O << "]";
369}
370
Chris Lattner35c33bd2010-04-04 04:47:45 +0000371void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
372 raw_ostream &O) {
Chris Lattner235e2f62009-10-20 06:22:33 +0000373 const MCOperand &MO1 = MI->getOperand(OpNum);
374 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000375
Bob Wilson226036e2010-03-20 22:13:40 +0000376 O << "[" << getRegisterName(MO1.getReg());
377 if (MO2.getImm()) {
378 // FIXME: Both darwin as and GNU as violate ARM docs here.
Bob Wilson273ff312010-07-14 23:54:43 +0000379 O << ", :" << (MO2.getImm() << 3);
Chris Lattner235e2f62009-10-20 06:22:33 +0000380 }
Bob Wilson226036e2010-03-20 22:13:40 +0000381 O << "]";
382}
383
384void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000385 unsigned OpNum,
386 raw_ostream &O) {
Bob Wilson226036e2010-03-20 22:13:40 +0000387 const MCOperand &MO = MI->getOperand(OpNum);
388 if (MO.getReg() == 0)
389 O << "!";
390 else
391 O << ", " << getRegisterName(MO.getReg());
Chris Lattner235e2f62009-10-20 06:22:33 +0000392}
393
394void ARMInstPrinter::printAddrModePCOperand(const MCInst *MI, unsigned OpNum,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000395 raw_ostream &O,
Chris Lattner235e2f62009-10-20 06:22:33 +0000396 const char *Modifier) {
397 assert(0 && "FIXME: Implement printAddrModePCOperand");
398}
399
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000400void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
401 unsigned OpNum,
402 raw_ostream &O) {
Chris Lattner235e2f62009-10-20 06:22:33 +0000403 const MCOperand &MO = MI->getOperand(OpNum);
404 uint32_t v = ~MO.getImm();
405 int32_t lsb = CountTrailingZeros_32(v);
406 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
407 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
408 O << '#' << lsb << ", #" << width;
409}
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000410
Johnny Chen1adc40c2010-08-12 20:46:17 +0000411void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
412 raw_ostream &O) {
413 unsigned val = MI->getOperand(OpNum).getImm();
414 O << ARM_MB::MemBOptToString(val);
415}
416
Bob Wilson22f5dc72010-08-16 18:27:34 +0000417void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000418 raw_ostream &O) {
419 unsigned ShiftOp = MI->getOperand(OpNum).getImm();
420 ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp);
421 switch (Opc) {
422 case ARM_AM::no_shift:
423 return;
424 case ARM_AM::lsl:
425 O << ", lsl #";
426 break;
427 case ARM_AM::asr:
428 O << ", asr #";
429 break;
430 default:
Bob Wilson22f5dc72010-08-16 18:27:34 +0000431 assert(0 && "unexpected shift opcode for shift immediate operand");
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000432 }
433 O << ARM_AM::getSORegOffset(ShiftOp);
434}
435
Chris Lattner35c33bd2010-04-04 04:47:45 +0000436void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
437 raw_ostream &O) {
Chris Lattnere306d8d2009-10-19 22:09:23 +0000438 O << "{";
Johnny Chen9e088762010-03-17 17:52:21 +0000439 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
440 if (i != OpNum) O << ", ";
Chris Lattnere306d8d2009-10-19 22:09:23 +0000441 O << getRegisterName(MI->getOperand(i).getReg());
442 }
443 O << "}";
444}
Chris Lattner4d152222009-10-19 22:23:04 +0000445
Chris Lattner35c33bd2010-04-04 04:47:45 +0000446void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum,
447 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000448 const MCOperand &Op = MI->getOperand(OpNum);
449 unsigned option = Op.getImm();
450 unsigned mode = option & 31;
451 bool changemode = option >> 5 & 1;
452 unsigned AIF = option >> 6 & 7;
453 unsigned imod = option >> 9 & 3;
454 if (imod == 2)
455 O << "ie";
456 else if (imod == 3)
457 O << "id";
458 O << '\t';
459 if (imod > 1) {
460 if (AIF & 4) O << 'a';
461 if (AIF & 2) O << 'i';
462 if (AIF & 1) O << 'f';
463 if (AIF > 0 && changemode) O << ", ";
464 }
465 if (changemode)
466 O << '#' << mode;
467}
468
Chris Lattner35c33bd2010-04-04 04:47:45 +0000469void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
470 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000471 const MCOperand &Op = MI->getOperand(OpNum);
472 unsigned Mask = Op.getImm();
473 if (Mask) {
474 O << '_';
475 if (Mask & 8) O << 'f';
476 if (Mask & 4) O << 's';
477 if (Mask & 2) O << 'x';
478 if (Mask & 1) O << 'c';
479 }
480}
481
Chris Lattner35c33bd2010-04-04 04:47:45 +0000482void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum,
483 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000484 const MCOperand &Op = MI->getOperand(OpNum);
485 O << '#';
486 if (Op.getImm() < 0)
487 O << '-' << (-Op.getImm() - 1);
488 else
489 O << Op.getImm();
490}
491
Chris Lattner35c33bd2010-04-04 04:47:45 +0000492void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
493 raw_ostream &O) {
Chris Lattner413ae252009-10-20 00:42:49 +0000494 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
495 if (CC != ARMCC::AL)
496 O << ARMCondCodeToString(CC);
497}
498
Jim Grosbach15d78982010-09-14 22:27:15 +0000499void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000500 unsigned OpNum,
501 raw_ostream &O) {
Johnny Chen9d3acaa2010-03-02 17:57:15 +0000502 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
503 O << ARMCondCodeToString(CC);
504}
505
Chris Lattner35c33bd2010-04-04 04:47:45 +0000506void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
507 raw_ostream &O) {
Daniel Dunbara7cc6522009-10-20 22:10:05 +0000508 if (MI->getOperand(OpNum).getReg()) {
509 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
510 "Expect ARM CPSR register!");
Chris Lattner233917c2009-10-20 00:46:11 +0000511 O << 's';
512 }
513}
514
515
Chris Lattner4d152222009-10-19 22:23:04 +0000516
Chris Lattnera70e6442009-10-19 22:33:05 +0000517void ARMInstPrinter::printCPInstOperand(const MCInst *MI, unsigned OpNum,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000518 raw_ostream &O,
Chris Lattnera70e6442009-10-19 22:33:05 +0000519 const char *Modifier) {
520 // FIXME: remove this.
521 abort();
522}
Chris Lattner4d152222009-10-19 22:23:04 +0000523
Chris Lattner35c33bd2010-04-04 04:47:45 +0000524void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
525 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000526 O << MI->getOperand(OpNum).getImm();
527}
528
529
Chris Lattner35c33bd2010-04-04 04:47:45 +0000530void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
531 raw_ostream &O) {
Chris Lattner4d152222009-10-19 22:23:04 +0000532 // FIXME: remove this.
533 abort();
534}
Evan Cheng2ef9c8a2009-11-19 06:57:41 +0000535
Chris Lattner35c33bd2010-04-04 04:47:45 +0000536void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
537 raw_ostream &O) {
Johnny Chen541ba7d2010-01-25 22:13:10 +0000538 O << "#" << MI->getOperand(OpNum).getImm() * 4;
Evan Cheng2ef9c8a2009-11-19 06:57:41 +0000539}
Johnny Chen9e088762010-03-17 17:52:21 +0000540
Chris Lattner35c33bd2010-04-04 04:47:45 +0000541void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
542 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000543 // (3 - the number of trailing zeros) is the number of then / else.
544 unsigned Mask = MI->getOperand(OpNum).getImm();
545 unsigned CondBit0 = Mask >> 4 & 1;
546 unsigned NumTZ = CountTrailingZeros_32(Mask);
547 assert(NumTZ <= 3 && "Invalid IT mask!");
548 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
549 bool T = ((Mask >> Pos) & 1) == CondBit0;
550 if (T)
551 O << 't';
552 else
553 O << 'e';
554 }
555}
556
Chris Lattner35c33bd2010-04-04 04:47:45 +0000557void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
558 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000559 const MCOperand &MO1 = MI->getOperand(Op);
560 const MCOperand &MO2 = MI->getOperand(Op+1);
561 O << "[" << getRegisterName(MO1.getReg());
562 O << ", " << getRegisterName(MO2.getReg()) << "]";
563}
564
565void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000566 raw_ostream &O,
Johnny Chen9e088762010-03-17 17:52:21 +0000567 unsigned Scale) {
568 const MCOperand &MO1 = MI->getOperand(Op);
569 const MCOperand &MO2 = MI->getOperand(Op+1);
570 const MCOperand &MO3 = MI->getOperand(Op+2);
571
572 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000573 printOperand(MI, Op, O);
Johnny Chen9e088762010-03-17 17:52:21 +0000574 return;
575 }
576
577 O << "[" << getRegisterName(MO1.getReg());
578 if (MO3.getReg())
579 O << ", " << getRegisterName(MO3.getReg());
580 else if (unsigned ImmOffs = MO2.getImm())
581 O << ", #" << ImmOffs * Scale;
582 O << "]";
583}
584
Chris Lattner35c33bd2010-04-04 04:47:45 +0000585void ARMInstPrinter::printThumbAddrModeS1Operand(const MCInst *MI, unsigned Op,
586 raw_ostream &O) {
587 printThumbAddrModeRI5Operand(MI, Op, O, 1);
Johnny Chen9e088762010-03-17 17:52:21 +0000588}
589
Chris Lattner35c33bd2010-04-04 04:47:45 +0000590void ARMInstPrinter::printThumbAddrModeS2Operand(const MCInst *MI, unsigned Op,
591 raw_ostream &O) {
592 printThumbAddrModeRI5Operand(MI, Op, O, 2);
Johnny Chen9e088762010-03-17 17:52:21 +0000593}
594
Chris Lattner35c33bd2010-04-04 04:47:45 +0000595void ARMInstPrinter::printThumbAddrModeS4Operand(const MCInst *MI, unsigned Op,
596 raw_ostream &O) {
597 printThumbAddrModeRI5Operand(MI, Op, O, 4);
Johnny Chen9e088762010-03-17 17:52:21 +0000598}
599
Chris Lattner35c33bd2010-04-04 04:47:45 +0000600void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
601 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000602 const MCOperand &MO1 = MI->getOperand(Op);
603 const MCOperand &MO2 = MI->getOperand(Op+1);
604 O << "[" << getRegisterName(MO1.getReg());
605 if (unsigned ImmOffs = MO2.getImm())
606 O << ", #" << ImmOffs*4;
607 O << "]";
608}
609
Chris Lattner35c33bd2010-04-04 04:47:45 +0000610void ARMInstPrinter::printTBAddrMode(const MCInst *MI, unsigned OpNum,
611 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000612 O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg());
613 if (MI->getOpcode() == ARM::t2TBH)
614 O << ", lsl #1";
615 O << ']';
616}
617
618// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
619// register with shift forms.
620// REG 0 0 - e.g. R5
621// REG IMM, SH_OPC - e.g. R5, LSL #3
Chris Lattner35c33bd2010-04-04 04:47:45 +0000622void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
623 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000624 const MCOperand &MO1 = MI->getOperand(OpNum);
625 const MCOperand &MO2 = MI->getOperand(OpNum+1);
626
627 unsigned Reg = MO1.getReg();
628 O << getRegisterName(Reg);
629
630 // Print the shift opc.
Johnny Chen9e088762010-03-17 17:52:21 +0000631 assert(MO2.isImm() && "Not a valid t2_so_reg value!");
Bob Wilson1d9125a2010-08-05 00:34:42 +0000632 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm());
633 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
634 if (ShOpc != ARM_AM::rrx)
635 O << " #" << ARM_AM::getSORegOffset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000636}
637
638void ARMInstPrinter::printT2AddrModeImm12Operand(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 unsigned OffImm = MO2.getImm();
647 if (OffImm) // Don't print +0.
648 O << ", #" << OffImm;
649 O << "]";
650}
651
652void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000653 unsigned OpNum,
654 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000655 const MCOperand &MO1 = MI->getOperand(OpNum);
656 const MCOperand &MO2 = MI->getOperand(OpNum+1);
657
658 O << "[" << getRegisterName(MO1.getReg());
659
660 int32_t OffImm = (int32_t)MO2.getImm();
661 // Don't print +0.
662 if (OffImm < 0)
663 O << ", #-" << -OffImm;
664 else if (OffImm > 0)
665 O << ", #" << OffImm;
666 O << "]";
667}
668
669void ARMInstPrinter::printT2AddrModeImm8s4Operand(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() / 4;
678 // Don't print +0.
679 if (OffImm < 0)
680 O << ", #-" << -OffImm * 4;
681 else if (OffImm > 0)
682 O << ", #" << OffImm * 4;
683 O << "]";
684}
685
686void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(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 int32_t OffImm = (int32_t)MO1.getImm();
691 // Don't print +0.
692 if (OffImm < 0)
693 O << "#-" << -OffImm;
694 else if (OffImm > 0)
695 O << "#" << OffImm;
696}
697
698void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000699 unsigned OpNum,
700 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000701 const MCOperand &MO1 = MI->getOperand(OpNum);
702 int32_t OffImm = (int32_t)MO1.getImm() / 4;
703 // Don't print +0.
704 if (OffImm < 0)
705 O << "#-" << -OffImm * 4;
706 else if (OffImm > 0)
707 O << "#" << OffImm * 4;
708}
709
710void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000711 unsigned OpNum,
712 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000713 const MCOperand &MO1 = MI->getOperand(OpNum);
714 const MCOperand &MO2 = MI->getOperand(OpNum+1);
715 const MCOperand &MO3 = MI->getOperand(OpNum+2);
716
717 O << "[" << getRegisterName(MO1.getReg());
718
719 assert(MO2.getReg() && "Invalid so_reg load / store address!");
720 O << ", " << getRegisterName(MO2.getReg());
721
722 unsigned ShAmt = MO3.getImm();
723 if (ShAmt) {
724 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
725 O << ", lsl #" << ShAmt;
726 }
727 O << "]";
728}
729
Chris Lattner35c33bd2010-04-04 04:47:45 +0000730void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum,
731 raw_ostream &O) {
Jim Grosbach26edbcb2010-09-15 18:47:08 +0000732 O << '#' << MI->getOperand(OpNum).getFPImm().convertToFloat();
Johnny Chen9e088762010-03-17 17:52:21 +0000733}
734
Chris Lattner35c33bd2010-04-04 04:47:45 +0000735void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum,
736 raw_ostream &O) {
Jim Grosbach26edbcb2010-09-15 18:47:08 +0000737 O << '#' << MI->getOperand(OpNum).getFPImm().convertToDouble();
Johnny Chen9e088762010-03-17 17:52:21 +0000738}
739
Bob Wilson1a913ed2010-06-11 21:34:50 +0000740void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
741 raw_ostream &O) {
Bob Wilson6dce00c2010-07-13 04:44:34 +0000742 unsigned EncodedImm = MI->getOperand(OpNum).getImm();
743 unsigned EltBits;
744 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
Bob Wilson1a913ed2010-06-11 21:34:50 +0000745 O << "#0x" << utohexstr(Val);
Johnny Chenc7b65912010-04-16 22:40:20 +0000746}