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