1 //===-- ARMInstPrinter.cpp - Convert ARM MCInst to assembly syntax --------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This class prints an ARM MCInst to a .s file.
12 //===----------------------------------------------------------------------===//
14 #include "ARMInstPrinter.h"
15 #include "Utils/ARMBaseInfo.h"
16 #include "MCTargetDesc/ARMAddressingModes.h"
17 #include "MCTargetDesc/ARMBaseInfo.h"
18 #include "llvm/MC/MCAsmInfo.h"
19 #include "llvm/MC/MCExpr.h"
20 #include "llvm/MC/MCInst.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 void ARMInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
77 OS << markup("<reg:") << getRegisterName(RegNo) << markup(">");
80 void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
81 StringRef Annot, const MCSubtargetInfo &STI) {
82 unsigned Opcode = MI->getOpcode();
85 // Check for MOVs and print canonical forms, instead.
87 // FIXME: Thumb variants?
88 const MCOperand &Dst = MI->getOperand(0);
89 const MCOperand &MO1 = MI->getOperand(1);
90 const MCOperand &MO2 = MI->getOperand(2);
91 const MCOperand &MO3 = MI->getOperand(3);
93 O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
94 printSBitModifierOperand(MI, 6, STI, O);
95 printPredicateOperand(MI, 4, STI, O);
98 printRegName(O, Dst.getReg());
100 printRegName(O, MO1.getReg());
103 printRegName(O, MO2.getReg());
104 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
105 printAnnotation(O, Annot);
110 // FIXME: Thumb variants?
111 const MCOperand &Dst = MI->getOperand(0);
112 const MCOperand &MO1 = MI->getOperand(1);
113 const MCOperand &MO2 = MI->getOperand(2);
115 O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()));
116 printSBitModifierOperand(MI, 5, STI, O);
117 printPredicateOperand(MI, 3, STI, O);
120 printRegName(O, Dst.getReg());
122 printRegName(O, MO1.getReg());
124 if (ARM_AM::getSORegShOp(MO2.getImm()) == ARM_AM::rrx) {
125 printAnnotation(O, Annot);
129 O << ", " << markup("<imm:") << "#"
130 << translateShiftImm(ARM_AM::getSORegOffset(MO2.getImm())) << markup(">");
131 printAnnotation(O, Annot);
137 case ARM::t2STMDB_UPD:
138 if (MI->getOperand(0).getReg() == ARM::SP && MI->getNumOperands() > 5) {
139 // Should only print PUSH if there are at least two registers in the list.
141 printPredicateOperand(MI, 2, STI, O);
142 if (Opcode == ARM::t2STMDB_UPD)
145 printRegisterList(MI, 4, STI, O);
146 printAnnotation(O, Annot);
151 case ARM::STR_PRE_IMM:
152 if (MI->getOperand(2).getReg() == ARM::SP &&
153 MI->getOperand(3).getImm() == -4) {
155 printPredicateOperand(MI, 4, STI, O);
157 printRegName(O, MI->getOperand(1).getReg());
159 printAnnotation(O, Annot);
166 case ARM::t2LDMIA_UPD:
167 if (MI->getOperand(0).getReg() == ARM::SP && MI->getNumOperands() > 5) {
168 // Should only print POP if there are at least two registers in the list.
170 printPredicateOperand(MI, 2, STI, O);
171 if (Opcode == ARM::t2LDMIA_UPD)
174 printRegisterList(MI, 4, STI, O);
175 printAnnotation(O, Annot);
180 case ARM::LDR_POST_IMM:
181 if (MI->getOperand(2).getReg() == ARM::SP &&
182 MI->getOperand(4).getImm() == 4) {
184 printPredicateOperand(MI, 5, STI, O);
186 printRegName(O, MI->getOperand(0).getReg());
188 printAnnotation(O, Annot);
194 case ARM::VSTMSDB_UPD:
195 case ARM::VSTMDDB_UPD:
196 if (MI->getOperand(0).getReg() == ARM::SP) {
197 O << '\t' << "vpush";
198 printPredicateOperand(MI, 2, STI, O);
200 printRegisterList(MI, 4, STI, O);
201 printAnnotation(O, Annot);
207 case ARM::VLDMSIA_UPD:
208 case ARM::VLDMDIA_UPD:
209 if (MI->getOperand(0).getReg() == ARM::SP) {
211 printPredicateOperand(MI, 2, STI, O);
213 printRegisterList(MI, 4, STI, O);
214 printAnnotation(O, Annot);
220 bool Writeback = true;
221 unsigned BaseReg = MI->getOperand(0).getReg();
222 for (unsigned i = 3; i < MI->getNumOperands(); ++i) {
223 if (MI->getOperand(i).getReg() == BaseReg)
229 printPredicateOperand(MI, 1, STI, O);
231 printRegName(O, BaseReg);
235 printRegisterList(MI, 3, STI, O);
236 printAnnotation(O, Annot);
240 // Combine 2 GPRs from disassember into a GPRPair to match with instr def.
241 // ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
242 // a single GPRPair reg operand is used in the .td file to replace the two
243 // GPRs. However, when decoding them, the two GRPs cannot be automatically
244 // expressed as a GPRPair, so we have to manually merge them.
245 // FIXME: We would really like to be able to tablegen'erate this.
250 const MCRegisterClass &MRC = MRI.getRegClass(ARM::GPRRegClassID);
251 bool isStore = Opcode == ARM::STREXD || Opcode == ARM::STLEXD;
252 unsigned Reg = MI->getOperand(isStore ? 1 : 0).getReg();
253 if (MRC.contains(Reg)) {
256 NewMI.setOpcode(Opcode);
259 NewMI.addOperand(MI->getOperand(0));
260 NewReg = MCOperand::createReg(MRI.getMatchingSuperReg(
261 Reg, ARM::gsub_0, &MRI.getRegClass(ARM::GPRPairRegClassID)));
262 NewMI.addOperand(NewReg);
264 // Copy the rest operands into NewMI.
265 for (unsigned i = isStore ? 3 : 2; i < MI->getNumOperands(); ++i)
266 NewMI.addOperand(MI->getOperand(i));
267 printInstruction(&NewMI, STI, O);
278 if (!printAliasInstr(MI, STI, O))
279 printInstruction(MI, STI, O);
281 printAnnotation(O, Annot);
284 void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
285 const MCSubtargetInfo &STI, raw_ostream &O) {
286 const MCOperand &Op = MI->getOperand(OpNo);
288 unsigned Reg = Op.getReg();
289 printRegName(O, Reg);
290 } else if (Op.isImm()) {
291 O << markup("<imm:") << '#' << formatImm(Op.getImm()) << markup(">");
293 assert(Op.isExpr() && "unknown operand kind in printOperand");
294 const MCExpr *Expr = Op.getExpr();
295 switch (Expr->getKind()) {
298 Expr->print(O, &MAI);
300 case MCExpr::Constant: {
301 // If a symbolic branch target was added as a constant expression then
302 // print that address in hex. And only print 32 unsigned bits for the
304 const MCConstantExpr *Constant = cast<MCConstantExpr>(Expr);
305 int64_t TargetAddress;
306 if (!Constant->evaluateAsAbsolute(TargetAddress)) {
308 Expr->print(O, &MAI);
311 O.write_hex(static_cast<uint32_t>(TargetAddress));
316 // FIXME: Should we always treat this as if it is a constant literal and
317 // prefix it with '#'?
318 Expr->print(O, &MAI);
324 void ARMInstPrinter::printThumbLdrLabelOperand(const MCInst *MI, unsigned OpNum,
325 const MCSubtargetInfo &STI,
327 const MCOperand &MO1 = MI->getOperand(OpNum);
329 MO1.getExpr()->print(O, &MAI);
333 O << markup("<mem:") << "[pc, ";
335 int32_t OffImm = (int32_t)MO1.getImm();
336 bool isSub = OffImm < 0;
338 // Special value for #-0. All others are normal.
339 if (OffImm == INT32_MIN)
342 O << markup("<imm:") << "#-" << formatImm(-OffImm) << markup(">");
344 O << markup("<imm:") << "#" << formatImm(OffImm) << markup(">");
346 O << "]" << markup(">");
349 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
350 // "Addressing Mode 1 - Data-processing operands" forms. This includes:
352 // REG REG 0,SH_OPC - e.g. R5, ROR R3
353 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3
354 void ARMInstPrinter::printSORegRegOperand(const MCInst *MI, unsigned OpNum,
355 const MCSubtargetInfo &STI,
357 const MCOperand &MO1 = MI->getOperand(OpNum);
358 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
359 const MCOperand &MO3 = MI->getOperand(OpNum + 2);
361 printRegName(O, MO1.getReg());
363 // Print the shift opc.
364 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
365 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
366 if (ShOpc == ARM_AM::rrx)
370 printRegName(O, MO2.getReg());
371 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
374 void ARMInstPrinter::printSORegImmOperand(const MCInst *MI, unsigned OpNum,
375 const MCSubtargetInfo &STI,
377 const MCOperand &MO1 = MI->getOperand(OpNum);
378 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
380 printRegName(O, MO1.getReg());
382 // Print the shift opc.
383 printRegImmShift(O, ARM_AM::getSORegShOp(MO2.getImm()),
384 ARM_AM::getSORegOffset(MO2.getImm()), UseMarkup);
387 //===--------------------------------------------------------------------===//
388 // Addressing Mode #2
389 //===--------------------------------------------------------------------===//
391 void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
392 const MCSubtargetInfo &STI,
394 const MCOperand &MO1 = MI->getOperand(Op);
395 const MCOperand &MO2 = MI->getOperand(Op + 1);
396 const MCOperand &MO3 = MI->getOperand(Op + 2);
398 O << markup("<mem:") << "[";
399 printRegName(O, MO1.getReg());
402 if (ARM_AM::getAM2Offset(MO3.getImm())) { // Don't print +0.
403 O << ", " << markup("<imm:") << "#"
404 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
405 << ARM_AM::getAM2Offset(MO3.getImm()) << markup(">");
407 O << "]" << markup(">");
412 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()));
413 printRegName(O, MO2.getReg());
415 printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO3.getImm()),
416 ARM_AM::getAM2Offset(MO3.getImm()), UseMarkup);
417 O << "]" << markup(">");
420 void ARMInstPrinter::printAddrModeTBB(const MCInst *MI, unsigned Op,
421 const MCSubtargetInfo &STI,
423 const MCOperand &MO1 = MI->getOperand(Op);
424 const MCOperand &MO2 = MI->getOperand(Op + 1);
425 O << markup("<mem:") << "[";
426 printRegName(O, MO1.getReg());
428 printRegName(O, MO2.getReg());
429 O << "]" << markup(">");
432 void ARMInstPrinter::printAddrModeTBH(const MCInst *MI, unsigned Op,
433 const MCSubtargetInfo &STI,
435 const MCOperand &MO1 = MI->getOperand(Op);
436 const MCOperand &MO2 = MI->getOperand(Op + 1);
437 O << markup("<mem:") << "[";
438 printRegName(O, MO1.getReg());
440 printRegName(O, MO2.getReg());
441 O << ", lsl " << markup("<imm:") << "#1" << markup(">") << "]" << markup(">");
444 void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
445 const MCSubtargetInfo &STI,
447 const MCOperand &MO1 = MI->getOperand(Op);
449 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
450 printOperand(MI, Op, STI, O);
455 const MCOperand &MO3 = MI->getOperand(Op + 2);
456 unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm());
457 assert(IdxMode != ARMII::IndexModePost && "Should be pre or offset index op");
460 printAM2PreOrOffsetIndexOp(MI, Op, STI, O);
463 void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
465 const MCSubtargetInfo &STI,
467 const MCOperand &MO1 = MI->getOperand(OpNum);
468 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
471 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
472 O << markup("<imm:") << '#'
473 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) << ImmOffs
478 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()));
479 printRegName(O, MO1.getReg());
481 printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO2.getImm()),
482 ARM_AM::getAM2Offset(MO2.getImm()), UseMarkup);
485 //===--------------------------------------------------------------------===//
486 // Addressing Mode #3
487 //===--------------------------------------------------------------------===//
489 void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
491 bool AlwaysPrintImm0) {
492 const MCOperand &MO1 = MI->getOperand(Op);
493 const MCOperand &MO2 = MI->getOperand(Op + 1);
494 const MCOperand &MO3 = MI->getOperand(Op + 2);
496 O << markup("<mem:") << '[';
497 printRegName(O, MO1.getReg());
500 O << ", " << getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()));
501 printRegName(O, MO2.getReg());
502 O << ']' << markup(">");
506 // If the op is sub we have to print the immediate even if it is 0
507 unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm());
508 ARM_AM::AddrOpc op = ARM_AM::getAM3Op(MO3.getImm());
510 if (AlwaysPrintImm0 || ImmOffs || (op == ARM_AM::sub)) {
511 O << ", " << markup("<imm:") << "#" << ARM_AM::getAddrOpcStr(op) << ImmOffs
514 O << ']' << markup(">");
517 template <bool AlwaysPrintImm0>
518 void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op,
519 const MCSubtargetInfo &STI,
521 const MCOperand &MO1 = MI->getOperand(Op);
522 if (!MO1.isReg()) { // For label symbolic references.
523 printOperand(MI, Op, STI, O);
527 assert(ARM_AM::getAM3IdxMode(MI->getOperand(Op + 2).getImm()) !=
528 ARMII::IndexModePost &&
529 "unexpected idxmode");
530 printAM3PreOrOffsetIndexOp(MI, Op, O, AlwaysPrintImm0);
533 void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
535 const MCSubtargetInfo &STI,
537 const MCOperand &MO1 = MI->getOperand(OpNum);
538 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
541 O << getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()));
542 printRegName(O, MO1.getReg());
546 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
547 O << markup("<imm:") << '#'
548 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm())) << ImmOffs
552 void ARMInstPrinter::printPostIdxImm8Operand(const MCInst *MI, unsigned OpNum,
553 const MCSubtargetInfo &STI,
555 const MCOperand &MO = MI->getOperand(OpNum);
556 unsigned Imm = MO.getImm();
557 O << markup("<imm:") << '#' << ((Imm & 256) ? "" : "-") << (Imm & 0xff)
561 void ARMInstPrinter::printPostIdxRegOperand(const MCInst *MI, unsigned OpNum,
562 const MCSubtargetInfo &STI,
564 const MCOperand &MO1 = MI->getOperand(OpNum);
565 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
567 O << (MO2.getImm() ? "" : "-");
568 printRegName(O, MO1.getReg());
571 void ARMInstPrinter::printPostIdxImm8s4Operand(const MCInst *MI, unsigned OpNum,
572 const MCSubtargetInfo &STI,
574 const MCOperand &MO = MI->getOperand(OpNum);
575 unsigned Imm = MO.getImm();
576 O << markup("<imm:") << '#' << ((Imm & 256) ? "" : "-") << ((Imm & 0xff) << 2)
580 void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,
581 const MCSubtargetInfo &STI,
583 ARM_AM::AMSubMode Mode =
584 ARM_AM::getAM4SubMode(MI->getOperand(OpNum).getImm());
585 O << ARM_AM::getAMSubModeStr(Mode);
588 template <bool AlwaysPrintImm0>
589 void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
590 const MCSubtargetInfo &STI,
592 const MCOperand &MO1 = MI->getOperand(OpNum);
593 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
595 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
596 printOperand(MI, OpNum, STI, O);
600 O << markup("<mem:") << "[";
601 printRegName(O, MO1.getReg());
603 unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm());
604 ARM_AM::AddrOpc Op = ARM_AM::getAM5Op(MO2.getImm());
605 if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM::sub) {
606 O << ", " << markup("<imm:") << "#" << ARM_AM::getAddrOpcStr(Op)
607 << ImmOffs * 4 << markup(">");
609 O << "]" << markup(">");
612 template <bool AlwaysPrintImm0>
613 void ARMInstPrinter::printAddrMode5FP16Operand(const MCInst *MI, unsigned OpNum,
614 const MCSubtargetInfo &STI,
616 const MCOperand &MO1 = MI->getOperand(OpNum);
617 const MCOperand &MO2 = MI->getOperand(OpNum+1);
619 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
620 printOperand(MI, OpNum, STI, O);
624 O << markup("<mem:") << "[";
625 printRegName(O, MO1.getReg());
627 unsigned ImmOffs = ARM_AM::getAM5FP16Offset(MO2.getImm());
628 unsigned Op = ARM_AM::getAM5FP16Op(MO2.getImm());
629 if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM::sub) {
633 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5FP16Op(MO2.getImm()))
637 O << "]" << markup(">");
640 void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
641 const MCSubtargetInfo &STI,
643 const MCOperand &MO1 = MI->getOperand(OpNum);
644 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
646 O << markup("<mem:") << "[";
647 printRegName(O, MO1.getReg());
649 O << ":" << (MO2.getImm() << 3);
651 O << "]" << markup(">");
654 void ARMInstPrinter::printAddrMode7Operand(const MCInst *MI, unsigned OpNum,
655 const MCSubtargetInfo &STI,
657 const MCOperand &MO1 = MI->getOperand(OpNum);
658 O << markup("<mem:") << "[";
659 printRegName(O, MO1.getReg());
660 O << "]" << markup(">");
663 void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
665 const MCSubtargetInfo &STI,
667 const MCOperand &MO = MI->getOperand(OpNum);
668 if (MO.getReg() == 0)
672 printRegName(O, MO.getReg());
676 void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
678 const MCSubtargetInfo &STI,
680 const MCOperand &MO = MI->getOperand(OpNum);
681 uint32_t v = ~MO.getImm();
682 int32_t lsb = countTrailingZeros(v);
683 int32_t width = (32 - countLeadingZeros(v)) - lsb;
684 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
685 O << markup("<imm:") << '#' << lsb << markup(">") << ", " << markup("<imm:")
686 << '#' << width << markup(">");
689 void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
690 const MCSubtargetInfo &STI,
692 unsigned val = MI->getOperand(OpNum).getImm();
693 O << ARM_MB::MemBOptToString(val, STI.getFeatureBits()[ARM::HasV8Ops]);
696 void ARMInstPrinter::printInstSyncBOption(const MCInst *MI, unsigned OpNum,
697 const MCSubtargetInfo &STI,
699 unsigned val = MI->getOperand(OpNum).getImm();
700 O << ARM_ISB::InstSyncBOptToString(val);
703 void ARMInstPrinter::printTraceSyncBOption(const MCInst *MI, unsigned OpNum,
704 const MCSubtargetInfo &STI,
706 unsigned val = MI->getOperand(OpNum).getImm();
707 O << ARM_TSB::TraceSyncBOptToString(val);
710 void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
711 const MCSubtargetInfo &STI,
713 unsigned ShiftOp = MI->getOperand(OpNum).getImm();
714 bool isASR = (ShiftOp & (1 << 5)) != 0;
715 unsigned Amt = ShiftOp & 0x1f;
717 O << ", asr " << markup("<imm:") << "#" << (Amt == 0 ? 32 : Amt)
720 O << ", lsl " << markup("<imm:") << "#" << Amt << markup(">");
724 void ARMInstPrinter::printPKHLSLShiftImm(const MCInst *MI, unsigned OpNum,
725 const MCSubtargetInfo &STI,
727 unsigned Imm = MI->getOperand(OpNum).getImm();
730 assert(Imm > 0 && Imm < 32 && "Invalid PKH shift immediate value!");
731 O << ", lsl " << markup("<imm:") << "#" << Imm << markup(">");
734 void ARMInstPrinter::printPKHASRShiftImm(const MCInst *MI, unsigned OpNum,
735 const MCSubtargetInfo &STI,
737 unsigned Imm = MI->getOperand(OpNum).getImm();
738 // A shift amount of 32 is encoded as 0.
741 assert(Imm > 0 && Imm <= 32 && "Invalid PKH shift immediate value!");
742 O << ", asr " << markup("<imm:") << "#" << Imm << markup(">");
745 void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
746 const MCSubtargetInfo &STI,
748 assert(std::is_sorted(MI->begin() + OpNum, MI->end(),
749 [&](const MCOperand &LHS, const MCOperand &RHS) {
750 return MRI.getEncodingValue(LHS.getReg()) <
751 MRI.getEncodingValue(RHS.getReg());
755 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
758 printRegName(O, MI->getOperand(i).getReg());
763 void ARMInstPrinter::printGPRPairOperand(const MCInst *MI, unsigned OpNum,
764 const MCSubtargetInfo &STI,
766 unsigned Reg = MI->getOperand(OpNum).getReg();
767 printRegName(O, MRI.getSubReg(Reg, ARM::gsub_0));
769 printRegName(O, MRI.getSubReg(Reg, ARM::gsub_1));
772 void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum,
773 const MCSubtargetInfo &STI,
775 const MCOperand &Op = MI->getOperand(OpNum);
782 void ARMInstPrinter::printCPSIMod(const MCInst *MI, unsigned OpNum,
783 const MCSubtargetInfo &STI, raw_ostream &O) {
784 const MCOperand &Op = MI->getOperand(OpNum);
785 O << ARM_PROC::IModToString(Op.getImm());
788 void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum,
789 const MCSubtargetInfo &STI, raw_ostream &O) {
790 const MCOperand &Op = MI->getOperand(OpNum);
791 unsigned IFlags = Op.getImm();
792 for (int i = 2; i >= 0; --i)
793 if (IFlags & (1 << i))
794 O << ARM_PROC::IFlagsToString(1 << i);
800 void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
801 const MCSubtargetInfo &STI,
803 const MCOperand &Op = MI->getOperand(OpNum);
804 const FeatureBitset &FeatureBits = STI.getFeatureBits();
805 if (FeatureBits[ARM::FeatureMClass]) {
807 unsigned SYSm = Op.getImm() & 0xFFF; // 12-bit SYSm
808 unsigned Opcode = MI->getOpcode();
810 // For writes, handle extended mask bits if the DSP extension is present.
811 if (Opcode == ARM::t2MSR_M && FeatureBits[ARM::FeatureDSP]) {
812 auto TheReg =ARMSysReg::lookupMClassSysRegBy12bitSYSmValue(SYSm);
813 if (TheReg && TheReg->isInRequiredFeatures({ARM::FeatureDSP})) {
819 // Handle the basic 8-bit mask.
821 if (Opcode == ARM::t2MSR_M && FeatureBits [ARM::HasV7Ops]) {
822 // ARMv7-M deprecates using MSR APSR without a _<bits> qualifier as an
823 // alias for MSR APSR_nzcvq.
824 auto TheReg = ARMSysReg::lookupMClassSysRegAPSRNonDeprecated(SYSm);
831 auto TheReg = ARMSysReg::lookupMClassSysRegBy8bitSYSmValue(SYSm);
842 // As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as
843 // APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.
844 unsigned SpecRegRBit = Op.getImm() >> 4;
845 unsigned Mask = Op.getImm() & 0xf;
847 if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
851 llvm_unreachable("Unexpected mask value!");
882 void ARMInstPrinter::printBankedRegOperand(const MCInst *MI, unsigned OpNum,
883 const MCSubtargetInfo &STI,
885 uint32_t Banked = MI->getOperand(OpNum).getImm();
886 auto TheReg = ARMBankedReg::lookupBankedRegByEncoding(Banked);
887 assert(TheReg && "invalid banked register operand");
888 std::string Name = TheReg->Name;
890 uint32_t isSPSR = (Banked & 0x20) >> 5;
892 Name.replace(0, 4, "SPSR"); // convert 'spsr_' to 'SPSR_'
896 void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
897 const MCSubtargetInfo &STI,
899 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
900 // Handle the undefined 15 CC value here for printing so we don't abort().
901 if ((unsigned)CC == 15)
903 else if (CC != ARMCC::AL)
904 O << ARMCondCodeToString(CC);
907 void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
909 const MCSubtargetInfo &STI,
911 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
912 O << ARMCondCodeToString(CC);
915 void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
916 const MCSubtargetInfo &STI,
918 if (MI->getOperand(OpNum).getReg()) {
919 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
920 "Expect ARM CPSR register!");
925 void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
926 const MCSubtargetInfo &STI,
928 O << MI->getOperand(OpNum).getImm();
931 void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum,
932 const MCSubtargetInfo &STI,
934 O << "p" << MI->getOperand(OpNum).getImm();
937 void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum,
938 const MCSubtargetInfo &STI,
940 O << "c" << MI->getOperand(OpNum).getImm();
943 void ARMInstPrinter::printCoprocOptionImm(const MCInst *MI, unsigned OpNum,
944 const MCSubtargetInfo &STI,
946 O << "{" << MI->getOperand(OpNum).getImm() << "}";
949 void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
950 const MCSubtargetInfo &STI, raw_ostream &O) {
951 llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
954 template <unsigned scale>
955 void ARMInstPrinter::printAdrLabelOperand(const MCInst *MI, unsigned OpNum,
956 const MCSubtargetInfo &STI,
958 const MCOperand &MO = MI->getOperand(OpNum);
961 MO.getExpr()->print(O, &MAI);
965 int32_t OffImm = (int32_t)MO.getImm() << scale;
967 O << markup("<imm:");
968 if (OffImm == INT32_MIN)
971 O << "#-" << -OffImm;
977 void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
978 const MCSubtargetInfo &STI,
980 O << markup("<imm:") << "#" << formatImm(MI->getOperand(OpNum).getImm() * 4)
984 void ARMInstPrinter::printThumbSRImm(const MCInst *MI, unsigned OpNum,
985 const MCSubtargetInfo &STI,
987 unsigned Imm = MI->getOperand(OpNum).getImm();
988 O << markup("<imm:") << "#" << formatImm((Imm == 0 ? 32 : Imm))
992 void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
993 const MCSubtargetInfo &STI,
995 // (3 - the number of trailing zeros) is the number of then / else.
996 unsigned Mask = MI->getOperand(OpNum).getImm();
997 unsigned Firstcond = MI->getOperand(OpNum - 1).getImm();
998 unsigned CondBit0 = Firstcond & 1;
999 unsigned NumTZ = countTrailingZeros(Mask);
1000 assert(NumTZ <= 3 && "Invalid IT mask!");
1001 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
1002 bool T = ((Mask >> Pos) & 1) == CondBit0;
1010 void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
1011 const MCSubtargetInfo &STI,
1013 const MCOperand &MO1 = MI->getOperand(Op);
1014 const MCOperand &MO2 = MI->getOperand(Op + 1);
1016 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
1017 printOperand(MI, Op, STI, O);
1021 O << markup("<mem:") << "[";
1022 printRegName(O, MO1.getReg());
1023 if (unsigned RegNum = MO2.getReg()) {
1025 printRegName(O, RegNum);
1027 O << "]" << markup(">");
1030 void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI,
1032 const MCSubtargetInfo &STI,
1035 const MCOperand &MO1 = MI->getOperand(Op);
1036 const MCOperand &MO2 = MI->getOperand(Op + 1);
1038 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
1039 printOperand(MI, Op, STI, O);
1043 O << markup("<mem:") << "[";
1044 printRegName(O, MO1.getReg());
1045 if (unsigned ImmOffs = MO2.getImm()) {
1046 O << ", " << markup("<imm:") << "#" << formatImm(ImmOffs * Scale)
1049 O << "]" << markup(">");
1052 void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI,
1054 const MCSubtargetInfo &STI,
1056 printThumbAddrModeImm5SOperand(MI, Op, STI, O, 1);
1059 void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI,
1061 const MCSubtargetInfo &STI,
1063 printThumbAddrModeImm5SOperand(MI, Op, STI, O, 2);
1066 void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI,
1068 const MCSubtargetInfo &STI,
1070 printThumbAddrModeImm5SOperand(MI, Op, STI, O, 4);
1073 void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
1074 const MCSubtargetInfo &STI,
1076 printThumbAddrModeImm5SOperand(MI, Op, STI, O, 4);
1079 // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
1080 // register with shift forms.
1081 // REG 0 0 - e.g. R5
1082 // REG IMM, SH_OPC - e.g. R5, LSL #3
1083 void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
1084 const MCSubtargetInfo &STI,
1086 const MCOperand &MO1 = MI->getOperand(OpNum);
1087 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1089 unsigned Reg = MO1.getReg();
1090 printRegName(O, Reg);
1092 // Print the shift opc.
1093 assert(MO2.isImm() && "Not a valid t2_so_reg value!");
1094 printRegImmShift(O, ARM_AM::getSORegShOp(MO2.getImm()),
1095 ARM_AM::getSORegOffset(MO2.getImm()), UseMarkup);
1098 template <bool AlwaysPrintImm0>
1099 void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
1100 const MCSubtargetInfo &STI,
1102 const MCOperand &MO1 = MI->getOperand(OpNum);
1103 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1105 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
1106 printOperand(MI, OpNum, STI, O);
1110 O << markup("<mem:") << "[";
1111 printRegName(O, MO1.getReg());
1113 int32_t OffImm = (int32_t)MO2.getImm();
1114 bool isSub = OffImm < 0;
1115 // Special value for #-0. All others are normal.
1116 if (OffImm == INT32_MIN)
1119 O << ", " << markup("<imm:") << "#-" << formatImm(-OffImm) << markup(">");
1120 } else if (AlwaysPrintImm0 || OffImm > 0) {
1121 O << ", " << markup("<imm:") << "#" << formatImm(OffImm) << markup(">");
1123 O << "]" << markup(">");
1126 template <bool AlwaysPrintImm0>
1127 void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
1129 const MCSubtargetInfo &STI,
1131 const MCOperand &MO1 = MI->getOperand(OpNum);
1132 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1134 O << markup("<mem:") << "[";
1135 printRegName(O, MO1.getReg());
1137 int32_t OffImm = (int32_t)MO2.getImm();
1138 bool isSub = OffImm < 0;
1140 if (OffImm == INT32_MIN)
1143 O << ", " << markup("<imm:") << "#-" << -OffImm << markup(">");
1144 } else if (AlwaysPrintImm0 || OffImm > 0) {
1145 O << ", " << markup("<imm:") << "#" << OffImm << markup(">");
1147 O << "]" << markup(">");
1150 template <bool AlwaysPrintImm0>
1151 void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
1153 const MCSubtargetInfo &STI,
1155 const MCOperand &MO1 = MI->getOperand(OpNum);
1156 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1158 if (!MO1.isReg()) { // For label symbolic references.
1159 printOperand(MI, OpNum, STI, O);
1163 O << markup("<mem:") << "[";
1164 printRegName(O, MO1.getReg());
1166 int32_t OffImm = (int32_t)MO2.getImm();
1167 bool isSub = OffImm < 0;
1169 assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
1172 if (OffImm == INT32_MIN)
1175 O << ", " << markup("<imm:") << "#-" << -OffImm << markup(">");
1176 } else if (AlwaysPrintImm0 || OffImm > 0) {
1177 O << ", " << markup("<imm:") << "#" << OffImm << markup(">");
1179 O << "]" << markup(">");
1182 void ARMInstPrinter::printT2AddrModeImm0_1020s4Operand(
1183 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1185 const MCOperand &MO1 = MI->getOperand(OpNum);
1186 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1188 O << markup("<mem:") << "[";
1189 printRegName(O, MO1.getReg());
1191 O << ", " << markup("<imm:") << "#" << formatImm(MO2.getImm() * 4)
1194 O << "]" << markup(">");
1197 void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(
1198 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1200 const MCOperand &MO1 = MI->getOperand(OpNum);
1201 int32_t OffImm = (int32_t)MO1.getImm();
1202 O << ", " << markup("<imm:");
1203 if (OffImm == INT32_MIN)
1205 else if (OffImm < 0)
1206 O << "#-" << -OffImm;
1212 void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(
1213 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1215 const MCOperand &MO1 = MI->getOperand(OpNum);
1216 int32_t OffImm = (int32_t)MO1.getImm();
1218 assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
1220 O << ", " << markup("<imm:");
1221 if (OffImm == INT32_MIN)
1223 else if (OffImm < 0)
1224 O << "#-" << -OffImm;
1230 void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
1232 const MCSubtargetInfo &STI,
1234 const MCOperand &MO1 = MI->getOperand(OpNum);
1235 const MCOperand &MO2 = MI->getOperand(OpNum + 1);
1236 const MCOperand &MO3 = MI->getOperand(OpNum + 2);
1238 O << markup("<mem:") << "[";
1239 printRegName(O, MO1.getReg());
1241 assert(MO2.getReg() && "Invalid so_reg load / store address!");
1243 printRegName(O, MO2.getReg());
1245 unsigned ShAmt = MO3.getImm();
1247 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
1248 O << ", lsl " << markup("<imm:") << "#" << ShAmt << markup(">");
1250 O << "]" << markup(">");
1253 void ARMInstPrinter::printFPImmOperand(const MCInst *MI, unsigned OpNum,
1254 const MCSubtargetInfo &STI,
1256 const MCOperand &MO = MI->getOperand(OpNum);
1257 O << markup("<imm:") << '#' << ARM_AM::getFPImmFloat(MO.getImm())
1261 void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
1262 const MCSubtargetInfo &STI,
1264 unsigned EncodedImm = MI->getOperand(OpNum).getImm();
1266 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
1267 O << markup("<imm:") << "#0x";
1272 void ARMInstPrinter::printImmPlusOneOperand(const MCInst *MI, unsigned OpNum,
1273 const MCSubtargetInfo &STI,
1275 unsigned Imm = MI->getOperand(OpNum).getImm();
1276 O << markup("<imm:") << "#" << formatImm(Imm + 1) << markup(">");
1279 void ARMInstPrinter::printRotImmOperand(const MCInst *MI, unsigned OpNum,
1280 const MCSubtargetInfo &STI,
1282 unsigned Imm = MI->getOperand(OpNum).getImm();
1285 assert(Imm <= 3 && "illegal ror immediate!");
1286 O << ", ror " << markup("<imm:") << "#" << 8 * Imm << markup(">");
1289 void ARMInstPrinter::printModImmOperand(const MCInst *MI, unsigned OpNum,
1290 const MCSubtargetInfo &STI,
1292 MCOperand Op = MI->getOperand(OpNum);
1294 // Support for fixups (MCFixup)
1296 return printOperand(MI, OpNum, STI, O);
1298 unsigned Bits = Op.getImm() & 0xFF;
1299 unsigned Rot = (Op.getImm() & 0xF00) >> 7;
1301 bool PrintUnsigned = false;
1302 switch (MI->getOpcode()) {
1304 // Movs to PC should be treated unsigned
1305 PrintUnsigned = (MI->getOperand(OpNum - 1).getReg() == ARM::PC);
1308 // Movs to special registers should be treated unsigned
1309 PrintUnsigned = true;
1313 int32_t Rotated = ARM_AM::rotr32(Bits, Rot);
1314 if (ARM_AM::getSOImmVal(Rotated) == Op.getImm()) {
1315 // #rot has the least possible value
1316 O << "#" << markup("<imm:");
1318 O << static_cast<uint32_t>(Rotated);
1325 // Explicit #bits, #rot implied
1326 O << "#" << markup("<imm:") << Bits << markup(">") << ", #" << markup("<imm:")
1327 << Rot << markup(">");
1330 void ARMInstPrinter::printFBits16(const MCInst *MI, unsigned OpNum,
1331 const MCSubtargetInfo &STI, raw_ostream &O) {
1332 O << markup("<imm:") << "#" << 16 - MI->getOperand(OpNum).getImm()
1336 void ARMInstPrinter::printFBits32(const MCInst *MI, unsigned OpNum,
1337 const MCSubtargetInfo &STI, raw_ostream &O) {
1338 O << markup("<imm:") << "#" << 32 - MI->getOperand(OpNum).getImm()
1342 void ARMInstPrinter::printVectorIndex(const MCInst *MI, unsigned OpNum,
1343 const MCSubtargetInfo &STI,
1345 O << "[" << MI->getOperand(OpNum).getImm() << "]";
1348 void ARMInstPrinter::printVectorListOne(const MCInst *MI, unsigned OpNum,
1349 const MCSubtargetInfo &STI,
1352 printRegName(O, MI->getOperand(OpNum).getReg());
1356 void ARMInstPrinter::printVectorListTwo(const MCInst *MI, unsigned OpNum,
1357 const MCSubtargetInfo &STI,
1359 unsigned Reg = MI->getOperand(OpNum).getReg();
1360 unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
1361 unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_1);
1363 printRegName(O, Reg0);
1365 printRegName(O, Reg1);
1369 void ARMInstPrinter::printVectorListTwoSpaced(const MCInst *MI, unsigned OpNum,
1370 const MCSubtargetInfo &STI,
1372 unsigned Reg = MI->getOperand(OpNum).getReg();
1373 unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
1374 unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_2);
1376 printRegName(O, Reg0);
1378 printRegName(O, Reg1);
1382 void ARMInstPrinter::printVectorListThree(const MCInst *MI, unsigned OpNum,
1383 const MCSubtargetInfo &STI,
1385 // Normally, it's not safe to use register enum values directly with
1386 // addition to get the next register, but for VFP registers, the
1387 // sort order is guaranteed because they're all of the form D<n>.
1389 printRegName(O, MI->getOperand(OpNum).getReg());
1391 printRegName(O, MI->getOperand(OpNum).getReg() + 1);
1393 printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1397 void ARMInstPrinter::printVectorListFour(const MCInst *MI, unsigned OpNum,
1398 const MCSubtargetInfo &STI,
1400 // Normally, it's not safe to use register enum values directly with
1401 // addition to get the next register, but for VFP registers, the
1402 // sort order is guaranteed because they're all of the form D<n>.
1404 printRegName(O, MI->getOperand(OpNum).getReg());
1406 printRegName(O, MI->getOperand(OpNum).getReg() + 1);
1408 printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1410 printRegName(O, MI->getOperand(OpNum).getReg() + 3);
1414 void ARMInstPrinter::printVectorListOneAllLanes(const MCInst *MI,
1416 const MCSubtargetInfo &STI,
1419 printRegName(O, MI->getOperand(OpNum).getReg());
1423 void ARMInstPrinter::printVectorListTwoAllLanes(const MCInst *MI,
1425 const MCSubtargetInfo &STI,
1427 unsigned Reg = MI->getOperand(OpNum).getReg();
1428 unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
1429 unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_1);
1431 printRegName(O, Reg0);
1433 printRegName(O, Reg1);
1437 void ARMInstPrinter::printVectorListThreeAllLanes(const MCInst *MI,
1439 const MCSubtargetInfo &STI,
1441 // Normally, it's not safe to use register enum values directly with
1442 // addition to get the next register, but for VFP registers, the
1443 // sort order is guaranteed because they're all of the form D<n>.
1445 printRegName(O, MI->getOperand(OpNum).getReg());
1447 printRegName(O, MI->getOperand(OpNum).getReg() + 1);
1449 printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1453 void ARMInstPrinter::printVectorListFourAllLanes(const MCInst *MI,
1455 const MCSubtargetInfo &STI,
1457 // Normally, it's not safe to use register enum values directly with
1458 // addition to get the next register, but for VFP registers, the
1459 // sort order is guaranteed because they're all of the form D<n>.
1461 printRegName(O, MI->getOperand(OpNum).getReg());
1463 printRegName(O, MI->getOperand(OpNum).getReg() + 1);
1465 printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1467 printRegName(O, MI->getOperand(OpNum).getReg() + 3);
1471 void ARMInstPrinter::printVectorListTwoSpacedAllLanes(
1472 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1474 unsigned Reg = MI->getOperand(OpNum).getReg();
1475 unsigned Reg0 = MRI.getSubReg(Reg, ARM::dsub_0);
1476 unsigned Reg1 = MRI.getSubReg(Reg, ARM::dsub_2);
1478 printRegName(O, Reg0);
1480 printRegName(O, Reg1);
1484 void ARMInstPrinter::printVectorListThreeSpacedAllLanes(
1485 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1487 // Normally, it's not safe to use register enum values directly with
1488 // addition to get the next register, but for VFP registers, the
1489 // sort order is guaranteed because they're all of the form D<n>.
1491 printRegName(O, MI->getOperand(OpNum).getReg());
1493 printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1495 printRegName(O, MI->getOperand(OpNum).getReg() + 4);
1499 void ARMInstPrinter::printVectorListFourSpacedAllLanes(
1500 const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI,
1502 // Normally, it's not safe to use register enum values directly with
1503 // addition to get the next register, but for VFP registers, the
1504 // sort order is guaranteed because they're all of the form D<n>.
1506 printRegName(O, MI->getOperand(OpNum).getReg());
1508 printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1510 printRegName(O, MI->getOperand(OpNum).getReg() + 4);
1512 printRegName(O, MI->getOperand(OpNum).getReg() + 6);
1516 void ARMInstPrinter::printVectorListThreeSpaced(const MCInst *MI,
1518 const MCSubtargetInfo &STI,
1520 // Normally, it's not safe to use register enum values directly with
1521 // addition to get the next register, but for VFP registers, the
1522 // sort order is guaranteed because they're all of the form D<n>.
1524 printRegName(O, MI->getOperand(OpNum).getReg());
1526 printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1528 printRegName(O, MI->getOperand(OpNum).getReg() + 4);
1532 void ARMInstPrinter::printVectorListFourSpaced(const MCInst *MI, unsigned OpNum,
1533 const MCSubtargetInfo &STI,
1535 // Normally, it's not safe to use register enum values directly with
1536 // addition to get the next register, but for VFP registers, the
1537 // sort order is guaranteed because they're all of the form D<n>.
1539 printRegName(O, MI->getOperand(OpNum).getReg());
1541 printRegName(O, MI->getOperand(OpNum).getReg() + 2);
1543 printRegName(O, MI->getOperand(OpNum).getReg() + 4);
1545 printRegName(O, MI->getOperand(OpNum).getReg() + 6);
1549 template<int64_t Angle, int64_t Remainder>
1550 void ARMInstPrinter::printComplexRotationOp(const MCInst *MI, unsigned OpNo,
1551 const MCSubtargetInfo &STI,
1553 unsigned Val = MI->getOperand(OpNo).getImm();
1554 O << "#" << (Val * Angle) + Remainder;