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