1 //===-- ARMInstPrinter.cpp - Convert ARM MCInst to assembly syntax --------===//
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
7 //===----------------------------------------------------------------------===//
9 // This class prints an ARM MCInst to a .s file.
11 //===----------------------------------------------------------------------===//
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/MCInstrInfo.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/MC/MCSubtargetInfo.h"
23 #include "llvm/MC/SubtargetFeature.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"
34 #define DEBUG_TYPE "asm-printer"
36 #define PRINT_ALIAS_INSTR
37 #include "ARMGenAsmWriter.inc"
39 /// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing.
41 /// getSORegOffset returns an integer from 0-31, representing '32' as 0.
42 static unsigned translateShiftImm(unsigned imm
) {
43 // lsr #32 and asr #32 exist, but should be encoded as a 0.
44 assert((imm
& ~0x1f) == 0 && "Invalid shift encoding");
51 /// Prints the shift value with an immediate value.
52 static void printRegImmShift(raw_ostream
&O
, ARM_AM::ShiftOpc ShOpc
,
53 unsigned ShImm
, bool UseMarkup
) {
54 if (ShOpc
== ARM_AM::no_shift
|| (ShOpc
== ARM_AM::lsl
&& !ShImm
))
58 assert(!(ShOpc
== ARM_AM::ror
&& !ShImm
) && "Cannot have ror #0");
59 O
<< getShiftOpcStr(ShOpc
);
61 if (ShOpc
!= ARM_AM::rrx
) {
65 O
<< "#" << translateShiftImm(ShImm
);
71 ARMInstPrinter::ARMInstPrinter(const MCAsmInfo
&MAI
, const MCInstrInfo
&MII
,
72 const MCRegisterInfo
&MRI
)
73 : MCInstPrinter(MAI
, MII
, MRI
) {}
75 bool ARMInstPrinter::applyTargetSpecificCLOption(StringRef Opt
) {
76 if (Opt
== "reg-names-std") {
77 DefaultAltIdx
= ARM::NoRegAltName
;
80 if (Opt
== "reg-names-raw") {
81 DefaultAltIdx
= ARM::RegNamesRaw
;
87 void ARMInstPrinter::printRegName(raw_ostream
&OS
, unsigned RegNo
) const {
88 OS
<< markup("<reg:") << getRegisterName(RegNo
, DefaultAltIdx
) << markup(">");
91 void ARMInstPrinter::printInst(const MCInst
*MI
, raw_ostream
&O
,
92 StringRef Annot
, const MCSubtargetInfo
&STI
) {
93 unsigned Opcode
= MI
->getOpcode();
96 // Check for MOVs and print canonical forms, instead.
98 // FIXME: Thumb variants?
99 const MCOperand
&Dst
= MI
->getOperand(0);
100 const MCOperand
&MO1
= MI
->getOperand(1);
101 const MCOperand
&MO2
= MI
->getOperand(2);
102 const MCOperand
&MO3
= MI
->getOperand(3);
104 O
<< '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3
.getImm()));
105 printSBitModifierOperand(MI
, 6, STI
, O
);
106 printPredicateOperand(MI
, 4, STI
, O
);
109 printRegName(O
, Dst
.getReg());
111 printRegName(O
, MO1
.getReg());
114 printRegName(O
, MO2
.getReg());
115 assert(ARM_AM::getSORegOffset(MO3
.getImm()) == 0);
116 printAnnotation(O
, Annot
);
121 // FIXME: Thumb variants?
122 const MCOperand
&Dst
= MI
->getOperand(0);
123 const MCOperand
&MO1
= MI
->getOperand(1);
124 const MCOperand
&MO2
= MI
->getOperand(2);
126 O
<< '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2
.getImm()));
127 printSBitModifierOperand(MI
, 5, STI
, O
);
128 printPredicateOperand(MI
, 3, STI
, O
);
131 printRegName(O
, Dst
.getReg());
133 printRegName(O
, MO1
.getReg());
135 if (ARM_AM::getSORegShOp(MO2
.getImm()) == ARM_AM::rrx
) {
136 printAnnotation(O
, Annot
);
140 O
<< ", " << markup("<imm:") << "#"
141 << translateShiftImm(ARM_AM::getSORegOffset(MO2
.getImm())) << markup(">");
142 printAnnotation(O
, Annot
);
148 case ARM::t2STMDB_UPD
:
149 if (MI
->getOperand(0).getReg() == ARM::SP
&& MI
->getNumOperands() > 5) {
150 // Should only print PUSH if there are at least two registers in the list.
152 printPredicateOperand(MI
, 2, STI
, O
);
153 if (Opcode
== ARM::t2STMDB_UPD
)
156 printRegisterList(MI
, 4, STI
, O
);
157 printAnnotation(O
, Annot
);
162 case ARM::STR_PRE_IMM
:
163 if (MI
->getOperand(2).getReg() == ARM::SP
&&
164 MI
->getOperand(3).getImm() == -4) {
166 printPredicateOperand(MI
, 4, STI
, O
);
168 printRegName(O
, MI
->getOperand(1).getReg());
170 printAnnotation(O
, Annot
);
177 case ARM::t2LDMIA_UPD
:
178 if (MI
->getOperand(0).getReg() == ARM::SP
&& MI
->getNumOperands() > 5) {
179 // Should only print POP if there are at least two registers in the list.
181 printPredicateOperand(MI
, 2, STI
, O
);
182 if (Opcode
== ARM::t2LDMIA_UPD
)
185 printRegisterList(MI
, 4, STI
, O
);
186 printAnnotation(O
, Annot
);
191 case ARM::LDR_POST_IMM
:
192 if (MI
->getOperand(2).getReg() == ARM::SP
&&
193 MI
->getOperand(4).getImm() == 4) {
195 printPredicateOperand(MI
, 5, STI
, O
);
197 printRegName(O
, MI
->getOperand(0).getReg());
199 printAnnotation(O
, Annot
);
205 case ARM::VSTMSDB_UPD
:
206 case ARM::VSTMDDB_UPD
:
207 if (MI
->getOperand(0).getReg() == ARM::SP
) {
208 O
<< '\t' << "vpush";
209 printPredicateOperand(MI
, 2, STI
, O
);
211 printRegisterList(MI
, 4, STI
, O
);
212 printAnnotation(O
, Annot
);
218 case ARM::VLDMSIA_UPD
:
219 case ARM::VLDMDIA_UPD
:
220 if (MI
->getOperand(0).getReg() == ARM::SP
) {
222 printPredicateOperand(MI
, 2, STI
, O
);
224 printRegisterList(MI
, 4, STI
, O
);
225 printAnnotation(O
, Annot
);
231 bool Writeback
= true;
232 unsigned BaseReg
= MI
->getOperand(0).getReg();
233 for (unsigned i
= 3; i
< MI
->getNumOperands(); ++i
) {
234 if (MI
->getOperand(i
).getReg() == BaseReg
)
240 printPredicateOperand(MI
, 1, STI
, O
);
242 printRegName(O
, BaseReg
);
246 printRegisterList(MI
, 3, STI
, O
);
247 printAnnotation(O
, Annot
);
251 // Combine 2 GPRs from disassember into a GPRPair to match with instr def.
252 // ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
253 // a single GPRPair reg operand is used in the .td file to replace the two
254 // GPRs. However, when decoding them, the two GRPs cannot be automatically
255 // expressed as a GPRPair, so we have to manually merge them.
256 // FIXME: We would really like to be able to tablegen'erate this.
261 const MCRegisterClass
&MRC
= MRI
.getRegClass(ARM::GPRRegClassID
);
262 bool isStore
= Opcode
== ARM::STREXD
|| Opcode
== ARM::STLEXD
;
263 unsigned Reg
= MI
->getOperand(isStore
? 1 : 0).getReg();
264 if (MRC
.contains(Reg
)) {
267 NewMI
.setOpcode(Opcode
);
270 NewMI
.addOperand(MI
->getOperand(0));
271 NewReg
= MCOperand::createReg(MRI
.getMatchingSuperReg(
272 Reg
, ARM::gsub_0
, &MRI
.getRegClass(ARM::GPRPairRegClassID
)));
273 NewMI
.addOperand(NewReg
);
275 // Copy the rest operands into NewMI.
276 for (unsigned i
= isStore
? 3 : 2; i
< MI
->getNumOperands(); ++i
)
277 NewMI
.addOperand(MI
->getOperand(i
));
278 printInstruction(&NewMI
, STI
, O
);
288 switch (MI
->getOperand(0).getImm()) {
290 if (!printAliasInstr(MI
, STI
, O
))
291 printInstruction(MI
, STI
, O
);
300 printAnnotation(O
, Annot
);
304 if (!printAliasInstr(MI
, STI
, O
))
305 printInstruction(MI
, STI
, O
);
307 printAnnotation(O
, Annot
);
310 void ARMInstPrinter::printOperand(const MCInst
*MI
, unsigned OpNo
,
311 const MCSubtargetInfo
&STI
, raw_ostream
&O
) {
312 const MCOperand
&Op
= MI
->getOperand(OpNo
);
314 unsigned Reg
= Op
.getReg();
315 printRegName(O
, Reg
);
316 } else if (Op
.isImm()) {
317 O
<< markup("<imm:") << '#' << formatImm(Op
.getImm()) << markup(">");
319 assert(Op
.isExpr() && "unknown operand kind in printOperand");
320 const MCExpr
*Expr
= Op
.getExpr();
321 switch (Expr
->getKind()) {
324 Expr
->print(O
, &MAI
);
326 case MCExpr::Constant
: {
327 // If a symbolic branch target was added as a constant expression then
328 // print that address in hex. And only print 32 unsigned bits for the
330 const MCConstantExpr
*Constant
= cast
<MCConstantExpr
>(Expr
);
331 int64_t TargetAddress
;
332 if (!Constant
->evaluateAsAbsolute(TargetAddress
)) {
334 Expr
->print(O
, &MAI
);
337 O
.write_hex(static_cast<uint32_t>(TargetAddress
));
342 // FIXME: Should we always treat this as if it is a constant literal and
343 // prefix it with '#'?
344 Expr
->print(O
, &MAI
);
350 void ARMInstPrinter::printThumbLdrLabelOperand(const MCInst
*MI
, unsigned OpNum
,
351 const MCSubtargetInfo
&STI
,
353 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
355 MO1
.getExpr()->print(O
, &MAI
);
359 O
<< markup("<mem:") << "[pc, ";
361 int32_t OffImm
= (int32_t)MO1
.getImm();
362 bool isSub
= OffImm
< 0;
364 // Special value for #-0. All others are normal.
365 if (OffImm
== INT32_MIN
)
368 O
<< markup("<imm:") << "#-" << formatImm(-OffImm
) << markup(">");
370 O
<< markup("<imm:") << "#" << formatImm(OffImm
) << markup(">");
372 O
<< "]" << markup(">");
375 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
376 // "Addressing Mode 1 - Data-processing operands" forms. This includes:
378 // REG REG 0,SH_OPC - e.g. R5, ROR R3
379 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3
380 void ARMInstPrinter::printSORegRegOperand(const MCInst
*MI
, unsigned OpNum
,
381 const MCSubtargetInfo
&STI
,
383 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
384 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
385 const MCOperand
&MO3
= MI
->getOperand(OpNum
+ 2);
387 printRegName(O
, MO1
.getReg());
389 // Print the shift opc.
390 ARM_AM::ShiftOpc ShOpc
= ARM_AM::getSORegShOp(MO3
.getImm());
391 O
<< ", " << ARM_AM::getShiftOpcStr(ShOpc
);
392 if (ShOpc
== ARM_AM::rrx
)
396 printRegName(O
, MO2
.getReg());
397 assert(ARM_AM::getSORegOffset(MO3
.getImm()) == 0);
400 void ARMInstPrinter::printSORegImmOperand(const MCInst
*MI
, unsigned OpNum
,
401 const MCSubtargetInfo
&STI
,
403 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
404 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
406 printRegName(O
, MO1
.getReg());
408 // Print the shift opc.
409 printRegImmShift(O
, ARM_AM::getSORegShOp(MO2
.getImm()),
410 ARM_AM::getSORegOffset(MO2
.getImm()), UseMarkup
);
413 //===--------------------------------------------------------------------===//
414 // Addressing Mode #2
415 //===--------------------------------------------------------------------===//
417 void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst
*MI
, unsigned Op
,
418 const MCSubtargetInfo
&STI
,
420 const MCOperand
&MO1
= MI
->getOperand(Op
);
421 const MCOperand
&MO2
= MI
->getOperand(Op
+ 1);
422 const MCOperand
&MO3
= MI
->getOperand(Op
+ 2);
424 O
<< markup("<mem:") << "[";
425 printRegName(O
, MO1
.getReg());
428 if (ARM_AM::getAM2Offset(MO3
.getImm())) { // Don't print +0.
429 O
<< ", " << markup("<imm:") << "#"
430 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3
.getImm()))
431 << ARM_AM::getAM2Offset(MO3
.getImm()) << markup(">");
433 O
<< "]" << markup(">");
438 O
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3
.getImm()));
439 printRegName(O
, MO2
.getReg());
441 printRegImmShift(O
, ARM_AM::getAM2ShiftOpc(MO3
.getImm()),
442 ARM_AM::getAM2Offset(MO3
.getImm()), UseMarkup
);
443 O
<< "]" << markup(">");
446 void ARMInstPrinter::printAddrModeTBB(const MCInst
*MI
, unsigned Op
,
447 const MCSubtargetInfo
&STI
,
449 const MCOperand
&MO1
= MI
->getOperand(Op
);
450 const MCOperand
&MO2
= MI
->getOperand(Op
+ 1);
451 O
<< markup("<mem:") << "[";
452 printRegName(O
, MO1
.getReg());
454 printRegName(O
, MO2
.getReg());
455 O
<< "]" << markup(">");
458 void ARMInstPrinter::printAddrModeTBH(const MCInst
*MI
, unsigned Op
,
459 const MCSubtargetInfo
&STI
,
461 const MCOperand
&MO1
= MI
->getOperand(Op
);
462 const MCOperand
&MO2
= MI
->getOperand(Op
+ 1);
463 O
<< markup("<mem:") << "[";
464 printRegName(O
, MO1
.getReg());
466 printRegName(O
, MO2
.getReg());
467 O
<< ", lsl " << markup("<imm:") << "#1" << markup(">") << "]" << markup(">");
470 void ARMInstPrinter::printAddrMode2Operand(const MCInst
*MI
, unsigned Op
,
471 const MCSubtargetInfo
&STI
,
473 const MCOperand
&MO1
= MI
->getOperand(Op
);
475 if (!MO1
.isReg()) { // FIXME: This is for CP entries, but isn't right.
476 printOperand(MI
, Op
, STI
, O
);
481 const MCOperand
&MO3
= MI
->getOperand(Op
+ 2);
482 unsigned IdxMode
= ARM_AM::getAM2IdxMode(MO3
.getImm());
483 assert(IdxMode
!= ARMII::IndexModePost
&& "Should be pre or offset index op");
486 printAM2PreOrOffsetIndexOp(MI
, Op
, STI
, O
);
489 void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst
*MI
,
491 const MCSubtargetInfo
&STI
,
493 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
494 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
497 unsigned ImmOffs
= ARM_AM::getAM2Offset(MO2
.getImm());
498 O
<< markup("<imm:") << '#'
499 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2
.getImm())) << ImmOffs
504 O
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2
.getImm()));
505 printRegName(O
, MO1
.getReg());
507 printRegImmShift(O
, ARM_AM::getAM2ShiftOpc(MO2
.getImm()),
508 ARM_AM::getAM2Offset(MO2
.getImm()), UseMarkup
);
511 //===--------------------------------------------------------------------===//
512 // Addressing Mode #3
513 //===--------------------------------------------------------------------===//
515 void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst
*MI
, unsigned Op
,
517 bool AlwaysPrintImm0
) {
518 const MCOperand
&MO1
= MI
->getOperand(Op
);
519 const MCOperand
&MO2
= MI
->getOperand(Op
+ 1);
520 const MCOperand
&MO3
= MI
->getOperand(Op
+ 2);
522 O
<< markup("<mem:") << '[';
523 printRegName(O
, MO1
.getReg());
526 O
<< ", " << getAddrOpcStr(ARM_AM::getAM3Op(MO3
.getImm()));
527 printRegName(O
, MO2
.getReg());
528 O
<< ']' << markup(">");
532 // If the op is sub we have to print the immediate even if it is 0
533 unsigned ImmOffs
= ARM_AM::getAM3Offset(MO3
.getImm());
534 ARM_AM::AddrOpc op
= ARM_AM::getAM3Op(MO3
.getImm());
536 if (AlwaysPrintImm0
|| ImmOffs
|| (op
== ARM_AM::sub
)) {
537 O
<< ", " << markup("<imm:") << "#" << ARM_AM::getAddrOpcStr(op
) << ImmOffs
540 O
<< ']' << markup(">");
543 template <bool AlwaysPrintImm0
>
544 void ARMInstPrinter::printAddrMode3Operand(const MCInst
*MI
, unsigned Op
,
545 const MCSubtargetInfo
&STI
,
547 const MCOperand
&MO1
= MI
->getOperand(Op
);
548 if (!MO1
.isReg()) { // For label symbolic references.
549 printOperand(MI
, Op
, STI
, O
);
553 assert(ARM_AM::getAM3IdxMode(MI
->getOperand(Op
+ 2).getImm()) !=
554 ARMII::IndexModePost
&&
555 "unexpected idxmode");
556 printAM3PreOrOffsetIndexOp(MI
, Op
, O
, AlwaysPrintImm0
);
559 void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst
*MI
,
561 const MCSubtargetInfo
&STI
,
563 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
564 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
567 O
<< getAddrOpcStr(ARM_AM::getAM3Op(MO2
.getImm()));
568 printRegName(O
, MO1
.getReg());
572 unsigned ImmOffs
= ARM_AM::getAM3Offset(MO2
.getImm());
573 O
<< markup("<imm:") << '#'
574 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2
.getImm())) << ImmOffs
578 void ARMInstPrinter::printPostIdxImm8Operand(const MCInst
*MI
, unsigned OpNum
,
579 const MCSubtargetInfo
&STI
,
581 const MCOperand
&MO
= MI
->getOperand(OpNum
);
582 unsigned Imm
= MO
.getImm();
583 O
<< markup("<imm:") << '#' << ((Imm
& 256) ? "" : "-") << (Imm
& 0xff)
587 void ARMInstPrinter::printPostIdxRegOperand(const MCInst
*MI
, unsigned OpNum
,
588 const MCSubtargetInfo
&STI
,
590 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
591 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
593 O
<< (MO2
.getImm() ? "" : "-");
594 printRegName(O
, MO1
.getReg());
597 void ARMInstPrinter::printPostIdxImm8s4Operand(const MCInst
*MI
, unsigned OpNum
,
598 const MCSubtargetInfo
&STI
,
600 const MCOperand
&MO
= MI
->getOperand(OpNum
);
601 unsigned Imm
= MO
.getImm();
602 O
<< markup("<imm:") << '#' << ((Imm
& 256) ? "" : "-") << ((Imm
& 0xff) << 2)
607 void ARMInstPrinter::printMveAddrModeRQOperand(const MCInst
*MI
, unsigned OpNum
,
608 const MCSubtargetInfo
&STI
,
610 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
611 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
613 O
<< markup("<mem:") << "[";
614 printRegName(O
, MO1
.getReg());
616 printRegName(O
, MO2
.getReg());
619 printRegImmShift(O
, ARM_AM::uxtw
, shift
, UseMarkup
);
621 O
<< "]" << markup(">");
624 void ARMInstPrinter::printMveAddrModeQOperand(const MCInst
*MI
, unsigned OpNum
,
625 const MCSubtargetInfo
&STI
,
627 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
628 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
630 O
<< markup("<mem:") << "[";
631 printRegName(O
, MO1
.getReg());
633 int64_t Imm
= MO2
.getImm();
635 O
<< ", " << markup("<imm:") << '#' << Imm
<< markup(">");
637 O
<< "]" << markup(">");
640 void ARMInstPrinter::printLdStmModeOperand(const MCInst
*MI
, unsigned OpNum
,
641 const MCSubtargetInfo
&STI
,
643 ARM_AM::AMSubMode Mode
=
644 ARM_AM::getAM4SubMode(MI
->getOperand(OpNum
).getImm());
645 O
<< ARM_AM::getAMSubModeStr(Mode
);
648 template <bool AlwaysPrintImm0
>
649 void ARMInstPrinter::printAddrMode5Operand(const MCInst
*MI
, unsigned OpNum
,
650 const MCSubtargetInfo
&STI
,
652 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
653 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
655 if (!MO1
.isReg()) { // FIXME: This is for CP entries, but isn't right.
656 printOperand(MI
, OpNum
, STI
, O
);
660 O
<< markup("<mem:") << "[";
661 printRegName(O
, MO1
.getReg());
663 unsigned ImmOffs
= ARM_AM::getAM5Offset(MO2
.getImm());
664 ARM_AM::AddrOpc Op
= ARM_AM::getAM5Op(MO2
.getImm());
665 if (AlwaysPrintImm0
|| ImmOffs
|| Op
== ARM_AM::sub
) {
666 O
<< ", " << markup("<imm:") << "#" << ARM_AM::getAddrOpcStr(Op
)
667 << ImmOffs
* 4 << markup(">");
669 O
<< "]" << markup(">");
672 template <bool AlwaysPrintImm0
>
673 void ARMInstPrinter::printAddrMode5FP16Operand(const MCInst
*MI
, unsigned OpNum
,
674 const MCSubtargetInfo
&STI
,
676 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
677 const MCOperand
&MO2
= MI
->getOperand(OpNum
+1);
679 if (!MO1
.isReg()) { // FIXME: This is for CP entries, but isn't right.
680 printOperand(MI
, OpNum
, STI
, O
);
684 O
<< markup("<mem:") << "[";
685 printRegName(O
, MO1
.getReg());
687 unsigned ImmOffs
= ARM_AM::getAM5FP16Offset(MO2
.getImm());
688 unsigned Op
= ARM_AM::getAM5FP16Op(MO2
.getImm());
689 if (AlwaysPrintImm0
|| ImmOffs
|| Op
== ARM_AM::sub
) {
693 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5FP16Op(MO2
.getImm()))
697 O
<< "]" << markup(">");
700 void ARMInstPrinter::printAddrMode6Operand(const MCInst
*MI
, unsigned OpNum
,
701 const MCSubtargetInfo
&STI
,
703 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
704 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
706 O
<< markup("<mem:") << "[";
707 printRegName(O
, MO1
.getReg());
709 O
<< ":" << (MO2
.getImm() << 3);
711 O
<< "]" << markup(">");
714 void ARMInstPrinter::printAddrMode7Operand(const MCInst
*MI
, unsigned OpNum
,
715 const MCSubtargetInfo
&STI
,
717 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
718 O
<< markup("<mem:") << "[";
719 printRegName(O
, MO1
.getReg());
720 O
<< "]" << markup(">");
723 void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst
*MI
,
725 const MCSubtargetInfo
&STI
,
727 const MCOperand
&MO
= MI
->getOperand(OpNum
);
728 if (MO
.getReg() == 0)
732 printRegName(O
, MO
.getReg());
736 void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst
*MI
,
738 const MCSubtargetInfo
&STI
,
740 const MCOperand
&MO
= MI
->getOperand(OpNum
);
741 uint32_t v
= ~MO
.getImm();
742 int32_t lsb
= countTrailingZeros(v
);
743 int32_t width
= (32 - countLeadingZeros(v
)) - lsb
;
744 assert(MO
.isImm() && "Not a valid bf_inv_mask_imm value!");
745 O
<< markup("<imm:") << '#' << lsb
<< markup(">") << ", " << markup("<imm:")
746 << '#' << width
<< markup(">");
749 void ARMInstPrinter::printMemBOption(const MCInst
*MI
, unsigned OpNum
,
750 const MCSubtargetInfo
&STI
,
752 unsigned val
= MI
->getOperand(OpNum
).getImm();
753 O
<< ARM_MB::MemBOptToString(val
, STI
.getFeatureBits()[ARM::HasV8Ops
]);
756 void ARMInstPrinter::printInstSyncBOption(const MCInst
*MI
, unsigned OpNum
,
757 const MCSubtargetInfo
&STI
,
759 unsigned val
= MI
->getOperand(OpNum
).getImm();
760 O
<< ARM_ISB::InstSyncBOptToString(val
);
763 void ARMInstPrinter::printTraceSyncBOption(const MCInst
*MI
, unsigned OpNum
,
764 const MCSubtargetInfo
&STI
,
766 unsigned val
= MI
->getOperand(OpNum
).getImm();
767 O
<< ARM_TSB::TraceSyncBOptToString(val
);
770 void ARMInstPrinter::printShiftImmOperand(const MCInst
*MI
, unsigned OpNum
,
771 const MCSubtargetInfo
&STI
,
773 unsigned ShiftOp
= MI
->getOperand(OpNum
).getImm();
774 bool isASR
= (ShiftOp
& (1 << 5)) != 0;
775 unsigned Amt
= ShiftOp
& 0x1f;
777 O
<< ", asr " << markup("<imm:") << "#" << (Amt
== 0 ? 32 : Amt
)
780 O
<< ", lsl " << markup("<imm:") << "#" << Amt
<< markup(">");
784 void ARMInstPrinter::printPKHLSLShiftImm(const MCInst
*MI
, unsigned OpNum
,
785 const MCSubtargetInfo
&STI
,
787 unsigned Imm
= MI
->getOperand(OpNum
).getImm();
790 assert(Imm
> 0 && Imm
< 32 && "Invalid PKH shift immediate value!");
791 O
<< ", lsl " << markup("<imm:") << "#" << Imm
<< markup(">");
794 void ARMInstPrinter::printPKHASRShiftImm(const MCInst
*MI
, unsigned OpNum
,
795 const MCSubtargetInfo
&STI
,
797 unsigned Imm
= MI
->getOperand(OpNum
).getImm();
798 // A shift amount of 32 is encoded as 0.
801 assert(Imm
> 0 && Imm
<= 32 && "Invalid PKH shift immediate value!");
802 O
<< ", asr " << markup("<imm:") << "#" << Imm
<< markup(">");
805 void ARMInstPrinter::printRegisterList(const MCInst
*MI
, unsigned OpNum
,
806 const MCSubtargetInfo
&STI
,
808 if (MI
->getOpcode() != ARM::t2CLRM
) {
809 assert(std::is_sorted(MI
->begin() + OpNum
, MI
->end(),
810 [&](const MCOperand
&LHS
, const MCOperand
&RHS
) {
811 return MRI
.getEncodingValue(LHS
.getReg()) <
812 MRI
.getEncodingValue(RHS
.getReg());
817 for (unsigned i
= OpNum
, e
= MI
->getNumOperands(); i
!= e
; ++i
) {
820 printRegName(O
, MI
->getOperand(i
).getReg());
825 void ARMInstPrinter::printGPRPairOperand(const MCInst
*MI
, unsigned OpNum
,
826 const MCSubtargetInfo
&STI
,
828 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
829 printRegName(O
, MRI
.getSubReg(Reg
, ARM::gsub_0
));
831 printRegName(O
, MRI
.getSubReg(Reg
, ARM::gsub_1
));
834 void ARMInstPrinter::printSetendOperand(const MCInst
*MI
, unsigned OpNum
,
835 const MCSubtargetInfo
&STI
,
837 const MCOperand
&Op
= MI
->getOperand(OpNum
);
844 void ARMInstPrinter::printCPSIMod(const MCInst
*MI
, unsigned OpNum
,
845 const MCSubtargetInfo
&STI
, raw_ostream
&O
) {
846 const MCOperand
&Op
= MI
->getOperand(OpNum
);
847 O
<< ARM_PROC::IModToString(Op
.getImm());
850 void ARMInstPrinter::printCPSIFlag(const MCInst
*MI
, unsigned OpNum
,
851 const MCSubtargetInfo
&STI
, raw_ostream
&O
) {
852 const MCOperand
&Op
= MI
->getOperand(OpNum
);
853 unsigned IFlags
= Op
.getImm();
854 for (int i
= 2; i
>= 0; --i
)
855 if (IFlags
& (1 << i
))
856 O
<< ARM_PROC::IFlagsToString(1 << i
);
862 void ARMInstPrinter::printMSRMaskOperand(const MCInst
*MI
, unsigned OpNum
,
863 const MCSubtargetInfo
&STI
,
865 const MCOperand
&Op
= MI
->getOperand(OpNum
);
866 const FeatureBitset
&FeatureBits
= STI
.getFeatureBits();
867 if (FeatureBits
[ARM::FeatureMClass
]) {
869 unsigned SYSm
= Op
.getImm() & 0xFFF; // 12-bit SYSm
870 unsigned Opcode
= MI
->getOpcode();
872 // For writes, handle extended mask bits if the DSP extension is present.
873 if (Opcode
== ARM::t2MSR_M
&& FeatureBits
[ARM::FeatureDSP
]) {
874 auto TheReg
=ARMSysReg::lookupMClassSysRegBy12bitSYSmValue(SYSm
);
875 if (TheReg
&& TheReg
->isInRequiredFeatures({ARM::FeatureDSP
})) {
881 // Handle the basic 8-bit mask.
883 if (Opcode
== ARM::t2MSR_M
&& FeatureBits
[ARM::HasV7Ops
]) {
884 // ARMv7-M deprecates using MSR APSR without a _<bits> qualifier as an
885 // alias for MSR APSR_nzcvq.
886 auto TheReg
= ARMSysReg::lookupMClassSysRegAPSRNonDeprecated(SYSm
);
893 auto TheReg
= ARMSysReg::lookupMClassSysRegBy8bitSYSmValue(SYSm
);
904 // As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as
905 // APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.
906 unsigned SpecRegRBit
= Op
.getImm() >> 4;
907 unsigned Mask
= Op
.getImm() & 0xf;
909 if (!SpecRegRBit
&& (Mask
== 8 || Mask
== 4 || Mask
== 12)) {
913 llvm_unreachable("Unexpected mask value!");
944 void ARMInstPrinter::printBankedRegOperand(const MCInst
*MI
, unsigned OpNum
,
945 const MCSubtargetInfo
&STI
,
947 uint32_t Banked
= MI
->getOperand(OpNum
).getImm();
948 auto TheReg
= ARMBankedReg::lookupBankedRegByEncoding(Banked
);
949 assert(TheReg
&& "invalid banked register operand");
950 std::string Name
= TheReg
->Name
;
952 uint32_t isSPSR
= (Banked
& 0x20) >> 5;
954 Name
.replace(0, 4, "SPSR"); // convert 'spsr_' to 'SPSR_'
958 void ARMInstPrinter::printPredicateOperand(const MCInst
*MI
, unsigned OpNum
,
959 const MCSubtargetInfo
&STI
,
961 ARMCC::CondCodes CC
= (ARMCC::CondCodes
)MI
->getOperand(OpNum
).getImm();
962 // Handle the undefined 15 CC value here for printing so we don't abort().
963 if ((unsigned)CC
== 15)
965 else if (CC
!= ARMCC::AL
)
966 O
<< ARMCondCodeToString(CC
);
969 void ARMInstPrinter::printMandatoryRestrictedPredicateOperand(
970 const MCInst
*MI
, unsigned OpNum
, const MCSubtargetInfo
&STI
,
972 if ((ARMCC::CondCodes
)MI
->getOperand(OpNum
).getImm() == ARMCC::HS
)
975 printMandatoryPredicateOperand(MI
, OpNum
, STI
, O
);
978 void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst
*MI
,
980 const MCSubtargetInfo
&STI
,
982 ARMCC::CondCodes CC
= (ARMCC::CondCodes
)MI
->getOperand(OpNum
).getImm();
983 O
<< ARMCondCodeToString(CC
);
986 void ARMInstPrinter::printMandatoryInvertedPredicateOperand(const MCInst
*MI
,
988 const MCSubtargetInfo
&STI
,
990 ARMCC::CondCodes CC
= (ARMCC::CondCodes
)MI
->getOperand(OpNum
).getImm();
991 O
<< ARMCondCodeToString(ARMCC::getOppositeCondition(CC
));
994 void ARMInstPrinter::printSBitModifierOperand(const MCInst
*MI
, unsigned OpNum
,
995 const MCSubtargetInfo
&STI
,
997 if (MI
->getOperand(OpNum
).getReg()) {
998 assert(MI
->getOperand(OpNum
).getReg() == ARM::CPSR
&&
999 "Expect ARM CPSR register!");
1004 void ARMInstPrinter::printNoHashImmediate(const MCInst
*MI
, unsigned OpNum
,
1005 const MCSubtargetInfo
&STI
,
1007 O
<< MI
->getOperand(OpNum
).getImm();
1010 void ARMInstPrinter::printPImmediate(const MCInst
*MI
, unsigned OpNum
,
1011 const MCSubtargetInfo
&STI
,
1013 O
<< "p" << MI
->getOperand(OpNum
).getImm();
1016 void ARMInstPrinter::printCImmediate(const MCInst
*MI
, unsigned OpNum
,
1017 const MCSubtargetInfo
&STI
,
1019 O
<< "c" << MI
->getOperand(OpNum
).getImm();
1022 void ARMInstPrinter::printCoprocOptionImm(const MCInst
*MI
, unsigned OpNum
,
1023 const MCSubtargetInfo
&STI
,
1025 O
<< "{" << MI
->getOperand(OpNum
).getImm() << "}";
1028 void ARMInstPrinter::printPCLabel(const MCInst
*MI
, unsigned OpNum
,
1029 const MCSubtargetInfo
&STI
, raw_ostream
&O
) {
1030 llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
1033 template <unsigned scale
>
1034 void ARMInstPrinter::printAdrLabelOperand(const MCInst
*MI
, unsigned OpNum
,
1035 const MCSubtargetInfo
&STI
,
1037 const MCOperand
&MO
= MI
->getOperand(OpNum
);
1040 MO
.getExpr()->print(O
, &MAI
);
1044 int32_t OffImm
= (int32_t)MO
.getImm() << scale
;
1046 O
<< markup("<imm:");
1047 if (OffImm
== INT32_MIN
)
1049 else if (OffImm
< 0)
1050 O
<< "#-" << -OffImm
;
1056 void ARMInstPrinter::printThumbS4ImmOperand(const MCInst
*MI
, unsigned OpNum
,
1057 const MCSubtargetInfo
&STI
,
1059 O
<< markup("<imm:") << "#" << formatImm(MI
->getOperand(OpNum
).getImm() * 4)
1063 void ARMInstPrinter::printThumbSRImm(const MCInst
*MI
, unsigned OpNum
,
1064 const MCSubtargetInfo
&STI
,
1066 unsigned Imm
= MI
->getOperand(OpNum
).getImm();
1067 O
<< markup("<imm:") << "#" << formatImm((Imm
== 0 ? 32 : Imm
))
1071 void ARMInstPrinter::printThumbITMask(const MCInst
*MI
, unsigned OpNum
,
1072 const MCSubtargetInfo
&STI
,
1074 // (3 - the number of trailing zeros) is the number of then / else.
1075 unsigned Mask
= MI
->getOperand(OpNum
).getImm();
1076 unsigned NumTZ
= countTrailingZeros(Mask
);
1077 assert(NumTZ
<= 3 && "Invalid IT mask!");
1078 for (unsigned Pos
= 3, e
= NumTZ
; Pos
> e
; --Pos
) {
1079 if ((Mask
>> Pos
) & 1)
1086 void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst
*MI
, unsigned Op
,
1087 const MCSubtargetInfo
&STI
,
1089 const MCOperand
&MO1
= MI
->getOperand(Op
);
1090 const MCOperand
&MO2
= MI
->getOperand(Op
+ 1);
1092 if (!MO1
.isReg()) { // FIXME: This is for CP entries, but isn't right.
1093 printOperand(MI
, Op
, STI
, O
);
1097 O
<< markup("<mem:") << "[";
1098 printRegName(O
, MO1
.getReg());
1099 if (unsigned RegNum
= MO2
.getReg()) {
1101 printRegName(O
, RegNum
);
1103 O
<< "]" << markup(">");
1106 void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst
*MI
,
1108 const MCSubtargetInfo
&STI
,
1111 const MCOperand
&MO1
= MI
->getOperand(Op
);
1112 const MCOperand
&MO2
= MI
->getOperand(Op
+ 1);
1114 if (!MO1
.isReg()) { // FIXME: This is for CP entries, but isn't right.
1115 printOperand(MI
, Op
, STI
, O
);
1119 O
<< markup("<mem:") << "[";
1120 printRegName(O
, MO1
.getReg());
1121 if (unsigned ImmOffs
= MO2
.getImm()) {
1122 O
<< ", " << markup("<imm:") << "#" << formatImm(ImmOffs
* Scale
)
1125 O
<< "]" << markup(">");
1128 void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst
*MI
,
1130 const MCSubtargetInfo
&STI
,
1132 printThumbAddrModeImm5SOperand(MI
, Op
, STI
, O
, 1);
1135 void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst
*MI
,
1137 const MCSubtargetInfo
&STI
,
1139 printThumbAddrModeImm5SOperand(MI
, Op
, STI
, O
, 2);
1142 void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst
*MI
,
1144 const MCSubtargetInfo
&STI
,
1146 printThumbAddrModeImm5SOperand(MI
, Op
, STI
, O
, 4);
1149 void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst
*MI
, unsigned Op
,
1150 const MCSubtargetInfo
&STI
,
1152 printThumbAddrModeImm5SOperand(MI
, Op
, STI
, O
, 4);
1155 // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
1156 // register with shift forms.
1157 // REG 0 0 - e.g. R5
1158 // REG IMM, SH_OPC - e.g. R5, LSL #3
1159 void ARMInstPrinter::printT2SOOperand(const MCInst
*MI
, unsigned OpNum
,
1160 const MCSubtargetInfo
&STI
,
1162 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
1163 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
1165 unsigned Reg
= MO1
.getReg();
1166 printRegName(O
, Reg
);
1168 // Print the shift opc.
1169 assert(MO2
.isImm() && "Not a valid t2_so_reg value!");
1170 printRegImmShift(O
, ARM_AM::getSORegShOp(MO2
.getImm()),
1171 ARM_AM::getSORegOffset(MO2
.getImm()), UseMarkup
);
1174 template <bool AlwaysPrintImm0
>
1175 void ARMInstPrinter::printAddrModeImm12Operand(const MCInst
*MI
, unsigned OpNum
,
1176 const MCSubtargetInfo
&STI
,
1178 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
1179 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
1181 if (!MO1
.isReg()) { // FIXME: This is for CP entries, but isn't right.
1182 printOperand(MI
, OpNum
, STI
, O
);
1186 O
<< markup("<mem:") << "[";
1187 printRegName(O
, MO1
.getReg());
1189 int32_t OffImm
= (int32_t)MO2
.getImm();
1190 bool isSub
= OffImm
< 0;
1191 // Special value for #-0. All others are normal.
1192 if (OffImm
== INT32_MIN
)
1195 O
<< ", " << markup("<imm:") << "#-" << formatImm(-OffImm
) << markup(">");
1196 } else if (AlwaysPrintImm0
|| OffImm
> 0) {
1197 O
<< ", " << markup("<imm:") << "#" << formatImm(OffImm
) << markup(">");
1199 O
<< "]" << markup(">");
1202 template <bool AlwaysPrintImm0
>
1203 void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst
*MI
,
1205 const MCSubtargetInfo
&STI
,
1207 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
1208 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
1210 O
<< markup("<mem:") << "[";
1211 printRegName(O
, MO1
.getReg());
1213 int32_t OffImm
= (int32_t)MO2
.getImm();
1214 bool isSub
= OffImm
< 0;
1216 if (OffImm
== INT32_MIN
)
1219 O
<< ", " << markup("<imm:") << "#-" << -OffImm
<< markup(">");
1220 } else if (AlwaysPrintImm0
|| OffImm
> 0) {
1221 O
<< ", " << markup("<imm:") << "#" << OffImm
<< markup(">");
1223 O
<< "]" << markup(">");
1226 template <bool AlwaysPrintImm0
>
1227 void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst
*MI
,
1229 const MCSubtargetInfo
&STI
,
1231 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
1232 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
1234 if (!MO1
.isReg()) { // For label symbolic references.
1235 printOperand(MI
, OpNum
, STI
, O
);
1239 O
<< markup("<mem:") << "[";
1240 printRegName(O
, MO1
.getReg());
1242 int32_t OffImm
= (int32_t)MO2
.getImm();
1243 bool isSub
= OffImm
< 0;
1245 assert(((OffImm
& 0x3) == 0) && "Not a valid immediate!");
1248 if (OffImm
== INT32_MIN
)
1251 O
<< ", " << markup("<imm:") << "#-" << -OffImm
<< markup(">");
1252 } else if (AlwaysPrintImm0
|| OffImm
> 0) {
1253 O
<< ", " << markup("<imm:") << "#" << OffImm
<< markup(">");
1255 O
<< "]" << markup(">");
1258 void ARMInstPrinter::printT2AddrModeImm0_1020s4Operand(
1259 const MCInst
*MI
, unsigned OpNum
, const MCSubtargetInfo
&STI
,
1261 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
1262 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
1264 O
<< markup("<mem:") << "[";
1265 printRegName(O
, MO1
.getReg());
1267 O
<< ", " << markup("<imm:") << "#" << formatImm(MO2
.getImm() * 4)
1270 O
<< "]" << markup(">");
1273 void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(
1274 const MCInst
*MI
, unsigned OpNum
, const MCSubtargetInfo
&STI
,
1276 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
1277 int32_t OffImm
= (int32_t)MO1
.getImm();
1278 O
<< ", " << markup("<imm:");
1279 if (OffImm
== INT32_MIN
)
1281 else if (OffImm
< 0)
1282 O
<< "#-" << -OffImm
;
1288 void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(
1289 const MCInst
*MI
, unsigned OpNum
, const MCSubtargetInfo
&STI
,
1291 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
1292 int32_t OffImm
= (int32_t)MO1
.getImm();
1294 assert(((OffImm
& 0x3) == 0) && "Not a valid immediate!");
1296 O
<< ", " << markup("<imm:");
1297 if (OffImm
== INT32_MIN
)
1299 else if (OffImm
< 0)
1300 O
<< "#-" << -OffImm
;
1306 void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst
*MI
,
1308 const MCSubtargetInfo
&STI
,
1310 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
1311 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
1312 const MCOperand
&MO3
= MI
->getOperand(OpNum
+ 2);
1314 O
<< markup("<mem:") << "[";
1315 printRegName(O
, MO1
.getReg());
1317 assert(MO2
.getReg() && "Invalid so_reg load / store address!");
1319 printRegName(O
, MO2
.getReg());
1321 unsigned ShAmt
= MO3
.getImm();
1323 assert(ShAmt
<= 3 && "Not a valid Thumb2 addressing mode!");
1324 O
<< ", lsl " << markup("<imm:") << "#" << ShAmt
<< markup(">");
1326 O
<< "]" << markup(">");
1329 void ARMInstPrinter::printFPImmOperand(const MCInst
*MI
, unsigned OpNum
,
1330 const MCSubtargetInfo
&STI
,
1332 const MCOperand
&MO
= MI
->getOperand(OpNum
);
1333 O
<< markup("<imm:") << '#' << ARM_AM::getFPImmFloat(MO
.getImm())
1337 void ARMInstPrinter::printVMOVModImmOperand(const MCInst
*MI
, unsigned OpNum
,
1338 const MCSubtargetInfo
&STI
,
1340 unsigned EncodedImm
= MI
->getOperand(OpNum
).getImm();
1342 uint64_t Val
= ARM_AM::decodeVMOVModImm(EncodedImm
, EltBits
);
1343 O
<< markup("<imm:") << "#0x";
1348 void ARMInstPrinter::printImmPlusOneOperand(const MCInst
*MI
, unsigned OpNum
,
1349 const MCSubtargetInfo
&STI
,
1351 unsigned Imm
= MI
->getOperand(OpNum
).getImm();
1352 O
<< markup("<imm:") << "#" << formatImm(Imm
+ 1) << markup(">");
1355 void ARMInstPrinter::printRotImmOperand(const MCInst
*MI
, unsigned OpNum
,
1356 const MCSubtargetInfo
&STI
,
1358 unsigned Imm
= MI
->getOperand(OpNum
).getImm();
1361 assert(Imm
<= 3 && "illegal ror immediate!");
1362 O
<< ", ror " << markup("<imm:") << "#" << 8 * Imm
<< markup(">");
1365 void ARMInstPrinter::printModImmOperand(const MCInst
*MI
, unsigned OpNum
,
1366 const MCSubtargetInfo
&STI
,
1368 MCOperand Op
= MI
->getOperand(OpNum
);
1370 // Support for fixups (MCFixup)
1372 return printOperand(MI
, OpNum
, STI
, O
);
1374 unsigned Bits
= Op
.getImm() & 0xFF;
1375 unsigned Rot
= (Op
.getImm() & 0xF00) >> 7;
1377 bool PrintUnsigned
= false;
1378 switch (MI
->getOpcode()) {
1380 // Movs to PC should be treated unsigned
1381 PrintUnsigned
= (MI
->getOperand(OpNum
- 1).getReg() == ARM::PC
);
1384 // Movs to special registers should be treated unsigned
1385 PrintUnsigned
= true;
1389 int32_t Rotated
= ARM_AM::rotr32(Bits
, Rot
);
1390 if (ARM_AM::getSOImmVal(Rotated
) == Op
.getImm()) {
1391 // #rot has the least possible value
1392 O
<< "#" << markup("<imm:");
1394 O
<< static_cast<uint32_t>(Rotated
);
1401 // Explicit #bits, #rot implied
1402 O
<< "#" << markup("<imm:") << Bits
<< markup(">") << ", #" << markup("<imm:")
1403 << Rot
<< markup(">");
1406 void ARMInstPrinter::printFBits16(const MCInst
*MI
, unsigned OpNum
,
1407 const MCSubtargetInfo
&STI
, raw_ostream
&O
) {
1408 O
<< markup("<imm:") << "#" << 16 - MI
->getOperand(OpNum
).getImm()
1412 void ARMInstPrinter::printFBits32(const MCInst
*MI
, unsigned OpNum
,
1413 const MCSubtargetInfo
&STI
, raw_ostream
&O
) {
1414 O
<< markup("<imm:") << "#" << 32 - MI
->getOperand(OpNum
).getImm()
1418 void ARMInstPrinter::printVectorIndex(const MCInst
*MI
, unsigned OpNum
,
1419 const MCSubtargetInfo
&STI
,
1421 O
<< "[" << MI
->getOperand(OpNum
).getImm() << "]";
1424 void ARMInstPrinter::printVectorListOne(const MCInst
*MI
, unsigned OpNum
,
1425 const MCSubtargetInfo
&STI
,
1428 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1432 void ARMInstPrinter::printVectorListTwo(const MCInst
*MI
, unsigned OpNum
,
1433 const MCSubtargetInfo
&STI
,
1435 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1436 unsigned Reg0
= MRI
.getSubReg(Reg
, ARM::dsub_0
);
1437 unsigned Reg1
= MRI
.getSubReg(Reg
, ARM::dsub_1
);
1439 printRegName(O
, Reg0
);
1441 printRegName(O
, Reg1
);
1445 void ARMInstPrinter::printVectorListTwoSpaced(const MCInst
*MI
, unsigned OpNum
,
1446 const MCSubtargetInfo
&STI
,
1448 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1449 unsigned Reg0
= MRI
.getSubReg(Reg
, ARM::dsub_0
);
1450 unsigned Reg1
= MRI
.getSubReg(Reg
, ARM::dsub_2
);
1452 printRegName(O
, Reg0
);
1454 printRegName(O
, Reg1
);
1458 void ARMInstPrinter::printVectorListThree(const MCInst
*MI
, unsigned OpNum
,
1459 const MCSubtargetInfo
&STI
,
1461 // Normally, it's not safe to use register enum values directly with
1462 // addition to get the next register, but for VFP registers, the
1463 // sort order is guaranteed because they're all of the form D<n>.
1465 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1467 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 1);
1469 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 2);
1473 void ARMInstPrinter::printVectorListFour(const MCInst
*MI
, unsigned OpNum
,
1474 const MCSubtargetInfo
&STI
,
1476 // Normally, it's not safe to use register enum values directly with
1477 // addition to get the next register, but for VFP registers, the
1478 // sort order is guaranteed because they're all of the form D<n>.
1480 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1482 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 1);
1484 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 2);
1486 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 3);
1490 void ARMInstPrinter::printVectorListOneAllLanes(const MCInst
*MI
,
1492 const MCSubtargetInfo
&STI
,
1495 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1499 void ARMInstPrinter::printVectorListTwoAllLanes(const MCInst
*MI
,
1501 const MCSubtargetInfo
&STI
,
1503 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1504 unsigned Reg0
= MRI
.getSubReg(Reg
, ARM::dsub_0
);
1505 unsigned Reg1
= MRI
.getSubReg(Reg
, ARM::dsub_1
);
1507 printRegName(O
, Reg0
);
1509 printRegName(O
, Reg1
);
1513 void ARMInstPrinter::printVectorListThreeAllLanes(const MCInst
*MI
,
1515 const MCSubtargetInfo
&STI
,
1517 // Normally, it's not safe to use register enum values directly with
1518 // addition to get the next register, but for VFP registers, the
1519 // sort order is guaranteed because they're all of the form D<n>.
1521 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1523 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 1);
1525 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 2);
1529 void ARMInstPrinter::printVectorListFourAllLanes(const MCInst
*MI
,
1531 const MCSubtargetInfo
&STI
,
1533 // Normally, it's not safe to use register enum values directly with
1534 // addition to get the next register, but for VFP registers, the
1535 // sort order is guaranteed because they're all of the form D<n>.
1537 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1539 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 1);
1541 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 2);
1543 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 3);
1547 void ARMInstPrinter::printVectorListTwoSpacedAllLanes(
1548 const MCInst
*MI
, unsigned OpNum
, const MCSubtargetInfo
&STI
,
1550 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1551 unsigned Reg0
= MRI
.getSubReg(Reg
, ARM::dsub_0
);
1552 unsigned Reg1
= MRI
.getSubReg(Reg
, ARM::dsub_2
);
1554 printRegName(O
, Reg0
);
1556 printRegName(O
, Reg1
);
1560 void ARMInstPrinter::printVectorListThreeSpacedAllLanes(
1561 const MCInst
*MI
, unsigned OpNum
, const MCSubtargetInfo
&STI
,
1563 // Normally, it's not safe to use register enum values directly with
1564 // addition to get the next register, but for VFP registers, the
1565 // sort order is guaranteed because they're all of the form D<n>.
1567 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1569 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 2);
1571 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 4);
1575 void ARMInstPrinter::printVectorListFourSpacedAllLanes(
1576 const MCInst
*MI
, unsigned OpNum
, const MCSubtargetInfo
&STI
,
1578 // Normally, it's not safe to use register enum values directly with
1579 // addition to get the next register, but for VFP registers, the
1580 // sort order is guaranteed because they're all of the form D<n>.
1582 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1584 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 2);
1586 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 4);
1588 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 6);
1592 void ARMInstPrinter::printVectorListThreeSpaced(const MCInst
*MI
,
1594 const MCSubtargetInfo
&STI
,
1596 // Normally, it's not safe to use register enum values directly with
1597 // addition to get the next register, but for VFP registers, the
1598 // sort order is guaranteed because they're all of the form D<n>.
1600 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1602 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 2);
1604 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 4);
1608 void ARMInstPrinter::printVectorListFourSpaced(const MCInst
*MI
, unsigned OpNum
,
1609 const MCSubtargetInfo
&STI
,
1611 // Normally, it's not safe to use register enum values directly with
1612 // addition to get the next register, but for VFP registers, the
1613 // sort order is guaranteed because they're all of the form D<n>.
1615 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1617 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 2);
1619 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 4);
1621 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 6);
1625 template<unsigned NumRegs
>
1626 void ARMInstPrinter::printMVEVectorList(const MCInst
*MI
, unsigned OpNum
,
1627 const MCSubtargetInfo
&STI
,
1629 unsigned Reg
= MI
->getOperand(OpNum
).getReg();
1630 const char *Prefix
= "{";
1631 for (unsigned i
= 0; i
< NumRegs
; i
++) {
1633 printRegName(O
, MRI
.getSubReg(Reg
, ARM::qsub_0
+ i
));
1639 template<int64_t Angle
, int64_t Remainder
>
1640 void ARMInstPrinter::printComplexRotationOp(const MCInst
*MI
, unsigned OpNo
,
1641 const MCSubtargetInfo
&STI
,
1643 unsigned Val
= MI
->getOperand(OpNo
).getImm();
1644 O
<< "#" << (Val
* Angle
) + Remainder
;
1647 void ARMInstPrinter::printVPTPredicateOperand(const MCInst
*MI
, unsigned OpNum
,
1648 const MCSubtargetInfo
&STI
,
1650 ARMVCC::VPTCodes CC
= (ARMVCC::VPTCodes
)MI
->getOperand(OpNum
).getImm();
1651 if (CC
!= ARMVCC::None
)
1652 O
<< ARMVPTPredToString(CC
);
1655 void ARMInstPrinter::printVPTMask(const MCInst
*MI
, unsigned OpNum
,
1656 const MCSubtargetInfo
&STI
,
1658 // (3 - the number of trailing zeroes) is the number of them / else.
1659 unsigned Mask
= MI
->getOperand(OpNum
).getImm();
1660 unsigned NumTZ
= countTrailingZeros(Mask
);
1661 assert(NumTZ
<= 3 && "Invalid VPT mask!");
1662 for (unsigned Pos
= 3, e
= NumTZ
; Pos
> e
; --Pos
) {
1663 bool T
= ((Mask
>> Pos
) & 1) == 0;
1671 void ARMInstPrinter::printExpandedImmOperand(const MCInst
*MI
, unsigned OpNum
,
1672 const MCSubtargetInfo
&STI
,
1674 uint32_t Val
= MI
->getOperand(OpNum
).getImm();
1675 O
<< markup("<imm:") << "#0x";
1680 void ARMInstPrinter::printMveSaturateOp(const MCInst
*MI
, unsigned OpNum
,
1681 const MCSubtargetInfo
&STI
,
1683 uint32_t Val
= MI
->getOperand(OpNum
).getImm();
1684 assert(Val
<= 1 && "Invalid MVE saturate operand");
1685 O
<< "#" << (Val
== 1 ? 48 : 64);