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 #include "ARMInstPrinter.h"
15 #include "MCTargetDesc/ARMAddressingModes.h"
16 #include "MCTargetDesc/ARMBaseInfo.h"
17 #include "llvm/MC/MCAsmInfo.h"
18 #include "llvm/MC/MCExpr.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCInstrInfo.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/Support/raw_ostream.h"
23 using namespace llvm;
24 
25 #define DEBUG_TYPE "asm-printer"
26 
27 #include "ARMGenAsmWriter.inc"
28 
29 /// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing.
30 ///
31 /// getSORegOffset returns an integer from 0-31, representing '32' as 0.
translateShiftImm(unsigned imm)32 static unsigned translateShiftImm(unsigned imm) {
33   // lsr #32 and asr #32 exist, but should be encoded as a 0.
34   assert((imm & ~0x1f) == 0 && "Invalid shift encoding");
35 
36   if (imm == 0)
37     return 32;
38   return imm;
39 }
40 
41 /// Prints the shift value with an immediate value.
printRegImmShift(raw_ostream & O,ARM_AM::ShiftOpc ShOpc,unsigned ShImm,bool UseMarkup)42 static void printRegImmShift(raw_ostream &O, ARM_AM::ShiftOpc ShOpc,
43                              unsigned ShImm, bool UseMarkup) {
44   if (ShOpc == ARM_AM::no_shift || (ShOpc == ARM_AM::lsl && !ShImm))
45     return;
46   O << ", ";
47 
48   assert(!(ShOpc == ARM_AM::ror && !ShImm) && "Cannot have ror #0");
49   O << getShiftOpcStr(ShOpc);
50 
51   if (ShOpc != ARM_AM::rrx) {
52     O << " ";
53     if (UseMarkup)
54       O << "<imm:";
55     O << "#" << translateShiftImm(ShImm);
56     if (UseMarkup)
57       O << ">";
58   }
59 }
60 
ARMInstPrinter(const MCAsmInfo & MAI,const MCInstrInfo & MII,const MCRegisterInfo & MRI)61 ARMInstPrinter::ARMInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
62                                const MCRegisterInfo &MRI)
63     : MCInstPrinter(MAI, MII, MRI) {}
64 
printRegName(raw_ostream & OS,unsigned RegNo) const65 void ARMInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
66   OS << markup("<reg:") << getRegisterName(RegNo) << markup(">");
67 }
68 
printInst(const MCInst * MI,raw_ostream & O,StringRef Annot,const MCSubtargetInfo & STI)69 void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
70                                StringRef Annot, const MCSubtargetInfo &STI) {
71   unsigned Opcode = MI->getOpcode();
72 
73   switch (Opcode) {
74 
75   // Check for HINT instructions w/ canonical names.
76   case ARM::HINT:
77   case ARM::tHINT:
78   case ARM::t2HINT:
79     switch (MI->getOperand(0).getImm()) {
80     case 0:
81       O << "\tnop";
82       break;
83     case 1:
84       O << "\tyield";
85       break;
86     case 2:
87       O << "\twfe";
88       break;
89     case 3:
90       O << "\twfi";
91       break;
92     case 4:
93       O << "\tsev";
94       break;
95     case 5:
96       if (STI.getFeatureBits()[ARM::HasV8Ops]) {
97         O << "\tsevl";
98         break;
99       } // Fallthrough for non-v8
100     default:
101       // Anything else should just print normally.
102       printInstruction(MI, STI, O);
103       printAnnotation(O, Annot);
104       return;
105     }
106     printPredicateOperand(MI, 1, STI, O);
107     if (Opcode == ARM::t2HINT)
108       O << ".w";
109     printAnnotation(O, Annot);
110     return;
111 
112   // Check for MOVs and print canonical forms, instead.
113   case ARM::MOVsr: {
114     // FIXME: Thumb variants?
115     const MCOperand &Dst = MI->getOperand(0);
116     const MCOperand &MO1 = MI->getOperand(1);
117     const MCOperand &MO2 = MI->getOperand(2);
118     const MCOperand &MO3 = MI->getOperand(3);
119 
120     O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
121     printSBitModifierOperand(MI, 6, STI, O);
122     printPredicateOperand(MI, 4, STI, O);
123 
124     O << '\t';
125     printRegName(O, Dst.getReg());
126     O << ", ";
127     printRegName(O, MO1.getReg());
128 
129     O << ", ";
130     printRegName(O, MO2.getReg());
131     assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
132     printAnnotation(O, Annot);
133     return;
134   }
135 
136   case ARM::MOVsi: {
137     // FIXME: Thumb variants?
138     const MCOperand &Dst = MI->getOperand(0);
139     const MCOperand &MO1 = MI->getOperand(1);
140     const MCOperand &MO2 = MI->getOperand(2);
141 
142     O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()));
143     printSBitModifierOperand(MI, 5, STI, O);
144     printPredicateOperand(MI, 3, STI, O);
145 
146     O << '\t';
147     printRegName(O, Dst.getReg());
148     O << ", ";
149     printRegName(O, MO1.getReg());
150 
151     if (ARM_AM::getSORegShOp(MO2.getImm()) == ARM_AM::rrx) {
152       printAnnotation(O, Annot);
153       return;
154     }
155 
156     O << ", " << markup("<imm:") << "#"
157       << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm())) << markup(">");
158     printAnnotation(O, Annot);
159     return;
160   }
161 
162   // A8.6.123 PUSH
163   case ARM::STMDB_UPD:
164   case ARM::t2STMDB_UPD:
165     if (MI->getOperand(0).getReg() == ARM::SP && MI->getNumOperands() > 5) {
166       // Should only print PUSH if there are at least two registers in the list.
167       O << '\t' << "push";
168       printPredicateOperand(MI, 2, STI, O);
169       if (Opcode == ARM::t2STMDB_UPD)
170         O << ".w";
171       O << '\t';
172       printRegisterList(MI, 4, STI, O);
173       printAnnotation(O, Annot);
174       return;
175     } else
176       break;
177 
178   case ARM::STR_PRE_IMM:
179     if (MI->getOperand(2).getReg() == ARM::SP &&
180         MI->getOperand(3).getImm() == -4) {
181       O << '\t' << "push";
182       printPredicateOperand(MI, 4, STI, O);
183       O << "\t{";
184       printRegName(O, MI->getOperand(1).getReg());
185       O << "}";
186       printAnnotation(O, Annot);
187       return;
188     } else
189       break;
190 
191   // A8.6.122 POP
192   case ARM::LDMIA_UPD:
193   case ARM::t2LDMIA_UPD:
194     if (MI->getOperand(0).getReg() == ARM::SP && MI->getNumOperands() > 5) {
195       // Should only print POP if there are at least two registers in the list.
196       O << '\t' << "pop";
197       printPredicateOperand(MI, 2, STI, O);
198       if (Opcode == ARM::t2LDMIA_UPD)
199         O << ".w";
200       O << '\t';
201       printRegisterList(MI, 4, STI, O);
202       printAnnotation(O, Annot);
203       return;
204     } else
205       break;
206 
207   case ARM::LDR_POST_IMM:
208     if (MI->getOperand(2).getReg() == ARM::SP &&
209         MI->getOperand(4).getImm() == 4) {
210       O << '\t' << "pop";
211       printPredicateOperand(MI, 5, STI, O);
212       O << "\t{";
213       printRegName(O, MI->getOperand(0).getReg());
214       O << "}";
215       printAnnotation(O, Annot);
216       return;
217     } else
218       break;
219 
220   // A8.6.355 VPUSH
221   case ARM::VSTMSDB_UPD:
222   case ARM::VSTMDDB_UPD:
223     if (MI->getOperand(0).getReg() == ARM::SP) {
224       O << '\t' << "vpush";
225       printPredicateOperand(MI, 2, STI, O);
226       O << '\t';
227       printRegisterList(MI, 4, STI, O);
228       printAnnotation(O, Annot);
229       return;
230     } else
231       break;
232 
233   // A8.6.354 VPOP
234   case ARM::VLDMSIA_UPD:
235   case ARM::VLDMDIA_UPD:
236     if (MI->getOperand(0).getReg() == ARM::SP) {
237       O << '\t' << "vpop";
238       printPredicateOperand(MI, 2, STI, O);
239       O << '\t';
240       printRegisterList(MI, 4, STI, O);
241       printAnnotation(O, Annot);
242       return;
243     } else
244       break;
245 
246   case ARM::tLDMIA: {
247     bool Writeback = true;
248     unsigned BaseReg = MI->getOperand(0).getReg();
249     for (unsigned i = 3; i < MI->getNumOperands(); ++i) {
250       if (MI->getOperand(i).getReg() == BaseReg)
251         Writeback = false;
252     }
253 
254     O << "\tldm";
255 
256     printPredicateOperand(MI, 1, STI, O);
257     O << '\t';
258     printRegName(O, BaseReg);
259     if (Writeback)
260       O << "!";
261     O << ", ";
262     printRegisterList(MI, 3, STI, O);
263     printAnnotation(O, Annot);
264     return;
265   }
266 
267   // Combine 2 GPRs from disassember into a GPRPair to match with instr def.
268   // ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
269   // a single GPRPair reg operand is used in the .td file to replace the two
270   // GPRs. However, when decoding them, the two GRPs cannot be automatically
271   // expressed as a GPRPair, so we have to manually merge them.
272   // FIXME: We would really like to be able to tablegen'erate this.
273   case ARM::LDREXD:
274   case ARM::STREXD:
275   case ARM::LDAEXD:
276   case ARM::STLEXD: {
277     const MCRegisterClass &MRC = MRI.getRegClass(ARM::GPRRegClassID);
278     bool isStore = Opcode == ARM::STREXD || Opcode == ARM::STLEXD;
279     unsigned Reg = MI->getOperand(isStore ? 1 : 0).getReg();
280     if (MRC.contains(Reg)) {
281       MCInst NewMI;
282       MCOperand NewReg;
283       NewMI.setOpcode(Opcode);
284 
285       if (isStore)
286         NewMI.addOperand(MI->getOperand(0));
287       NewReg = MCOperand::createReg(MRI.getMatchingSuperReg(
288           Reg, ARM::gsub_0, &MRI.getRegClass(ARM::GPRPairRegClassID)));
289       NewMI.addOperand(NewReg);
290 
291       // Copy the rest operands into NewMI.
292       for (unsigned i = isStore ? 3 : 2; i < MI->getNumOperands(); ++i)
293         NewMI.addOperand(MI->getOperand(i));
294       printInstruction(&NewMI, STI, O);
295       return;
296     }
297     break;
298   }
299   // B9.3.3 ERET (Thumb)
300   // For a target that has Virtualization Extensions, ERET is the preferred
301   // disassembly of SUBS PC, LR, #0
302   case ARM::t2SUBS_PC_LR: {
303     if (MI->getNumOperands() == 3 && MI->getOperand(0).isImm() &&
304         MI->getOperand(0).getImm() == 0 &&
305         STI.getFeatureBits()[ARM::FeatureVirtualization]) {
306       O << "\teret";
307       printPredicateOperand(MI, 1, STI, O);
308       printAnnotation(O, Annot);
309       return;
310     }
311     break;
312   }
313   }
314 
315   printInstruction(MI, STI, O);
316   printAnnotation(O, Annot);
317 }
318 
printOperand(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)319 void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
320                                   const MCSubtargetInfo &STI, raw_ostream &O) {
321   const MCOperand &Op = MI->getOperand(OpNo);
322   if (Op.isReg()) {
323     unsigned Reg = Op.getReg();
324     printRegName(O, Reg);
325   } else if (Op.isImm()) {
326     O << markup("<imm:") << '#' << formatImm(Op.getImm()) << markup(">");
327   } else {
328     assert(Op.isExpr() && "unknown operand kind in printOperand");
329     const MCExpr *Expr = Op.getExpr();
330     switch (Expr->getKind()) {
331     case MCExpr::Binary:
332       O << '#';
333       Expr->print(O, &MAI);
334       break;
335     case MCExpr::Constant: {
336       // If a symbolic branch target was added as a constant expression then
337       // print that address in hex. And only print 32 unsigned bits for the
338       // address.
339       const MCConstantExpr *Constant = cast<MCConstantExpr>(Expr);
340       int64_t TargetAddress;
341       if (!Constant->evaluateAsAbsolute(TargetAddress)) {
342         O << '#';
343         Expr->print(O, &MAI);
344       } else {
345         O << "0x";
346         O.write_hex(static_cast<uint32_t>(TargetAddress));
347       }
348       break;
349     }
350     default:
351       // FIXME: Should we always treat this as if it is a constant literal and
352       // prefix it with '#'?
353       Expr->print(O, &MAI);
354       break;
355     }
356   }
357 }
358 
printThumbLdrLabelOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)359 void ARMInstPrinter::printThumbLdrLabelOperand(const MCInst *MI, unsigned OpNum,
360                                                const MCSubtargetInfo &STI,
361                                                raw_ostream &O) {
362   const MCOperand &MO1 = MI->getOperand(OpNum);
363   if (MO1.isExpr()) {
364     MO1.getExpr()->print(O, &MAI);
365     return;
366   }
367 
368   O << markup("<mem:") << "[pc, ";
369 
370   int32_t OffImm = (int32_t)MO1.getImm();
371   bool isSub = OffImm < 0;
372 
373   // Special value for #-0. All others are normal.
374   if (OffImm == INT32_MIN)
375     OffImm = 0;
376   if (isSub) {
377     O << markup("<imm:") << "#-" << formatImm(-OffImm) << markup(">");
378   } else {
379     O << markup("<imm:") << "#" << formatImm(OffImm) << markup(">");
380   }
381   O << "]" << markup(">");
382 }
383 
384 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
385 // "Addressing Mode 1 - Data-processing operands" forms.  This includes:
386 //    REG 0   0           - e.g. R5
387 //    REG REG 0,SH_OPC    - e.g. R5, ROR R3
388 //    REG 0   IMM,SH_OPC  - e.g. R5, LSL #3
printSORegRegOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)389 void ARMInstPrinter::printSORegRegOperand(const MCInst *MI, unsigned OpNum,
390                                           const MCSubtargetInfo &STI,
391                                           raw_ostream &O) {
392   const MCOperand &MO1 = MI->getOperand(OpNum);
393   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
394   const MCOperand &MO3 = MI->getOperand(OpNum + 2);
395 
396   printRegName(O, MO1.getReg());
397 
398   // Print the shift opc.
399   ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
400   O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
401   if (ShOpc == ARM_AM::rrx)
402     return;
403 
404   O << ' ';
405   printRegName(O, MO2.getReg());
406   assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
407 }
408 
printSORegImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)409 void ARMInstPrinter::printSORegImmOperand(const MCInst *MI, unsigned OpNum,
410                                           const MCSubtargetInfo &STI,
411                                           raw_ostream &O) {
412   const MCOperand &MO1 = MI->getOperand(OpNum);
413   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
414 
415   printRegName(O, MO1.getReg());
416 
417   // Print the shift opc.
418   printRegImmShift(O, ARM_AM::getSORegShOp(MO2.getImm()),
419                    ARM_AM::getSORegOffset(MO2.getImm()), UseMarkup);
420 }
421 
422 //===--------------------------------------------------------------------===//
423 // Addressing Mode #2
424 //===--------------------------------------------------------------------===//
425 
printAM2PreOrOffsetIndexOp(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)426 void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
427                                                 const MCSubtargetInfo &STI,
428                                                 raw_ostream &O) {
429   const MCOperand &MO1 = MI->getOperand(Op);
430   const MCOperand &MO2 = MI->getOperand(Op + 1);
431   const MCOperand &MO3 = MI->getOperand(Op + 2);
432 
433   O << markup("<mem:") << "[";
434   printRegName(O, MO1.getReg());
435 
436   if (!MO2.getReg()) {
437     if (ARM_AM::getAM2Offset(MO3.getImm())) { // Don't print +0.
438       O << ", " << markup("<imm:") << "#"
439         << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
440         << ARM_AM::getAM2Offset(MO3.getImm()) << markup(">");
441     }
442     O << "]" << markup(">");
443     return;
444   }
445 
446   O << ", ";
447   O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()));
448   printRegName(O, MO2.getReg());
449 
450   printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO3.getImm()),
451                    ARM_AM::getAM2Offset(MO3.getImm()), UseMarkup);
452   O << "]" << markup(">");
453 }
454 
printAddrModeTBB(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)455 void ARMInstPrinter::printAddrModeTBB(const MCInst *MI, unsigned Op,
456                                       const MCSubtargetInfo &STI,
457                                       raw_ostream &O) {
458   const MCOperand &MO1 = MI->getOperand(Op);
459   const MCOperand &MO2 = MI->getOperand(Op + 1);
460   O << markup("<mem:") << "[";
461   printRegName(O, MO1.getReg());
462   O << ", ";
463   printRegName(O, MO2.getReg());
464   O << "]" << markup(">");
465 }
466 
printAddrModeTBH(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)467 void ARMInstPrinter::printAddrModeTBH(const MCInst *MI, unsigned Op,
468                                       const MCSubtargetInfo &STI,
469                                       raw_ostream &O) {
470   const MCOperand &MO1 = MI->getOperand(Op);
471   const MCOperand &MO2 = MI->getOperand(Op + 1);
472   O << markup("<mem:") << "[";
473   printRegName(O, MO1.getReg());
474   O << ", ";
475   printRegName(O, MO2.getReg());
476   O << ", lsl " << markup("<imm:") << "#1" << markup(">") << "]" << markup(">");
477 }
478 
printAddrMode2Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)479 void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
480                                            const MCSubtargetInfo &STI,
481                                            raw_ostream &O) {
482   const MCOperand &MO1 = MI->getOperand(Op);
483 
484   if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
485     printOperand(MI, Op, STI, O);
486     return;
487   }
488 
489 #ifndef NDEBUG
490   const MCOperand &MO3 = MI->getOperand(Op + 2);
491   unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm());
492   assert(IdxMode != ARMII::IndexModePost && "Should be pre or offset index op");
493 #endif
494 
495   printAM2PreOrOffsetIndexOp(MI, Op, STI, O);
496 }
497 
printAddrMode2OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)498 void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
499                                                  unsigned OpNum,
500                                                  const MCSubtargetInfo &STI,
501                                                  raw_ostream &O) {
502   const MCOperand &MO1 = MI->getOperand(OpNum);
503   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
504 
505   if (!MO1.getReg()) {
506     unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
507     O << markup("<imm:") << '#'
508       << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) << ImmOffs
509       << markup(">");
510     return;
511   }
512 
513   O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()));
514   printRegName(O, MO1.getReg());
515 
516   printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO2.getImm()),
517                    ARM_AM::getAM2Offset(MO2.getImm()), UseMarkup);
518 }
519 
520 //===--------------------------------------------------------------------===//
521 // Addressing Mode #3
522 //===--------------------------------------------------------------------===//
523 
printAM3PreOrOffsetIndexOp(const MCInst * MI,unsigned Op,raw_ostream & O,bool AlwaysPrintImm0)524 void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
525                                                 raw_ostream &O,
526                                                 bool AlwaysPrintImm0) {
527   const MCOperand &MO1 = MI->getOperand(Op);
528   const MCOperand &MO2 = MI->getOperand(Op + 1);
529   const MCOperand &MO3 = MI->getOperand(Op + 2);
530 
531   O << markup("<mem:") << '[';
532   printRegName(O, MO1.getReg());
533 
534   if (MO2.getReg()) {
535     O << ", " << getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()));
536     printRegName(O, MO2.getReg());
537     O << ']' << markup(">");
538     return;
539   }
540 
541   // If the op is sub we have to print the immediate even if it is 0
542   unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm());
543   ARM_AM::AddrOpc op = ARM_AM::getAM3Op(MO3.getImm());
544 
545   if (AlwaysPrintImm0 || ImmOffs || (op == ARM_AM::sub)) {
546     O << ", " << markup("<imm:") << "#" << ARM_AM::getAddrOpcStr(op) << ImmOffs
547       << markup(">");
548   }
549   O << ']' << markup(">");
550 }
551 
552 template <bool AlwaysPrintImm0>
printAddrMode3Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)553 void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op,
554                                            const MCSubtargetInfo &STI,
555                                            raw_ostream &O) {
556   const MCOperand &MO1 = MI->getOperand(Op);
557   if (!MO1.isReg()) { //  For label symbolic references.
558     printOperand(MI, Op, STI, O);
559     return;
560   }
561 
562   assert(ARM_AM::getAM3IdxMode(MI->getOperand(Op + 2).getImm()) !=
563              ARMII::IndexModePost &&
564          "unexpected idxmode");
565   printAM3PreOrOffsetIndexOp(MI, Op, O, AlwaysPrintImm0);
566 }
567 
printAddrMode3OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)568 void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
569                                                  unsigned OpNum,
570                                                  const MCSubtargetInfo &STI,
571                                                  raw_ostream &O) {
572   const MCOperand &MO1 = MI->getOperand(OpNum);
573   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
574 
575   if (MO1.getReg()) {
576     O << getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()));
577     printRegName(O, MO1.getReg());
578     return;
579   }
580 
581   unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
582   O << markup("<imm:") << '#'
583     << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm())) << ImmOffs
584     << markup(">");
585 }
586 
printPostIdxImm8Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)587 void ARMInstPrinter::printPostIdxImm8Operand(const MCInst *MI, unsigned OpNum,
588                                              const MCSubtargetInfo &STI,
589                                              raw_ostream &O) {
590   const MCOperand &MO = MI->getOperand(OpNum);
591   unsigned Imm = MO.getImm();
592   O << markup("<imm:") << '#' << ((Imm & 256) ? "" : "-") << (Imm & 0xff)
593     << markup(">");
594 }
595 
printPostIdxRegOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)596 void ARMInstPrinter::printPostIdxRegOperand(const MCInst *MI, unsigned OpNum,
597                                             const MCSubtargetInfo &STI,
598                                             raw_ostream &O) {
599   const MCOperand &MO1 = MI->getOperand(OpNum);
600   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
601 
602   O << (MO2.getImm() ? "" : "-");
603   printRegName(O, MO1.getReg());
604 }
605 
printPostIdxImm8s4Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)606 void ARMInstPrinter::printPostIdxImm8s4Operand(const MCInst *MI, unsigned OpNum,
607                                                const MCSubtargetInfo &STI,
608                                                raw_ostream &O) {
609   const MCOperand &MO = MI->getOperand(OpNum);
610   unsigned Imm = MO.getImm();
611   O << markup("<imm:") << '#' << ((Imm & 256) ? "" : "-") << ((Imm & 0xff) << 2)
612     << markup(">");
613 }
614 
printLdStmModeOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)615 void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,
616                                            const MCSubtargetInfo &STI,
617                                            raw_ostream &O) {
618   ARM_AM::AMSubMode Mode =
619       ARM_AM::getAM4SubMode(MI->getOperand(OpNum).getImm());
620   O << ARM_AM::getAMSubModeStr(Mode);
621 }
622 
623 template <bool AlwaysPrintImm0>
printAddrMode5Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)624 void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
625                                            const MCSubtargetInfo &STI,
626                                            raw_ostream &O) {
627   const MCOperand &MO1 = MI->getOperand(OpNum);
628   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
629 
630   if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
631     printOperand(MI, OpNum, STI, O);
632     return;
633   }
634 
635   O << markup("<mem:") << "[";
636   printRegName(O, MO1.getReg());
637 
638   unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm());
639   ARM_AM::AddrOpc Op = ARM_AM::getAM5Op(MO2.getImm());
640   if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM::sub) {
641     O << ", " << markup("<imm:") << "#" << ARM_AM::getAddrOpcStr(Op)
642       << ImmOffs * 4 << markup(">");
643   }
644   O << "]" << markup(">");
645 }
646 
printAddrMode6Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)647 void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
648                                            const MCSubtargetInfo &STI,
649                                            raw_ostream &O) {
650   const MCOperand &MO1 = MI->getOperand(OpNum);
651   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
652 
653   O << markup("<mem:") << "[";
654   printRegName(O, MO1.getReg());
655   if (MO2.getImm()) {
656     O << ":" << (MO2.getImm() << 3);
657   }
658   O << "]" << markup(">");
659 }
660 
printAddrMode7Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)661 void ARMInstPrinter::printAddrMode7Operand(const MCInst *MI, unsigned OpNum,
662                                            const MCSubtargetInfo &STI,
663                                            raw_ostream &O) {
664   const MCOperand &MO1 = MI->getOperand(OpNum);
665   O << markup("<mem:") << "[";
666   printRegName(O, MO1.getReg());
667   O << "]" << markup(">");
668 }
669 
printAddrMode6OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)670 void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
671                                                  unsigned OpNum,
672                                                  const MCSubtargetInfo &STI,
673                                                  raw_ostream &O) {
674   const MCOperand &MO = MI->getOperand(OpNum);
675   if (MO.getReg() == 0)
676     O << "!";
677   else {
678     O << ", ";
679     printRegName(O, MO.getReg());
680   }
681 }
682 
printBitfieldInvMaskImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)683 void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
684                                                     unsigned OpNum,
685                                                     const MCSubtargetInfo &STI,
686                                                     raw_ostream &O) {
687   const MCOperand &MO = MI->getOperand(OpNum);
688   uint32_t v = ~MO.getImm();
689   int32_t lsb = countTrailingZeros(v);
690   int32_t width = (32 - countLeadingZeros(v)) - lsb;
691   assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
692   O << markup("<imm:") << '#' << lsb << markup(">") << ", " << markup("<imm:")
693     << '#' << width << markup(">");
694 }
695 
printMemBOption(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)696 void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
697                                      const MCSubtargetInfo &STI,
698                                      raw_ostream &O) {
699   unsigned val = MI->getOperand(OpNum).getImm();
700   O << ARM_MB::MemBOptToString(val, STI.getFeatureBits()[ARM::HasV8Ops]);
701 }
702 
printInstSyncBOption(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)703 void ARMInstPrinter::printInstSyncBOption(const MCInst *MI, unsigned OpNum,
704                                           const MCSubtargetInfo &STI,
705                                           raw_ostream &O) {
706   unsigned val = MI->getOperand(OpNum).getImm();
707   O << ARM_ISB::InstSyncBOptToString(val);
708 }
709 
printShiftImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)710 void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
711                                           const MCSubtargetInfo &STI,
712                                           raw_ostream &O) {
713   unsigned ShiftOp = MI->getOperand(OpNum).getImm();
714   bool isASR = (ShiftOp & (1 << 5)) != 0;
715   unsigned Amt = ShiftOp & 0x1f;
716   if (isASR) {
717     O << ", asr " << markup("<imm:") << "#" << (Amt == 0 ? 32 : Amt)
718       << markup(">");
719   } else if (Amt) {
720     O << ", lsl " << markup("<imm:") << "#" << Amt << markup(">");
721   }
722 }
723 
printPKHLSLShiftImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)724 void ARMInstPrinter::printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum,
725                                          const MCSubtargetInfo &STI,
726                                          raw_ostream &O) {
727   unsigned Imm = MI->getOperand(OpNum).getImm();
728   if (Imm == 0)
729     return;
730   assert(Imm > 0 && Imm < 32 && "Invalid PKH shift immediate value!");
731   O << ", lsl " << markup("<imm:") << "#" << Imm << markup(">");
732 }
733 
printPKHASRShiftImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)734 void ARMInstPrinter::printPKHASRShiftImm(const MCInst *MI, unsigned OpNum,
735                                          const MCSubtargetInfo &STI,
736                                          raw_ostream &O) {
737   unsigned Imm = MI->getOperand(OpNum).getImm();
738   // A shift amount of 32 is encoded as 0.
739   if (Imm == 0)
740     Imm = 32;
741   assert(Imm > 0 && Imm <= 32 && "Invalid PKH shift immediate value!");
742   O << ", asr " << markup("<imm:") << "#" << Imm << markup(">");
743 }
744 
printRegisterList(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)745 void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
746                                        const MCSubtargetInfo &STI,
747                                        raw_ostream &O) {
748   O << "{";
749   for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
750     if (i != OpNum)
751       O << ", ";
752     printRegName(O, MI->getOperand(i).getReg());
753   }
754   O << "}";
755 }
756 
printGPRPairOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)757 void ARMInstPrinter::printGPRPairOperand(const MCInst *MI, unsigned OpNum,
758                                          const MCSubtargetInfo &STI,
759                                          raw_ostream &O) {
760   unsigned Reg = MI->getOperand(OpNum).getReg();
761   printRegName(O, MRI.getSubReg(Reg, ARM::gsub_0));
762   O << ", ";
763   printRegName(O, MRI.getSubReg(Reg, ARM::gsub_1));
764 }
765 
printSetendOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)766 void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum,
767                                         const MCSubtargetInfo &STI,
768                                         raw_ostream &O) {
769   const MCOperand &Op = MI->getOperand(OpNum);
770   if (Op.getImm())
771     O << "be";
772   else
773     O << "le";
774 }
775 
printCPSIMod(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)776 void ARMInstPrinter::printCPSIMod(const MCInst *MI, unsigned OpNum,
777                                   const MCSubtargetInfo &STI, raw_ostream &O) {
778   const MCOperand &Op = MI->getOperand(OpNum);
779   O << ARM_PROC::IModToString(Op.getImm());
780 }
781 
printCPSIFlag(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)782 void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum,
783                                    const MCSubtargetInfo &STI, raw_ostream &O) {
784   const MCOperand &Op = MI->getOperand(OpNum);
785   unsigned IFlags = Op.getImm();
786   for (int i = 2; i >= 0; --i)
787     if (IFlags & (1 << i))
788       O << ARM_PROC::IFlagsToString(1 << i);
789 
790   if (IFlags == 0)
791     O << "none";
792 }
793 
printMSRMaskOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)794 void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
795                                          const MCSubtargetInfo &STI,
796                                          raw_ostream &O) {
797   const MCOperand &Op = MI->getOperand(OpNum);
798   unsigned SpecRegRBit = Op.getImm() >> 4;
799   unsigned Mask = Op.getImm() & 0xf;
800   const FeatureBitset &FeatureBits = STI.getFeatureBits();
801 
802   if (FeatureBits[ARM::FeatureMClass]) {
803     unsigned SYSm = Op.getImm();
804     unsigned Opcode = MI->getOpcode();
805 
806     // For writes, handle extended mask bits if the DSP extension is present.
807     if (Opcode == ARM::t2MSR_M && FeatureBits[ARM::FeatureDSP]) {
808       switch (SYSm) {
809       case 0x400:
810         O << "apsr_g";
811         return;
812       case 0xc00:
813         O << "apsr_nzcvqg";
814         return;
815       case 0x401:
816         O << "iapsr_g";
817         return;
818       case 0xc01:
819         O << "iapsr_nzcvqg";
820         return;
821       case 0x402:
822         O << "eapsr_g";
823         return;
824       case 0xc02:
825         O << "eapsr_nzcvqg";
826         return;
827       case 0x403:
828         O << "xpsr_g";
829         return;
830       case 0xc03:
831         O << "xpsr_nzcvqg";
832         return;
833       }
834     }
835 
836     // Handle the basic 8-bit mask.
837     SYSm &= 0xff;
838 
839     if (Opcode == ARM::t2MSR_M && FeatureBits [ARM::HasV7Ops]) {
840       // ARMv7-M deprecates using MSR APSR without a _<bits> qualifier as an
841       // alias for MSR APSR_nzcvq.
842       switch (SYSm) {
843       case 0:
844         O << "apsr_nzcvq";
845         return;
846       case 1:
847         O << "iapsr_nzcvq";
848         return;
849       case 2:
850         O << "eapsr_nzcvq";
851         return;
852       case 3:
853         O << "xpsr_nzcvq";
854         return;
855       }
856     }
857 
858     switch (SYSm) {
859     default:
860       llvm_unreachable("Unexpected mask value!");
861     case 0:
862       O << "apsr";
863       return;
864     case 1:
865       O << "iapsr";
866       return;
867     case 2:
868       O << "eapsr";
869       return;
870     case 3:
871       O << "xpsr";
872       return;
873     case 5:
874       O << "ipsr";
875       return;
876     case 6:
877       O << "epsr";
878       return;
879     case 7:
880       O << "iepsr";
881       return;
882     case 8:
883       O << "msp";
884       return;
885     case 9:
886       O << "psp";
887       return;
888     case 16:
889       O << "primask";
890       return;
891     case 17:
892       O << "basepri";
893       return;
894     case 18:
895       O << "basepri_max";
896       return;
897     case 19:
898       O << "faultmask";
899       return;
900     case 20:
901       O << "control";
902       return;
903     }
904   }
905 
906   // As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as
907   // APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.
908   if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
909     O << "APSR_";
910     switch (Mask) {
911     default:
912       llvm_unreachable("Unexpected mask value!");
913     case 4:
914       O << "g";
915       return;
916     case 8:
917       O << "nzcvq";
918       return;
919     case 12:
920       O << "nzcvqg";
921       return;
922     }
923   }
924 
925   if (SpecRegRBit)
926     O << "SPSR";
927   else
928     O << "CPSR";
929 
930   if (Mask) {
931     O << '_';
932     if (Mask & 8)
933       O << 'f';
934     if (Mask & 4)
935       O << 's';
936     if (Mask & 2)
937       O << 'x';
938     if (Mask & 1)
939       O << 'c';
940   }
941 }
942 
printBankedRegOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)943 void ARMInstPrinter::printBankedRegOperand(const MCInst *MI, unsigned OpNum,
944                                            const MCSubtargetInfo &STI,
945                                            raw_ostream &O) {
946   uint32_t Banked = MI->getOperand(OpNum).getImm();
947   uint32_t R = (Banked & 0x20) >> 5;
948   uint32_t SysM = Banked & 0x1f;
949 
950   // Nothing much we can do about this, the encodings are specified in B9.2.3 of
951   // the ARM ARM v7C, and are all over the shop.
952   if (R) {
953     O << "SPSR_";
954 
955     switch (SysM) {
956     case 0x0e:
957       O << "fiq";
958       return;
959     case 0x10:
960       O << "irq";
961       return;
962     case 0x12:
963       O << "svc";
964       return;
965     case 0x14:
966       O << "abt";
967       return;
968     case 0x16:
969       O << "und";
970       return;
971     case 0x1c:
972       O << "mon";
973       return;
974     case 0x1e:
975       O << "hyp";
976       return;
977     default:
978       llvm_unreachable("Invalid banked SPSR register");
979     }
980   }
981 
982   assert(!R && "should have dealt with SPSR regs");
983   const char *RegNames[] = {
984       "r8_usr", "r9_usr", "r10_usr", "r11_usr", "r12_usr", "sp_usr",  "lr_usr",
985       "",       "r8_fiq", "r9_fiq",  "r10_fiq", "r11_fiq", "r12_fiq", "sp_fiq",
986       "lr_fiq", "",       "lr_irq",  "sp_irq",  "lr_svc",  "sp_svc",  "lr_abt",
987       "sp_abt", "lr_und", "sp_und",  "",        "",        "",        "",
988       "lr_mon", "sp_mon", "elr_hyp", "sp_hyp"};
989   const char *Name = RegNames[SysM];
990   assert(Name[0] && "invalid banked register operand");
991 
992   O << Name;
993 }
994 
printPredicateOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)995 void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
996                                            const MCSubtargetInfo &STI,
997                                            raw_ostream &O) {
998   ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
999   // Handle the undefined 15 CC value here for printing so we don't abort().
1000   if ((unsigned)CC == 15)
1001     O << "<und>";
1002   else if (CC != ARMCC::AL)
1003     O << ARMCondCodeToString(CC);
1004 }
1005 
printMandatoryPredicateOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1006 void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
1007                                                     unsigned OpNum,
1008                                                     const MCSubtargetInfo &STI,
1009                                                     raw_ostream &O) {
1010   ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
1011   O << ARMCondCodeToString(CC);
1012 }
1013 
printSBitModifierOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1014 void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
1015                                               const MCSubtargetInfo &STI,
1016                                               raw_ostream &O) {
1017   if (MI->getOperand(OpNum).getReg()) {
1018     assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
1019            "Expect ARM CPSR register!");
1020     O << 's';
1021   }
1022 }
1023 
printNoHashImmediate(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1024 void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
1025                                           const MCSubtargetInfo &STI,
1026                                           raw_ostream &O) {
1027   O << MI->getOperand(OpNum).getImm();
1028 }
1029 
printPImmediate(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1030 void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum,
1031                                      const MCSubtargetInfo &STI,
1032                                      raw_ostream &O) {
1033   O << "p" << MI->getOperand(OpNum).getImm();
1034 }
1035 
printCImmediate(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1036 void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum,
1037                                      const MCSubtargetInfo &STI,
1038                                      raw_ostream &O) {
1039   O << "c" << MI->getOperand(OpNum).getImm();
1040 }
1041 
printCoprocOptionImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1042 void ARMInstPrinter::printCoprocOptionImm(const MCInst *MI, unsigned OpNum,
1043                                           const MCSubtargetInfo &STI,
1044                                           raw_ostream &O) {
1045   O << "{" << MI->getOperand(OpNum).getImm() << "}";
1046 }
1047 
printPCLabel(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1048 void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
1049                                   const MCSubtargetInfo &STI, raw_ostream &O) {
1050   llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
1051 }
1052 
1053 template <unsigned scale>
printAdrLabelOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1054 void ARMInstPrinter::printAdrLabelOperand(const MCInst *MI, unsigned OpNum,
1055                                           const MCSubtargetInfo &STI,
1056                                           raw_ostream &O) {
1057   const MCOperand &MO = MI->getOperand(OpNum);
1058 
1059   if (MO.isExpr()) {
1060     MO.getExpr()->print(O, &MAI);
1061     return;
1062   }
1063 
1064   int32_t OffImm = (int32_t)MO.getImm() << scale;
1065 
1066   O << markup("<imm:");
1067   if (OffImm == INT32_MIN)
1068     O << "#-0";
1069   else if (OffImm < 0)
1070     O << "#-" << -OffImm;
1071   else
1072     O << "#" << OffImm;
1073   O << markup(">");
1074 }
1075 
printThumbS4ImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1076 void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
1077                                             const MCSubtargetInfo &STI,
1078                                             raw_ostream &O) {
1079   O << markup("<imm:") << "#" << formatImm(MI->getOperand(OpNum).getImm() * 4)
1080     << markup(">");
1081 }
1082 
printThumbSRImm(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1083 void ARMInstPrinter::printThumbSRImm(const MCInst *MI, unsigned OpNum,
1084                                      const MCSubtargetInfo &STI,
1085                                      raw_ostream &O) {
1086   unsigned Imm = MI->getOperand(OpNum).getImm();
1087   O << markup("<imm:") << "#" << formatImm((Imm == 0 ? 32 : Imm))
1088     << markup(">");
1089 }
1090 
printThumbITMask(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1091 void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
1092                                       const MCSubtargetInfo &STI,
1093                                       raw_ostream &O) {
1094   // (3 - the number of trailing zeros) is the number of then / else.
1095   unsigned Mask = MI->getOperand(OpNum).getImm();
1096   unsigned Firstcond = MI->getOperand(OpNum - 1).getImm();
1097   unsigned CondBit0 = Firstcond & 1;
1098   unsigned NumTZ = countTrailingZeros(Mask);
1099   assert(NumTZ <= 3 && "Invalid IT mask!");
1100   for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
1101     bool T = ((Mask >> Pos) & 1) == CondBit0;
1102     if (T)
1103       O << 't';
1104     else
1105       O << 'e';
1106   }
1107 }
1108 
printThumbAddrModeRROperand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)1109 void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
1110                                                  const MCSubtargetInfo &STI,
1111                                                  raw_ostream &O) {
1112   const MCOperand &MO1 = MI->getOperand(Op);
1113   const MCOperand &MO2 = MI->getOperand(Op + 1);
1114 
1115   if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
1116     printOperand(MI, Op, STI, O);
1117     return;
1118   }
1119 
1120   O << markup("<mem:") << "[";
1121   printRegName(O, MO1.getReg());
1122   if (unsigned RegNum = MO2.getReg()) {
1123     O << ", ";
1124     printRegName(O, RegNum);
1125   }
1126   O << "]" << markup(">");
1127 }
1128 
printThumbAddrModeImm5SOperand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O,unsigned Scale)1129 void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI,
1130                                                     unsigned Op,
1131                                                     const MCSubtargetInfo &STI,
1132                                                     raw_ostream &O,
1133                                                     unsigned Scale) {
1134   const MCOperand &MO1 = MI->getOperand(Op);
1135   const MCOperand &MO2 = MI->getOperand(Op + 1);
1136 
1137   if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
1138     printOperand(MI, Op, STI, O);
1139     return;
1140   }
1141 
1142   O << markup("<mem:") << "[";
1143   printRegName(O, MO1.getReg());
1144   if (unsigned ImmOffs = MO2.getImm()) {
1145     O << ", " << markup("<imm:") << "#" << formatImm(ImmOffs * Scale)
1146       << markup(">");
1147   }
1148   O << "]" << markup(">");
1149 }
1150 
printThumbAddrModeImm5S1Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)1151 void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI,
1152                                                      unsigned Op,
1153                                                      const MCSubtargetInfo &STI,
1154                                                      raw_ostream &O) {
1155   printThumbAddrModeImm5SOperand(MI, Op, STI, O, 1);
1156 }
1157 
printThumbAddrModeImm5S2Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)1158 void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI,
1159                                                      unsigned Op,
1160                                                      const MCSubtargetInfo &STI,
1161                                                      raw_ostream &O) {
1162   printThumbAddrModeImm5SOperand(MI, Op, STI, O, 2);
1163 }
1164 
printThumbAddrModeImm5S4Operand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)1165 void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI,
1166                                                      unsigned Op,
1167                                                      const MCSubtargetInfo &STI,
1168                                                      raw_ostream &O) {
1169   printThumbAddrModeImm5SOperand(MI, Op, STI, O, 4);
1170 }
1171 
printThumbAddrModeSPOperand(const MCInst * MI,unsigned Op,const MCSubtargetInfo & STI,raw_ostream & O)1172 void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
1173                                                  const MCSubtargetInfo &STI,
1174                                                  raw_ostream &O) {
1175   printThumbAddrModeImm5SOperand(MI, Op, STI, O, 4);
1176 }
1177 
1178 // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
1179 // register with shift forms.
1180 // REG 0   0           - e.g. R5
1181 // REG IMM, SH_OPC     - e.g. R5, LSL #3
printT2SOOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1182 void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
1183                                       const MCSubtargetInfo &STI,
1184                                       raw_ostream &O) {
1185   const MCOperand &MO1 = MI->getOperand(OpNum);
1186   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1187 
1188   unsigned Reg = MO1.getReg();
1189   printRegName(O, Reg);
1190 
1191   // Print the shift opc.
1192   assert(MO2.isImm() && "Not a valid t2_so_reg value!");
1193   printRegImmShift(O, ARM_AM::getSORegShOp(MO2.getImm()),
1194                    ARM_AM::getSORegOffset(MO2.getImm()), UseMarkup);
1195 }
1196 
1197 template <bool AlwaysPrintImm0>
printAddrModeImm12Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1198 void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
1199                                                const MCSubtargetInfo &STI,
1200                                                raw_ostream &O) {
1201   const MCOperand &MO1 = MI->getOperand(OpNum);
1202   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1203 
1204   if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
1205     printOperand(MI, OpNum, STI, O);
1206     return;
1207   }
1208 
1209   O << markup("<mem:") << "[";
1210   printRegName(O, MO1.getReg());
1211 
1212   int32_t OffImm = (int32_t)MO2.getImm();
1213   bool isSub = OffImm < 0;
1214   // Special value for #-0. All others are normal.
1215   if (OffImm == INT32_MIN)
1216     OffImm = 0;
1217   if (isSub) {
1218     O << ", " << markup("<imm:") << "#-" << formatImm(-OffImm) << markup(">");
1219   } else if (AlwaysPrintImm0 || OffImm > 0) {
1220     O << ", " << markup("<imm:") << "#" << formatImm(OffImm) << markup(">");
1221   }
1222   O << "]" << markup(">");
1223 }
1224 
1225 template <bool AlwaysPrintImm0>
printT2AddrModeImm8Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1226 void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
1227                                                 unsigned OpNum,
1228                                                 const MCSubtargetInfo &STI,
1229                                                 raw_ostream &O) {
1230   const MCOperand &MO1 = MI->getOperand(OpNum);
1231   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1232 
1233   O << markup("<mem:") << "[";
1234   printRegName(O, MO1.getReg());
1235 
1236   int32_t OffImm = (int32_t)MO2.getImm();
1237   bool isSub = OffImm < 0;
1238   // Don't print +0.
1239   if (OffImm == INT32_MIN)
1240     OffImm = 0;
1241   if (isSub) {
1242     O << ", " << markup("<imm:") << "#-" << -OffImm << markup(">");
1243   } else if (AlwaysPrintImm0 || OffImm > 0) {
1244     O << ", " << markup("<imm:") << "#" << OffImm << markup(">");
1245   }
1246   O << "]" << markup(">");
1247 }
1248 
1249 template <bool AlwaysPrintImm0>
printT2AddrModeImm8s4Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1250 void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
1251                                                   unsigned OpNum,
1252                                                   const MCSubtargetInfo &STI,
1253                                                   raw_ostream &O) {
1254   const MCOperand &MO1 = MI->getOperand(OpNum);
1255   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1256 
1257   if (!MO1.isReg()) { //  For label symbolic references.
1258     printOperand(MI, OpNum, STI, O);
1259     return;
1260   }
1261 
1262   O << markup("<mem:") << "[";
1263   printRegName(O, MO1.getReg());
1264 
1265   int32_t OffImm = (int32_t)MO2.getImm();
1266   bool isSub = OffImm < 0;
1267 
1268   assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
1269 
1270   // Don't print +0.
1271   if (OffImm == INT32_MIN)
1272     OffImm = 0;
1273   if (isSub) {
1274     O << ", " << markup("<imm:") << "#-" << -OffImm << markup(">");
1275   } else if (AlwaysPrintImm0 || OffImm > 0) {
1276     O << ", " << markup("<imm:") << "#" << OffImm << markup(">");
1277   }
1278   O << "]" << markup(">");
1279 }
1280 
printT2AddrModeImm0_1020s4Operand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1281 void ARMInstPrinter::printT2AddrModeImm0_1020s4Operand(
1282     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1283     raw_ostream &O) {
1284   const MCOperand &MO1 = MI->getOperand(OpNum);
1285   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1286 
1287   O << markup("<mem:") << "[";
1288   printRegName(O, MO1.getReg());
1289   if (MO2.getImm()) {
1290     O << ", " << markup("<imm:") << "#" << formatImm(MO2.getImm() * 4)
1291       << markup(">");
1292   }
1293   O << "]" << markup(">");
1294 }
1295 
printT2AddrModeImm8OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1296 void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(
1297     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1298     raw_ostream &O) {
1299   const MCOperand &MO1 = MI->getOperand(OpNum);
1300   int32_t OffImm = (int32_t)MO1.getImm();
1301   O << ", " << markup("<imm:");
1302   if (OffImm == INT32_MIN)
1303     O << "#-0";
1304   else if (OffImm < 0)
1305     O << "#-" << -OffImm;
1306   else
1307     O << "#" << OffImm;
1308   O << markup(">");
1309 }
1310 
printT2AddrModeImm8s4OffsetOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1311 void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(
1312     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1313     raw_ostream &O) {
1314   const MCOperand &MO1 = MI->getOperand(OpNum);
1315   int32_t OffImm = (int32_t)MO1.getImm();
1316 
1317   assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
1318 
1319   O << ", " << markup("<imm:");
1320   if (OffImm == INT32_MIN)
1321     O << "#-0";
1322   else if (OffImm < 0)
1323     O << "#-" << -OffImm;
1324   else
1325     O << "#" << OffImm;
1326   O << markup(">");
1327 }
1328 
printT2AddrModeSoRegOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1329 void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
1330                                                  unsigned OpNum,
1331                                                  const MCSubtargetInfo &STI,
1332                                                  raw_ostream &O) {
1333   const MCOperand &MO1 = MI->getOperand(OpNum);
1334   const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1335   const MCOperand &MO3 = MI->getOperand(OpNum + 2);
1336 
1337   O << markup("<mem:") << "[";
1338   printRegName(O, MO1.getReg());
1339 
1340   assert(MO2.getReg() && "Invalid so_reg load / store address!");
1341   O << ", ";
1342   printRegName(O, MO2.getReg());
1343 
1344   unsigned ShAmt = MO3.getImm();
1345   if (ShAmt) {
1346     assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
1347     O << ", lsl " << markup("<imm:") << "#" << ShAmt << markup(">");
1348   }
1349   O << "]" << markup(">");
1350 }
1351 
printFPImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1352 void ARMInstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNum,
1353                                        const MCSubtargetInfo &STI,
1354                                        raw_ostream &O) {
1355   const MCOperand &MO = MI->getOperand(OpNum);
1356   O << markup("<imm:") << '#' << ARM_AM::getFPImmFloat(MO.getImm())
1357     << markup(">");
1358 }
1359 
printNEONModImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1360 void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
1361                                             const MCSubtargetInfo &STI,
1362                                             raw_ostream &O) {
1363   unsigned EncodedImm = MI->getOperand(OpNum).getImm();
1364   unsigned EltBits;
1365   uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
1366   O << markup("<imm:") << "#0x";
1367   O.write_hex(Val);
1368   O << markup(">");
1369 }
1370 
printImmPlusOneOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1371 void ARMInstPrinter::printImmPlusOneOperand(const MCInst *MI, unsigned OpNum,
1372                                             const MCSubtargetInfo &STI,
1373                                             raw_ostream &O) {
1374   unsigned Imm = MI->getOperand(OpNum).getImm();
1375   O << markup("<imm:") << "#" << formatImm(Imm + 1) << markup(">");
1376 }
1377 
printRotImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1378 void ARMInstPrinter::printRotImmOperand(const MCInst *MI, unsigned OpNum,
1379                                         const MCSubtargetInfo &STI,
1380                                         raw_ostream &O) {
1381   unsigned Imm = MI->getOperand(OpNum).getImm();
1382   if (Imm == 0)
1383     return;
1384   assert(Imm <= 3 && "illegal ror immediate!");
1385   O << ", ror " << markup("<imm:") << "#" << 8 * Imm << markup(">");
1386 }
1387 
printModImmOperand(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1388 void ARMInstPrinter::printModImmOperand(const MCInst *MI, unsigned OpNum,
1389                                         const MCSubtargetInfo &STI,
1390                                         raw_ostream &O) {
1391   MCOperand Op = MI->getOperand(OpNum);
1392 
1393   // Support for fixups (MCFixup)
1394   if (Op.isExpr())
1395     return printOperand(MI, OpNum, STI, O);
1396 
1397   unsigned Bits = Op.getImm() & 0xFF;
1398   unsigned Rot = (Op.getImm() & 0xF00) >> 7;
1399 
1400   bool PrintUnsigned = false;
1401   switch (MI->getOpcode()) {
1402   case ARM::MOVi:
1403     // Movs to PC should be treated unsigned
1404     PrintUnsigned = (MI->getOperand(OpNum - 1).getReg() == ARM::PC);
1405     break;
1406   case ARM::MSRi:
1407     // Movs to special registers should be treated unsigned
1408     PrintUnsigned = true;
1409     break;
1410   }
1411 
1412   int32_t Rotated = ARM_AM::rotr32(Bits, Rot);
1413   if (ARM_AM::getSOImmVal(Rotated) == Op.getImm()) {
1414     // #rot has the least possible value
1415     O << "#" << markup("<imm:");
1416     if (PrintUnsigned)
1417       O << static_cast<uint32_t>(Rotated);
1418     else
1419       O << Rotated;
1420     O << markup(">");
1421     return;
1422   }
1423 
1424   // Explicit #bits, #rot implied
1425   O << "#" << markup("<imm:") << Bits << markup(">") << ", #" << markup("<imm:")
1426     << Rot << markup(">");
1427 }
1428 
printFBits16(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1429 void ARMInstPrinter::printFBits16(const MCInst *MI, unsigned OpNum,
1430                                   const MCSubtargetInfo &STI, raw_ostream &O) {
1431   O << markup("<imm:") << "#" << 16 - MI->getOperand(OpNum).getImm()
1432     << markup(">");
1433 }
1434 
printFBits32(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1435 void ARMInstPrinter::printFBits32(const MCInst *MI, unsigned OpNum,
1436                                   const MCSubtargetInfo &STI, raw_ostream &O) {
1437   O << markup("<imm:") << "#" << 32 - MI->getOperand(OpNum).getImm()
1438     << markup(">");
1439 }
1440 
printVectorIndex(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1441 void ARMInstPrinter::printVectorIndex(const MCInst *MI, unsigned OpNum,
1442                                       const MCSubtargetInfo &STI,
1443                                       raw_ostream &O) {
1444   O << "[" << MI->getOperand(OpNum).getImm() << "]";
1445 }
1446 
printVectorListOne(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1447 void ARMInstPrinter::printVectorListOne(const MCInst *MI, unsigned OpNum,
1448                                         const MCSubtargetInfo &STI,
1449                                         raw_ostream &O) {
1450   O << "{";
1451   printRegName(O, MI->getOperand(OpNum).getReg());
1452   O << "}";
1453 }
1454 
printVectorListTwo(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1455 void ARMInstPrinter::printVectorListTwo(const MCInst *MI, unsigned OpNum,
1456                                         const MCSubtargetInfo &STI,
1457                                         raw_ostream &O) {
1458   unsigned Reg = MI->getOperand(OpNum).getReg();
1459   unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
1460   unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_1);
1461   O << "{";
1462   printRegName(O, Reg0);
1463   O << ", ";
1464   printRegName(O, Reg1);
1465   O << "}";
1466 }
1467 
printVectorListTwoSpaced(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1468 void ARMInstPrinter::printVectorListTwoSpaced(const MCInst *MI, unsigned OpNum,
1469                                               const MCSubtargetInfo &STI,
1470                                               raw_ostream &O) {
1471   unsigned Reg = MI->getOperand(OpNum).getReg();
1472   unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
1473   unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_2);
1474   O << "{";
1475   printRegName(O, Reg0);
1476   O << ", ";
1477   printRegName(O, Reg1);
1478   O << "}";
1479 }
1480 
printVectorListThree(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1481 void ARMInstPrinter::printVectorListThree(const MCInst *MI, unsigned OpNum,
1482                                           const MCSubtargetInfo &STI,
1483                                           raw_ostream &O) {
1484   // Normally, it's not safe to use register enum values directly with
1485   // addition to get the next register, but for VFP registers, the
1486   // sort order is guaranteed because they're all of the form D<n>.
1487   O << "{";
1488   printRegName(O, MI->getOperand(OpNum).getReg());
1489   O << ", ";
1490   printRegName(O, MI->getOperand(OpNum).getReg() + 1);
1491   O << ", ";
1492   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1493   O << "}";
1494 }
1495 
printVectorListFour(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1496 void ARMInstPrinter::printVectorListFour(const MCInst *MI, unsigned OpNum,
1497                                          const MCSubtargetInfo &STI,
1498                                          raw_ostream &O) {
1499   // Normally, it's not safe to use register enum values directly with
1500   // addition to get the next register, but for VFP registers, the
1501   // sort order is guaranteed because they're all of the form D<n>.
1502   O << "{";
1503   printRegName(O, MI->getOperand(OpNum).getReg());
1504   O << ", ";
1505   printRegName(O, MI->getOperand(OpNum).getReg() + 1);
1506   O << ", ";
1507   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1508   O << ", ";
1509   printRegName(O, MI->getOperand(OpNum).getReg() + 3);
1510   O << "}";
1511 }
1512 
printVectorListOneAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1513 void ARMInstPrinter::printVectorListOneAllLanes(const MCInst *MI,
1514                                                 unsigned OpNum,
1515                                                 const MCSubtargetInfo &STI,
1516                                                 raw_ostream &O) {
1517   O << "{";
1518   printRegName(O, MI->getOperand(OpNum).getReg());
1519   O << "[]}";
1520 }
1521 
printVectorListTwoAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1522 void ARMInstPrinter::printVectorListTwoAllLanes(const MCInst *MI,
1523                                                 unsigned OpNum,
1524                                                 const MCSubtargetInfo &STI,
1525                                                 raw_ostream &O) {
1526   unsigned Reg = MI->getOperand(OpNum).getReg();
1527   unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
1528   unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_1);
1529   O << "{";
1530   printRegName(O, Reg0);
1531   O << "[], ";
1532   printRegName(O, Reg1);
1533   O << "[]}";
1534 }
1535 
printVectorListThreeAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1536 void ARMInstPrinter::printVectorListThreeAllLanes(const MCInst *MI,
1537                                                   unsigned OpNum,
1538                                                   const MCSubtargetInfo &STI,
1539                                                   raw_ostream &O) {
1540   // Normally, it's not safe to use register enum values directly with
1541   // addition to get the next register, but for VFP registers, the
1542   // sort order is guaranteed because they're all of the form D<n>.
1543   O << "{";
1544   printRegName(O, MI->getOperand(OpNum).getReg());
1545   O << "[], ";
1546   printRegName(O, MI->getOperand(OpNum).getReg() + 1);
1547   O << "[], ";
1548   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1549   O << "[]}";
1550 }
1551 
printVectorListFourAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1552 void ARMInstPrinter::printVectorListFourAllLanes(const MCInst *MI,
1553                                                  unsigned OpNum,
1554                                                  const MCSubtargetInfo &STI,
1555                                                  raw_ostream &O) {
1556   // Normally, it's not safe to use register enum values directly with
1557   // addition to get the next register, but for VFP registers, the
1558   // sort order is guaranteed because they're all of the form D<n>.
1559   O << "{";
1560   printRegName(O, MI->getOperand(OpNum).getReg());
1561   O << "[], ";
1562   printRegName(O, MI->getOperand(OpNum).getReg() + 1);
1563   O << "[], ";
1564   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1565   O << "[], ";
1566   printRegName(O, MI->getOperand(OpNum).getReg() + 3);
1567   O << "[]}";
1568 }
1569 
printVectorListTwoSpacedAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1570 void ARMInstPrinter::printVectorListTwoSpacedAllLanes(
1571     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1572     raw_ostream &O) {
1573   unsigned Reg = MI->getOperand(OpNum).getReg();
1574   unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
1575   unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_2);
1576   O << "{";
1577   printRegName(O, Reg0);
1578   O << "[], ";
1579   printRegName(O, Reg1);
1580   O << "[]}";
1581 }
1582 
printVectorListThreeSpacedAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1583 void ARMInstPrinter::printVectorListThreeSpacedAllLanes(
1584     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1585     raw_ostream &O) {
1586   // Normally, it's not safe to use register enum values directly with
1587   // addition to get the next register, but for VFP registers, the
1588   // sort order is guaranteed because they're all of the form D<n>.
1589   O << "{";
1590   printRegName(O, MI->getOperand(OpNum).getReg());
1591   O << "[], ";
1592   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1593   O << "[], ";
1594   printRegName(O, MI->getOperand(OpNum).getReg() + 4);
1595   O << "[]}";
1596 }
1597 
printVectorListFourSpacedAllLanes(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1598 void ARMInstPrinter::printVectorListFourSpacedAllLanes(
1599     const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1600     raw_ostream &O) {
1601   // Normally, it's not safe to use register enum values directly with
1602   // addition to get the next register, but for VFP registers, the
1603   // sort order is guaranteed because they're all of the form D<n>.
1604   O << "{";
1605   printRegName(O, MI->getOperand(OpNum).getReg());
1606   O << "[], ";
1607   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1608   O << "[], ";
1609   printRegName(O, MI->getOperand(OpNum).getReg() + 4);
1610   O << "[], ";
1611   printRegName(O, MI->getOperand(OpNum).getReg() + 6);
1612   O << "[]}";
1613 }
1614 
printVectorListThreeSpaced(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1615 void ARMInstPrinter::printVectorListThreeSpaced(const MCInst *MI,
1616                                                 unsigned OpNum,
1617                                                 const MCSubtargetInfo &STI,
1618                                                 raw_ostream &O) {
1619   // Normally, it's not safe to use register enum values directly with
1620   // addition to get the next register, but for VFP registers, the
1621   // sort order is guaranteed because they're all of the form D<n>.
1622   O << "{";
1623   printRegName(O, MI->getOperand(OpNum).getReg());
1624   O << ", ";
1625   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1626   O << ", ";
1627   printRegName(O, MI->getOperand(OpNum).getReg() + 4);
1628   O << "}";
1629 }
1630 
printVectorListFourSpaced(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1631 void ARMInstPrinter::printVectorListFourSpaced(const MCInst *MI, unsigned OpNum,
1632                                                const MCSubtargetInfo &STI,
1633                                                raw_ostream &O) {
1634   // Normally, it's not safe to use register enum values directly with
1635   // addition to get the next register, but for VFP registers, the
1636   // sort order is guaranteed because they're all of the form D<n>.
1637   O << "{";
1638   printRegName(O, MI->getOperand(OpNum).getReg());
1639   O << ", ";
1640   printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1641   O << ", ";
1642   printRegName(O, MI->getOperand(OpNum).getReg() + 4);
1643   O << ", ";
1644   printRegName(O, MI->getOperand(OpNum).getReg() + 6);
1645   O << "}";
1646 }
1647