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