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 "MCTargetDesc/ARMAddressingModes.h"
15 #include "MCTargetDesc/ARMBaseInfo.h"
16 #include "Utils/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/raw_ostream.h"
27 #include "llvm/TargetParser/SubtargetFeature.h"
33 #define DEBUG_TYPE "asm-printer"
35 #define PRINT_ALIAS_INSTR
36 #include "ARMGenAsmWriter.inc"
38 /// translateShiftImm - Convert shift immediate from 0-31 to 1-32 for printing.
40 /// getSORegOffset returns an integer from 0-31, representing '32' as 0.
41 static unsigned translateShiftImm(unsigned imm
) {
42 // lsr #32 and asr #32 exist, but should be encoded as a 0.
43 assert((imm
& ~0x1f) == 0 && "Invalid shift encoding");
50 static void printRegImmShift(raw_ostream
&O
, ARM_AM::ShiftOpc ShOpc
,
51 unsigned ShImm
, ARMInstPrinter
&printer
) {
52 if (ShOpc
== ARM_AM::no_shift
|| (ShOpc
== ARM_AM::lsl
&& !ShImm
))
56 assert(!(ShOpc
== ARM_AM::ror
&& !ShImm
) && "Cannot have ror #0");
57 O
<< getShiftOpcStr(ShOpc
);
59 if (ShOpc
!= ARM_AM::rrx
) {
61 printer
.markup(O
, llvm::MCInstPrinter::Markup::Immediate
)
62 << "#" << translateShiftImm(ShImm
);
66 ARMInstPrinter::ARMInstPrinter(const MCAsmInfo
&MAI
, const MCInstrInfo
&MII
,
67 const MCRegisterInfo
&MRI
)
68 : MCInstPrinter(MAI
, MII
, MRI
) {}
70 bool ARMInstPrinter::applyTargetSpecificCLOption(StringRef Opt
) {
71 if (Opt
== "reg-names-std") {
72 DefaultAltIdx
= ARM::NoRegAltName
;
75 if (Opt
== "reg-names-raw") {
76 DefaultAltIdx
= ARM::RegNamesRaw
;
82 void ARMInstPrinter::printRegName(raw_ostream
&OS
, MCRegister Reg
) {
83 markup(OS
, Markup::Register
) << getRegisterName(Reg
, DefaultAltIdx
);
86 void ARMInstPrinter::printInst(const MCInst
*MI
, uint64_t Address
,
87 StringRef Annot
, const MCSubtargetInfo
&STI
,
89 unsigned Opcode
= MI
->getOpcode();
93 const MCOperand
&Reg
= MI
->getOperand(0);
94 O
<< '\t' << "vlldm" << '\t';
95 printRegName(O
, Reg
.getReg());
100 case ARM::VLLDM_T2
: {
101 const MCOperand
&Reg
= MI
->getOperand(0);
102 O
<< '\t' << "vlldm" << '\t';
103 printRegName(O
, Reg
.getReg());
109 const MCOperand
&Reg
= MI
->getOperand(0);
110 O
<< '\t' << "vlstm" << '\t';
111 printRegName(O
, Reg
.getReg());
116 case ARM::VLSTM_T2
: {
117 const MCOperand
&Reg
= MI
->getOperand(0);
118 O
<< '\t' << "vlstm" << '\t';
119 printRegName(O
, Reg
.getReg());
124 // Check for MOVs and print canonical forms, instead.
126 // FIXME: Thumb variants?
127 const MCOperand
&Dst
= MI
->getOperand(0);
128 const MCOperand
&MO1
= MI
->getOperand(1);
129 const MCOperand
&MO2
= MI
->getOperand(2);
130 const MCOperand
&MO3
= MI
->getOperand(3);
132 O
<< '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3
.getImm()));
133 printSBitModifierOperand(MI
, 6, STI
, O
);
134 printPredicateOperand(MI
, 4, STI
, O
);
137 printRegName(O
, Dst
.getReg());
139 printRegName(O
, MO1
.getReg());
142 printRegName(O
, MO2
.getReg());
143 assert(ARM_AM::getSORegOffset(MO3
.getImm()) == 0);
144 printAnnotation(O
, Annot
);
149 // FIXME: Thumb variants?
150 const MCOperand
&Dst
= MI
->getOperand(0);
151 const MCOperand
&MO1
= MI
->getOperand(1);
152 const MCOperand
&MO2
= MI
->getOperand(2);
154 O
<< '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2
.getImm()));
155 printSBitModifierOperand(MI
, 5, STI
, O
);
156 printPredicateOperand(MI
, 3, STI
, O
);
159 printRegName(O
, Dst
.getReg());
161 printRegName(O
, MO1
.getReg());
163 if (ARM_AM::getSORegShOp(MO2
.getImm()) == ARM_AM::rrx
) {
164 printAnnotation(O
, Annot
);
169 markup(O
, Markup::Immediate
)
170 << "#" << translateShiftImm(ARM_AM::getSORegOffset(MO2
.getImm()));
171 printAnnotation(O
, Annot
);
177 case ARM::t2STMDB_UPD
:
178 if (MI
->getOperand(0).getReg() == ARM::SP
&& MI
->getNumOperands() > 5) {
179 // Should only print PUSH if there are at least two registers in the list.
181 printPredicateOperand(MI
, 2, STI
, O
);
182 if (Opcode
== ARM::t2STMDB_UPD
)
185 printRegisterList(MI
, 4, STI
, O
);
186 printAnnotation(O
, Annot
);
191 case ARM::STR_PRE_IMM
:
192 if (MI
->getOperand(2).getReg() == ARM::SP
&&
193 MI
->getOperand(3).getImm() == -4) {
195 printPredicateOperand(MI
, 4, STI
, O
);
197 printRegName(O
, MI
->getOperand(1).getReg());
199 printAnnotation(O
, Annot
);
206 case ARM::t2LDMIA_UPD
:
207 if (MI
->getOperand(0).getReg() == ARM::SP
&& MI
->getNumOperands() > 5) {
208 // Should only print POP if there are at least two registers in the list.
210 printPredicateOperand(MI
, 2, STI
, O
);
211 if (Opcode
== ARM::t2LDMIA_UPD
)
214 printRegisterList(MI
, 4, STI
, O
);
215 printAnnotation(O
, Annot
);
220 case ARM::LDR_POST_IMM
:
221 if (MI
->getOperand(2).getReg() == ARM::SP
&&
222 MI
->getOperand(4).getImm() == 4) {
224 printPredicateOperand(MI
, 5, STI
, O
);
226 printRegName(O
, MI
->getOperand(0).getReg());
228 printAnnotation(O
, Annot
);
234 case ARM::VSTMSDB_UPD
:
235 case ARM::VSTMDDB_UPD
:
236 if (MI
->getOperand(0).getReg() == ARM::SP
) {
237 O
<< '\t' << "vpush";
238 printPredicateOperand(MI
, 2, STI
, O
);
240 printRegisterList(MI
, 4, STI
, O
);
241 printAnnotation(O
, Annot
);
247 case ARM::VLDMSIA_UPD
:
248 case ARM::VLDMDIA_UPD
:
249 if (MI
->getOperand(0).getReg() == ARM::SP
) {
251 printPredicateOperand(MI
, 2, STI
, O
);
253 printRegisterList(MI
, 4, STI
, O
);
254 printAnnotation(O
, Annot
);
260 bool Writeback
= true;
261 MCRegister BaseReg
= MI
->getOperand(0).getReg();
262 for (unsigned i
= 3; i
< MI
->getNumOperands(); ++i
) {
263 if (MI
->getOperand(i
).getReg() == BaseReg
)
269 printPredicateOperand(MI
, 1, STI
, O
);
271 printRegName(O
, BaseReg
);
275 printRegisterList(MI
, 3, STI
, O
);
276 printAnnotation(O
, Annot
);
280 // Combine 2 GPRs from disassember into a GPRPair to match with instr def.
281 // ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
282 // a single GPRPair reg operand is used in the .td file to replace the two
283 // GPRs. However, when decoding them, the two GRPs cannot be automatically
284 // expressed as a GPRPair, so we have to manually merge them.
285 // FIXME: We would really like to be able to tablegen'erate this.
290 const MCRegisterClass
&MRC
= MRI
.getRegClass(ARM::GPRRegClassID
);
291 bool isStore
= Opcode
== ARM::STREXD
|| Opcode
== ARM::STLEXD
;
292 MCRegister Reg
= MI
->getOperand(isStore
? 1 : 0).getReg();
293 if (MRC
.contains(Reg
)) {
296 NewMI
.setOpcode(Opcode
);
299 NewMI
.addOperand(MI
->getOperand(0));
300 NewReg
= MCOperand::createReg(MRI
.getMatchingSuperReg(
301 Reg
, ARM::gsub_0
, &MRI
.getRegClass(ARM::GPRPairRegClassID
)));
302 NewMI
.addOperand(NewReg
);
304 // Copy the rest operands into NewMI.
305 for (unsigned i
= isStore
? 3 : 2; i
< MI
->getNumOperands(); ++i
)
306 NewMI
.addOperand(MI
->getOperand(i
));
307 printInstruction(&NewMI
, Address
, STI
, O
);
317 switch (MI
->getOperand(0).getImm()) {
319 if (!printAliasInstr(MI
, Address
, STI
, O
))
320 printInstruction(MI
, Address
, STI
, O
);
329 printAnnotation(O
, Annot
);
333 if (!printAliasInstr(MI
, Address
, STI
, O
))
334 printInstruction(MI
, Address
, STI
, O
);
336 printAnnotation(O
, Annot
);
339 void ARMInstPrinter::printOperand(const MCInst
*MI
, unsigned OpNo
,
340 const MCSubtargetInfo
&STI
, raw_ostream
&O
) {
341 const MCOperand
&Op
= MI
->getOperand(OpNo
);
343 MCRegister Reg
= Op
.getReg();
344 printRegName(O
, Reg
);
345 } else if (Op
.isImm()) {
346 markup(O
, Markup::Immediate
) << '#' << formatImm(Op
.getImm());
348 assert(Op
.isExpr() && "unknown operand kind in printOperand");
349 const MCExpr
*Expr
= Op
.getExpr();
350 switch (Expr
->getKind()) {
353 Expr
->print(O
, &MAI
);
355 case MCExpr::Constant
: {
356 // If a symbolic branch target was added as a constant expression then
357 // print that address in hex. And only print 32 unsigned bits for the
359 const MCConstantExpr
*Constant
= cast
<MCConstantExpr
>(Expr
);
360 int64_t TargetAddress
;
361 if (!Constant
->evaluateAsAbsolute(TargetAddress
)) {
363 Expr
->print(O
, &MAI
);
366 O
.write_hex(static_cast<uint32_t>(TargetAddress
));
371 // FIXME: Should we always treat this as if it is a constant literal and
372 // prefix it with '#'?
373 Expr
->print(O
, &MAI
);
379 void ARMInstPrinter::printOperand(const MCInst
*MI
, uint64_t Address
,
380 unsigned OpNum
, const MCSubtargetInfo
&STI
,
382 const MCOperand
&Op
= MI
->getOperand(OpNum
);
383 if (!Op
.isImm() || !PrintBranchImmAsAddress
|| getUseMarkup())
384 return printOperand(MI
, OpNum
, STI
, O
);
385 uint64_t Target
= ARM_MC::evaluateBranchTarget(MII
.get(MI
->getOpcode()),
386 Address
, Op
.getImm());
387 Target
&= 0xffffffff;
388 O
<< formatHex(Target
);
390 *CommentStream
<< "imm = #" << formatImm(Op
.getImm()) << '\n';
393 void ARMInstPrinter::printThumbLdrLabelOperand(const MCInst
*MI
, unsigned OpNum
,
394 const MCSubtargetInfo
&STI
,
396 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
398 MO1
.getExpr()->print(O
, &MAI
);
402 WithMarkup ScopedMarkup
= markup(O
, Markup::Memory
);
405 int32_t OffImm
= (int32_t)MO1
.getImm();
406 bool isSub
= OffImm
< 0;
408 // Special value for #-0. All others are normal.
409 if (OffImm
== INT32_MIN
)
412 markup(O
, Markup::Immediate
) << "#-" << formatImm(-OffImm
);
414 markup(O
, Markup::Immediate
) << "#" << formatImm(OffImm
);
419 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
420 // "Addressing Mode 1 - Data-processing operands" forms. This includes:
422 // REG REG 0,SH_OPC - e.g. R5, ROR R3
423 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3
424 void ARMInstPrinter::printSORegRegOperand(const MCInst
*MI
, unsigned OpNum
,
425 const MCSubtargetInfo
&STI
,
427 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
428 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
429 const MCOperand
&MO3
= MI
->getOperand(OpNum
+ 2);
431 printRegName(O
, MO1
.getReg());
433 // Print the shift opc.
434 ARM_AM::ShiftOpc ShOpc
= ARM_AM::getSORegShOp(MO3
.getImm());
435 O
<< ", " << ARM_AM::getShiftOpcStr(ShOpc
);
436 if (ShOpc
== ARM_AM::rrx
)
440 printRegName(O
, MO2
.getReg());
441 assert(ARM_AM::getSORegOffset(MO3
.getImm()) == 0);
444 void ARMInstPrinter::printSORegImmOperand(const MCInst
*MI
, unsigned OpNum
,
445 const MCSubtargetInfo
&STI
,
447 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
448 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
450 printRegName(O
, MO1
.getReg());
452 // Print the shift opc.
453 printRegImmShift(O
, ARM_AM::getSORegShOp(MO2
.getImm()),
454 ARM_AM::getSORegOffset(MO2
.getImm()), *this);
457 //===--------------------------------------------------------------------===//
458 // Addressing Mode #2
459 //===--------------------------------------------------------------------===//
461 void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst
*MI
, unsigned Op
,
462 const MCSubtargetInfo
&STI
,
464 const MCOperand
&MO1
= MI
->getOperand(Op
);
465 const MCOperand
&MO2
= MI
->getOperand(Op
+ 1);
466 const MCOperand
&MO3
= MI
->getOperand(Op
+ 2);
468 WithMarkup ScopedMarkup
= markup(O
, Markup::Memory
);
470 printRegName(O
, MO1
.getReg());
473 if (ARM_AM::getAM2Offset(MO3
.getImm())) { // Don't print +0.
475 markup(O
, Markup::Immediate
)
476 << "#" << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3
.getImm()))
477 << ARM_AM::getAM2Offset(MO3
.getImm());
484 O
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3
.getImm()));
485 printRegName(O
, MO2
.getReg());
487 printRegImmShift(O
, ARM_AM::getAM2ShiftOpc(MO3
.getImm()),
488 ARM_AM::getAM2Offset(MO3
.getImm()), *this);
492 void ARMInstPrinter::printAddrModeTBB(const MCInst
*MI
, unsigned Op
,
493 const MCSubtargetInfo
&STI
,
495 const MCOperand
&MO1
= MI
->getOperand(Op
);
496 const MCOperand
&MO2
= MI
->getOperand(Op
+ 1);
498 WithMarkup ScopedMarkup
= markup(O
, Markup::Memory
);
500 printRegName(O
, MO1
.getReg());
502 printRegName(O
, MO2
.getReg());
506 void ARMInstPrinter::printAddrModeTBH(const MCInst
*MI
, unsigned Op
,
507 const MCSubtargetInfo
&STI
,
509 const MCOperand
&MO1
= MI
->getOperand(Op
);
510 const MCOperand
&MO2
= MI
->getOperand(Op
+ 1);
511 WithMarkup ScopedMarkup
= markup(O
, Markup::Memory
);
513 printRegName(O
, MO1
.getReg());
515 printRegName(O
, MO2
.getReg());
517 markup(O
, Markup::Immediate
) << "#1";
521 void ARMInstPrinter::printAddrMode2Operand(const MCInst
*MI
, unsigned Op
,
522 const MCSubtargetInfo
&STI
,
524 const MCOperand
&MO1
= MI
->getOperand(Op
);
526 if (!MO1
.isReg()) { // FIXME: This is for CP entries, but isn't right.
527 printOperand(MI
, Op
, STI
, O
);
532 const MCOperand
&MO3
= MI
->getOperand(Op
+ 2);
533 unsigned IdxMode
= ARM_AM::getAM2IdxMode(MO3
.getImm());
534 assert(IdxMode
!= ARMII::IndexModePost
&& "Should be pre or offset index op");
537 printAM2PreOrOffsetIndexOp(MI
, Op
, STI
, O
);
540 void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst
*MI
,
542 const MCSubtargetInfo
&STI
,
544 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
545 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
548 unsigned ImmOffs
= ARM_AM::getAM2Offset(MO2
.getImm());
549 markup(O
, Markup::Immediate
)
550 << '#' << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2
.getImm()))
555 O
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2
.getImm()));
556 printRegName(O
, MO1
.getReg());
558 printRegImmShift(O
, ARM_AM::getAM2ShiftOpc(MO2
.getImm()),
559 ARM_AM::getAM2Offset(MO2
.getImm()), *this);
562 //===--------------------------------------------------------------------===//
563 // Addressing Mode #3
564 //===--------------------------------------------------------------------===//
566 void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst
*MI
, unsigned Op
,
568 bool AlwaysPrintImm0
) {
569 const MCOperand
&MO1
= MI
->getOperand(Op
);
570 const MCOperand
&MO2
= MI
->getOperand(Op
+ 1);
571 const MCOperand
&MO3
= MI
->getOperand(Op
+ 2);
573 WithMarkup ScopedMarkup
= markup(O
, Markup::Memory
);
575 printRegName(O
, MO1
.getReg());
578 O
<< ", " << getAddrOpcStr(ARM_AM::getAM3Op(MO3
.getImm()));
579 printRegName(O
, MO2
.getReg());
584 // If the op is sub we have to print the immediate even if it is 0
585 unsigned ImmOffs
= ARM_AM::getAM3Offset(MO3
.getImm());
586 ARM_AM::AddrOpc op
= ARM_AM::getAM3Op(MO3
.getImm());
588 if (AlwaysPrintImm0
|| ImmOffs
|| (op
== ARM_AM::sub
)) {
590 markup(O
, Markup::Immediate
) << "#" << ARM_AM::getAddrOpcStr(op
) << ImmOffs
;
595 template <bool AlwaysPrintImm0
>
596 void ARMInstPrinter::printAddrMode3Operand(const MCInst
*MI
, unsigned Op
,
597 const MCSubtargetInfo
&STI
,
599 const MCOperand
&MO1
= MI
->getOperand(Op
);
600 if (!MO1
.isReg()) { // For label symbolic references.
601 printOperand(MI
, Op
, STI
, O
);
605 assert(ARM_AM::getAM3IdxMode(MI
->getOperand(Op
+ 2).getImm()) !=
606 ARMII::IndexModePost
&&
607 "unexpected idxmode");
608 printAM3PreOrOffsetIndexOp(MI
, Op
, O
, AlwaysPrintImm0
);
611 void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst
*MI
,
613 const MCSubtargetInfo
&STI
,
615 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
616 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
619 O
<< getAddrOpcStr(ARM_AM::getAM3Op(MO2
.getImm()));
620 printRegName(O
, MO1
.getReg());
624 unsigned ImmOffs
= ARM_AM::getAM3Offset(MO2
.getImm());
625 markup(O
, Markup::Immediate
)
626 << '#' << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2
.getImm()))
630 void ARMInstPrinter::printPostIdxImm8Operand(const MCInst
*MI
, unsigned OpNum
,
631 const MCSubtargetInfo
&STI
,
633 const MCOperand
&MO
= MI
->getOperand(OpNum
);
634 unsigned Imm
= MO
.getImm();
635 markup(O
, Markup::Immediate
)
636 << '#' << ((Imm
& 256) ? "" : "-") << (Imm
& 0xff);
639 void ARMInstPrinter::printPostIdxRegOperand(const MCInst
*MI
, unsigned OpNum
,
640 const MCSubtargetInfo
&STI
,
642 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
643 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
645 O
<< (MO2
.getImm() ? "" : "-");
646 printRegName(O
, MO1
.getReg());
649 void ARMInstPrinter::printPostIdxImm8s4Operand(const MCInst
*MI
, unsigned OpNum
,
650 const MCSubtargetInfo
&STI
,
652 const MCOperand
&MO
= MI
->getOperand(OpNum
);
653 unsigned Imm
= MO
.getImm();
654 markup(O
, Markup::Immediate
)
655 << '#' << ((Imm
& 256) ? "" : "-") << ((Imm
& 0xff) << 2);
659 void ARMInstPrinter::printMveAddrModeRQOperand(const MCInst
*MI
, unsigned OpNum
,
660 const MCSubtargetInfo
&STI
,
662 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
663 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
665 WithMarkup ScopedMarkup
= markup(O
, Markup::Memory
);
667 printRegName(O
, MO1
.getReg());
669 printRegName(O
, MO2
.getReg());
672 printRegImmShift(O
, ARM_AM::uxtw
, shift
, *this);
677 void ARMInstPrinter::printLdStmModeOperand(const MCInst
*MI
, unsigned OpNum
,
678 const MCSubtargetInfo
&STI
,
680 ARM_AM::AMSubMode Mode
=
681 ARM_AM::getAM4SubMode(MI
->getOperand(OpNum
).getImm());
682 O
<< ARM_AM::getAMSubModeStr(Mode
);
685 template <bool AlwaysPrintImm0
>
686 void ARMInstPrinter::printAddrMode5Operand(const MCInst
*MI
, unsigned OpNum
,
687 const MCSubtargetInfo
&STI
,
689 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
690 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
692 if (!MO1
.isReg()) { // FIXME: This is for CP entries, but isn't right.
693 printOperand(MI
, OpNum
, STI
, O
);
697 WithMarkup ScopedMarkup
= markup(O
, Markup::Memory
);
699 printRegName(O
, MO1
.getReg());
701 unsigned ImmOffs
= ARM_AM::getAM5Offset(MO2
.getImm());
702 ARM_AM::AddrOpc Op
= ARM_AM::getAM5Op(MO2
.getImm());
703 if (AlwaysPrintImm0
|| ImmOffs
|| Op
== ARM_AM::sub
) {
705 markup(O
, Markup::Immediate
)
706 << "#" << ARM_AM::getAddrOpcStr(Op
) << ImmOffs
* 4;
711 template <bool AlwaysPrintImm0
>
712 void ARMInstPrinter::printAddrMode5FP16Operand(const MCInst
*MI
, unsigned OpNum
,
713 const MCSubtargetInfo
&STI
,
715 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
716 const MCOperand
&MO2
= MI
->getOperand(OpNum
+1);
718 if (!MO1
.isReg()) { // FIXME: This is for CP entries, but isn't right.
719 printOperand(MI
, OpNum
, STI
, O
);
723 WithMarkup ScopedMarkup
= markup(O
, Markup::Memory
);
725 printRegName(O
, MO1
.getReg());
727 unsigned ImmOffs
= ARM_AM::getAM5FP16Offset(MO2
.getImm());
728 unsigned Op
= ARM_AM::getAM5FP16Op(MO2
.getImm());
729 if (AlwaysPrintImm0
|| ImmOffs
|| Op
== ARM_AM::sub
) {
731 markup(O
, Markup::Immediate
)
732 << "#" << ARM_AM::getAddrOpcStr(ARM_AM::getAM5FP16Op(MO2
.getImm()))
738 void ARMInstPrinter::printAddrMode6Operand(const MCInst
*MI
, unsigned OpNum
,
739 const MCSubtargetInfo
&STI
,
741 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
742 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
744 WithMarkup ScopedMarkup
= markup(O
, Markup::Memory
);
746 printRegName(O
, MO1
.getReg());
748 O
<< ":" << (MO2
.getImm() << 3);
753 void ARMInstPrinter::printAddrMode7Operand(const MCInst
*MI
, unsigned OpNum
,
754 const MCSubtargetInfo
&STI
,
756 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
757 WithMarkup ScopedMarkup
= markup(O
, Markup::Memory
);
759 printRegName(O
, MO1
.getReg());
763 void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst
*MI
,
765 const MCSubtargetInfo
&STI
,
767 const MCOperand
&MO
= MI
->getOperand(OpNum
);
772 printRegName(O
, MO
.getReg());
776 void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst
*MI
,
778 const MCSubtargetInfo
&STI
,
780 const MCOperand
&MO
= MI
->getOperand(OpNum
);
781 uint32_t v
= ~MO
.getImm();
782 int32_t lsb
= llvm::countr_zero(v
);
783 int32_t width
= llvm::bit_width(v
) - lsb
;
784 assert(MO
.isImm() && "Not a valid bf_inv_mask_imm value!");
785 markup(O
, Markup::Immediate
) << '#' << lsb
;
787 markup(O
, Markup::Immediate
) << '#' << width
;
790 void ARMInstPrinter::printMemBOption(const MCInst
*MI
, unsigned OpNum
,
791 const MCSubtargetInfo
&STI
,
793 unsigned val
= MI
->getOperand(OpNum
).getImm();
794 O
<< ARM_MB::MemBOptToString(val
, STI
.hasFeature(ARM::HasV8Ops
));
797 void ARMInstPrinter::printInstSyncBOption(const MCInst
*MI
, unsigned OpNum
,
798 const MCSubtargetInfo
&STI
,
800 unsigned val
= MI
->getOperand(OpNum
).getImm();
801 O
<< ARM_ISB::InstSyncBOptToString(val
);
804 void ARMInstPrinter::printTraceSyncBOption(const MCInst
*MI
, unsigned OpNum
,
805 const MCSubtargetInfo
&STI
,
807 unsigned val
= MI
->getOperand(OpNum
).getImm();
808 O
<< ARM_TSB::TraceSyncBOptToString(val
);
811 void ARMInstPrinter::printShiftImmOperand(const MCInst
*MI
, unsigned OpNum
,
812 const MCSubtargetInfo
&STI
,
814 unsigned ShiftOp
= MI
->getOperand(OpNum
).getImm();
815 bool isASR
= (ShiftOp
& (1 << 5)) != 0;
816 unsigned Amt
= ShiftOp
& 0x1f;
819 markup(O
, Markup::Immediate
) << "#" << (Amt
== 0 ? 32 : Amt
);
822 markup(O
, Markup::Immediate
) << "#" << Amt
;
826 void ARMInstPrinter::printPKHLSLShiftImm(const MCInst
*MI
, unsigned OpNum
,
827 const MCSubtargetInfo
&STI
,
829 unsigned Imm
= MI
->getOperand(OpNum
).getImm();
832 assert(Imm
> 0 && Imm
< 32 && "Invalid PKH shift immediate value!");
834 markup(O
, Markup::Immediate
) << "#" << Imm
;
837 void ARMInstPrinter::printPKHASRShiftImm(const MCInst
*MI
, unsigned OpNum
,
838 const MCSubtargetInfo
&STI
,
840 unsigned Imm
= MI
->getOperand(OpNum
).getImm();
841 // A shift amount of 32 is encoded as 0.
844 assert(Imm
> 0 && Imm
<= 32 && "Invalid PKH shift immediate value!");
846 markup(O
, Markup::Immediate
) << "#" << Imm
;
849 void ARMInstPrinter::printRegisterList(const MCInst
*MI
, unsigned OpNum
,
850 const MCSubtargetInfo
&STI
,
852 if (MI
->getOpcode() != ARM::t2CLRM
&& MI
->getOpcode() != ARM::VSCCLRMS
) {
853 assert(is_sorted(drop_begin(*MI
, OpNum
),
854 [&](const MCOperand
&LHS
, const MCOperand
&RHS
) {
855 return MRI
.getEncodingValue(LHS
.getReg()) <
856 MRI
.getEncodingValue(RHS
.getReg());
861 for (unsigned i
= OpNum
, e
= MI
->getNumOperands(); i
!= e
; ++i
) {
864 printRegName(O
, MI
->getOperand(i
).getReg());
869 void ARMInstPrinter::printGPRPairOperand(const MCInst
*MI
, unsigned OpNum
,
870 const MCSubtargetInfo
&STI
,
872 MCRegister Reg
= MI
->getOperand(OpNum
).getReg();
873 printRegName(O
, MRI
.getSubReg(Reg
, ARM::gsub_0
));
875 printRegName(O
, MRI
.getSubReg(Reg
, ARM::gsub_1
));
878 void ARMInstPrinter::printSetendOperand(const MCInst
*MI
, unsigned OpNum
,
879 const MCSubtargetInfo
&STI
,
881 const MCOperand
&Op
= MI
->getOperand(OpNum
);
888 void ARMInstPrinter::printCPSIMod(const MCInst
*MI
, unsigned OpNum
,
889 const MCSubtargetInfo
&STI
, raw_ostream
&O
) {
890 const MCOperand
&Op
= MI
->getOperand(OpNum
);
891 O
<< ARM_PROC::IModToString(Op
.getImm());
894 void ARMInstPrinter::printCPSIFlag(const MCInst
*MI
, unsigned OpNum
,
895 const MCSubtargetInfo
&STI
, raw_ostream
&O
) {
896 const MCOperand
&Op
= MI
->getOperand(OpNum
);
897 unsigned IFlags
= Op
.getImm();
898 for (int i
= 2; i
>= 0; --i
)
899 if (IFlags
& (1 << i
))
900 O
<< ARM_PROC::IFlagsToString(1 << i
);
906 void ARMInstPrinter::printMSRMaskOperand(const MCInst
*MI
, unsigned OpNum
,
907 const MCSubtargetInfo
&STI
,
909 const MCOperand
&Op
= MI
->getOperand(OpNum
);
910 const FeatureBitset
&FeatureBits
= STI
.getFeatureBits();
911 if (FeatureBits
[ARM::FeatureMClass
]) {
913 unsigned SYSm
= Op
.getImm() & 0xFFF; // 12-bit SYSm
914 unsigned Opcode
= MI
->getOpcode();
916 // For writes, handle extended mask bits if the DSP extension is present.
917 if (Opcode
== ARM::t2MSR_M
&& FeatureBits
[ARM::FeatureDSP
]) {
918 auto TheReg
=ARMSysReg::lookupMClassSysRegBy12bitSYSmValue(SYSm
);
919 if (TheReg
&& TheReg
->isInRequiredFeatures({ARM::FeatureDSP
})) {
925 // Handle the basic 8-bit mask.
927 if (Opcode
== ARM::t2MSR_M
&& FeatureBits
[ARM::HasV7Ops
]) {
928 // ARMv7-M deprecates using MSR APSR without a _<bits> qualifier as an
929 // alias for MSR APSR_nzcvq.
930 auto TheReg
= ARMSysReg::lookupMClassSysRegAPSRNonDeprecated(SYSm
);
937 auto TheReg
= ARMSysReg::lookupMClassSysRegBy8bitSYSmValue(SYSm
);
948 // As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as
949 // APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.
950 unsigned SpecRegRBit
= Op
.getImm() >> 4;
951 unsigned Mask
= Op
.getImm() & 0xf;
953 if (!SpecRegRBit
&& (Mask
== 8 || Mask
== 4 || Mask
== 12)) {
957 llvm_unreachable("Unexpected mask value!");
988 void ARMInstPrinter::printBankedRegOperand(const MCInst
*MI
, unsigned OpNum
,
989 const MCSubtargetInfo
&STI
,
991 uint32_t Banked
= MI
->getOperand(OpNum
).getImm();
992 auto TheReg
= ARMBankedReg::lookupBankedRegByEncoding(Banked
);
993 assert(TheReg
&& "invalid banked register operand");
994 std::string Name
= TheReg
->Name
;
996 uint32_t isSPSR
= (Banked
& 0x20) >> 5;
998 Name
.replace(0, 4, "SPSR"); // convert 'spsr_' to 'SPSR_'
1002 void ARMInstPrinter::printPredicateOperand(const MCInst
*MI
, unsigned OpNum
,
1003 const MCSubtargetInfo
&STI
,
1005 ARMCC::CondCodes CC
= (ARMCC::CondCodes
)MI
->getOperand(OpNum
).getImm();
1006 // Handle the undefined 15 CC value here for printing so we don't abort().
1007 if ((unsigned)CC
== 15)
1009 else if (CC
!= ARMCC::AL
)
1010 O
<< ARMCondCodeToString(CC
);
1013 void ARMInstPrinter::printMandatoryRestrictedPredicateOperand(
1014 const MCInst
*MI
, unsigned OpNum
, const MCSubtargetInfo
&STI
,
1016 if ((ARMCC::CondCodes
)MI
->getOperand(OpNum
).getImm() == ARMCC::HS
)
1019 printMandatoryPredicateOperand(MI
, OpNum
, STI
, O
);
1022 void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst
*MI
,
1024 const MCSubtargetInfo
&STI
,
1026 ARMCC::CondCodes CC
= (ARMCC::CondCodes
)MI
->getOperand(OpNum
).getImm();
1027 O
<< ARMCondCodeToString(CC
);
1030 void ARMInstPrinter::printMandatoryInvertedPredicateOperand(const MCInst
*MI
,
1032 const MCSubtargetInfo
&STI
,
1034 ARMCC::CondCodes CC
= (ARMCC::CondCodes
)MI
->getOperand(OpNum
).getImm();
1035 O
<< ARMCondCodeToString(ARMCC::getOppositeCondition(CC
));
1038 void ARMInstPrinter::printSBitModifierOperand(const MCInst
*MI
, unsigned OpNum
,
1039 const MCSubtargetInfo
&STI
,
1041 if (MI
->getOperand(OpNum
).getReg()) {
1042 assert(MI
->getOperand(OpNum
).getReg() == ARM::CPSR
&&
1043 "Expect ARM CPSR register!");
1048 void ARMInstPrinter::printNoHashImmediate(const MCInst
*MI
, unsigned OpNum
,
1049 const MCSubtargetInfo
&STI
,
1051 O
<< MI
->getOperand(OpNum
).getImm();
1054 void ARMInstPrinter::printPImmediate(const MCInst
*MI
, unsigned OpNum
,
1055 const MCSubtargetInfo
&STI
,
1057 O
<< "p" << MI
->getOperand(OpNum
).getImm();
1060 void ARMInstPrinter::printCImmediate(const MCInst
*MI
, unsigned OpNum
,
1061 const MCSubtargetInfo
&STI
,
1063 O
<< "c" << MI
->getOperand(OpNum
).getImm();
1066 void ARMInstPrinter::printCoprocOptionImm(const MCInst
*MI
, unsigned OpNum
,
1067 const MCSubtargetInfo
&STI
,
1069 O
<< "{" << MI
->getOperand(OpNum
).getImm() << "}";
1072 void ARMInstPrinter::printPCLabel(const MCInst
*MI
, unsigned OpNum
,
1073 const MCSubtargetInfo
&STI
, raw_ostream
&O
) {
1074 llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
1077 template <unsigned scale
>
1078 void ARMInstPrinter::printAdrLabelOperand(const MCInst
*MI
, unsigned OpNum
,
1079 const MCSubtargetInfo
&STI
,
1081 const MCOperand
&MO
= MI
->getOperand(OpNum
);
1084 MO
.getExpr()->print(O
, &MAI
);
1088 int32_t OffImm
= (int32_t)MO
.getImm() << scale
;
1090 WithMarkup ScopedMarkup
= markup(O
, Markup::Immediate
);
1091 if (OffImm
== INT32_MIN
)
1093 else if (OffImm
< 0)
1094 O
<< "#-" << -OffImm
;
1099 void ARMInstPrinter::printThumbS4ImmOperand(const MCInst
*MI
, unsigned OpNum
,
1100 const MCSubtargetInfo
&STI
,
1102 markup(O
, Markup::Immediate
)
1103 << "#" << formatImm(MI
->getOperand(OpNum
).getImm() * 4);
1106 void ARMInstPrinter::printThumbSRImm(const MCInst
*MI
, unsigned OpNum
,
1107 const MCSubtargetInfo
&STI
,
1109 unsigned Imm
= MI
->getOperand(OpNum
).getImm();
1110 markup(O
, Markup::Immediate
) << "#" << formatImm((Imm
== 0 ? 32 : Imm
));
1113 void ARMInstPrinter::printThumbITMask(const MCInst
*MI
, unsigned OpNum
,
1114 const MCSubtargetInfo
&STI
,
1116 // (3 - the number of trailing zeros) is the number of then / else.
1117 unsigned Mask
= MI
->getOperand(OpNum
).getImm();
1118 unsigned NumTZ
= llvm::countr_zero(Mask
);
1119 assert(NumTZ
<= 3 && "Invalid IT mask!");
1120 for (unsigned Pos
= 3, e
= NumTZ
; Pos
> e
; --Pos
) {
1121 if ((Mask
>> Pos
) & 1)
1128 void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst
*MI
, unsigned Op
,
1129 const MCSubtargetInfo
&STI
,
1131 const MCOperand
&MO1
= MI
->getOperand(Op
);
1132 const MCOperand
&MO2
= MI
->getOperand(Op
+ 1);
1134 if (!MO1
.isReg()) { // FIXME: This is for CP entries, but isn't right.
1135 printOperand(MI
, Op
, STI
, O
);
1139 WithMarkup ScopedMarkup
= markup(O
, Markup::Memory
);
1141 printRegName(O
, MO1
.getReg());
1142 if (MCRegister RegNum
= MO2
.getReg()) {
1144 printRegName(O
, RegNum
);
1149 void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst
*MI
,
1151 const MCSubtargetInfo
&STI
,
1154 const MCOperand
&MO1
= MI
->getOperand(Op
);
1155 const MCOperand
&MO2
= MI
->getOperand(Op
+ 1);
1157 if (!MO1
.isReg()) { // FIXME: This is for CP entries, but isn't right.
1158 printOperand(MI
, Op
, STI
, O
);
1162 WithMarkup ScopedMarkup
= markup(O
, Markup::Memory
);
1164 printRegName(O
, MO1
.getReg());
1165 if (unsigned ImmOffs
= MO2
.getImm()) {
1167 markup(O
, Markup::Immediate
) << "#" << formatImm(ImmOffs
* Scale
);
1172 void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst
*MI
,
1174 const MCSubtargetInfo
&STI
,
1176 printThumbAddrModeImm5SOperand(MI
, Op
, STI
, O
, 1);
1179 void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst
*MI
,
1181 const MCSubtargetInfo
&STI
,
1183 printThumbAddrModeImm5SOperand(MI
, Op
, STI
, O
, 2);
1186 void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst
*MI
,
1188 const MCSubtargetInfo
&STI
,
1190 printThumbAddrModeImm5SOperand(MI
, Op
, STI
, O
, 4);
1193 void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst
*MI
, unsigned Op
,
1194 const MCSubtargetInfo
&STI
,
1196 printThumbAddrModeImm5SOperand(MI
, Op
, STI
, O
, 4);
1199 // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
1200 // register with shift forms.
1201 // REG 0 0 - e.g. R5
1202 // REG IMM, SH_OPC - e.g. R5, LSL #3
1203 void ARMInstPrinter::printT2SOOperand(const MCInst
*MI
, unsigned OpNum
,
1204 const MCSubtargetInfo
&STI
,
1206 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
1207 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
1209 MCRegister Reg
= MO1
.getReg();
1210 printRegName(O
, Reg
);
1212 // Print the shift opc.
1213 assert(MO2
.isImm() && "Not a valid t2_so_reg value!");
1214 printRegImmShift(O
, ARM_AM::getSORegShOp(MO2
.getImm()),
1215 ARM_AM::getSORegOffset(MO2
.getImm()), *this);
1218 template <bool AlwaysPrintImm0
>
1219 void ARMInstPrinter::printAddrModeImm12Operand(const MCInst
*MI
, unsigned OpNum
,
1220 const MCSubtargetInfo
&STI
,
1222 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
1223 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
1225 if (!MO1
.isReg()) { // FIXME: This is for CP entries, but isn't right.
1226 printOperand(MI
, OpNum
, STI
, O
);
1230 WithMarkup ScopedMarkup
= markup(O
, Markup::Memory
);
1232 printRegName(O
, MO1
.getReg());
1234 int32_t OffImm
= (int32_t)MO2
.getImm();
1235 bool isSub
= OffImm
< 0;
1236 // Special value for #-0. All others are normal.
1237 if (OffImm
== INT32_MIN
)
1241 markup(O
, Markup::Immediate
) << "#-" << formatImm(-OffImm
);
1242 } else if (AlwaysPrintImm0
|| OffImm
> 0) {
1244 markup(O
, Markup::Immediate
) << "#" << formatImm(OffImm
);
1249 template <bool AlwaysPrintImm0
>
1250 void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst
*MI
,
1252 const MCSubtargetInfo
&STI
,
1254 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
1255 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
1257 WithMarkup ScopedMarkup
= markup(O
, Markup::Memory
);
1259 printRegName(O
, MO1
.getReg());
1261 int32_t OffImm
= (int32_t)MO2
.getImm();
1262 bool isSub
= OffImm
< 0;
1264 if (OffImm
== INT32_MIN
)
1268 markup(O
, Markup::Immediate
) << "#-" << -OffImm
;
1269 } else if (AlwaysPrintImm0
|| OffImm
> 0) {
1271 markup(O
, Markup::Immediate
) << "#" << OffImm
;
1276 template <bool AlwaysPrintImm0
>
1277 void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst
*MI
,
1279 const MCSubtargetInfo
&STI
,
1281 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
1282 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
1284 if (!MO1
.isReg()) { // For label symbolic references.
1285 printOperand(MI
, OpNum
, STI
, O
);
1289 WithMarkup ScopedMarkup
= markup(O
, Markup::Memory
);
1291 printRegName(O
, MO1
.getReg());
1293 int32_t OffImm
= (int32_t)MO2
.getImm();
1294 bool isSub
= OffImm
< 0;
1296 assert(((OffImm
& 0x3) == 0) && "Not a valid immediate!");
1299 if (OffImm
== INT32_MIN
)
1303 markup(O
, Markup::Immediate
) << "#-" << -OffImm
;
1304 } else if (AlwaysPrintImm0
|| OffImm
> 0) {
1306 markup(O
, Markup::Immediate
) << "#" << OffImm
;
1311 void ARMInstPrinter::printT2AddrModeImm0_1020s4Operand(
1312 const MCInst
*MI
, unsigned OpNum
, const MCSubtargetInfo
&STI
,
1314 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
1315 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
1317 WithMarkup ScopedMarkup
= markup(O
, Markup::Memory
);
1319 printRegName(O
, MO1
.getReg());
1322 markup(O
, Markup::Immediate
) << "#" << formatImm(MO2
.getImm() * 4);
1327 void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(
1328 const MCInst
*MI
, unsigned OpNum
, const MCSubtargetInfo
&STI
,
1330 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
1331 int32_t OffImm
= (int32_t)MO1
.getImm();
1333 WithMarkup ScopedMarkup
= markup(O
, Markup::Immediate
);
1334 if (OffImm
== INT32_MIN
)
1336 else if (OffImm
< 0)
1337 O
<< "#-" << -OffImm
;
1342 void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(
1343 const MCInst
*MI
, unsigned OpNum
, const MCSubtargetInfo
&STI
,
1345 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
1346 int32_t OffImm
= (int32_t)MO1
.getImm();
1348 assert(((OffImm
& 0x3) == 0) && "Not a valid immediate!");
1351 WithMarkup ScopedMarkup
= markup(O
, Markup::Immediate
);
1352 if (OffImm
== INT32_MIN
)
1354 else if (OffImm
< 0)
1355 O
<< "#-" << -OffImm
;
1360 void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst
*MI
,
1362 const MCSubtargetInfo
&STI
,
1364 const MCOperand
&MO1
= MI
->getOperand(OpNum
);
1365 const MCOperand
&MO2
= MI
->getOperand(OpNum
+ 1);
1366 const MCOperand
&MO3
= MI
->getOperand(OpNum
+ 2);
1368 WithMarkup ScopedMarkup
= markup(O
, Markup::Memory
);
1370 printRegName(O
, MO1
.getReg());
1372 assert(MO2
.getReg() && "Invalid so_reg load / store address!");
1374 printRegName(O
, MO2
.getReg());
1376 unsigned ShAmt
= MO3
.getImm();
1378 assert(ShAmt
<= 3 && "Not a valid Thumb2 addressing mode!");
1380 markup(O
, Markup::Immediate
) << "#" << ShAmt
;
1385 void ARMInstPrinter::printFPImmOperand(const MCInst
*MI
, unsigned OpNum
,
1386 const MCSubtargetInfo
&STI
,
1388 const MCOperand
&MO
= MI
->getOperand(OpNum
);
1389 markup(O
, Markup::Immediate
) << '#' << ARM_AM::getFPImmFloat(MO
.getImm());
1392 void ARMInstPrinter::printVMOVModImmOperand(const MCInst
*MI
, unsigned OpNum
,
1393 const MCSubtargetInfo
&STI
,
1395 unsigned EncodedImm
= MI
->getOperand(OpNum
).getImm();
1397 uint64_t Val
= ARM_AM::decodeVMOVModImm(EncodedImm
, EltBits
);
1399 WithMarkup ScopedMarkup
= markup(O
, Markup::Immediate
);
1404 void ARMInstPrinter::printImmPlusOneOperand(const MCInst
*MI
, unsigned OpNum
,
1405 const MCSubtargetInfo
&STI
,
1407 unsigned Imm
= MI
->getOperand(OpNum
).getImm();
1408 markup(O
, Markup::Immediate
) << "#" << formatImm(Imm
+ 1);
1411 void ARMInstPrinter::printRotImmOperand(const MCInst
*MI
, unsigned OpNum
,
1412 const MCSubtargetInfo
&STI
,
1414 unsigned Imm
= MI
->getOperand(OpNum
).getImm();
1417 assert(Imm
<= 3 && "illegal ror immediate!");
1419 markup(O
, Markup::Immediate
) << "#" << 8 * Imm
;
1422 void ARMInstPrinter::printModImmOperand(const MCInst
*MI
, unsigned OpNum
,
1423 const MCSubtargetInfo
&STI
,
1425 MCOperand Op
= MI
->getOperand(OpNum
);
1427 // Support for fixups (MCFixup)
1429 return printOperand(MI
, OpNum
, STI
, O
);
1431 unsigned Bits
= Op
.getImm() & 0xFF;
1432 unsigned Rot
= (Op
.getImm() & 0xF00) >> 7;
1434 bool PrintUnsigned
= false;
1435 switch (MI
->getOpcode()) {
1437 // Movs to PC should be treated unsigned
1438 PrintUnsigned
= (MI
->getOperand(OpNum
- 1).getReg() == ARM::PC
);
1441 // Movs to special registers should be treated unsigned
1442 PrintUnsigned
= true;
1446 int32_t Rotated
= llvm::rotr
<uint32_t>(Bits
, Rot
);
1447 if (ARM_AM::getSOImmVal(Rotated
) == Op
.getImm()) {
1448 // #rot has the least possible value
1451 markup(O
, Markup::Immediate
) << static_cast<uint32_t>(Rotated
);
1453 markup(O
, Markup::Immediate
) << Rotated
;
1457 // Explicit #bits, #rot implied
1459 markup(O
, Markup::Immediate
) << Bits
;
1461 markup(O
, Markup::Immediate
) << Rot
;
1464 void ARMInstPrinter::printFBits16(const MCInst
*MI
, unsigned OpNum
,
1465 const MCSubtargetInfo
&STI
, raw_ostream
&O
) {
1466 markup(O
, Markup::Immediate
) << "#" << 16 - MI
->getOperand(OpNum
).getImm();
1469 void ARMInstPrinter::printFBits32(const MCInst
*MI
, unsigned OpNum
,
1470 const MCSubtargetInfo
&STI
, raw_ostream
&O
) {
1471 markup(O
, Markup::Immediate
) << "#" << 32 - MI
->getOperand(OpNum
).getImm();
1474 void ARMInstPrinter::printVectorIndex(const MCInst
*MI
, unsigned OpNum
,
1475 const MCSubtargetInfo
&STI
,
1477 O
<< "[" << MI
->getOperand(OpNum
).getImm() << "]";
1480 void ARMInstPrinter::printVectorListOne(const MCInst
*MI
, unsigned OpNum
,
1481 const MCSubtargetInfo
&STI
,
1484 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1488 void ARMInstPrinter::printVectorListTwo(const MCInst
*MI
, unsigned OpNum
,
1489 const MCSubtargetInfo
&STI
,
1491 MCRegister Reg
= MI
->getOperand(OpNum
).getReg();
1492 MCRegister Reg0
= MRI
.getSubReg(Reg
, ARM::dsub_0
);
1493 MCRegister Reg1
= MRI
.getSubReg(Reg
, ARM::dsub_1
);
1495 printRegName(O
, Reg0
);
1497 printRegName(O
, Reg1
);
1501 void ARMInstPrinter::printVectorListTwoSpaced(const MCInst
*MI
, unsigned OpNum
,
1502 const MCSubtargetInfo
&STI
,
1504 MCRegister Reg
= MI
->getOperand(OpNum
).getReg();
1505 MCRegister Reg0
= MRI
.getSubReg(Reg
, ARM::dsub_0
);
1506 MCRegister Reg1
= MRI
.getSubReg(Reg
, ARM::dsub_2
);
1508 printRegName(O
, Reg0
);
1510 printRegName(O
, Reg1
);
1514 void ARMInstPrinter::printVectorListThree(const MCInst
*MI
, unsigned OpNum
,
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::printVectorListFour(const MCInst
*MI
, unsigned OpNum
,
1530 const MCSubtargetInfo
&STI
,
1532 // Normally, it's not safe to use register enum values directly with
1533 // addition to get the next register, but for VFP registers, the
1534 // sort order is guaranteed because they're all of the form D<n>.
1536 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1538 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 1);
1540 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 2);
1542 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 3);
1546 void ARMInstPrinter::printVectorListOneAllLanes(const MCInst
*MI
,
1548 const MCSubtargetInfo
&STI
,
1551 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1555 void ARMInstPrinter::printVectorListTwoAllLanes(const MCInst
*MI
,
1557 const MCSubtargetInfo
&STI
,
1559 MCRegister Reg
= MI
->getOperand(OpNum
).getReg();
1560 MCRegister Reg0
= MRI
.getSubReg(Reg
, ARM::dsub_0
);
1561 MCRegister Reg1
= MRI
.getSubReg(Reg
, ARM::dsub_1
);
1563 printRegName(O
, Reg0
);
1565 printRegName(O
, Reg1
);
1569 void ARMInstPrinter::printVectorListThreeAllLanes(const MCInst
*MI
,
1571 const MCSubtargetInfo
&STI
,
1573 // Normally, it's not safe to use register enum values directly with
1574 // addition to get the next register, but for VFP registers, the
1575 // sort order is guaranteed because they're all of the form D<n>.
1577 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1579 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 1);
1581 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 2);
1585 void ARMInstPrinter::printVectorListFourAllLanes(const MCInst
*MI
,
1587 const MCSubtargetInfo
&STI
,
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>.
1593 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1595 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 1);
1597 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 2);
1599 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 3);
1603 void ARMInstPrinter::printVectorListTwoSpacedAllLanes(
1604 const MCInst
*MI
, unsigned OpNum
, const MCSubtargetInfo
&STI
,
1606 MCRegister Reg
= MI
->getOperand(OpNum
).getReg();
1607 MCRegister Reg0
= MRI
.getSubReg(Reg
, ARM::dsub_0
);
1608 MCRegister Reg1
= MRI
.getSubReg(Reg
, ARM::dsub_2
);
1610 printRegName(O
, Reg0
);
1612 printRegName(O
, Reg1
);
1616 void ARMInstPrinter::printVectorListThreeSpacedAllLanes(
1617 const MCInst
*MI
, unsigned OpNum
, const MCSubtargetInfo
&STI
,
1619 // Normally, it's not safe to use register enum values directly with
1620 // addition to get the next register, but for VFP registers, the
1621 // sort order is guaranteed because they're all of the form D<n>.
1623 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1625 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 2);
1627 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 4);
1631 void ARMInstPrinter::printVectorListFourSpacedAllLanes(
1632 const MCInst
*MI
, unsigned OpNum
, const MCSubtargetInfo
&STI
,
1634 // Normally, it's not safe to use register enum values directly with
1635 // addition to get the next register, but for VFP registers, the
1636 // sort order is guaranteed because they're all of the form D<n>.
1638 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1640 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 2);
1642 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 4);
1644 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 6);
1648 void ARMInstPrinter::printVectorListThreeSpaced(const MCInst
*MI
,
1650 const MCSubtargetInfo
&STI
,
1652 // Normally, it's not safe to use register enum values directly with
1653 // addition to get the next register, but for VFP registers, the
1654 // sort order is guaranteed because they're all of the form D<n>.
1656 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1658 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 2);
1660 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 4);
1664 void ARMInstPrinter::printVectorListFourSpaced(const MCInst
*MI
, unsigned OpNum
,
1665 const MCSubtargetInfo
&STI
,
1667 // Normally, it's not safe to use register enum values directly with
1668 // addition to get the next register, but for VFP registers, the
1669 // sort order is guaranteed because they're all of the form D<n>.
1671 printRegName(O
, MI
->getOperand(OpNum
).getReg());
1673 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 2);
1675 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 4);
1677 printRegName(O
, MI
->getOperand(OpNum
).getReg() + 6);
1681 template<unsigned NumRegs
>
1682 void ARMInstPrinter::printMVEVectorList(const MCInst
*MI
, unsigned OpNum
,
1683 const MCSubtargetInfo
&STI
,
1685 MCRegister Reg
= MI
->getOperand(OpNum
).getReg();
1686 const char *Prefix
= "{";
1687 for (unsigned i
= 0; i
< NumRegs
; i
++) {
1689 printRegName(O
, MRI
.getSubReg(Reg
, ARM::qsub_0
+ i
));
1695 template<int64_t Angle
, int64_t Remainder
>
1696 void ARMInstPrinter::printComplexRotationOp(const MCInst
*MI
, unsigned OpNo
,
1697 const MCSubtargetInfo
&STI
,
1699 unsigned Val
= MI
->getOperand(OpNo
).getImm();
1700 O
<< "#" << (Val
* Angle
) + Remainder
;
1703 void ARMInstPrinter::printVPTPredicateOperand(const MCInst
*MI
, unsigned OpNum
,
1704 const MCSubtargetInfo
&STI
,
1706 ARMVCC::VPTCodes CC
= (ARMVCC::VPTCodes
)MI
->getOperand(OpNum
).getImm();
1707 if (CC
!= ARMVCC::None
)
1708 O
<< ARMVPTPredToString(CC
);
1711 void ARMInstPrinter::printVPTMask(const MCInst
*MI
, unsigned OpNum
,
1712 const MCSubtargetInfo
&STI
,
1714 // (3 - the number of trailing zeroes) is the number of them / else.
1715 unsigned Mask
= MI
->getOperand(OpNum
).getImm();
1716 unsigned NumTZ
= llvm::countr_zero(Mask
);
1717 assert(NumTZ
<= 3 && "Invalid VPT mask!");
1718 for (unsigned Pos
= 3, e
= NumTZ
; Pos
> e
; --Pos
) {
1719 bool T
= ((Mask
>> Pos
) & 1) == 0;
1727 void ARMInstPrinter::printMveSaturateOp(const MCInst
*MI
, unsigned OpNum
,
1728 const MCSubtargetInfo
&STI
,
1730 uint32_t Val
= MI
->getOperand(OpNum
).getImm();
1731 assert(Val
<= 1 && "Invalid MVE saturate operand");
1732 O
<< "#" << (Val
== 1 ? 48 : 64);