blob: f54398cb3027f4bc8f516895a36de80c774853fc [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 Wendling04863d02010-11-13 10:40:19 +000066 if ((Opcode == ARM::STM_UPD || Opcode == ARM::t2STM_UPD) &&
Johnny Chen9e088762010-03-17 17:52:21 +000067 MI->getOperand(0).getReg() == ARM::SP) {
68 const MCOperand &MO1 = MI->getOperand(2);
69 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) {
70 O << '\t' << "push";
Chris Lattner35c33bd2010-04-04 04:47:45 +000071 printPredicateOperand(MI, 3, O);
Johnny Chen9e088762010-03-17 17:52:21 +000072 O << '\t';
Chris Lattner35c33bd2010-04-04 04:47:45 +000073 printRegisterList(MI, 5, O);
Johnny Chen9e088762010-03-17 17:52:21 +000074 return;
75 }
76 }
77
78 // A8.6.122 POP
Bill Wendling04863d02010-11-13 10:40:19 +000079 if ((Opcode == ARM::LDM_UPD || Opcode == ARM::t2LDM_UPD) &&
Johnny Chen9e088762010-03-17 17:52:21 +000080 MI->getOperand(0).getReg() == ARM::SP) {
81 const MCOperand &MO1 = MI->getOperand(2);
82 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) {
83 O << '\t' << "pop";
Chris Lattner35c33bd2010-04-04 04:47:45 +000084 printPredicateOperand(MI, 3, O);
Johnny Chen9e088762010-03-17 17:52:21 +000085 O << '\t';
Chris Lattner35c33bd2010-04-04 04:47:45 +000086 printRegisterList(MI, 5, O);
Johnny Chen9e088762010-03-17 17:52:21 +000087 return;
88 }
89 }
90
91 // A8.6.355 VPUSH
Bill Wendling04863d02010-11-13 10:40:19 +000092 if ((Opcode == ARM::VSTMS_UPD || Opcode == ARM::VSTMD_UPD) &&
Johnny Chen9e088762010-03-17 17:52:21 +000093 MI->getOperand(0).getReg() == ARM::SP) {
94 const MCOperand &MO1 = MI->getOperand(2);
Bob Wilsond4bfd542010-08-27 23:18:17 +000095 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) {
Johnny Chen9e088762010-03-17 17:52:21 +000096 O << '\t' << "vpush";
Chris Lattner35c33bd2010-04-04 04:47:45 +000097 printPredicateOperand(MI, 3, O);
Johnny Chen9e088762010-03-17 17:52:21 +000098 O << '\t';
Chris Lattner35c33bd2010-04-04 04:47:45 +000099 printRegisterList(MI, 5, O);
Johnny Chen9e088762010-03-17 17:52:21 +0000100 return;
101 }
102 }
103
104 // A8.6.354 VPOP
Bill Wendling04863d02010-11-13 10:40:19 +0000105 if ((Opcode == ARM::VLDMS_UPD || Opcode == ARM::VLDMD_UPD) &&
Johnny Chen9e088762010-03-17 17:52:21 +0000106 MI->getOperand(0).getReg() == ARM::SP) {
107 const MCOperand &MO1 = MI->getOperand(2);
Bob Wilsond4bfd542010-08-27 23:18:17 +0000108 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) {
Johnny Chen9e088762010-03-17 17:52:21 +0000109 O << '\t' << "vpop";
Chris Lattner35c33bd2010-04-04 04:47:45 +0000110 printPredicateOperand(MI, 3, O);
Johnny Chen9e088762010-03-17 17:52:21 +0000111 O << '\t';
Chris Lattner35c33bd2010-04-04 04:47:45 +0000112 printRegisterList(MI, 5, O);
Johnny Chen9e088762010-03-17 17:52:21 +0000113 return;
114 }
115 }
116
Chris Lattner35c33bd2010-04-04 04:47:45 +0000117 printInstruction(MI, O);
Bill Wendling04863d02010-11-13 10:40:19 +0000118}
Chris Lattnerfd603822009-10-19 19:56:26 +0000119
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000120void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
Jim Grosbach0a2287b2010-11-03 01:11:15 +0000121 raw_ostream &O) {
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000122 const MCOperand &Op = MI->getOperand(OpNo);
123 if (Op.isReg()) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000124 unsigned Reg = Op.getReg();
Jim Grosbach35636282010-10-06 21:22:32 +0000125 O << getRegisterName(Reg);
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000126 } else if (Op.isImm()) {
127 O << '#' << Op.getImm();
128 } else {
129 assert(Op.isExpr() && "unknown operand kind in printOperand");
Chris Lattner8cb9a3b2010-01-18 00:37:40 +0000130 O << *Op.getExpr();
Chris Lattner8bc86cb2009-10-19 20:59:55 +0000131 }
132}
Chris Lattner61d35c22009-10-19 21:21:39 +0000133
Jim Grosbach74d7e6c2010-09-17 21:33:25 +0000134static void printSOImm(raw_ostream &O, int64_t V, raw_ostream *CommentStream,
Chris Lattner61d35c22009-10-19 21:21:39 +0000135 const MCAsmInfo *MAI) {
136 // Break it up into two parts that make up a shifter immediate.
Bob Wilsonb123b8b2010-04-13 02:11:48 +0000137 V = ARM_AM::getSOImmVal(V);
Chris Lattner61d35c22009-10-19 21:21:39 +0000138 assert(V != -1 && "Not a valid so_imm value!");
Jim Grosbach15d78982010-09-14 22:27:15 +0000139
Chris Lattner61d35c22009-10-19 21:21:39 +0000140 unsigned Imm = ARM_AM::getSOImmValImm(V);
141 unsigned Rot = ARM_AM::getSOImmValRot(V);
Jim Grosbach15d78982010-09-14 22:27:15 +0000142
Chris Lattner61d35c22009-10-19 21:21:39 +0000143 // Print low-level immediate formation info, per
144 // A5.1.3: "Data-processing operands - Immediate".
145 if (Rot) {
146 O << "#" << Imm << ", " << Rot;
147 // Pretty printed version.
Jim Grosbach74d7e6c2010-09-17 21:33:25 +0000148 if (CommentStream)
149 *CommentStream << (int)ARM_AM::rotr32(Imm, Rot) << "\n";
Chris Lattner61d35c22009-10-19 21:21:39 +0000150 } else {
151 O << "#" << Imm;
152 }
153}
154
155
156/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
157/// immediate in bits 0-7.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000158void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum,
159 raw_ostream &O) {
Chris Lattner61d35c22009-10-19 21:21:39 +0000160 const MCOperand &MO = MI->getOperand(OpNum);
161 assert(MO.isImm() && "Not a valid so_imm value!");
Jim Grosbach74d7e6c2010-09-17 21:33:25 +0000162 printSOImm(O, MO.getImm(), CommentStream, &MAI);
Chris Lattner61d35c22009-10-19 21:21:39 +0000163}
Chris Lattner084f87d2009-10-19 21:57:05 +0000164
Chris Lattner017d9472009-10-20 00:40:56 +0000165// so_reg is a 4-operand unit corresponding to register forms of the A5.1
166// "Addressing Mode 1 - Data-processing operands" forms. This includes:
167// REG 0 0 - e.g. R5
168// REG REG 0,SH_OPC - e.g. R5, ROR R3
169// REG 0 IMM,SH_OPC - e.g. R5, LSL #3
Chris Lattner35c33bd2010-04-04 04:47:45 +0000170void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum,
171 raw_ostream &O) {
Chris Lattner017d9472009-10-20 00:40:56 +0000172 const MCOperand &MO1 = MI->getOperand(OpNum);
173 const MCOperand &MO2 = MI->getOperand(OpNum+1);
174 const MCOperand &MO3 = MI->getOperand(OpNum+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000175
Chris Lattner017d9472009-10-20 00:40:56 +0000176 O << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000177
Chris Lattner017d9472009-10-20 00:40:56 +0000178 // Print the shift opc.
Bob Wilson1d9125a2010-08-05 00:34:42 +0000179 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
180 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
Chris Lattner017d9472009-10-20 00:40:56 +0000181 if (MO2.getReg()) {
Bob Wilson1d9125a2010-08-05 00:34:42 +0000182 O << ' ' << getRegisterName(MO2.getReg());
Chris Lattner017d9472009-10-20 00:40:56 +0000183 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
Bob Wilson1d9125a2010-08-05 00:34:42 +0000184 } else if (ShOpc != ARM_AM::rrx) {
185 O << " #" << ARM_AM::getSORegOffset(MO3.getImm());
Chris Lattner017d9472009-10-20 00:40:56 +0000186 }
187}
Chris Lattner084f87d2009-10-19 21:57:05 +0000188
189
Chris Lattner35c33bd2010-04-04 04:47:45 +0000190void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
191 raw_ostream &O) {
Chris Lattner084f87d2009-10-19 21:57:05 +0000192 const MCOperand &MO1 = MI->getOperand(Op);
193 const MCOperand &MO2 = MI->getOperand(Op+1);
194 const MCOperand &MO3 = MI->getOperand(Op+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000195
Chris Lattner084f87d2009-10-19 21:57:05 +0000196 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000197 printOperand(MI, Op, O);
Chris Lattner084f87d2009-10-19 21:57:05 +0000198 return;
199 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000200
Chris Lattner084f87d2009-10-19 21:57:05 +0000201 O << "[" << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000202
Chris Lattner084f87d2009-10-19 21:57:05 +0000203 if (!MO2.getReg()) {
Johnny Chen9e088762010-03-17 17:52:21 +0000204 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
Chris Lattner084f87d2009-10-19 21:57:05 +0000205 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000206 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
207 << ARM_AM::getAM2Offset(MO3.getImm());
Chris Lattner084f87d2009-10-19 21:57:05 +0000208 O << "]";
209 return;
210 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000211
Chris Lattner084f87d2009-10-19 21:57:05 +0000212 O << ", "
Johnny Chen9e088762010-03-17 17:52:21 +0000213 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
214 << getRegisterName(MO2.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000215
Chris Lattner084f87d2009-10-19 21:57:05 +0000216 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
217 O << ", "
218 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
219 << " #" << ShImm;
220 O << "]";
Jim Grosbach15d78982010-09-14 22:27:15 +0000221}
Chris Lattnere306d8d2009-10-19 22:09:23 +0000222
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000223void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000224 unsigned OpNum,
225 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000226 const MCOperand &MO1 = MI->getOperand(OpNum);
227 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000228
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000229 if (!MO1.getReg()) {
230 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000231 O << '#'
232 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
233 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000234 return;
235 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000236
Johnny Chen9e088762010-03-17 17:52:21 +0000237 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
238 << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000239
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000240 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
241 O << ", "
242 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
243 << " #" << ShImm;
244}
245
Chris Lattner35c33bd2010-04-04 04:47:45 +0000246void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum,
247 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000248 const MCOperand &MO1 = MI->getOperand(OpNum);
249 const MCOperand &MO2 = MI->getOperand(OpNum+1);
250 const MCOperand &MO3 = MI->getOperand(OpNum+2);
Jim Grosbach15d78982010-09-14 22:27:15 +0000251
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000252 O << '[' << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000253
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000254 if (MO2.getReg()) {
255 O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm())
256 << getRegisterName(MO2.getReg()) << ']';
257 return;
258 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000259
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000260 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
261 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000262 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
263 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000264 O << ']';
265}
266
267void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000268 unsigned OpNum,
269 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000270 const MCOperand &MO1 = MI->getOperand(OpNum);
271 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000272
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000273 if (MO1.getReg()) {
274 O << (char)ARM_AM::getAM3Op(MO2.getImm())
275 << getRegisterName(MO1.getReg());
276 return;
277 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000278
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000279 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000280 O << '#'
281 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
282 << ImmOffs;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000283}
284
Jim Grosbache6913602010-11-03 01:01:43 +0000285void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,
Jim Grosbach0a2287b2010-11-03 01:11:15 +0000286 raw_ostream &O) {
Jim Grosbache6913602010-11-03 01:01:43 +0000287 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(OpNum)
288 .getImm());
289 O << ARM_AM::getAMSubModeStr(Mode);
Chris Lattnere306d8d2009-10-19 22:09:23 +0000290}
291
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000292void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
Jim Grosbach0a2287b2010-11-03 01:11:15 +0000293 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000294 const MCOperand &MO1 = MI->getOperand(OpNum);
295 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000296
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000297 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000298 printOperand(MI, OpNum, O);
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000299 return;
300 }
Jim Grosbach15d78982010-09-14 22:27:15 +0000301
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000302 O << "[" << getRegisterName(MO1.getReg());
Jim Grosbach15d78982010-09-14 22:27:15 +0000303
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000304 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
305 O << ", #"
Johnny Chen9e088762010-03-17 17:52:21 +0000306 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
Bill Wendling92b5a2e2010-11-03 01:49:29 +0000307 << ImmOffs * 4;
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000308 }
309 O << "]";
310}
311
Chris Lattner35c33bd2010-04-04 04:47:45 +0000312void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
313 raw_ostream &O) {
Chris Lattner235e2f62009-10-20 06:22:33 +0000314 const MCOperand &MO1 = MI->getOperand(OpNum);
315 const MCOperand &MO2 = MI->getOperand(OpNum+1);
Jim Grosbach15d78982010-09-14 22:27:15 +0000316
Bob Wilson226036e2010-03-20 22:13:40 +0000317 O << "[" << getRegisterName(MO1.getReg());
318 if (MO2.getImm()) {
319 // FIXME: Both darwin as and GNU as violate ARM docs here.
Bob Wilson273ff312010-07-14 23:54:43 +0000320 O << ", :" << (MO2.getImm() << 3);
Chris Lattner235e2f62009-10-20 06:22:33 +0000321 }
Bob Wilson226036e2010-03-20 22:13:40 +0000322 O << "]";
323}
324
325void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000326 unsigned OpNum,
327 raw_ostream &O) {
Bob Wilson226036e2010-03-20 22:13:40 +0000328 const MCOperand &MO = MI->getOperand(OpNum);
329 if (MO.getReg() == 0)
330 O << "!";
331 else
332 O << ", " << getRegisterName(MO.getReg());
Chris Lattner235e2f62009-10-20 06:22:33 +0000333}
334
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000335void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
336 unsigned OpNum,
337 raw_ostream &O) {
Chris Lattner235e2f62009-10-20 06:22:33 +0000338 const MCOperand &MO = MI->getOperand(OpNum);
339 uint32_t v = ~MO.getImm();
340 int32_t lsb = CountTrailingZeros_32(v);
341 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
342 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
343 O << '#' << lsb << ", #" << width;
344}
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000345
Johnny Chen1adc40c2010-08-12 20:46:17 +0000346void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
347 raw_ostream &O) {
348 unsigned val = MI->getOperand(OpNum).getImm();
349 O << ARM_MB::MemBOptToString(val);
350}
351
Bob Wilson22f5dc72010-08-16 18:27:34 +0000352void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000353 raw_ostream &O) {
354 unsigned ShiftOp = MI->getOperand(OpNum).getImm();
355 ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp);
356 switch (Opc) {
357 case ARM_AM::no_shift:
358 return;
359 case ARM_AM::lsl:
360 O << ", lsl #";
361 break;
362 case ARM_AM::asr:
363 O << ", asr #";
364 break;
365 default:
Bob Wilson22f5dc72010-08-16 18:27:34 +0000366 assert(0 && "unexpected shift opcode for shift immediate operand");
Bob Wilsoneaf1c982010-08-11 23:10:46 +0000367 }
368 O << ARM_AM::getSORegOffset(ShiftOp);
369}
370
Chris Lattner35c33bd2010-04-04 04:47:45 +0000371void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
372 raw_ostream &O) {
Chris Lattnere306d8d2009-10-19 22:09:23 +0000373 O << "{";
Johnny Chen9e088762010-03-17 17:52:21 +0000374 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
375 if (i != OpNum) O << ", ";
Chris Lattnere306d8d2009-10-19 22:09:23 +0000376 O << getRegisterName(MI->getOperand(i).getReg());
377 }
378 O << "}";
379}
Chris Lattner4d152222009-10-19 22:23:04 +0000380
Jim Grosbachb3af5de2010-10-13 21:00:04 +0000381void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum,
382 raw_ostream &O) {
383 const MCOperand &Op = MI->getOperand(OpNum);
384 if (Op.getImm())
385 O << "be";
386 else
387 O << "le";
388}
389
Chris Lattner35c33bd2010-04-04 04:47:45 +0000390void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum,
391 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000392 const MCOperand &Op = MI->getOperand(OpNum);
393 unsigned option = Op.getImm();
394 unsigned mode = option & 31;
395 bool changemode = option >> 5 & 1;
396 unsigned AIF = option >> 6 & 7;
397 unsigned imod = option >> 9 & 3;
398 if (imod == 2)
399 O << "ie";
400 else if (imod == 3)
401 O << "id";
402 O << '\t';
403 if (imod > 1) {
404 if (AIF & 4) O << 'a';
405 if (AIF & 2) O << 'i';
406 if (AIF & 1) O << 'f';
407 if (AIF > 0 && changemode) O << ", ";
408 }
409 if (changemode)
410 O << '#' << mode;
411}
412
Chris Lattner35c33bd2010-04-04 04:47:45 +0000413void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
414 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000415 const MCOperand &Op = MI->getOperand(OpNum);
416 unsigned Mask = Op.getImm();
417 if (Mask) {
418 O << '_';
419 if (Mask & 8) O << 'f';
420 if (Mask & 4) O << 's';
421 if (Mask & 2) O << 'x';
422 if (Mask & 1) O << 'c';
423 }
424}
425
Chris Lattner35c33bd2010-04-04 04:47:45 +0000426void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum,
427 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000428 const MCOperand &Op = MI->getOperand(OpNum);
429 O << '#';
430 if (Op.getImm() < 0)
431 O << '-' << (-Op.getImm() - 1);
432 else
433 O << Op.getImm();
434}
435
Chris Lattner35c33bd2010-04-04 04:47:45 +0000436void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
437 raw_ostream &O) {
Chris Lattner413ae252009-10-20 00:42:49 +0000438 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
439 if (CC != ARMCC::AL)
440 O << ARMCondCodeToString(CC);
441}
442
Jim Grosbach15d78982010-09-14 22:27:15 +0000443void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000444 unsigned OpNum,
445 raw_ostream &O) {
Johnny Chen9d3acaa2010-03-02 17:57:15 +0000446 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
447 O << ARMCondCodeToString(CC);
448}
449
Chris Lattner35c33bd2010-04-04 04:47:45 +0000450void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
451 raw_ostream &O) {
Daniel Dunbara7cc6522009-10-20 22:10:05 +0000452 if (MI->getOperand(OpNum).getReg()) {
453 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
454 "Expect ARM CPSR register!");
Chris Lattner233917c2009-10-20 00:46:11 +0000455 O << 's';
456 }
457}
458
Chris Lattner35c33bd2010-04-04 04:47:45 +0000459void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
460 raw_ostream &O) {
Chris Lattnerbf16faa2009-10-20 06:15:28 +0000461 O << MI->getOperand(OpNum).getImm();
462}
463
Chris Lattner35c33bd2010-04-04 04:47:45 +0000464void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
465 raw_ostream &O) {
Jim Grosbachd30cfde2010-09-18 00:04:53 +0000466 llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
Chris Lattner4d152222009-10-19 22:23:04 +0000467}
Evan Cheng2ef9c8a2009-11-19 06:57:41 +0000468
Chris Lattner35c33bd2010-04-04 04:47:45 +0000469void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
470 raw_ostream &O) {
Johnny Chen541ba7d2010-01-25 22:13:10 +0000471 O << "#" << MI->getOperand(OpNum).getImm() * 4;
Evan Cheng2ef9c8a2009-11-19 06:57:41 +0000472}
Johnny Chen9e088762010-03-17 17:52:21 +0000473
Chris Lattner35c33bd2010-04-04 04:47:45 +0000474void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
475 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000476 // (3 - the number of trailing zeros) is the number of then / else.
477 unsigned Mask = MI->getOperand(OpNum).getImm();
478 unsigned CondBit0 = Mask >> 4 & 1;
479 unsigned NumTZ = CountTrailingZeros_32(Mask);
480 assert(NumTZ <= 3 && "Invalid IT mask!");
481 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
482 bool T = ((Mask >> Pos) & 1) == CondBit0;
483 if (T)
484 O << 't';
485 else
486 O << 'e';
487 }
488}
489
Chris Lattner35c33bd2010-04-04 04:47:45 +0000490void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
491 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000492 const MCOperand &MO1 = MI->getOperand(Op);
493 const MCOperand &MO2 = MI->getOperand(Op+1);
494 O << "[" << getRegisterName(MO1.getReg());
495 O << ", " << getRegisterName(MO2.getReg()) << "]";
496}
497
498void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000499 raw_ostream &O,
Johnny Chen9e088762010-03-17 17:52:21 +0000500 unsigned Scale) {
501 const MCOperand &MO1 = MI->getOperand(Op);
502 const MCOperand &MO2 = MI->getOperand(Op+1);
503 const MCOperand &MO3 = MI->getOperand(Op+2);
504
505 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
Chris Lattner35c33bd2010-04-04 04:47:45 +0000506 printOperand(MI, Op, O);
Johnny Chen9e088762010-03-17 17:52:21 +0000507 return;
508 }
509
510 O << "[" << getRegisterName(MO1.getReg());
511 if (MO3.getReg())
512 O << ", " << getRegisterName(MO3.getReg());
513 else if (unsigned ImmOffs = MO2.getImm())
514 O << ", #" << ImmOffs * Scale;
515 O << "]";
516}
517
Chris Lattner35c33bd2010-04-04 04:47:45 +0000518void ARMInstPrinter::printThumbAddrModeS1Operand(const MCInst *MI, unsigned Op,
519 raw_ostream &O) {
520 printThumbAddrModeRI5Operand(MI, Op, O, 1);
Johnny Chen9e088762010-03-17 17:52:21 +0000521}
522
Chris Lattner35c33bd2010-04-04 04:47:45 +0000523void ARMInstPrinter::printThumbAddrModeS2Operand(const MCInst *MI, unsigned Op,
524 raw_ostream &O) {
525 printThumbAddrModeRI5Operand(MI, Op, O, 2);
Johnny Chen9e088762010-03-17 17:52:21 +0000526}
527
Chris Lattner35c33bd2010-04-04 04:47:45 +0000528void ARMInstPrinter::printThumbAddrModeS4Operand(const MCInst *MI, unsigned Op,
529 raw_ostream &O) {
530 printThumbAddrModeRI5Operand(MI, Op, O, 4);
Johnny Chen9e088762010-03-17 17:52:21 +0000531}
532
Chris Lattner35c33bd2010-04-04 04:47:45 +0000533void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
534 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000535 const MCOperand &MO1 = MI->getOperand(Op);
536 const MCOperand &MO2 = MI->getOperand(Op+1);
537 O << "[" << getRegisterName(MO1.getReg());
538 if (unsigned ImmOffs = MO2.getImm())
539 O << ", #" << ImmOffs*4;
540 O << "]";
541}
542
Chris Lattner35c33bd2010-04-04 04:47:45 +0000543void ARMInstPrinter::printTBAddrMode(const MCInst *MI, unsigned OpNum,
544 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000545 O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg());
546 if (MI->getOpcode() == ARM::t2TBH)
547 O << ", lsl #1";
548 O << ']';
549}
550
551// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
552// register with shift forms.
553// REG 0 0 - e.g. R5
554// REG IMM, SH_OPC - e.g. R5, LSL #3
Chris Lattner35c33bd2010-04-04 04:47:45 +0000555void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
556 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000557 const MCOperand &MO1 = MI->getOperand(OpNum);
558 const MCOperand &MO2 = MI->getOperand(OpNum+1);
559
560 unsigned Reg = MO1.getReg();
561 O << getRegisterName(Reg);
562
563 // Print the shift opc.
Johnny Chen9e088762010-03-17 17:52:21 +0000564 assert(MO2.isImm() && "Not a valid t2_so_reg value!");
Bob Wilson1d9125a2010-08-05 00:34:42 +0000565 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm());
566 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
567 if (ShOpc != ARM_AM::rrx)
568 O << " #" << ARM_AM::getSORegOffset(MO2.getImm());
Johnny Chen9e088762010-03-17 17:52:21 +0000569}
570
Jim Grosbach458f2dc2010-10-25 20:00:01 +0000571void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
572 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000573 const MCOperand &MO1 = MI->getOperand(OpNum);
574 const MCOperand &MO2 = MI->getOperand(OpNum+1);
575
Jim Grosbach3e556122010-10-26 22:37:02 +0000576 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
577 printOperand(MI, OpNum, O);
578 return;
579 }
580
Johnny Chen9e088762010-03-17 17:52:21 +0000581 O << "[" << getRegisterName(MO1.getReg());
582
Jim Grosbach77aee8e2010-10-27 01:19:41 +0000583 int32_t OffImm = (int32_t)MO2.getImm();
Jim Grosbachab682a22010-10-28 18:34:10 +0000584 bool isSub = OffImm < 0;
585 // Special value for #-0. All others are normal.
586 if (OffImm == INT32_MIN)
587 OffImm = 0;
588 if (isSub)
Jim Grosbach77aee8e2010-10-27 01:19:41 +0000589 O << ", #-" << -OffImm;
590 else if (OffImm > 0)
Johnny Chen9e088762010-03-17 17:52:21 +0000591 O << ", #" << OffImm;
592 O << "]";
593}
594
595void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000596 unsigned OpNum,
597 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000598 const MCOperand &MO1 = MI->getOperand(OpNum);
599 const MCOperand &MO2 = MI->getOperand(OpNum+1);
600
601 O << "[" << getRegisterName(MO1.getReg());
602
603 int32_t OffImm = (int32_t)MO2.getImm();
604 // Don't print +0.
605 if (OffImm < 0)
606 O << ", #-" << -OffImm;
607 else if (OffImm > 0)
608 O << ", #" << OffImm;
609 O << "]";
610}
611
612void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000613 unsigned OpNum,
614 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000615 const MCOperand &MO1 = MI->getOperand(OpNum);
616 const MCOperand &MO2 = MI->getOperand(OpNum+1);
617
618 O << "[" << getRegisterName(MO1.getReg());
619
620 int32_t OffImm = (int32_t)MO2.getImm() / 4;
621 // Don't print +0.
622 if (OffImm < 0)
623 O << ", #-" << -OffImm * 4;
624 else if (OffImm > 0)
625 O << ", #" << OffImm * 4;
626 O << "]";
627}
628
629void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(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();
634 // Don't print +0.
635 if (OffImm < 0)
636 O << "#-" << -OffImm;
637 else if (OffImm > 0)
638 O << "#" << OffImm;
639}
640
641void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(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 int32_t OffImm = (int32_t)MO1.getImm() / 4;
646 // Don't print +0.
647 if (OffImm < 0)
648 O << "#-" << -OffImm * 4;
649 else if (OffImm > 0)
650 O << "#" << OffImm * 4;
651}
652
653void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
Chris Lattner35c33bd2010-04-04 04:47:45 +0000654 unsigned OpNum,
655 raw_ostream &O) {
Johnny Chen9e088762010-03-17 17:52:21 +0000656 const MCOperand &MO1 = MI->getOperand(OpNum);
657 const MCOperand &MO2 = MI->getOperand(OpNum+1);
658 const MCOperand &MO3 = MI->getOperand(OpNum+2);
659
660 O << "[" << getRegisterName(MO1.getReg());
661
662 assert(MO2.getReg() && "Invalid so_reg load / store address!");
663 O << ", " << getRegisterName(MO2.getReg());
664
665 unsigned ShAmt = MO3.getImm();
666 if (ShAmt) {
667 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
668 O << ", lsl #" << ShAmt;
669 }
670 O << "]";
671}
672
Chris Lattner35c33bd2010-04-04 04:47:45 +0000673void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum,
674 raw_ostream &O) {
Jim Grosbacha8e47b32010-09-16 03:45:21 +0000675 O << '#' << (float)MI->getOperand(OpNum).getFPImm();
Johnny Chen9e088762010-03-17 17:52:21 +0000676}
677
Chris Lattner35c33bd2010-04-04 04:47:45 +0000678void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum,
679 raw_ostream &O) {
Jim Grosbacha8e47b32010-09-16 03:45:21 +0000680 O << '#' << MI->getOperand(OpNum).getFPImm();
Johnny Chen9e088762010-03-17 17:52:21 +0000681}
682
Bob Wilson1a913ed2010-06-11 21:34:50 +0000683void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
684 raw_ostream &O) {
Bob Wilson6dce00c2010-07-13 04:44:34 +0000685 unsigned EncodedImm = MI->getOperand(OpNum).getImm();
686 unsigned EltBits;
687 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
Bob Wilson1a913ed2010-06-11 21:34:50 +0000688 O << "#0x" << utohexstr(Val);
Johnny Chenc7b65912010-04-16 22:40:20 +0000689}