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