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