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/MCInstrAnalysis.h"
21 #include "llvm/MC/MCInstrInfo.h"
22 #include "llvm/MC/MCRegisterInfo.h"
23 #include "llvm/MC/MCSubtargetInfo.h"
24 #include "llvm/MC/SubtargetFeature.h"
25 #include "llvm/Support/Casting.h"
26 #include "llvm/Support/ErrorHandling.h"
27 #include "llvm/Support/MathExtras.h"
28 #include "llvm/Support/raw_ostream.h"
35 #define DEBUG_TYPE "asm-printer"
37 #define PRINT_ALIAS_INSTR
38 #include "ARMGenAsmWriter.inc"
40 /// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing.
42 /// getSORegOffset returns an integer from 0-31, representing '32' as 0.
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");
52 /// Prints the shift value with an immediate value.
53 static void printRegImmShift(raw_ostream
&O
, ARM_AM::ShiftOpc ShOpc
,
54 unsigned ShImm
, bool UseMarkup
) {
55 if (ShOpc
== ARM_AM::no_shift
|| (ShOpc
== ARM_AM::lsl
&& !ShImm
))
59 assert(!(ShOpc
== ARM_AM::ror
&& !ShImm
) && "Cannot have ror #0");
60 O
<< getShiftOpcStr(ShOpc
);
62 if (ShOpc
!= ARM_AM::rrx
) {
66 O
<< "#" << translateShiftImm(ShImm
);
72 ARMInstPrinter::ARMInstPrinter(const MCAsmInfo
&MAI
, const MCInstrInfo
&MII
,
73 const MCRegisterInfo
&MRI
)
74 : MCInstPrinter(MAI
, MII
, MRI
) {}
76 bool ARMInstPrinter::applyTargetSpecificCLOption(StringRef Opt
) {
77 if (Opt
== "reg-names-std") {
78 DefaultAltIdx
= ARM::NoRegAltName
;
81 if (Opt
== "reg-names-raw") {
82 DefaultAltIdx
= ARM::RegNamesRaw
;
88 void ARMInstPrinter::printRegName(raw_ostream
&OS
, unsigned RegNo
) const {
89 OS
<< markup("<reg:") << getRegisterName(RegNo
, DefaultAltIdx
) << markup(">");
92 void ARMInstPrinter::printInst(const MCInst
*MI
, uint64_t Address
,
93 StringRef Annot
, const MCSubtargetInfo
&STI
,
95 unsigned Opcode
= MI
->getOpcode();
98 // Check for MOVs and print canonical forms, instead.
100 // FIXME: Thumb variants?
101 const MCOperand
&Dst
= MI
->getOperand(0);
102 const MCOperand
&MO1
= MI
->getOperand(1);
103 const MCOperand
&MO2
= MI
->getOperand(2);
104 const MCOperand
&MO3
= MI
->getOperand(3);
106 O
<< '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3
.getImm()));
107 printSBitModifierOperand(MI
, 6, STI
, O
);
108 printPredicateOperand(MI
, 4, STI
, O
);
111 printRegName(O
, Dst
.getReg());
113 printRegName(O
, MO1
.getReg());
116 printRegName(O
, MO2
.getReg());
117 assert(ARM_AM::getSORegOffset(MO3
.getImm()) == 0);
118 printAnnotation(O
, Annot
);
123 // FIXME: Thumb variants?
124 const MCOperand
&Dst
= MI
->getOperand(0);
125 const MCOperand
&MO1
= MI
->getOperand(1);
126 const MCOperand
&MO2
= MI
->getOperand(2);
128 O
<< '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2
.getImm()));
129 printSBitModifierOperand(MI
, 5, STI
, O
);
130 printPredicateOperand(MI
, 3, STI
, O
);
133 printRegName(O
, Dst
.getReg());
135 printRegName(O
, MO1
.getReg());
137 if (ARM_AM::getSORegShOp(MO2
.getImm()) == ARM_AM::rrx
) {
138 printAnnotation(O
, Annot
);
142 O
<< ", " << markup("<imm:") << "#"
143 << translateShiftImm(ARM_AM::getSORegOffset(MO2
.getImm())) << markup(">");
144 printAnnotation(O
, Annot
);
150 case ARM::t2STMDB_UPD
:
151 if (MI
->getOperand(0).getReg() == ARM::SP
&& MI
->getNumOperands() > 5) {
152 // Should only print PUSH if there are at least two registers in the list.
154 printPredicateOperand(MI
, 2, STI
, O
);
155 if (Opcode
== ARM::t2STMDB_UPD
)
158 printRegisterList(MI
, 4, STI
, O
);
159 printAnnotation(O
, Annot
);
164 case ARM::STR_PRE_IMM
:
165 if (MI
->getOperand(2).getReg() == ARM::SP
&&
166 MI
->getOperand(3).getImm() == -4) {
168 printPredicateOperand(MI
, 4, STI
, O
);
170 printRegName(O
, MI
->getOperand(1).getReg());
172 printAnnotation(O
, Annot
);
179 case ARM::t2LDMIA_UPD
:
180 if (MI
->getOperand(0).getReg() == ARM::SP
&& MI
->getNumOperands() > 5) {
181 // Should only print POP if there are at least two registers in the list.
183 printPredicateOperand(MI
, 2, STI
, O
);
184 if (Opcode
== ARM::t2LDMIA_UPD
)
187 printRegisterList(MI
, 4, STI
, O
);
188 printAnnotation(O
, Annot
);
193 case ARM::LDR_POST_IMM
:
194 if (MI
->getOperand(2).getReg() == ARM::SP
&&
195 MI
->getOperand(4).getImm() == 4) {
197 printPredicateOperand(MI
, 5, STI
, O
);
199 printRegName(O
, MI
->getOperand(0).getReg());
201 printAnnotation(O
, Annot
);
207 case ARM::VSTMSDB_UPD
:
208 case ARM::VSTMDDB_UPD
:
209 if (MI
->getOperand(0).getReg() == ARM::SP
) {
210 O
<< '\t' << "vpush";
211 printPredicateOperand(MI
, 2, STI
, O
);
213 printRegisterList(MI
, 4, STI
, O
);
214 printAnnotation(O
, Annot
);
220 case ARM::VLDMSIA_UPD
:
221 case ARM::VLDMDIA_UPD
:
222 if (MI
->getOperand(0).getReg() == ARM::SP
) {
224 printPredicateOperand(MI
, 2, STI
, O
);
226 printRegisterList(MI
, 4, STI
, O
);
227 printAnnotation(O
, Annot
);
233 bool Writeback
= true;
234 unsigned BaseReg
= MI
->getOperand(0).getReg();
235 for (unsigned i
= 3; i
< MI
->getNumOperands(); ++i
) {
236 if (MI
->getOperand(i
).getReg() == BaseReg
)
242 printPredicateOperand(MI
, 1, STI
, O
);
244 printRegName(O
, BaseReg
);
248 printRegisterList(MI
, 3, STI
, O
);
249 printAnnotation(O
, Annot
);
253 // Combine 2 GPRs from disassember into a GPRPair to match with instr def.
254 // ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
255 // a single GPRPair reg operand is used in the .td file to replace the two
256 // GPRs. However, when decoding them, the two GRPs cannot be automatically
257 // expressed as a GPRPair, so we have to manually merge them.
258 // FIXME: We would really like to be able to tablegen'erate this.
263 const MCRegisterClass
&MRC
= MRI
.getRegClass(ARM::GPRRegClassID
);
264 bool isStore
= Opcode
== ARM::STREXD
|| Opcode
== ARM::STLEXD
;
265 unsigned Reg
= MI
->getOperand(isStore
? 1 : 0).getReg();
266 if (MRC
.contains(Reg
)) {
269 NewMI
.setOpcode(Opcode
);
272 NewMI
.addOperand(MI
->getOperand(0));
273 NewReg
= MCOperand::createReg(MRI
.getMatchingSuperReg(
274 Reg
, ARM::gsub_0
, &MRI
.getRegClass(ARM::GPRPairRegClassID
)));
275 NewMI
.addOperand(NewReg
);
277 // Copy the rest operands into NewMI.
278 for (unsigned i
= isStore
? 3 : 2; i
< MI
->getNumOperands(); ++i
)
279 NewMI
.addOperand(MI
->getOperand(i
));
280 printInstruction(&NewMI
, Address
, STI
, O
);
290 switch (MI
->getOperand(0).getImm()) {
292 if (!printAliasInstr(MI
, Address
, STI
, O
))
293 printInstruction(MI
, Address
, STI
, O
);
302 printAnnotation(O
, Annot
);
306 if (!printAliasInstr(MI
, Address
, STI
, O
))
307 printInstruction(MI
, Address
, STI
, O
);
309 printAnnotation(O
, Annot
);
312 void ARMInstPrinter::printOperand(const MCInst
*MI
, unsigned OpNo
,
313 const MCSubtargetInfo
&STI
, raw_ostream
&O
) {
314 const MCOperand
&Op
= MI
->getOperand(OpNo
);
316 unsigned Reg
= Op
.getReg();
317 printRegName(O
, Reg
);
318 } else if (Op
.isImm()) {
319 O
<< markup("<imm:") << '#' << formatImm(Op
.getImm()) << markup(">");
321 assert(Op
.isExpr() && "unknown operand kind in printOperand");
322 const MCExpr
*Expr
= Op
.getExpr();
323 switch (Expr
->getKind()) {
326 Expr
->print(O
, &MAI
);
328 case MCExpr::Constant
: {
329 // If a symbolic branch target was added as a constant expression then
330 // print that address in hex. And only print 32 unsigned bits for the
332 const MCConstantExpr
*Constant
= cast
<MCConstantExpr
>(Expr
);
333 int64_t TargetAddress
;
334 if (!Constant
->evaluateAsAbsolute(TargetAddress
)) {
336 Expr
->print(O
, &MAI
);
339 O
.write_hex(static_cast<uint32_t>(TargetAddress
));
344 // FIXME: Should we always treat this as if it is a constant literal and
345 // prefix it with '#'?
346 Expr
->print(O
, &MAI
);
352 void ARMInstPrinter::printOperand(const MCInst
*MI
, uint64_t Address
,
353 unsigned OpNum
, const MCSubtargetInfo
&STI
,
355 const MCOperand
&Op
= MI
->getOperand(OpNum
);
356 if (!Op
.isImm() || !PrintBranchImmAsAddress
|| getUseMarkup())
357 return printOperand(MI
, OpNum
, STI
, O
);
358 uint64_t Target
= ARM_MC::evaluateBranchTarget(MII
.get(MI
->getOpcode()),
359 Address
, Op
.getImm());
360 Target
&= 0xffffffff;
361 O
<< formatHex(Target
);
363 *CommentStream
<< "imm = #" << formatImm(Op
.getImm()) << '\n';
366 void ARMInstPrinter::printThumbLdrLabelOperand(const MCInst
*MI
, unsigned OpNum
,
367 const MCSubtargetInfo
&STI
,
369 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
371 MO1
.getExpr()->print(O
, &MAI
);
375 O
<< markup("<mem:") << "[pc, ";
377 int32_t OffImm
= (int32_t)MO1
.getImm();
378 bool isSub
= OffImm
< 0;
380 // Special value for #-0. All others are normal.
381 if (OffImm
== INT32_MIN
)
384 O
<< markup("<imm:") << "#-" << formatImm(-OffImm
) << markup(">");
386 O
<< markup("<imm:") << "#" << formatImm(OffImm
) << markup(">");
388 O
<< "]" << markup(">");
391 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
392 // "Addressing Mode 1 - Data-processing operands" forms. This includes:
394 // REG REG 0,SH_OPC - e.g. R5, ROR R3
395 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3
396 void ARMInstPrinter::printSORegRegOperand(const MCInst
*MI
, unsigned OpNum
,
397 const MCSubtargetInfo
&STI
,
399 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
400 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
401 const MCOperand
&MO3
= MI
->getOperand(OpNum
+ 2);
403 printRegName(O
, MO1
.getReg());
405 // Print the shift opc.
406 ARM_AM::ShiftOpc ShOpc
= ARM_AM::getSORegShOp(MO3
.getImm());
407 O
<< ", " << ARM_AM::getShiftOpcStr(ShOpc
);
408 if (ShOpc
== ARM_AM::rrx
)
412 printRegName(O
, MO2
.getReg());
413 assert(ARM_AM::getSORegOffset(MO3
.getImm()) == 0);
416 void ARMInstPrinter::printSORegImmOperand(const MCInst
*MI
, unsigned OpNum
,
417 const MCSubtargetInfo
&STI
,
419 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
420 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
422 printRegName(O
, MO1
.getReg());
424 // Print the shift opc.
425 printRegImmShift(O
, ARM_AM::getSORegShOp(MO2
.getImm()),
426 ARM_AM::getSORegOffset(MO2
.getImm()), UseMarkup
);
429 //===--------------------------------------------------------------------===//
430 // Addressing Mode #2
431 //===--------------------------------------------------------------------===//
433 void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst
*MI
, unsigned Op
,
434 const MCSubtargetInfo
&STI
,
436 const MCOperand
&MO1
= MI
->getOperand(Op
);
437 const MCOperand
&MO2
= MI
->getOperand(Op
+ 1);
438 const MCOperand
&MO3
= MI
->getOperand(Op
+ 2);
440 O
<< markup("<mem:") << "[";
441 printRegName(O
, MO1
.getReg());
444 if (ARM_AM::getAM2Offset(MO3
.getImm())) { // Don't print +0.
445 O
<< ", " << markup("<imm:") << "#"
446 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3
.getImm()))
447 << ARM_AM::getAM2Offset(MO3
.getImm()) << markup(">");
449 O
<< "]" << markup(">");
454 O
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3
.getImm()));
455 printRegName(O
, MO2
.getReg());
457 printRegImmShift(O
, ARM_AM::getAM2ShiftOpc(MO3
.getImm()),
458 ARM_AM::getAM2Offset(MO3
.getImm()), UseMarkup
);
459 O
<< "]" << markup(">");
462 void ARMInstPrinter::printAddrModeTBB(const MCInst
*MI
, unsigned Op
,
463 const MCSubtargetInfo
&STI
,
465 const MCOperand
&MO1
= MI
->getOperand(Op
);
466 const MCOperand
&MO2
= MI
->getOperand(Op
+ 1);
467 O
<< markup("<mem:") << "[";
468 printRegName(O
, MO1
.getReg());
470 printRegName(O
, MO2
.getReg());
471 O
<< "]" << markup(">");
474 void ARMInstPrinter::printAddrModeTBH(const MCInst
*MI
, unsigned Op
,
475 const MCSubtargetInfo
&STI
,
477 const MCOperand
&MO1
= MI
->getOperand(Op
);
478 const MCOperand
&MO2
= MI
->getOperand(Op
+ 1);
479 O
<< markup("<mem:") << "[";
480 printRegName(O
, MO1
.getReg());
482 printRegName(O
, MO2
.getReg());
483 O
<< ", lsl " << markup("<imm:") << "#1" << markup(">") << "]" << markup(">");
486 void ARMInstPrinter::printAddrMode2Operand(const MCInst
*MI
, unsigned Op
,
487 const MCSubtargetInfo
&STI
,
489 const MCOperand
&MO1
= MI
->getOperand(Op
);
491 if (!MO1
.isReg()) { // FIXME: This is for CP entries, but isn't right.
492 printOperand(MI
, Op
, STI
, O
);
497 const MCOperand
&MO3
= MI
->getOperand(Op
+ 2);
498 unsigned IdxMode
= ARM_AM::getAM2IdxMode(MO3
.getImm());
499 assert(IdxMode
!= ARMII::IndexModePost
&& "Should be pre or offset index op");
502 printAM2PreOrOffsetIndexOp(MI
, Op
, STI
, O
);
505 void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst
*MI
,
507 const MCSubtargetInfo
&STI
,
509 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
510 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
513 unsigned ImmOffs
= ARM_AM::getAM2Offset(MO2
.getImm());
514 O
<< markup("<imm:") << '#'
515 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2
.getImm())) << ImmOffs
520 O
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2
.getImm()));
521 printRegName(O
, MO1
.getReg());
523 printRegImmShift(O
, ARM_AM::getAM2ShiftOpc(MO2
.getImm()),
524 ARM_AM::getAM2Offset(MO2
.getImm()), UseMarkup
);
527 //===--------------------------------------------------------------------===//
528 // Addressing Mode #3
529 //===--------------------------------------------------------------------===//
531 void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst
*MI
, unsigned Op
,
533 bool AlwaysPrintImm0
) {
534 const MCOperand
&MO1
= MI
->getOperand(Op
);
535 const MCOperand
&MO2
= MI
->getOperand(Op
+ 1);
536 const MCOperand
&MO3
= MI
->getOperand(Op
+ 2);
538 O
<< markup("<mem:") << '[';
539 printRegName(O
, MO1
.getReg());
542 O
<< ", " << getAddrOpcStr(ARM_AM::getAM3Op(MO3
.getImm()));
543 printRegName(O
, MO2
.getReg());
544 O
<< ']' << markup(">");
548 // If the op is sub we have to print the immediate even if it is 0
549 unsigned ImmOffs
= ARM_AM::getAM3Offset(MO3
.getImm());
550 ARM_AM::AddrOpc op
= ARM_AM::getAM3Op(MO3
.getImm());
552 if (AlwaysPrintImm0
|| ImmOffs
|| (op
== ARM_AM::sub
)) {
553 O
<< ", " << markup("<imm:") << "#" << ARM_AM::getAddrOpcStr(op
) << ImmOffs
556 O
<< ']' << markup(">");
559 template <bool AlwaysPrintImm0
>
560 void ARMInstPrinter::printAddrMode3Operand(const MCInst
*MI
, unsigned Op
,
561 const MCSubtargetInfo
&STI
,
563 const MCOperand
&MO1
= MI
->getOperand(Op
);
564 if (!MO1
.isReg()) { // For label symbolic references.
565 printOperand(MI
, Op
, STI
, O
);
569 assert(ARM_AM::getAM3IdxMode(MI
->getOperand(Op
+ 2).getImm()) !=
570 ARMII::IndexModePost
&&
571 "unexpected idxmode");
572 printAM3PreOrOffsetIndexOp(MI
, Op
, O
, AlwaysPrintImm0
);
575 void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst
*MI
,
577 const MCSubtargetInfo
&STI
,
579 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
580 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
583 O
<< getAddrOpcStr(ARM_AM::getAM3Op(MO2
.getImm()));
584 printRegName(O
, MO1
.getReg());
588 unsigned ImmOffs
= ARM_AM::getAM3Offset(MO2
.getImm());
589 O
<< markup("<imm:") << '#'
590 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2
.getImm())) << ImmOffs
594 void ARMInstPrinter::printPostIdxImm8Operand(const MCInst
*MI
, unsigned OpNum
,
595 const MCSubtargetInfo
&STI
,
597 const MCOperand
&MO
= MI
->getOperand(OpNum
);
598 unsigned Imm
= MO
.getImm();
599 O
<< markup("<imm:") << '#' << ((Imm
& 256) ? "" : "-") << (Imm
& 0xff)
603 void ARMInstPrinter::printPostIdxRegOperand(const MCInst
*MI
, unsigned OpNum
,
604 const MCSubtargetInfo
&STI
,
606 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
607 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
609 O
<< (MO2
.getImm() ? "" : "-");
610 printRegName(O
, MO1
.getReg());
613 void ARMInstPrinter::printPostIdxImm8s4Operand(const MCInst
*MI
, unsigned OpNum
,
614 const MCSubtargetInfo
&STI
,
616 const MCOperand
&MO
= MI
->getOperand(OpNum
);
617 unsigned Imm
= MO
.getImm();
618 O
<< markup("<imm:") << '#' << ((Imm
& 256) ? "" : "-") << ((Imm
& 0xff) << 2)
623 void ARMInstPrinter::printMveAddrModeRQOperand(const MCInst
*MI
, unsigned OpNum
,
624 const MCSubtargetInfo
&STI
,
626 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
627 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
629 O
<< markup("<mem:") << "[";
630 printRegName(O
, MO1
.getReg());
632 printRegName(O
, MO2
.getReg());
635 printRegImmShift(O
, ARM_AM::uxtw
, shift
, UseMarkup
);
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(is_sorted(drop_begin(*MI
, OpNum
),
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::printMveSaturateOp(const MCInst
*MI
, unsigned OpNum
,
1672 const MCSubtargetInfo
&STI
,
1674 uint32_t Val
= MI
->getOperand(OpNum
).getImm();
1675 assert(Val
<= 1 && "Invalid MVE saturate operand");
1676 O
<< "#" << (Val
== 1 ? 48 : 64);