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