blob: f865b146b8fa7b2ec066ed260e0bb22d218aa02a [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
32
Chris Lattnerd3740872010-04-04 05:04:31 +000033void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
Bill Wendling04863d02010-11-13 10:40:19 +000034 unsigned Opcode = MI->getOpcode();
35
Johnny Chen9e088762010-03-17 17:52:21 +000036 // Check for MOVs and print canonical forms, instead.
Bill Wendling04863d02010-11-13 10:40:19 +000037 if (Opcode == ARM::MOVs) {
Jim Grosbache6be85e2010-09-17 22:36:38 +000038 // FIXME: Thumb variants?
Johnny Chen9e088762010-03-17 17:52:21 +000039 const MCOperand &Dst = MI->getOperand(0);
40 const MCOperand &MO1 = MI->getOperand(1);
41 const MCOperand &MO2 = MI->getOperand(2);
42 const MCOperand &MO3 = MI->getOperand(3);
43
44 O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
Chris Lattner35c33bd2010-04-04 04:47:45 +000045 printSBitModifierOperand(MI, 6, O);
46 printPredicateOperand(MI, 4, O);
Johnny Chen9e088762010-03-17 17:52:21 +000047
48 O << '\t' << getRegisterName(Dst.getReg())
49 << ", " << getRegisterName(MO1.getReg());
50
51 if (ARM_AM::getSORegShOp(MO3.getImm()) == ARM_AM::rrx)
52 return;
53
54 O << ", ";
55
56 if (MO2.getReg()) {
57 O << getRegisterName(MO2.getReg());
58 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
59 } else {
60 O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
61 }
62 return;
63 }
64
65 // A8.6.123 PUSH
Bill Wendling73fe34a2010-11-16 01:16:36 +000066 if ((Opcode == ARM::STMDB_UPD || Opcode == ARM::t2STMDB_UPD) &&
Johnny Chen9e088762010-03-17 17:52:21 +000067 MI->getOperand(0).getReg() == ARM::SP) {
Bill Wendling73fe34a2010-11-16 01:16:36 +000068 O << '\t' << "push";
69 printPredicateOperand(MI, 2, O);
70 O << '\t';
71 printRegisterList(MI, 4, O);
72 return;
Johnny Chen9e088762010-03-17 17:52:21 +000073 }
74
75 // A8.6.122 POP
Bill Wendling73fe34a2010-11-16 01:16:36 +000076 if ((Opcode == ARM::LDMIA_UPD || Opcode == ARM::t2LDMIA_UPD) &&
Johnny Chen9e088762010-03-17 17:52:21 +000077 MI->getOperand(0).getReg() == ARM::SP) {
Bill Wendling73fe34a2010-11-16 01:16:36 +000078 O << '\t' << "pop";
79 printPredicateOperand(MI, 2, O);
80 O << '\t';
81 printRegisterList(MI, 4, O);
82 return;
Johnny Chen9e088762010-03-17 17:52:21 +000083 }
84
85 // A8.6.355 VPUSH
Bill Wendling73fe34a2010-11-16 01:16:36 +000086 if ((Opcode == ARM::VSTMSDB_UPD || Opcode == ARM::VSTMDDB_UPD) &&
Johnny Chen9e088762010-03-17 17:52:21 +000087 MI->getOperand(0).getReg() == ARM::SP) {
Bill Wendling73fe34a2010-11-16 01:16:36 +000088 O << '\t' << "vpush";
89 printPredicateOperand(MI, 2, O);
90 O << '\t';
91 printRegisterList(MI, 4, O);
92 return;
Johnny Chen9e088762010-03-17 17:52:21 +000093 }
94
95 // A8.6.354 VPOP
Bill Wendling73fe34a2010-11-16 01:16:36 +000096 if ((Opcode == ARM::VLDMSIA_UPD || Opcode == ARM::VLDMDIA_UPD) &&
Johnny Chen9e088762010-03-17 17:52:21 +000097 MI->getOperand(0).getReg() == ARM::SP) {
Bill Wendling73fe34a2010-11-16 01:16:36 +000098 O << '\t' << "vpop";
99 printPredicateOperand(MI, 2, O);
100 O << '\t';
101 printRegisterList(MI, 4, O);
102 return;
Johnny Chen9e088762010-03-17 17:52:21 +0000103 }
104
Chris Lattner35c33bd2010-04-04 04:47:45 +0000105 printInstruction(MI, O);
Bill Wendling04863d02010-11-13 10:40:19 +0000106}
Chris Lattnerfd603822009-10-19 19:56:26 +0000107
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000108void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
Jim Grosbach0a2287b2010-11-03 01:11:15 +0000109 raw_ostream &O) {
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000110 const MCOperand &Op = MI->getOperand(OpNo);
111 if (Op.isReg()) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000112 unsigned Reg = Op.getReg();
Jim Grosbach35636282010-10-06 21:22:32 +0000113 O << getRegisterName(Reg);
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000114 } else if (Op.isImm()) {
115 O << '#' << Op.getImm();
116 } else {
117 assert(Op.isExpr() && "unknown operand kind in printOperand");
Chris Lattner8cb9a3b2010-01-18 00:37:40 +0000118 O << *Op.getExpr();
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000119 }
120}
Chris Lattner61d35c22009-10-19 21:21:39 +0000121
Jim Grosbach74d7e6c2010-09-17 21:33:25 +0000122static void printSOImm(raw_ostream &O, int64_t V, raw_ostream *CommentStream,
Chris Lattner61d35c22009-10-19 21:21:39 +0000123 const MCAsmInfo *MAI) {
124 // Break it up into two parts that make up a shifter immediate.
Bob Wilsonb123b8b2010-04-13 02:11:48 +0000125 V = ARM_AM::getSOImmVal(V);
Chris Lattner61d35c22009-10-19 21:21:39 +0000126 assert(V != -1 && "Not a valid so_imm value!");
Jim Grosbach15d78982010-09-14 22:27:15 +0000127
Chris Lattner61d35c22009-10-19 21:21:39 +0000128 unsigned Imm = ARM_AM::getSOImmValImm(V);
129 unsigned Rot = ARM_AM::getSOImmValRot(V);
Jim Grosbach15d78982010-09-14 22:27:15 +0000130
Chris Lattner61d35c22009-10-19 21:21:39 +0000131 // Print low-level immediate formation info, per
132 // A5.1.3: "Data-processing operands - Immediate".
133 if (Rot) {
134 O << "#" << Imm << ", " << Rot;
135 // Pretty printed version.
Jim Grosbach74d7e6c2010-09-17 21:33:25 +0000136 if (CommentStream)
137 *CommentStream << (int)ARM_AM::rotr32(Imm, Rot) << "\n";
Chris Lattner61d35c22009-10-19 21:21:39 +0000138 } else {
139 O << "#" << Imm;
140 }
141}
142
143
144/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
145/// immediate in bits 0-7.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000146void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum,
147 raw_ostream &O) {
Chris Lattner61d35c22009-10-19 21:21:39 +0000148 const MCOperand &MO = MI->getOperand(OpNum);
149 assert(MO.isImm() && "Not a valid so_imm value!");
Jim Grosbach74d7e6c2010-09-17 21:33:25 +0000150 printSOImm(O, MO.getImm(), CommentStream, &MAI);
Chris Lattner61d35c22009-10-19 21:21:39 +0000151}
Chris Lattner084f87d2009-10-19 21:57:05 +0000152
Chris Lattner017d9472009-10-20 00:40:56 +0000153// so_reg is a 4-operand unit corresponding to register forms of the A5.1
154// "Addressing Mode 1 - Data-processing operands" forms. This includes:
155// REG 0 0 - e.g. R5
156// REG REG 0,SH_OPC - e.g. R5, ROR R3
157// REG 0 IMM,SH_OPC - e.g. R5, LSL #3
Chris Lattner35c33bd2010-04-04 04:47:45 +0000158void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum,
159 raw_ostream &O) {
Chris Lattner017d9472009-10-20 00:40:56 +0000160 const MCOperand &MO1 = MI->getOperand(OpNum);
161 const MCOperand &MO2 = MI->getOperand(OpNum+1);
162 const MCOperand &MO3 = MI->getOperand(OpNum+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000163
Chris Lattner017d9472009-10-20 00:40:56 +0000164 O << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000165
Chris Lattner017d9472009-10-20 00:40:56 +0000166 // Print the shift opc.
Bob Wilson1d9125a2010-08-05 00:34:42 +0000167 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
168 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
Chris Lattner017d9472009-10-20 00:40:56 +0000169 if (MO2.getReg()) {
Bob Wilson1d9125a2010-08-05 00:34:42 +0000170 O << ' ' << getRegisterName(MO2.getReg());
Chris Lattner017d9472009-10-20 00:40:56 +0000171 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
Bob Wilson1d9125a2010-08-05 00:34:42 +0000172 } else if (ShOpc != ARM_AM::rrx) {
173 O << " #" << ARM_AM::getSORegOffset(MO3.getImm());
Chris Lattner017d9472009-10-20 00:40:56 +0000174 }
175}
Chris Lattner084f87d2009-10-19 21:57:05 +0000176
177
Chris Lattner35c33bd2010-04-04 04:47:45 +0000178void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
179 raw_ostream &O) {
Chris Lattner084f87d2009-10-19 21:57:05 +0000180 const MCOperand &MO1 = MI->getOperand(Op);
181 const MCOperand &MO2 = MI->getOperand(Op+1);
182 const MCOperand &MO3 = MI->getOperand(Op+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000183
Chris Lattner084f87d2009-10-19 21:57:05 +0000184 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000185 printOperand(MI, Op, O);
Chris Lattner084f87d2009-10-19 21:57:05 +0000186 return;
187 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000188
Chris Lattner084f87d2009-10-19 21:57:05 +0000189 O << "[" << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000190
Chris Lattner084f87d2009-10-19 21:57:05 +0000191 if (!MO2.getReg()) {
Johnny Chen9e088762010-03-17 17:52:21 +0000192 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
Chris Lattner084f87d2009-10-19 21:57:05 +0000193 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000194 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
195 << ARM_AM::getAM2Offset(MO3.getImm());
Chris Lattner084f87d2009-10-19 21:57:05 +0000196 O << "]";
197 return;
198 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000199
Chris Lattner084f87d2009-10-19 21:57:05 +0000200 O << ", "
Johnny Chen9e088762010-03-17 17:52:21 +0000201 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
202 << getRegisterName(MO2.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000203
Chris Lattner084f87d2009-10-19 21:57:05 +0000204 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
205 O << ", "
206 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
207 << " #" << ShImm;
208 O << "]";
Jim Grosbach15d78982010-09-14 22:27:15 +0000209}
Chris Lattnere306d8d2009-10-19 22:09:23 +0000210
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000211void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000212 unsigned OpNum,
213 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000214 const MCOperand &MO1 = MI->getOperand(OpNum);
215 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000216
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000217 if (!MO1.getReg()) {
218 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000219 O << '#'
220 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
221 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000222 return;
223 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000224
Johnny Chen9e088762010-03-17 17:52:21 +0000225 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
226 << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000227
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000228 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
229 O << ", "
230 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
231 << " #" << ShImm;
232}
233
Chris Lattner35c33bd2010-04-04 04:47:45 +0000234void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum,
235 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000236 const MCOperand &MO1 = MI->getOperand(OpNum);
237 const MCOperand &MO2 = MI->getOperand(OpNum+1);
238 const MCOperand &MO3 = MI->getOperand(OpNum+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000239
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000240 O << '[' << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000241
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000242 if (MO2.getReg()) {
243 O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm())
244 << getRegisterName(MO2.getReg()) << ']';
245 return;
246 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000247
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000248 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
249 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000250 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
251 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000252 O << ']';
253}
254
255void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000256 unsigned OpNum,
257 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000258 const MCOperand &MO1 = MI->getOperand(OpNum);
259 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000260
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000261 if (MO1.getReg()) {
262 O << (char)ARM_AM::getAM3Op(MO2.getImm())
263 << getRegisterName(MO1.getReg());
264 return;
265 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000266
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000267 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000268 O << '#'
269 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
270 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000271}
272
Jim Grosbache6913602010-11-03 01:01:43 +0000273void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,
Jim Grosbach0a2287b2010-11-03 01:11:15 +0000274 raw_ostream &O) {
Jim Grosbache6913602010-11-03 01:01:43 +0000275 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(OpNum)
276 .getImm());
277 O << ARM_AM::getAMSubModeStr(Mode);
Chris Lattnere306d8d2009-10-19 22:09:23 +0000278}
279
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000280void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
Jim Grosbach0a2287b2010-11-03 01:11:15 +0000281 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000282 const MCOperand &MO1 = MI->getOperand(OpNum);
283 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000284
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000285 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000286 printOperand(MI, OpNum, O);
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000287 return;
288 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000289
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000290 O << "[" << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000291
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000292 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
293 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000294 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000295 << ImmOffs * 4;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000296 }
297 O << "]";
298}
299
Chris Lattner35c33bd2010-04-04 04:47:45 +0000300void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
301 raw_ostream &O) {
Chris Lattner235e2f62009-10-20 06:22:33 +0000302 const MCOperand &MO1 = MI->getOperand(OpNum);
303 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000304
Bob Wilson226036e2010-03-20 22:13:40 +0000305 O << "[" << getRegisterName(MO1.getReg());
306 if (MO2.getImm()) {
307 // FIXME: Both darwin as and GNU as violate ARM docs here.
Bob Wilson273ff312010-07-14 23:54:43 +0000308 O << ", :" << (MO2.getImm() << 3);
Chris Lattner235e2f62009-10-20 06:22:33 +0000309 }
Bob Wilson226036e2010-03-20 22:13:40 +0000310 O << "]";
311}
312
313void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000314 unsigned OpNum,
315 raw_ostream &O) {
Bob Wilson226036e2010-03-20 22:13:40 +0000316 const MCOperand &MO = MI->getOperand(OpNum);
317 if (MO.getReg() == 0)
318 O << "!";
319 else
320 O << ", " << getRegisterName(MO.getReg());
Chris Lattner235e2f62009-10-20 06:22:33 +0000321}
322
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000323void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
324 unsigned OpNum,
325 raw_ostream &O) {
Chris Lattner235e2f62009-10-20 06:22:33 +0000326 const MCOperand &MO = MI->getOperand(OpNum);
327 uint32_t v = ~MO.getImm();
328 int32_t lsb = CountTrailingZeros_32(v);
329 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
330 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
331 O << '#' << lsb << ", #" << width;
332}
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000333
Johnny Chen1adc40c2010-08-12 20:46:17 +0000334void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
335 raw_ostream &O) {
336 unsigned val = MI->getOperand(OpNum).getImm();
337 O << ARM_MB::MemBOptToString(val);
338}
339
Bob Wilson22f5dc72010-08-16 18:27:34 +0000340void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000341 raw_ostream &O) {
342 unsigned ShiftOp = MI->getOperand(OpNum).getImm();
343 ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp);
344 switch (Opc) {
345 case ARM_AM::no_shift:
346 return;
347 case ARM_AM::lsl:
348 O << ", lsl #";
349 break;
350 case ARM_AM::asr:
351 O << ", asr #";
352 break;
353 default:
Bob Wilson22f5dc72010-08-16 18:27:34 +0000354 assert(0 && "unexpected shift opcode for shift immediate operand");
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000355 }
356 O << ARM_AM::getSORegOffset(ShiftOp);
357}
358
Chris Lattner35c33bd2010-04-04 04:47:45 +0000359void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
360 raw_ostream &O) {
Chris Lattnere306d8d2009-10-19 22:09:23 +0000361 O << "{";
Johnny Chen9e088762010-03-17 17:52:21 +0000362 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
363 if (i != OpNum) O << ", ";
Chris Lattnere306d8d2009-10-19 22:09:23 +0000364 O << getRegisterName(MI->getOperand(i).getReg());
365 }
366 O << "}";
367}
Chris Lattner4d152222009-10-19 22:23:04 +0000368
Jim Grosbachb3af5de2010-10-13 21:00:04 +0000369void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum,
370 raw_ostream &O) {
371 const MCOperand &Op = MI->getOperand(OpNum);
372 if (Op.getImm())
373 O << "be";
374 else
375 O << "le";
376}
377
Chris Lattner35c33bd2010-04-04 04:47:45 +0000378void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum,
379 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000380 const MCOperand &Op = MI->getOperand(OpNum);
381 unsigned option = Op.getImm();
382 unsigned mode = option & 31;
383 bool changemode = option >> 5 & 1;
384 unsigned AIF = option >> 6 & 7;
385 unsigned imod = option >> 9 & 3;
386 if (imod == 2)
387 O << "ie";
388 else if (imod == 3)
389 O << "id";
390 O << '\t';
391 if (imod > 1) {
392 if (AIF & 4) O << 'a';
393 if (AIF & 2) O << 'i';
394 if (AIF & 1) O << 'f';
395 if (AIF > 0 && changemode) O << ", ";
396 }
397 if (changemode)
398 O << '#' << mode;
399}
400
Chris Lattner35c33bd2010-04-04 04:47:45 +0000401void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
402 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000403 const MCOperand &Op = MI->getOperand(OpNum);
404 unsigned Mask = Op.getImm();
405 if (Mask) {
406 O << '_';
407 if (Mask & 8) O << 'f';
408 if (Mask & 4) O << 's';
409 if (Mask & 2) O << 'x';
410 if (Mask & 1) O << 'c';
411 }
412}
413
Chris Lattner35c33bd2010-04-04 04:47:45 +0000414void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum,
415 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000416 const MCOperand &Op = MI->getOperand(OpNum);
417 O << '#';
418 if (Op.getImm() < 0)
419 O << '-' << (-Op.getImm() - 1);
420 else
421 O << Op.getImm();
422}
423
Chris Lattner35c33bd2010-04-04 04:47:45 +0000424void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
425 raw_ostream &O) {
Chris Lattner413ae252009-10-20 00:42:49 +0000426 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
427 if (CC != ARMCC::AL)
428 O << ARMCondCodeToString(CC);
429}
430
Jim Grosbach15d78982010-09-14 22:27:15 +0000431void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000432 unsigned OpNum,
433 raw_ostream &O) {
Johnny Chen9d3acaa2010-03-02 17:57:15 +0000434 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
435 O << ARMCondCodeToString(CC);
436}
437
Chris Lattner35c33bd2010-04-04 04:47:45 +0000438void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
439 raw_ostream &O) {
Daniel Dunbara7cc6522009-10-20 22:10:05 +0000440 if (MI->getOperand(OpNum).getReg()) {
441 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
442 "Expect ARM CPSR register!");
Chris Lattner233917c2009-10-20 00:46:11 +0000443 O << 's';
444 }
445}
446
Chris Lattner35c33bd2010-04-04 04:47:45 +0000447void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
448 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000449 O << MI->getOperand(OpNum).getImm();
450}
451
Chris Lattner35c33bd2010-04-04 04:47:45 +0000452void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
453 raw_ostream &O) {
Jim Grosbachd30cfde2010-09-18 00:04:53 +0000454 llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
Chris Lattner4d152222009-10-19 22:23:04 +0000455}
Evan Cheng2ef9c8a2009-11-19 06:57:41 +0000456
Chris Lattner35c33bd2010-04-04 04:47:45 +0000457void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
458 raw_ostream &O) {
Johnny Chen541ba7d2010-01-25 22:13:10 +0000459 O << "#" << MI->getOperand(OpNum).getImm() * 4;
Evan Cheng2ef9c8a2009-11-19 06:57:41 +0000460}
Johnny Chen9e088762010-03-17 17:52:21 +0000461
Chris Lattner35c33bd2010-04-04 04:47:45 +0000462void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
463 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000464 // (3 - the number of trailing zeros) is the number of then / else.
465 unsigned Mask = MI->getOperand(OpNum).getImm();
466 unsigned CondBit0 = Mask >> 4 & 1;
467 unsigned NumTZ = CountTrailingZeros_32(Mask);
468 assert(NumTZ <= 3 && "Invalid IT mask!");
469 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
470 bool T = ((Mask >> Pos) & 1) == CondBit0;
471 if (T)
472 O << 't';
473 else
474 O << 'e';
475 }
476}
477
Chris Lattner35c33bd2010-04-04 04:47:45 +0000478void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
479 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000480 const MCOperand &MO1 = MI->getOperand(Op);
481 const MCOperand &MO2 = MI->getOperand(Op+1);
482 O << "[" << getRegisterName(MO1.getReg());
483 O << ", " << getRegisterName(MO2.getReg()) << "]";
484}
485
486void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000487 raw_ostream &O,
Johnny Chen9e088762010-03-17 17:52:21 +0000488 unsigned Scale) {
489 const MCOperand &MO1 = MI->getOperand(Op);
490 const MCOperand &MO2 = MI->getOperand(Op+1);
491 const MCOperand &MO3 = MI->getOperand(Op+2);
492
493 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000494 printOperand(MI, Op, O);
Johnny Chen9e088762010-03-17 17:52:21 +0000495 return;
496 }
497
498 O << "[" << getRegisterName(MO1.getReg());
499 if (MO3.getReg())
500 O << ", " << getRegisterName(MO3.getReg());
501 else if (unsigned ImmOffs = MO2.getImm())
502 O << ", #" << ImmOffs * Scale;
503 O << "]";
504}
505
Chris Lattner35c33bd2010-04-04 04:47:45 +0000506void ARMInstPrinter::printThumbAddrModeS1Operand(const MCInst *MI, unsigned Op,
507 raw_ostream &O) {
508 printThumbAddrModeRI5Operand(MI, Op, O, 1);
Johnny Chen9e088762010-03-17 17:52:21 +0000509}
510
Chris Lattner35c33bd2010-04-04 04:47:45 +0000511void ARMInstPrinter::printThumbAddrModeS2Operand(const MCInst *MI, unsigned Op,
512 raw_ostream &O) {
513 printThumbAddrModeRI5Operand(MI, Op, O, 2);
Johnny Chen9e088762010-03-17 17:52:21 +0000514}
515
Chris Lattner35c33bd2010-04-04 04:47:45 +0000516void ARMInstPrinter::printThumbAddrModeS4Operand(const MCInst *MI, unsigned Op,
517 raw_ostream &O) {
518 printThumbAddrModeRI5Operand(MI, Op, O, 4);
Johnny Chen9e088762010-03-17 17:52:21 +0000519}
520
Chris Lattner35c33bd2010-04-04 04:47:45 +0000521void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
522 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000523 const MCOperand &MO1 = MI->getOperand(Op);
524 const MCOperand &MO2 = MI->getOperand(Op+1);
525 O << "[" << getRegisterName(MO1.getReg());
526 if (unsigned ImmOffs = MO2.getImm())
527 O << ", #" << ImmOffs*4;
528 O << "]";
529}
530
Chris Lattner35c33bd2010-04-04 04:47:45 +0000531void ARMInstPrinter::printTBAddrMode(const MCInst *MI, unsigned OpNum,
532 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000533 O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg());
534 if (MI->getOpcode() == ARM::t2TBH)
535 O << ", lsl #1";
536 O << ']';
537}
538
539// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
540// register with shift forms.
541// REG 0 0 - e.g. R5
542// REG IMM, SH_OPC - e.g. R5, LSL #3
Chris Lattner35c33bd2010-04-04 04:47:45 +0000543void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
544 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000545 const MCOperand &MO1 = MI->getOperand(OpNum);
546 const MCOperand &MO2 = MI->getOperand(OpNum+1);
547
548 unsigned Reg = MO1.getReg();
549 O << getRegisterName(Reg);
550
551 // Print the shift opc.
Johnny Chen9e088762010-03-17 17:52:21 +0000552 assert(MO2.isImm() && "Not a valid t2_so_reg value!");
Bob Wilson1d9125a2010-08-05 00:34:42 +0000553 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm());
554 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
555 if (ShOpc != ARM_AM::rrx)
556 O << " #" << ARM_AM::getSORegOffset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000557}
558
Jim Grosbach458f2dc2010-10-25 20:00:01 +0000559void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
560 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000561 const MCOperand &MO1 = MI->getOperand(OpNum);
562 const MCOperand &MO2 = MI->getOperand(OpNum+1);
563
Jim Grosbach3e556122010-10-26 22:37:02 +0000564 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
565 printOperand(MI, OpNum, O);
566 return;
567 }
568
Johnny Chen9e088762010-03-17 17:52:21 +0000569 O << "[" << getRegisterName(MO1.getReg());
570
Jim Grosbach77aee8e2010-10-27 01:19:41 +0000571 int32_t OffImm = (int32_t)MO2.getImm();
Jim Grosbachab682a22010-10-28 18:34:10 +0000572 bool isSub = OffImm < 0;
573 // Special value for #-0. All others are normal.
574 if (OffImm == INT32_MIN)
575 OffImm = 0;
576 if (isSub)
Jim Grosbach77aee8e2010-10-27 01:19:41 +0000577 O << ", #-" << -OffImm;
578 else if (OffImm > 0)
Johnny Chen9e088762010-03-17 17:52:21 +0000579 O << ", #" << OffImm;
580 O << "]";
581}
582
583void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000584 unsigned OpNum,
585 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000586 const MCOperand &MO1 = MI->getOperand(OpNum);
587 const MCOperand &MO2 = MI->getOperand(OpNum+1);
588
589 O << "[" << getRegisterName(MO1.getReg());
590
591 int32_t OffImm = (int32_t)MO2.getImm();
592 // Don't print +0.
593 if (OffImm < 0)
594 O << ", #-" << -OffImm;
595 else if (OffImm > 0)
596 O << ", #" << OffImm;
597 O << "]";
598}
599
600void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000601 unsigned OpNum,
602 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000603 const MCOperand &MO1 = MI->getOperand(OpNum);
604 const MCOperand &MO2 = MI->getOperand(OpNum+1);
605
606 O << "[" << getRegisterName(MO1.getReg());
607
608 int32_t OffImm = (int32_t)MO2.getImm() / 4;
609 // Don't print +0.
610 if (OffImm < 0)
611 O << ", #-" << -OffImm * 4;
612 else if (OffImm > 0)
613 O << ", #" << OffImm * 4;
614 O << "]";
615}
616
617void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000618 unsigned OpNum,
619 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000620 const MCOperand &MO1 = MI->getOperand(OpNum);
621 int32_t OffImm = (int32_t)MO1.getImm();
622 // Don't print +0.
623 if (OffImm < 0)
624 O << "#-" << -OffImm;
625 else if (OffImm > 0)
626 O << "#" << OffImm;
627}
628
629void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000630 unsigned OpNum,
631 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000632 const MCOperand &MO1 = MI->getOperand(OpNum);
633 int32_t OffImm = (int32_t)MO1.getImm() / 4;
634 // Don't print +0.
635 if (OffImm < 0)
636 O << "#-" << -OffImm * 4;
637 else if (OffImm > 0)
638 O << "#" << OffImm * 4;
639}
640
641void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000642 unsigned OpNum,
643 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000644 const MCOperand &MO1 = MI->getOperand(OpNum);
645 const MCOperand &MO2 = MI->getOperand(OpNum+1);
646 const MCOperand &MO3 = MI->getOperand(OpNum+2);
647
648 O << "[" << getRegisterName(MO1.getReg());
649
650 assert(MO2.getReg() && "Invalid so_reg load / store address!");
651 O << ", " << getRegisterName(MO2.getReg());
652
653 unsigned ShAmt = MO3.getImm();
654 if (ShAmt) {
655 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
656 O << ", lsl #" << ShAmt;
657 }
658 O << "]";
659}
660
Chris Lattner35c33bd2010-04-04 04:47:45 +0000661void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum,
662 raw_ostream &O) {
Jim Grosbacha8e47b32010-09-16 03:45:21 +0000663 O << '#' << (float)MI->getOperand(OpNum).getFPImm();
Johnny Chen9e088762010-03-17 17:52:21 +0000664}
665
Chris Lattner35c33bd2010-04-04 04:47:45 +0000666void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum,
667 raw_ostream &O) {
Jim Grosbacha8e47b32010-09-16 03:45:21 +0000668 O << '#' << MI->getOperand(OpNum).getFPImm();
Johnny Chen9e088762010-03-17 17:52:21 +0000669}
670
Bob Wilson1a913ed2010-06-11 21:34:50 +0000671void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
672 raw_ostream &O) {
Bob Wilson6dce00c2010-07-13 04:44:34 +0000673 unsigned EncodedImm = MI->getOperand(OpNum).getImm();
674 unsigned EltBits;
675 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
Bob Wilson1a913ed2010-06-11 21:34:50 +0000676 O << "#0x" << utohexstr(Val);
Johnny Chenc7b65912010-04-16 22:40:20 +0000677}