ARMInstPrinter.cpp revision cefe4c9c483d8a50ff13f36881090ab44ec67f13
1//===-- 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"
15#include "ARMInstPrinter.h"
16#include "MCTargetDesc/ARMBaseInfo.h"
17#include "MCTargetDesc/ARMAddressingModes.h"
18#include "llvm/MC/MCInst.h"
19#include "llvm/MC/MCAsmInfo.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/ADT/StringExtras.h"
22#include "llvm/Support/raw_ostream.h"
23using namespace llvm;
24
25#define GET_INSTRUCTION_NAME
26#include "ARMGenAsmWriter.inc"
27
28/// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing.
29///
30/// getSORegOffset returns an integer from 0-31, but '0' should actually be printed
31/// 32 as the immediate shouldbe within the range 1-32.
32static unsigned translateShiftImm(unsigned imm) {
33  if (imm == 0)
34    return 32;
35  return imm;
36}
37
38StringRef ARMInstPrinter::getOpcodeName(unsigned Opcode) const {
39  return getInstructionName(Opcode);
40}
41
42void ARMInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
43  OS << getRegisterName(RegNo);
44}
45
46void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
47  unsigned Opcode = MI->getOpcode();
48
49  // Check for MOVs and print canonical forms, instead.
50  if (Opcode == ARM::MOVsr) {
51    // FIXME: Thumb variants?
52    const MCOperand &Dst = MI->getOperand(0);
53    const MCOperand &MO1 = MI->getOperand(1);
54    const MCOperand &MO2 = MI->getOperand(2);
55    const MCOperand &MO3 = MI->getOperand(3);
56
57    O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
58    printSBitModifierOperand(MI, 6, O);
59    printPredicateOperand(MI, 4, O);
60
61    O << '\t' << getRegisterName(Dst.getReg())
62      << ", " << getRegisterName(MO1.getReg());
63
64    O << ", " << getRegisterName(MO2.getReg());
65    assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
66    return;
67  }
68
69  if (Opcode == ARM::MOVsi) {
70    // FIXME: Thumb variants?
71    const MCOperand &Dst = MI->getOperand(0);
72    const MCOperand &MO1 = MI->getOperand(1);
73    const MCOperand &MO2 = MI->getOperand(2);
74
75    O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()));
76    printSBitModifierOperand(MI, 5, O);
77    printPredicateOperand(MI, 3, O);
78
79    O << '\t' << getRegisterName(Dst.getReg())
80      << ", " << getRegisterName(MO1.getReg());
81
82    if (ARM_AM::getSORegShOp(MO2.getImm()) == ARM_AM::rrx)
83      return;
84
85    O << ", #" << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm()));
86    return;
87  }
88
89
90  // A8.6.123 PUSH
91  if ((Opcode == ARM::STMDB_UPD || Opcode == ARM::t2STMDB_UPD) &&
92      MI->getOperand(0).getReg() == ARM::SP) {
93    O << '\t' << "push";
94    printPredicateOperand(MI, 2, O);
95    if (Opcode == ARM::t2STMDB_UPD)
96      O << ".w";
97    O << '\t';
98    printRegisterList(MI, 4, O);
99    return;
100  }
101  if (Opcode == ARM::STR_PRE_IMM && MI->getOperand(2).getReg() == ARM::SP &&
102      MI->getOperand(3).getImm() == -4) {
103    O << '\t' << "push";
104    printPredicateOperand(MI, 4, O);
105    O << "\t{" << getRegisterName(MI->getOperand(1).getReg()) << "}";
106    return;
107  }
108
109  // A8.6.122 POP
110  if ((Opcode == ARM::LDMIA_UPD || Opcode == ARM::t2LDMIA_UPD) &&
111      MI->getOperand(0).getReg() == ARM::SP) {
112    O << '\t' << "pop";
113    printPredicateOperand(MI, 2, O);
114    if (Opcode == ARM::t2LDMIA_UPD)
115      O << ".w";
116    O << '\t';
117    printRegisterList(MI, 4, O);
118    return;
119  }
120  if (Opcode == ARM::LDR_POST_IMM && MI->getOperand(2).getReg() == ARM::SP &&
121      MI->getOperand(4).getImm() == 4) {
122    O << '\t' << "pop";
123    printPredicateOperand(MI, 5, O);
124    O << "\t{" << getRegisterName(MI->getOperand(0).getReg()) << "}";
125    return;
126  }
127
128
129  // A8.6.355 VPUSH
130  if ((Opcode == ARM::VSTMSDB_UPD || Opcode == ARM::VSTMDDB_UPD) &&
131      MI->getOperand(0).getReg() == ARM::SP) {
132    O << '\t' << "vpush";
133    printPredicateOperand(MI, 2, O);
134    O << '\t';
135    printRegisterList(MI, 4, O);
136    return;
137  }
138
139  // A8.6.354 VPOP
140  if ((Opcode == ARM::VLDMSIA_UPD || Opcode == ARM::VLDMDIA_UPD) &&
141      MI->getOperand(0).getReg() == ARM::SP) {
142    O << '\t' << "vpop";
143    printPredicateOperand(MI, 2, O);
144    O << '\t';
145    printRegisterList(MI, 4, O);
146    return;
147  }
148
149  if (Opcode == ARM::tLDMIA) {
150    bool Writeback = true;
151    unsigned BaseReg = MI->getOperand(0).getReg();
152    for (unsigned i = 3; i < MI->getNumOperands(); ++i) {
153      if (MI->getOperand(i).getReg() == BaseReg)
154        Writeback = false;
155    }
156
157    O << "\tldm";
158
159    printPredicateOperand(MI, 1, O);
160    O << '\t' << getRegisterName(BaseReg);
161    if (Writeback) O << "!";
162    O << ", ";
163    printRegisterList(MI, 3, O);
164    return;
165  }
166
167  // Thumb1 NOP
168  if (Opcode == ARM::tMOVr && MI->getOperand(0).getReg() == ARM::R8 &&
169      MI->getOperand(1).getReg() == ARM::R8) {
170    O << "\tnop";
171    return;
172  }
173
174  printInstruction(MI, O);
175}
176
177void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
178                                  raw_ostream &O) {
179  const MCOperand &Op = MI->getOperand(OpNo);
180  if (Op.isReg()) {
181    unsigned Reg = Op.getReg();
182    O << getRegisterName(Reg);
183  } else if (Op.isImm()) {
184    O << '#' << Op.getImm();
185  } else {
186    assert(Op.isExpr() && "unknown operand kind in printOperand");
187    O << *Op.getExpr();
188  }
189}
190
191// so_reg is a 4-operand unit corresponding to register forms of the A5.1
192// "Addressing Mode 1 - Data-processing operands" forms.  This includes:
193//    REG 0   0           - e.g. R5
194//    REG REG 0,SH_OPC    - e.g. R5, ROR R3
195//    REG 0   IMM,SH_OPC  - e.g. R5, LSL #3
196void ARMInstPrinter::printSORegRegOperand(const MCInst *MI, unsigned OpNum,
197                                       raw_ostream &O) {
198  const MCOperand &MO1 = MI->getOperand(OpNum);
199  const MCOperand &MO2 = MI->getOperand(OpNum+1);
200  const MCOperand &MO3 = MI->getOperand(OpNum+2);
201
202  O << getRegisterName(MO1.getReg());
203
204  // Print the shift opc.
205  ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
206  O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
207  if (ShOpc == ARM_AM::rrx)
208    return;
209
210  O << ' ' << getRegisterName(MO2.getReg());
211  assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
212}
213
214void ARMInstPrinter::printSORegImmOperand(const MCInst *MI, unsigned OpNum,
215                                       raw_ostream &O) {
216  const MCOperand &MO1 = MI->getOperand(OpNum);
217  const MCOperand &MO2 = MI->getOperand(OpNum+1);
218
219  O << getRegisterName(MO1.getReg());
220
221  // Print the shift opc.
222  ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm());
223  O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
224  if (ShOpc == ARM_AM::rrx)
225    return;
226  O << " #" << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm()));
227}
228
229
230//===--------------------------------------------------------------------===//
231// Addressing Mode #2
232//===--------------------------------------------------------------------===//
233
234void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
235                                                raw_ostream &O) {
236  const MCOperand &MO1 = MI->getOperand(Op);
237  const MCOperand &MO2 = MI->getOperand(Op+1);
238  const MCOperand &MO3 = MI->getOperand(Op+2);
239
240  O << "[" << getRegisterName(MO1.getReg());
241
242  if (!MO2.getReg()) {
243    if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
244      O << ", #"
245        << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
246        << ARM_AM::getAM2Offset(MO3.getImm());
247    O << "]";
248    return;
249  }
250
251  O << ", "
252    << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
253    << getRegisterName(MO2.getReg());
254
255  if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
256    O << ", "
257    << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
258    << " #" << ShImm;
259  O << "]";
260}
261
262void ARMInstPrinter::printAM2PostIndexOp(const MCInst *MI, unsigned Op,
263                                         raw_ostream &O) {
264  const MCOperand &MO1 = MI->getOperand(Op);
265  const MCOperand &MO2 = MI->getOperand(Op+1);
266  const MCOperand &MO3 = MI->getOperand(Op+2);
267
268  O << "[" << getRegisterName(MO1.getReg()) << "], ";
269
270  if (!MO2.getReg()) {
271    unsigned ImmOffs = ARM_AM::getAM2Offset(MO3.getImm());
272    O << '#'
273      << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
274      << ImmOffs;
275    return;
276  }
277
278  O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
279    << getRegisterName(MO2.getReg());
280
281  if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
282    O << ", "
283    << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
284    << " #" << ShImm;
285}
286
287void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
288                                           raw_ostream &O) {
289  const MCOperand &MO1 = MI->getOperand(Op);
290
291  if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
292    printOperand(MI, Op, O);
293    return;
294  }
295
296  const MCOperand &MO3 = MI->getOperand(Op+2);
297  unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm());
298
299  if (IdxMode == ARMII::IndexModePost) {
300    printAM2PostIndexOp(MI, Op, O);
301    return;
302  }
303  printAM2PreOrOffsetIndexOp(MI, Op, O);
304}
305
306void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
307                                                 unsigned OpNum,
308                                                 raw_ostream &O) {
309  const MCOperand &MO1 = MI->getOperand(OpNum);
310  const MCOperand &MO2 = MI->getOperand(OpNum+1);
311
312  if (!MO1.getReg()) {
313    unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
314    O << '#'
315      << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
316      << ImmOffs;
317    return;
318  }
319
320  O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
321    << getRegisterName(MO1.getReg());
322
323  if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
324    O << ", "
325    << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
326    << " #" << ShImm;
327}
328
329//===--------------------------------------------------------------------===//
330// Addressing Mode #3
331//===--------------------------------------------------------------------===//
332
333void ARMInstPrinter::printAM3PostIndexOp(const MCInst *MI, unsigned Op,
334                                         raw_ostream &O) {
335  const MCOperand &MO1 = MI->getOperand(Op);
336  const MCOperand &MO2 = MI->getOperand(Op+1);
337  const MCOperand &MO3 = MI->getOperand(Op+2);
338
339  O << "[" << getRegisterName(MO1.getReg()) << "], ";
340
341  if (MO2.getReg()) {
342    O << (char)ARM_AM::getAM3Op(MO3.getImm())
343    << getRegisterName(MO2.getReg());
344    return;
345  }
346
347  unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm());
348  O << '#'
349    << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
350    << ImmOffs;
351}
352
353void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
354                                                raw_ostream &O) {
355  const MCOperand &MO1 = MI->getOperand(Op);
356  const MCOperand &MO2 = MI->getOperand(Op+1);
357  const MCOperand &MO3 = MI->getOperand(Op+2);
358
359  O << '[' << getRegisterName(MO1.getReg());
360
361  if (MO2.getReg()) {
362    O << ", " << getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
363      << getRegisterName(MO2.getReg()) << ']';
364    return;
365  }
366
367  if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
368    O << ", #"
369      << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
370      << ImmOffs;
371  O << ']';
372}
373
374void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op,
375                                           raw_ostream &O) {
376  const MCOperand &MO3 = MI->getOperand(Op+2);
377  unsigned IdxMode = ARM_AM::getAM3IdxMode(MO3.getImm());
378
379  if (IdxMode == ARMII::IndexModePost) {
380    printAM3PostIndexOp(MI, Op, O);
381    return;
382  }
383  printAM3PreOrOffsetIndexOp(MI, Op, O);
384}
385
386void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
387                                                 unsigned OpNum,
388                                                 raw_ostream &O) {
389  const MCOperand &MO1 = MI->getOperand(OpNum);
390  const MCOperand &MO2 = MI->getOperand(OpNum+1);
391
392  if (MO1.getReg()) {
393    O << getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
394      << getRegisterName(MO1.getReg());
395    return;
396  }
397
398  unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
399  O << '#'
400    << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
401    << ImmOffs;
402}
403
404void ARMInstPrinter::printPostIdxImm8Operand(const MCInst *MI,
405                                             unsigned OpNum,
406                                             raw_ostream &O) {
407  const MCOperand &MO = MI->getOperand(OpNum);
408  unsigned Imm = MO.getImm();
409  O << '#' << ((Imm & 256) ? "" : "-") << (Imm & 0xff);
410}
411
412void ARMInstPrinter::printPostIdxRegOperand(const MCInst *MI, unsigned OpNum,
413                                            raw_ostream &O) {
414  const MCOperand &MO1 = MI->getOperand(OpNum);
415  const MCOperand &MO2 = MI->getOperand(OpNum+1);
416
417  O << (MO2.getImm() ? "" : "-") << getRegisterName(MO1.getReg());
418}
419
420void ARMInstPrinter::printPostIdxImm8s4Operand(const MCInst *MI,
421                                             unsigned OpNum,
422                                             raw_ostream &O) {
423  const MCOperand &MO = MI->getOperand(OpNum);
424  unsigned Imm = MO.getImm();
425  O << '#' << ((Imm & 256) ? "" : "-") << ((Imm & 0xff) << 2);
426}
427
428
429void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,
430                                           raw_ostream &O) {
431  ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(OpNum)
432                                                 .getImm());
433  O << ARM_AM::getAMSubModeStr(Mode);
434}
435
436void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
437                                           raw_ostream &O) {
438  const MCOperand &MO1 = MI->getOperand(OpNum);
439  const MCOperand &MO2 = MI->getOperand(OpNum+1);
440
441  if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
442    printOperand(MI, OpNum, O);
443    return;
444  }
445
446  O << "[" << getRegisterName(MO1.getReg());
447
448  if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
449    O << ", #"
450      << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
451      << ImmOffs * 4;
452  }
453  O << "]";
454}
455
456void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
457                                           raw_ostream &O) {
458  const MCOperand &MO1 = MI->getOperand(OpNum);
459  const MCOperand &MO2 = MI->getOperand(OpNum+1);
460
461  O << "[" << getRegisterName(MO1.getReg());
462  if (MO2.getImm()) {
463    // FIXME: Both darwin as and GNU as violate ARM docs here.
464    O << ", :" << (MO2.getImm() << 3);
465  }
466  O << "]";
467}
468
469void ARMInstPrinter::printAddrMode7Operand(const MCInst *MI, unsigned OpNum,
470                                           raw_ostream &O) {
471  const MCOperand &MO1 = MI->getOperand(OpNum);
472  O << "[" << getRegisterName(MO1.getReg()) << "]";
473}
474
475void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
476                                                 unsigned OpNum,
477                                                 raw_ostream &O) {
478  const MCOperand &MO = MI->getOperand(OpNum);
479  if (MO.getReg() == 0)
480    O << "!";
481  else
482    O << ", " << getRegisterName(MO.getReg());
483}
484
485void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
486                                                    unsigned OpNum,
487                                                    raw_ostream &O) {
488  const MCOperand &MO = MI->getOperand(OpNum);
489  uint32_t v = ~MO.getImm();
490  int32_t lsb = CountTrailingZeros_32(v);
491  int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
492  assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
493  O << '#' << lsb << ", #" << width;
494}
495
496void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
497                                     raw_ostream &O) {
498  unsigned val = MI->getOperand(OpNum).getImm();
499  O << ARM_MB::MemBOptToString(val);
500}
501
502void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
503                                          raw_ostream &O) {
504  unsigned ShiftOp = MI->getOperand(OpNum).getImm();
505  bool isASR = (ShiftOp & (1 << 5)) != 0;
506  unsigned Amt = ShiftOp & 0x1f;
507  if (isASR)
508    O << ", asr #" << (Amt == 0 ? 32 : Amt);
509  else if (Amt)
510    O << ", lsl #" << Amt;
511}
512
513void ARMInstPrinter::printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum,
514                                         raw_ostream &O) {
515  unsigned Imm = MI->getOperand(OpNum).getImm();
516  if (Imm == 0)
517    return;
518  assert(Imm > 0 && Imm < 32 && "Invalid PKH shift immediate value!");
519  O << ", lsl #" << Imm;
520}
521
522void ARMInstPrinter::printPKHASRShiftImm(const MCInst *MI, unsigned OpNum,
523                                         raw_ostream &O) {
524  unsigned Imm = MI->getOperand(OpNum).getImm();
525  // A shift amount of 32 is encoded as 0.
526  if (Imm == 0)
527    Imm = 32;
528  assert(Imm > 0 && Imm <= 32 && "Invalid PKH shift immediate value!");
529  O << ", asr #" << Imm;
530}
531
532void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
533                                       raw_ostream &O) {
534  O << "{";
535  for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
536    if (i != OpNum) O << ", ";
537    O << getRegisterName(MI->getOperand(i).getReg());
538  }
539  O << "}";
540}
541
542void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum,
543                                        raw_ostream &O) {
544  const MCOperand &Op = MI->getOperand(OpNum);
545  if (Op.getImm())
546    O << "be";
547  else
548    O << "le";
549}
550
551void ARMInstPrinter::printCPSIMod(const MCInst *MI, unsigned OpNum,
552                                  raw_ostream &O) {
553  const MCOperand &Op = MI->getOperand(OpNum);
554  O << ARM_PROC::IModToString(Op.getImm());
555}
556
557void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum,
558                                   raw_ostream &O) {
559  const MCOperand &Op = MI->getOperand(OpNum);
560  unsigned IFlags = Op.getImm();
561  for (int i=2; i >= 0; --i)
562    if (IFlags & (1 << i))
563      O << ARM_PROC::IFlagsToString(1 << i);
564}
565
566void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
567                                         raw_ostream &O) {
568  const MCOperand &Op = MI->getOperand(OpNum);
569  unsigned SpecRegRBit = Op.getImm() >> 4;
570  unsigned Mask = Op.getImm() & 0xf;
571
572  // As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as
573  // APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.
574  if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
575    O << "APSR_";
576    switch (Mask) {
577    default: assert(0);
578    case 4:  O << "g"; return;
579    case 8:  O << "nzcvq"; return;
580    case 12: O << "nzcvqg"; return;
581    }
582    llvm_unreachable("Unexpected mask value!");
583  }
584
585  if (SpecRegRBit)
586    O << "SPSR";
587  else
588    O << "CPSR";
589
590  if (Mask) {
591    O << '_';
592    if (Mask & 8) O << 'f';
593    if (Mask & 4) O << 's';
594    if (Mask & 2) O << 'x';
595    if (Mask & 1) O << 'c';
596  }
597}
598
599void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
600                                           raw_ostream &O) {
601  ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
602  if (CC != ARMCC::AL)
603    O << ARMCondCodeToString(CC);
604}
605
606void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
607                                                    unsigned OpNum,
608                                                    raw_ostream &O) {
609  ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
610  O << ARMCondCodeToString(CC);
611}
612
613void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
614                                              raw_ostream &O) {
615  if (MI->getOperand(OpNum).getReg()) {
616    assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
617           "Expect ARM CPSR register!");
618    O << 's';
619  }
620}
621
622void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
623                                          raw_ostream &O) {
624  O << MI->getOperand(OpNum).getImm();
625}
626
627void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum,
628                                          raw_ostream &O) {
629  O << "p" << MI->getOperand(OpNum).getImm();
630}
631
632void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum,
633                                          raw_ostream &O) {
634  O << "c" << MI->getOperand(OpNum).getImm();
635}
636
637void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
638                                  raw_ostream &O) {
639  llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
640}
641
642void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
643                                            raw_ostream &O) {
644  O << "#" << MI->getOperand(OpNum).getImm() * 4;
645}
646
647void ARMInstPrinter::printThumbSRImm(const MCInst *MI, unsigned OpNum,
648                                     raw_ostream &O) {
649  unsigned Imm = MI->getOperand(OpNum).getImm();
650  O << "#" << (Imm == 0 ? 32 : Imm);
651}
652
653void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
654                                      raw_ostream &O) {
655  // (3 - the number of trailing zeros) is the number of then / else.
656  unsigned Mask = MI->getOperand(OpNum).getImm();
657  unsigned CondBit0 = Mask >> 4 & 1;
658  unsigned NumTZ = CountTrailingZeros_32(Mask);
659  assert(NumTZ <= 3 && "Invalid IT mask!");
660  for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
661    bool T = ((Mask >> Pos) & 1) == CondBit0;
662    if (T)
663      O << 't';
664    else
665      O << 'e';
666  }
667}
668
669void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
670                                                 raw_ostream &O) {
671  const MCOperand &MO1 = MI->getOperand(Op);
672  const MCOperand &MO2 = MI->getOperand(Op + 1);
673
674  if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
675    printOperand(MI, Op, O);
676    return;
677  }
678
679  O << "[" << getRegisterName(MO1.getReg());
680  if (unsigned RegNum = MO2.getReg())
681    O << ", " << getRegisterName(RegNum);
682  O << "]";
683}
684
685void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI,
686                                                    unsigned Op,
687                                                    raw_ostream &O,
688                                                    unsigned Scale) {
689  const MCOperand &MO1 = MI->getOperand(Op);
690  const MCOperand &MO2 = MI->getOperand(Op + 1);
691
692  if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
693    printOperand(MI, Op, O);
694    return;
695  }
696
697  O << "[" << getRegisterName(MO1.getReg());
698  if (unsigned ImmOffs = MO2.getImm())
699    O << ", #" << ImmOffs * Scale;
700  O << "]";
701}
702
703void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI,
704                                                     unsigned Op,
705                                                     raw_ostream &O) {
706  printThumbAddrModeImm5SOperand(MI, Op, O, 1);
707}
708
709void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI,
710                                                     unsigned Op,
711                                                     raw_ostream &O) {
712  printThumbAddrModeImm5SOperand(MI, Op, O, 2);
713}
714
715void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI,
716                                                     unsigned Op,
717                                                     raw_ostream &O) {
718  printThumbAddrModeImm5SOperand(MI, Op, O, 4);
719}
720
721void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
722                                                 raw_ostream &O) {
723  printThumbAddrModeImm5SOperand(MI, Op, O, 4);
724}
725
726// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
727// register with shift forms.
728// REG 0   0           - e.g. R5
729// REG IMM, SH_OPC     - e.g. R5, LSL #3
730void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
731                                      raw_ostream &O) {
732  const MCOperand &MO1 = MI->getOperand(OpNum);
733  const MCOperand &MO2 = MI->getOperand(OpNum+1);
734
735  unsigned Reg = MO1.getReg();
736  O << getRegisterName(Reg);
737
738  // Print the shift opc.
739  assert(MO2.isImm() && "Not a valid t2_so_reg value!");
740  ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm());
741  O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
742  if (ShOpc != ARM_AM::rrx)
743    O << " #" << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm()));
744}
745
746void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
747                                               raw_ostream &O) {
748  const MCOperand &MO1 = MI->getOperand(OpNum);
749  const MCOperand &MO2 = MI->getOperand(OpNum+1);
750
751  if (!MO1.isReg()) {   // FIXME: This is for CP entries, but isn't right.
752    printOperand(MI, OpNum, O);
753    return;
754  }
755
756  O << "[" << getRegisterName(MO1.getReg());
757
758  int32_t OffImm = (int32_t)MO2.getImm();
759  bool isSub = OffImm < 0;
760  // Special value for #-0. All others are normal.
761  if (OffImm == INT32_MIN)
762    OffImm = 0;
763  if (isSub)
764    O << ", #-" << -OffImm;
765  else if (OffImm > 0)
766    O << ", #" << OffImm;
767  O << "]";
768}
769
770void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
771                                                unsigned OpNum,
772                                                raw_ostream &O) {
773  const MCOperand &MO1 = MI->getOperand(OpNum);
774  const MCOperand &MO2 = MI->getOperand(OpNum+1);
775
776  O << "[" << getRegisterName(MO1.getReg());
777
778  int32_t OffImm = (int32_t)MO2.getImm();
779  // Don't print +0.
780  if (OffImm < 0)
781    O << ", #-" << -OffImm;
782  else if (OffImm > 0)
783    O << ", #" << OffImm;
784  O << "]";
785}
786
787void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
788                                                  unsigned OpNum,
789                                                  raw_ostream &O) {
790  const MCOperand &MO1 = MI->getOperand(OpNum);
791  const MCOperand &MO2 = MI->getOperand(OpNum+1);
792
793  O << "[" << getRegisterName(MO1.getReg());
794
795  int32_t OffImm = (int32_t)MO2.getImm() / 4;
796  // Don't print +0.
797  if (OffImm < 0)
798    O << ", #-" << -OffImm * 4;
799  else if (OffImm > 0)
800    O << ", #" << OffImm * 4;
801  O << "]";
802}
803
804void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
805                                                      unsigned OpNum,
806                                                      raw_ostream &O) {
807  const MCOperand &MO1 = MI->getOperand(OpNum);
808  int32_t OffImm = (int32_t)MO1.getImm();
809  // Don't print +0.
810  if (OffImm < 0)
811    O << "#-" << -OffImm;
812  else if (OffImm > 0)
813    O << "#" << OffImm;
814}
815
816void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
817                                                        unsigned OpNum,
818                                                        raw_ostream &O) {
819  const MCOperand &MO1 = MI->getOperand(OpNum);
820  int32_t OffImm = (int32_t)MO1.getImm() / 4;
821  // Don't print +0.
822  if (OffImm < 0)
823    O << "#-" << -OffImm * 4;
824  else if (OffImm > 0)
825    O << "#" << OffImm * 4;
826}
827
828void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
829                                                 unsigned OpNum,
830                                                 raw_ostream &O) {
831  const MCOperand &MO1 = MI->getOperand(OpNum);
832  const MCOperand &MO2 = MI->getOperand(OpNum+1);
833  const MCOperand &MO3 = MI->getOperand(OpNum+2);
834
835  O << "[" << getRegisterName(MO1.getReg());
836
837  assert(MO2.getReg() && "Invalid so_reg load / store address!");
838  O << ", " << getRegisterName(MO2.getReg());
839
840  unsigned ShAmt = MO3.getImm();
841  if (ShAmt) {
842    assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
843    O << ", lsl #" << ShAmt;
844  }
845  O << "]";
846}
847
848void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum,
849                                           raw_ostream &O) {
850  const MCOperand &MO = MI->getOperand(OpNum);
851  O << '#';
852  if (MO.isFPImm()) {
853    O << (float)MO.getFPImm();
854  } else {
855    union {
856      uint32_t I;
857      float F;
858    } FPUnion;
859
860    FPUnion.I = MO.getImm();
861    O << FPUnion.F;
862  }
863}
864
865void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum,
866                                           raw_ostream &O) {
867  const MCOperand &MO = MI->getOperand(OpNum);
868  O << '#';
869  if (MO.isFPImm()) {
870    O << MO.getFPImm();
871  } else {
872    // We expect the binary encoding of a floating point number here.
873    union {
874      uint64_t I;
875      double D;
876    } FPUnion;
877
878    FPUnion.I = MO.getImm();
879    O << FPUnion.D;
880  }
881}
882
883void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
884                                            raw_ostream &O) {
885  unsigned EncodedImm = MI->getOperand(OpNum).getImm();
886  unsigned EltBits;
887  uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
888  O << "#0x" << utohexstr(Val);
889}
890
891void ARMInstPrinter::printImmPlusOneOperand(const MCInst *MI, unsigned OpNum,
892                                            raw_ostream &O) {
893  unsigned Imm = MI->getOperand(OpNum).getImm();
894  O << "#" << Imm + 1;
895}
896
897void ARMInstPrinter::printRotImmOperand(const MCInst *MI, unsigned OpNum,
898                                        raw_ostream &O) {
899  unsigned Imm = MI->getOperand(OpNum).getImm();
900  if (Imm == 0)
901    return;
902  O << ", ror #";
903  switch (Imm) {
904  default: assert (0 && "illegal ror immediate!");
905  case 1: O << "8"; break;
906  case 2: O << "16"; break;
907  case 3: O << "24"; break;
908  }
909}
910