blob: c998748d47282d79cfc4a2e194ecc1d3e2277a84 [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"
Bruno Cardoso Lopes40829ed2011-03-30 23:32:32 +000017#include "ARMInstrInfo.h"
Chris Lattner61d35c22009-10-19 21:21:39 +000018#include "ARMAddressingModes.h"
Chris Lattnerfd603822009-10-19 19:56:26 +000019#include "llvm/MC/MCInst.h"
Chris Lattner61d35c22009-10-19 21:21:39 +000020#include "llvm/MC/MCAsmInfo.h"
Chris Lattner6f997762009-10-19 21:53:00 +000021#include "llvm/MC/MCExpr.h"
Johnny Chenc7b65912010-04-16 22:40:20 +000022#include "llvm/ADT/StringExtras.h"
Chris Lattner6f997762009-10-19 21:53:00 +000023#include "llvm/Support/raw_ostream.h"
Chris Lattnerfd603822009-10-19 19:56:26 +000024using namespace llvm;
25
Chris Lattner6274ec42010-10-28 21:37:33 +000026#define GET_INSTRUCTION_NAME
Chris Lattnerfd603822009-10-19 19:56:26 +000027#include "ARMGenAsmWriter.inc"
Chris Lattnerfd603822009-10-19 19:56:26 +000028
Chris Lattner6274ec42010-10-28 21:37:33 +000029StringRef ARMInstPrinter::getOpcodeName(unsigned Opcode) const {
30 return getInstructionName(Opcode);
31}
32
Anton Korobeynikov57caad72011-03-05 18:43:32 +000033StringRef ARMInstPrinter::getRegName(unsigned RegNo) const {
34 return getRegisterName(RegNo);
35}
Chris Lattner6274ec42010-10-28 21:37:33 +000036
Chris Lattnerd3740872010-04-04 05:04:31 +000037void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
Bill Wendling04863d02010-11-13 10:40:19 +000038 unsigned Opcode = MI->getOpcode();
39
Johnny Chen9e088762010-03-17 17:52:21 +000040 // Check for MOVs and print canonical forms, instead.
Bill Wendling04863d02010-11-13 10:40:19 +000041 if (Opcode == ARM::MOVs) {
Jim Grosbache6be85e2010-09-17 22:36:38 +000042 // FIXME: Thumb variants?
Johnny Chen9e088762010-03-17 17:52:21 +000043 const MCOperand &Dst = MI->getOperand(0);
44 const MCOperand &MO1 = MI->getOperand(1);
45 const MCOperand &MO2 = MI->getOperand(2);
46 const MCOperand &MO3 = MI->getOperand(3);
47
48 O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
Chris Lattner35c33bd2010-04-04 04:47:45 +000049 printSBitModifierOperand(MI, 6, O);
50 printPredicateOperand(MI, 4, O);
Johnny Chen9e088762010-03-17 17:52:21 +000051
52 O << '\t' << getRegisterName(Dst.getReg())
53 << ", " << getRegisterName(MO1.getReg());
54
55 if (ARM_AM::getSORegShOp(MO3.getImm()) == ARM_AM::rrx)
56 return;
57
58 O << ", ";
59
60 if (MO2.getReg()) {
61 O << getRegisterName(MO2.getReg());
62 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
63 } else {
64 O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
65 }
66 return;
67 }
68
69 // A8.6.123 PUSH
Bill Wendling73fe34a2010-11-16 01:16:36 +000070 if ((Opcode == ARM::STMDB_UPD || Opcode == ARM::t2STMDB_UPD) &&
Johnny Chen9e088762010-03-17 17:52:21 +000071 MI->getOperand(0).getReg() == ARM::SP) {
Bill Wendling73fe34a2010-11-16 01:16:36 +000072 O << '\t' << "push";
73 printPredicateOperand(MI, 2, O);
Jim Grosbach41ad0c42010-12-03 20:33:01 +000074 if (Opcode == ARM::t2STMDB_UPD)
75 O << ".w";
Bill Wendling73fe34a2010-11-16 01:16:36 +000076 O << '\t';
77 printRegisterList(MI, 4, O);
78 return;
Johnny Chen9e088762010-03-17 17:52:21 +000079 }
80
81 // A8.6.122 POP
Bill Wendling73fe34a2010-11-16 01:16:36 +000082 if ((Opcode == ARM::LDMIA_UPD || Opcode == ARM::t2LDMIA_UPD) &&
Johnny Chen9e088762010-03-17 17:52:21 +000083 MI->getOperand(0).getReg() == ARM::SP) {
Bill Wendling73fe34a2010-11-16 01:16:36 +000084 O << '\t' << "pop";
85 printPredicateOperand(MI, 2, O);
Jim Grosbach41ad0c42010-12-03 20:33:01 +000086 if (Opcode == ARM::t2LDMIA_UPD)
87 O << ".w";
Bill Wendling73fe34a2010-11-16 01:16:36 +000088 O << '\t';
89 printRegisterList(MI, 4, O);
90 return;
Johnny Chen9e088762010-03-17 17:52:21 +000091 }
92
93 // A8.6.355 VPUSH
Bill Wendling73fe34a2010-11-16 01:16:36 +000094 if ((Opcode == ARM::VSTMSDB_UPD || Opcode == ARM::VSTMDDB_UPD) &&
Johnny Chen9e088762010-03-17 17:52:21 +000095 MI->getOperand(0).getReg() == ARM::SP) {
Bill Wendling73fe34a2010-11-16 01:16:36 +000096 O << '\t' << "vpush";
97 printPredicateOperand(MI, 2, O);
98 O << '\t';
99 printRegisterList(MI, 4, O);
100 return;
Johnny Chen9e088762010-03-17 17:52:21 +0000101 }
102
103 // A8.6.354 VPOP
Bill Wendling73fe34a2010-11-16 01:16:36 +0000104 if ((Opcode == ARM::VLDMSIA_UPD || Opcode == ARM::VLDMDIA_UPD) &&
Johnny Chen9e088762010-03-17 17:52:21 +0000105 MI->getOperand(0).getReg() == ARM::SP) {
Bill Wendling73fe34a2010-11-16 01:16:36 +0000106 O << '\t' << "vpop";
107 printPredicateOperand(MI, 2, O);
108 O << '\t';
109 printRegisterList(MI, 4, O);
110 return;
Johnny Chen9e088762010-03-17 17:52:21 +0000111 }
112
Chris Lattner35c33bd2010-04-04 04:47:45 +0000113 printInstruction(MI, O);
Bill Wendling04863d02010-11-13 10:40:19 +0000114}
Chris Lattnerfd603822009-10-19 19:56:26 +0000115
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000116void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
Jim Grosbach0a2287b2010-11-03 01:11:15 +0000117 raw_ostream &O) {
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000118 const MCOperand &Op = MI->getOperand(OpNo);
119 if (Op.isReg()) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000120 unsigned Reg = Op.getReg();
Jim Grosbach35636282010-10-06 21:22:32 +0000121 O << getRegisterName(Reg);
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000122 } else if (Op.isImm()) {
123 O << '#' << Op.getImm();
124 } else {
125 assert(Op.isExpr() && "unknown operand kind in printOperand");
Chris Lattner8cb9a3b2010-01-18 00:37:40 +0000126 O << *Op.getExpr();
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000127 }
128}
Chris Lattner61d35c22009-10-19 21:21:39 +0000129
Jim Grosbach74d7e6c2010-09-17 21:33:25 +0000130static void printSOImm(raw_ostream &O, int64_t V, raw_ostream *CommentStream,
Chris Lattner61d35c22009-10-19 21:21:39 +0000131 const MCAsmInfo *MAI) {
132 // Break it up into two parts that make up a shifter immediate.
Bob Wilsonb123b8b2010-04-13 02:11:48 +0000133 V = ARM_AM::getSOImmVal(V);
Chris Lattner61d35c22009-10-19 21:21:39 +0000134 assert(V != -1 && "Not a valid so_imm value!");
Jim Grosbach15d78982010-09-14 22:27:15 +0000135
Chris Lattner61d35c22009-10-19 21:21:39 +0000136 unsigned Imm = ARM_AM::getSOImmValImm(V);
137 unsigned Rot = ARM_AM::getSOImmValRot(V);
Jim Grosbach15d78982010-09-14 22:27:15 +0000138
Chris Lattner61d35c22009-10-19 21:21:39 +0000139 // Print low-level immediate formation info, per
140 // A5.1.3: "Data-processing operands - Immediate".
141 if (Rot) {
142 O << "#" << Imm << ", " << Rot;
143 // Pretty printed version.
Jim Grosbach74d7e6c2010-09-17 21:33:25 +0000144 if (CommentStream)
145 *CommentStream << (int)ARM_AM::rotr32(Imm, Rot) << "\n";
Chris Lattner61d35c22009-10-19 21:21:39 +0000146 } else {
147 O << "#" << Imm;
148 }
149}
150
151
152/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
153/// immediate in bits 0-7.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000154void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum,
155 raw_ostream &O) {
Chris Lattner61d35c22009-10-19 21:21:39 +0000156 const MCOperand &MO = MI->getOperand(OpNum);
157 assert(MO.isImm() && "Not a valid so_imm value!");
Jim Grosbach74d7e6c2010-09-17 21:33:25 +0000158 printSOImm(O, MO.getImm(), CommentStream, &MAI);
Chris Lattner61d35c22009-10-19 21:21:39 +0000159}
Chris Lattner084f87d2009-10-19 21:57:05 +0000160
Chris Lattner017d9472009-10-20 00:40:56 +0000161// so_reg is a 4-operand unit corresponding to register forms of the A5.1
162// "Addressing Mode 1 - Data-processing operands" forms. This includes:
163// REG 0 0 - e.g. R5
164// REG REG 0,SH_OPC - e.g. R5, ROR R3
165// REG 0 IMM,SH_OPC - e.g. R5, LSL #3
Chris Lattner35c33bd2010-04-04 04:47:45 +0000166void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum,
167 raw_ostream &O) {
Chris Lattner017d9472009-10-20 00:40:56 +0000168 const MCOperand &MO1 = MI->getOperand(OpNum);
169 const MCOperand &MO2 = MI->getOperand(OpNum+1);
170 const MCOperand &MO3 = MI->getOperand(OpNum+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000171
Chris Lattner017d9472009-10-20 00:40:56 +0000172 O << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000173
Chris Lattner017d9472009-10-20 00:40:56 +0000174 // Print the shift opc.
Bob Wilson1d9125a2010-08-05 00:34:42 +0000175 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
176 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
Chris Lattner017d9472009-10-20 00:40:56 +0000177 if (MO2.getReg()) {
Bob Wilson1d9125a2010-08-05 00:34:42 +0000178 O << ' ' << getRegisterName(MO2.getReg());
Chris Lattner017d9472009-10-20 00:40:56 +0000179 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
Bob Wilson1d9125a2010-08-05 00:34:42 +0000180 } else if (ShOpc != ARM_AM::rrx) {
181 O << " #" << ARM_AM::getSORegOffset(MO3.getImm());
Chris Lattner017d9472009-10-20 00:40:56 +0000182 }
183}
Chris Lattner084f87d2009-10-19 21:57:05 +0000184
Bruno Cardoso Lopes40829ed2011-03-30 23:32:32 +0000185void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
186 raw_ostream &O) {
Chris Lattner084f87d2009-10-19 21:57:05 +0000187 const MCOperand &MO1 = MI->getOperand(Op);
188 const MCOperand &MO2 = MI->getOperand(Op+1);
189 const MCOperand &MO3 = MI->getOperand(Op+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000190
Chris Lattner084f87d2009-10-19 21:57:05 +0000191 O << "[" << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000192
Chris Lattner084f87d2009-10-19 21:57:05 +0000193 if (!MO2.getReg()) {
Johnny Chen9e088762010-03-17 17:52:21 +0000194 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
Chris Lattner084f87d2009-10-19 21:57:05 +0000195 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000196 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
197 << ARM_AM::getAM2Offset(MO3.getImm());
Chris Lattner084f87d2009-10-19 21:57:05 +0000198 O << "]";
199 return;
200 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000201
Chris Lattner084f87d2009-10-19 21:57:05 +0000202 O << ", "
Johnny Chen9e088762010-03-17 17:52:21 +0000203 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
204 << getRegisterName(MO2.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000205
Chris Lattner084f87d2009-10-19 21:57:05 +0000206 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
207 O << ", "
208 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
209 << " #" << ShImm;
210 O << "]";
Jim Grosbach15d78982010-09-14 22:27:15 +0000211}
Chris Lattnere306d8d2009-10-19 22:09:23 +0000212
Bruno Cardoso Lopes40829ed2011-03-30 23:32:32 +0000213void ARMInstPrinter::printAM2PostIndexOp(const MCInst *MI, unsigned Op,
214 raw_ostream &O) {
215 const MCOperand &MO1 = MI->getOperand(Op);
216 const MCOperand &MO2 = MI->getOperand(Op+1);
217 const MCOperand &MO3 = MI->getOperand(Op+2);
218
219 O << "[" << getRegisterName(MO1.getReg()) << "], ";
220
221 if (!MO2.getReg()) {
222 unsigned ImmOffs = ARM_AM::getAM2Offset(MO3.getImm());
223 O << '#'
224 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
225 << ImmOffs;
226 return;
227 }
228
229 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
230 << getRegisterName(MO2.getReg());
231
232 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
233 O << ", "
234 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
235 << " #" << ShImm;
236}
237
238void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
239 raw_ostream &O) {
240 const MCOperand &MO1 = MI->getOperand(Op);
241
242 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
243 printOperand(MI, Op, O);
244 return;
245 }
246
247 unsigned Opcode = MI->getOpcode();
248 const TargetInstrDesc &Desc = TM.getInstrInfo()->get(Opcode);
249 uint64_t TSFlags = Desc.TSFlags;
250 unsigned IdxMode = (TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
251
252 if (IdxMode == ARMII::IndexModePost) {
253 printAM2PostIndexOp(MI, Op, O);
254 return;
255 }
256 printAM2PreOrOffsetIndexOp(MI, Op, O);
257}
258
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000259void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000260 unsigned OpNum,
261 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000262 const MCOperand &MO1 = MI->getOperand(OpNum);
263 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000264
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000265 if (!MO1.getReg()) {
266 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000267 O << '#'
268 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
269 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000270 return;
271 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000272
Johnny Chen9e088762010-03-17 17:52:21 +0000273 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
274 << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000275
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000276 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
277 O << ", "
278 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
279 << " #" << ShImm;
280}
281
Chris Lattner35c33bd2010-04-04 04:47:45 +0000282void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum,
283 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000284 const MCOperand &MO1 = MI->getOperand(OpNum);
285 const MCOperand &MO2 = MI->getOperand(OpNum+1);
286 const MCOperand &MO3 = MI->getOperand(OpNum+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000287
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000288 O << '[' << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000289
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000290 if (MO2.getReg()) {
291 O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm())
292 << getRegisterName(MO2.getReg()) << ']';
293 return;
294 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000295
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000296 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
297 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000298 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
299 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000300 O << ']';
301}
302
303void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000304 unsigned OpNum,
305 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000306 const MCOperand &MO1 = MI->getOperand(OpNum);
307 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000308
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000309 if (MO1.getReg()) {
310 O << (char)ARM_AM::getAM3Op(MO2.getImm())
311 << getRegisterName(MO1.getReg());
312 return;
313 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000314
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000315 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000316 O << '#'
317 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
318 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000319}
320
Jim Grosbache6913602010-11-03 01:01:43 +0000321void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,
Jim Grosbach0a2287b2010-11-03 01:11:15 +0000322 raw_ostream &O) {
Jim Grosbache6913602010-11-03 01:01:43 +0000323 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(OpNum)
324 .getImm());
325 O << ARM_AM::getAMSubModeStr(Mode);
Chris Lattnere306d8d2009-10-19 22:09:23 +0000326}
327
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000328void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
Jim Grosbach0a2287b2010-11-03 01:11:15 +0000329 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000330 const MCOperand &MO1 = MI->getOperand(OpNum);
331 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000332
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000333 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000334 printOperand(MI, OpNum, O);
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000335 return;
336 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000337
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000338 O << "[" << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000339
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000340 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
341 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000342 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000343 << ImmOffs * 4;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000344 }
345 O << "]";
346}
347
Chris Lattner35c33bd2010-04-04 04:47:45 +0000348void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
349 raw_ostream &O) {
Chris Lattner235e2f62009-10-20 06:22:33 +0000350 const MCOperand &MO1 = MI->getOperand(OpNum);
351 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000352
Bob Wilson226036e2010-03-20 22:13:40 +0000353 O << "[" << getRegisterName(MO1.getReg());
354 if (MO2.getImm()) {
355 // FIXME: Both darwin as and GNU as violate ARM docs here.
Bob Wilson273ff312010-07-14 23:54:43 +0000356 O << ", :" << (MO2.getImm() << 3);
Chris Lattner235e2f62009-10-20 06:22:33 +0000357 }
Bob Wilson226036e2010-03-20 22:13:40 +0000358 O << "]";
359}
360
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +0000361void ARMInstPrinter::printAddrMode7Operand(const MCInst *MI, unsigned OpNum,
362 raw_ostream &O) {
363 const MCOperand &MO1 = MI->getOperand(OpNum);
364 O << "[" << getRegisterName(MO1.getReg()) << "]";
365}
366
Bob Wilson226036e2010-03-20 22:13:40 +0000367void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000368 unsigned OpNum,
369 raw_ostream &O) {
Bob Wilson226036e2010-03-20 22:13:40 +0000370 const MCOperand &MO = MI->getOperand(OpNum);
371 if (MO.getReg() == 0)
372 O << "!";
373 else
374 O << ", " << getRegisterName(MO.getReg());
Chris Lattner235e2f62009-10-20 06:22:33 +0000375}
376
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000377void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
378 unsigned OpNum,
379 raw_ostream &O) {
Chris Lattner235e2f62009-10-20 06:22:33 +0000380 const MCOperand &MO = MI->getOperand(OpNum);
381 uint32_t v = ~MO.getImm();
382 int32_t lsb = CountTrailingZeros_32(v);
383 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
384 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
385 O << '#' << lsb << ", #" << width;
386}
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000387
Johnny Chen1adc40c2010-08-12 20:46:17 +0000388void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
389 raw_ostream &O) {
390 unsigned val = MI->getOperand(OpNum).getImm();
391 O << ARM_MB::MemBOptToString(val);
392}
393
Bob Wilson22f5dc72010-08-16 18:27:34 +0000394void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000395 raw_ostream &O) {
396 unsigned ShiftOp = MI->getOperand(OpNum).getImm();
397 ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp);
398 switch (Opc) {
399 case ARM_AM::no_shift:
400 return;
401 case ARM_AM::lsl:
402 O << ", lsl #";
403 break;
404 case ARM_AM::asr:
405 O << ", asr #";
406 break;
407 default:
Bob Wilson22f5dc72010-08-16 18:27:34 +0000408 assert(0 && "unexpected shift opcode for shift immediate operand");
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000409 }
410 O << ARM_AM::getSORegOffset(ShiftOp);
411}
412
Chris Lattner35c33bd2010-04-04 04:47:45 +0000413void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
414 raw_ostream &O) {
Chris Lattnere306d8d2009-10-19 22:09:23 +0000415 O << "{";
Johnny Chen9e088762010-03-17 17:52:21 +0000416 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
417 if (i != OpNum) O << ", ";
Chris Lattnere306d8d2009-10-19 22:09:23 +0000418 O << getRegisterName(MI->getOperand(i).getReg());
419 }
420 O << "}";
421}
Chris Lattner4d152222009-10-19 22:23:04 +0000422
Jim Grosbachb3af5de2010-10-13 21:00:04 +0000423void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum,
424 raw_ostream &O) {
425 const MCOperand &Op = MI->getOperand(OpNum);
426 if (Op.getImm())
427 O << "be";
428 else
429 O << "le";
430}
431
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000432void ARMInstPrinter::printCPSIMod(const MCInst *MI, unsigned OpNum,
433 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000434 const MCOperand &Op = MI->getOperand(OpNum);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000435 O << ARM_PROC::IModToString(Op.getImm());
436}
437
438void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum,
439 raw_ostream &O) {
440 const MCOperand &Op = MI->getOperand(OpNum);
441 unsigned IFlags = Op.getImm();
442 for (int i=2; i >= 0; --i)
443 if (IFlags & (1 << i))
444 O << ARM_PROC::IFlagsToString(1 << i);
Johnny Chen9e088762010-03-17 17:52:21 +0000445}
446
Chris Lattner35c33bd2010-04-04 04:47:45 +0000447void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
448 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000449 const MCOperand &Op = MI->getOperand(OpNum);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000450 unsigned SpecRegRBit = Op.getImm() >> 4;
451 unsigned Mask = Op.getImm() & 0xf;
452
453 if (SpecRegRBit)
454 O << "spsr";
455 else
456 O << "cpsr";
457
Johnny Chen9e088762010-03-17 17:52:21 +0000458 if (Mask) {
459 O << '_';
460 if (Mask & 8) O << 'f';
461 if (Mask & 4) O << 's';
462 if (Mask & 2) O << 'x';
463 if (Mask & 1) O << 'c';
464 }
465}
466
Chris Lattner35c33bd2010-04-04 04:47:45 +0000467void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
468 raw_ostream &O) {
Chris Lattner413ae252009-10-20 00:42:49 +0000469 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
470 if (CC != ARMCC::AL)
471 O << ARMCondCodeToString(CC);
472}
473
Jim Grosbach15d78982010-09-14 22:27:15 +0000474void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000475 unsigned OpNum,
476 raw_ostream &O) {
Johnny Chen9d3acaa2010-03-02 17:57:15 +0000477 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
478 O << ARMCondCodeToString(CC);
479}
480
Chris Lattner35c33bd2010-04-04 04:47:45 +0000481void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
482 raw_ostream &O) {
Daniel Dunbara7cc6522009-10-20 22:10:05 +0000483 if (MI->getOperand(OpNum).getReg()) {
484 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
485 "Expect ARM CPSR register!");
Chris Lattner233917c2009-10-20 00:46:11 +0000486 O << 's';
487 }
488}
489
Chris Lattner35c33bd2010-04-04 04:47:45 +0000490void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
491 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000492 O << MI->getOperand(OpNum).getImm();
493}
494
Owen Andersone4e5e2a2011-01-13 21:46:02 +0000495void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum,
496 raw_ostream &O) {
497 O << "p" << MI->getOperand(OpNum).getImm();
498}
499
500void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum,
501 raw_ostream &O) {
502 O << "c" << MI->getOperand(OpNum).getImm();
503}
504
Chris Lattner35c33bd2010-04-04 04:47:45 +0000505void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
506 raw_ostream &O) {
Jim Grosbachd30cfde2010-09-18 00:04:53 +0000507 llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
Chris Lattner4d152222009-10-19 22:23:04 +0000508}
Evan Cheng2ef9c8a2009-11-19 06:57:41 +0000509
Chris Lattner35c33bd2010-04-04 04:47:45 +0000510void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
511 raw_ostream &O) {
Johnny Chen541ba7d2010-01-25 22:13:10 +0000512 O << "#" << MI->getOperand(OpNum).getImm() * 4;
Evan Cheng2ef9c8a2009-11-19 06:57:41 +0000513}
Johnny Chen9e088762010-03-17 17:52:21 +0000514
Chris Lattner35c33bd2010-04-04 04:47:45 +0000515void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
516 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000517 // (3 - the number of trailing zeros) is the number of then / else.
518 unsigned Mask = MI->getOperand(OpNum).getImm();
519 unsigned CondBit0 = Mask >> 4 & 1;
520 unsigned NumTZ = CountTrailingZeros_32(Mask);
521 assert(NumTZ <= 3 && "Invalid IT mask!");
522 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
523 bool T = ((Mask >> Pos) & 1) == CondBit0;
524 if (T)
525 O << 't';
526 else
527 O << 'e';
528 }
529}
530
Chris Lattner35c33bd2010-04-04 04:47:45 +0000531void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
532 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000533 const MCOperand &MO1 = MI->getOperand(Op);
Bill Wendlingf4caf692010-12-14 03:36:38 +0000534 const MCOperand &MO2 = MI->getOperand(Op + 1);
Johnny Chen9e088762010-03-17 17:52:21 +0000535
536 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000537 printOperand(MI, Op, O);
Johnny Chen9e088762010-03-17 17:52:21 +0000538 return;
539 }
540
541 O << "[" << getRegisterName(MO1.getReg());
Bill Wendlingf4caf692010-12-14 03:36:38 +0000542 if (unsigned RegNum = MO2.getReg())
543 O << ", " << getRegisterName(RegNum);
544 O << "]";
545}
546
547void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI,
548 unsigned Op,
549 raw_ostream &O,
550 unsigned Scale) {
551 const MCOperand &MO1 = MI->getOperand(Op);
552 const MCOperand &MO2 = MI->getOperand(Op + 1);
553
554 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
555 printOperand(MI, Op, O);
556 return;
557 }
558
559 O << "[" << getRegisterName(MO1.getReg());
560 if (unsigned ImmOffs = MO2.getImm())
Johnny Chen9e088762010-03-17 17:52:21 +0000561 O << ", #" << ImmOffs * Scale;
562 O << "]";
563}
564
Bill Wendlingf4caf692010-12-14 03:36:38 +0000565void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI,
566 unsigned Op,
567 raw_ostream &O) {
568 printThumbAddrModeImm5SOperand(MI, Op, O, 1);
Johnny Chen9e088762010-03-17 17:52:21 +0000569}
570
Bill Wendlingf4caf692010-12-14 03:36:38 +0000571void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI,
572 unsigned Op,
573 raw_ostream &O) {
574 printThumbAddrModeImm5SOperand(MI, Op, O, 2);
Johnny Chen9e088762010-03-17 17:52:21 +0000575}
576
Bill Wendlingf4caf692010-12-14 03:36:38 +0000577void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI,
578 unsigned Op,
579 raw_ostream &O) {
580 printThumbAddrModeImm5SOperand(MI, Op, O, 4);
Johnny Chen9e088762010-03-17 17:52:21 +0000581}
582
Chris Lattner35c33bd2010-04-04 04:47:45 +0000583void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
584 raw_ostream &O) {
Bill Wendlingf4caf692010-12-14 03:36:38 +0000585 printThumbAddrModeImm5SOperand(MI, Op, O, 4);
Johnny Chen9e088762010-03-17 17:52:21 +0000586}
587
Johnny Chen9e088762010-03-17 17:52:21 +0000588// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
589// register with shift forms.
590// REG 0 0 - e.g. R5
591// REG IMM, SH_OPC - e.g. R5, LSL #3
Chris Lattner35c33bd2010-04-04 04:47:45 +0000592void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
593 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000594 const MCOperand &MO1 = MI->getOperand(OpNum);
595 const MCOperand &MO2 = MI->getOperand(OpNum+1);
596
597 unsigned Reg = MO1.getReg();
598 O << getRegisterName(Reg);
599
600 // Print the shift opc.
Johnny Chen9e088762010-03-17 17:52:21 +0000601 assert(MO2.isImm() && "Not a valid t2_so_reg value!");
Bob Wilson1d9125a2010-08-05 00:34:42 +0000602 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm());
603 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
604 if (ShOpc != ARM_AM::rrx)
605 O << " #" << ARM_AM::getSORegOffset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000606}
607
Jim Grosbach458f2dc2010-10-25 20:00:01 +0000608void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
609 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000610 const MCOperand &MO1 = MI->getOperand(OpNum);
611 const MCOperand &MO2 = MI->getOperand(OpNum+1);
612
Jim Grosbach3e556122010-10-26 22:37:02 +0000613 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
614 printOperand(MI, OpNum, O);
615 return;
616 }
617
Johnny Chen9e088762010-03-17 17:52:21 +0000618 O << "[" << getRegisterName(MO1.getReg());
619
Jim Grosbach77aee8e2010-10-27 01:19:41 +0000620 int32_t OffImm = (int32_t)MO2.getImm();
Jim Grosbachab682a22010-10-28 18:34:10 +0000621 bool isSub = OffImm < 0;
622 // Special value for #-0. All others are normal.
623 if (OffImm == INT32_MIN)
624 OffImm = 0;
625 if (isSub)
Jim Grosbach77aee8e2010-10-27 01:19:41 +0000626 O << ", #-" << -OffImm;
627 else if (OffImm > 0)
Johnny Chen9e088762010-03-17 17:52:21 +0000628 O << ", #" << OffImm;
629 O << "]";
630}
631
632void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000633 unsigned OpNum,
634 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000635 const MCOperand &MO1 = MI->getOperand(OpNum);
636 const MCOperand &MO2 = MI->getOperand(OpNum+1);
637
638 O << "[" << getRegisterName(MO1.getReg());
639
640 int32_t OffImm = (int32_t)MO2.getImm();
641 // Don't print +0.
642 if (OffImm < 0)
643 O << ", #-" << -OffImm;
644 else if (OffImm > 0)
645 O << ", #" << OffImm;
646 O << "]";
647}
648
649void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000650 unsigned OpNum,
651 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000652 const MCOperand &MO1 = MI->getOperand(OpNum);
653 const MCOperand &MO2 = MI->getOperand(OpNum+1);
654
655 O << "[" << getRegisterName(MO1.getReg());
656
657 int32_t OffImm = (int32_t)MO2.getImm() / 4;
658 // Don't print +0.
659 if (OffImm < 0)
660 O << ", #-" << -OffImm * 4;
661 else if (OffImm > 0)
662 O << ", #" << OffImm * 4;
663 O << "]";
664}
665
666void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000667 unsigned OpNum,
668 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000669 const MCOperand &MO1 = MI->getOperand(OpNum);
670 int32_t OffImm = (int32_t)MO1.getImm();
671 // Don't print +0.
672 if (OffImm < 0)
673 O << "#-" << -OffImm;
674 else if (OffImm > 0)
675 O << "#" << OffImm;
676}
677
678void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000679 unsigned OpNum,
680 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000681 const MCOperand &MO1 = MI->getOperand(OpNum);
682 int32_t OffImm = (int32_t)MO1.getImm() / 4;
683 // Don't print +0.
684 if (OffImm < 0)
685 O << "#-" << -OffImm * 4;
686 else if (OffImm > 0)
687 O << "#" << OffImm * 4;
688}
689
690void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000691 unsigned OpNum,
692 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000693 const MCOperand &MO1 = MI->getOperand(OpNum);
694 const MCOperand &MO2 = MI->getOperand(OpNum+1);
695 const MCOperand &MO3 = MI->getOperand(OpNum+2);
696
697 O << "[" << getRegisterName(MO1.getReg());
698
699 assert(MO2.getReg() && "Invalid so_reg load / store address!");
700 O << ", " << getRegisterName(MO2.getReg());
701
702 unsigned ShAmt = MO3.getImm();
703 if (ShAmt) {
704 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
705 O << ", lsl #" << ShAmt;
706 }
707 O << "]";
708}
709
Chris Lattner35c33bd2010-04-04 04:47:45 +0000710void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum,
711 raw_ostream &O) {
Bill Wendling8cb415e2011-01-26 20:57:43 +0000712 const MCOperand &MO = MI->getOperand(OpNum);
713 O << '#';
714 if (MO.isFPImm()) {
715 O << (float)MO.getFPImm();
716 } else {
717 union {
718 uint32_t I;
719 float F;
720 } FPUnion;
721
722 FPUnion.I = MO.getImm();
723 O << FPUnion.F;
724 }
Johnny Chen9e088762010-03-17 17:52:21 +0000725}
726
Chris Lattner35c33bd2010-04-04 04:47:45 +0000727void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum,
728 raw_ostream &O) {
Bill Wendling8cb415e2011-01-26 20:57:43 +0000729 const MCOperand &MO = MI->getOperand(OpNum);
730 O << '#';
731 if (MO.isFPImm()) {
732 O << MO.getFPImm();
733 } else {
734 // We expect the binary encoding of a floating point number here.
735 union {
736 uint64_t I;
737 double D;
738 } FPUnion;
739
740 FPUnion.I = MO.getImm();
741 O << FPUnion.D;
742 }
Johnny Chen9e088762010-03-17 17:52:21 +0000743}
744
Bob Wilson1a913ed2010-06-11 21:34:50 +0000745void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
746 raw_ostream &O) {
Bob Wilson6dce00c2010-07-13 04:44:34 +0000747 unsigned EncodedImm = MI->getOperand(OpNum).getImm();
748 unsigned EltBits;
749 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
Bob Wilson1a913ed2010-06-11 21:34:50 +0000750 O << "#0x" << utohexstr(Val);
Johnny Chenc7b65912010-04-16 22:40:20 +0000751}