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