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