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