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 #define DEBUG_TYPE "asm-printer"
15 #include "ARMBaseInfo.h"
16 #include "ARMInstPrinter.h"
17 #include "ARMAddressingModes.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCAsmInfo.h"
20 #include "llvm/MC/MCExpr.h"
21 #include "llvm/ADT/StringExtras.h"
22 #include "llvm/Support/raw_ostream.h"
25 #define GET_INSTRUCTION_NAME
26 #include "ARMGenAsmWriter.inc"
28 StringRef ARMInstPrinter::getOpcodeName(unsigned Opcode) const {
29 return getInstructionName(Opcode);
32 void ARMInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
33 OS << getRegisterName(RegNo);
36 void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
37 unsigned Opcode = MI->getOpcode();
39 // Check for MOVs and print canonical forms, instead.
40 if (Opcode == ARM::MOVs) {
41 // FIXME: Thumb variants?
42 const MCOperand &Dst = MI->getOperand(0);
43 const MCOperand &MO1 = MI->getOperand(1);
44 const MCOperand &MO2 = MI->getOperand(2);
45 const MCOperand &MO3 = MI->getOperand(3);
47 O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
48 printSBitModifierOperand(MI, 6, O);
49 printPredicateOperand(MI, 4, O);
51 O << '\t' << getRegisterName(Dst.getReg())
52 << ", " << getRegisterName(MO1.getReg());
54 if (ARM_AM::getSORegShOp(MO3.getImm()) == ARM_AM::rrx)
60 O << getRegisterName(MO2.getReg());
61 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
63 O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
69 if ((Opcode == ARM::STMDB_UPD || Opcode == ARM::t2STMDB_UPD) &&
70 MI->getOperand(0).getReg() == ARM::SP) {
72 printPredicateOperand(MI, 2, O);
73 if (Opcode == ARM::t2STMDB_UPD)
76 printRegisterList(MI, 4, O);
81 if ((Opcode == ARM::LDMIA_UPD || Opcode == ARM::t2LDMIA_UPD) &&
82 MI->getOperand(0).getReg() == ARM::SP) {
84 printPredicateOperand(MI, 2, O);
85 if (Opcode == ARM::t2LDMIA_UPD)
88 printRegisterList(MI, 4, O);
93 if ((Opcode == ARM::VSTMSDB_UPD || Opcode == ARM::VSTMDDB_UPD) &&
94 MI->getOperand(0).getReg() == ARM::SP) {
96 printPredicateOperand(MI, 2, O);
98 printRegisterList(MI, 4, O);
103 if ((Opcode == ARM::VLDMSIA_UPD || Opcode == ARM::VLDMDIA_UPD) &&
104 MI->getOperand(0).getReg() == ARM::SP) {
106 printPredicateOperand(MI, 2, O);
108 printRegisterList(MI, 4, O);
112 printInstruction(MI, O);
115 void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
117 const MCOperand &Op = MI->getOperand(OpNo);
119 unsigned Reg = Op.getReg();
120 O << getRegisterName(Reg);
121 } else if (Op.isImm()) {
122 O << '#' << Op.getImm();
124 assert(Op.isExpr() && "unknown operand kind in printOperand");
129 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
130 // "Addressing Mode 1 - Data-processing operands" forms. This includes:
132 // REG REG 0,SH_OPC - e.g. R5, ROR R3
133 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3
134 void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum,
136 const MCOperand &MO1 = MI->getOperand(OpNum);
137 const MCOperand &MO2 = MI->getOperand(OpNum+1);
138 const MCOperand &MO3 = MI->getOperand(OpNum+2);
140 O << getRegisterName(MO1.getReg());
142 // Print the shift opc.
143 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
144 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
145 if (ShOpc == ARM_AM::rrx)
148 O << ' ' << getRegisterName(MO2.getReg());
149 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
150 } else if (ShOpc != ARM_AM::rrx) {
151 O << " #" << ARM_AM::getSORegOffset(MO3.getImm());
155 //===--------------------------------------------------------------------===//
156 // Addressing Mode #2
157 //===--------------------------------------------------------------------===//
159 void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
161 const MCOperand &MO1 = MI->getOperand(Op);
162 const MCOperand &MO2 = MI->getOperand(Op+1);
163 const MCOperand &MO3 = MI->getOperand(Op+2);
165 O << "[" << getRegisterName(MO1.getReg());
168 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
170 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
171 << ARM_AM::getAM2Offset(MO3.getImm());
177 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
178 << getRegisterName(MO2.getReg());
180 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
182 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
187 void ARMInstPrinter::printAM2PostIndexOp(const MCInst *MI, unsigned Op,
189 const MCOperand &MO1 = MI->getOperand(Op);
190 const MCOperand &MO2 = MI->getOperand(Op+1);
191 const MCOperand &MO3 = MI->getOperand(Op+2);
193 O << "[" << getRegisterName(MO1.getReg()) << "], ";
196 unsigned ImmOffs = ARM_AM::getAM2Offset(MO3.getImm());
198 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
203 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
204 << getRegisterName(MO2.getReg());
206 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
208 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
212 void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
214 const MCOperand &MO1 = MI->getOperand(Op);
216 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
217 printOperand(MI, Op, O);
221 const MCOperand &MO3 = MI->getOperand(Op+2);
222 unsigned IdxMode = ARM_AM::getAM2IdxMode(MO3.getImm());
224 if (IdxMode == ARMII::IndexModePost) {
225 printAM2PostIndexOp(MI, Op, O);
228 printAM2PreOrOffsetIndexOp(MI, Op, O);
231 void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
234 const MCOperand &MO1 = MI->getOperand(OpNum);
235 const MCOperand &MO2 = MI->getOperand(OpNum+1);
238 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
240 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
245 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
246 << getRegisterName(MO1.getReg());
248 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
250 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
254 //===--------------------------------------------------------------------===//
255 // Addressing Mode #3
256 //===--------------------------------------------------------------------===//
258 void ARMInstPrinter::printAM3PostIndexOp(const MCInst *MI, unsigned Op,
260 const MCOperand &MO1 = MI->getOperand(Op);
261 const MCOperand &MO2 = MI->getOperand(Op+1);
262 const MCOperand &MO3 = MI->getOperand(Op+2);
264 O << "[" << getRegisterName(MO1.getReg()) << "], ";
267 O << (char)ARM_AM::getAM3Op(MO3.getImm())
268 << getRegisterName(MO2.getReg());
272 unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm());
274 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
278 void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
280 const MCOperand &MO1 = MI->getOperand(Op);
281 const MCOperand &MO2 = MI->getOperand(Op+1);
282 const MCOperand &MO3 = MI->getOperand(Op+2);
284 O << '[' << getRegisterName(MO1.getReg());
287 O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm())
288 << getRegisterName(MO2.getReg()) << ']';
292 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
294 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
299 void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op,
301 const MCOperand &MO3 = MI->getOperand(Op+2);
302 unsigned IdxMode = ARM_AM::getAM3IdxMode(MO3.getImm());
304 if (IdxMode == ARMII::IndexModePost) {
305 printAM3PostIndexOp(MI, Op, O);
308 printAM3PreOrOffsetIndexOp(MI, Op, O);
311 void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
314 const MCOperand &MO1 = MI->getOperand(OpNum);
315 const MCOperand &MO2 = MI->getOperand(OpNum+1);
318 O << (char)ARM_AM::getAM3Op(MO2.getImm())
319 << getRegisterName(MO1.getReg());
323 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
325 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
329 void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,
331 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(OpNum)
333 O << ARM_AM::getAMSubModeStr(Mode);
336 void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
338 const MCOperand &MO1 = MI->getOperand(OpNum);
339 const MCOperand &MO2 = MI->getOperand(OpNum+1);
341 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
342 printOperand(MI, OpNum, O);
346 O << "[" << getRegisterName(MO1.getReg());
348 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
350 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
356 void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
358 const MCOperand &MO1 = MI->getOperand(OpNum);
359 const MCOperand &MO2 = MI->getOperand(OpNum+1);
361 O << "[" << getRegisterName(MO1.getReg());
363 // FIXME: Both darwin as and GNU as violate ARM docs here.
364 O << ", :" << (MO2.getImm() << 3);
369 void ARMInstPrinter::printAddrMode7Operand(const MCInst *MI, unsigned OpNum,
371 const MCOperand &MO1 = MI->getOperand(OpNum);
372 O << "[" << getRegisterName(MO1.getReg()) << "]";
375 void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
378 const MCOperand &MO = MI->getOperand(OpNum);
379 if (MO.getReg() == 0)
382 O << ", " << getRegisterName(MO.getReg());
385 void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
388 const MCOperand &MO = MI->getOperand(OpNum);
389 uint32_t v = ~MO.getImm();
390 int32_t lsb = CountTrailingZeros_32(v);
391 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
392 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
393 O << '#' << lsb << ", #" << width;
396 void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
398 unsigned val = MI->getOperand(OpNum).getImm();
399 O << ARM_MB::MemBOptToString(val);
402 void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
404 unsigned ShiftOp = MI->getOperand(OpNum).getImm();
405 ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp);
407 case ARM_AM::no_shift:
416 assert(0 && "unexpected shift opcode for shift immediate operand");
418 O << ARM_AM::getSORegOffset(ShiftOp);
421 void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
424 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
425 if (i != OpNum) O << ", ";
426 O << getRegisterName(MI->getOperand(i).getReg());
431 void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum,
433 const MCOperand &Op = MI->getOperand(OpNum);
440 void ARMInstPrinter::printCPSIMod(const MCInst *MI, unsigned OpNum,
442 const MCOperand &Op = MI->getOperand(OpNum);
443 O << ARM_PROC::IModToString(Op.getImm());
446 void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum,
448 const MCOperand &Op = MI->getOperand(OpNum);
449 unsigned IFlags = Op.getImm();
450 for (int i=2; i >= 0; --i)
451 if (IFlags & (1 << i))
452 O << ARM_PROC::IFlagsToString(1 << i);
455 void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
457 const MCOperand &Op = MI->getOperand(OpNum);
458 unsigned SpecRegRBit = Op.getImm() >> 4;
459 unsigned Mask = Op.getImm() & 0xf;
468 if (Mask & 8) O << 'f';
469 if (Mask & 4) O << 's';
470 if (Mask & 2) O << 'x';
471 if (Mask & 1) O << 'c';
475 void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
477 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
479 O << ARMCondCodeToString(CC);
482 void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
485 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
486 O << ARMCondCodeToString(CC);
489 void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
491 if (MI->getOperand(OpNum).getReg()) {
492 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
493 "Expect ARM CPSR register!");
498 void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
500 O << MI->getOperand(OpNum).getImm();
503 void ARMInstPrinter::printPImmediate(const MCInst *MI, unsigned OpNum,
505 O << "p" << MI->getOperand(OpNum).getImm();
508 void ARMInstPrinter::printCImmediate(const MCInst *MI, unsigned OpNum,
510 O << "c" << MI->getOperand(OpNum).getImm();
513 void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
515 llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
518 void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
520 O << "#" << MI->getOperand(OpNum).getImm() * 4;
523 void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
525 // (3 - the number of trailing zeros) is the number of then / else.
526 unsigned Mask = MI->getOperand(OpNum).getImm();
527 unsigned CondBit0 = Mask >> 4 & 1;
528 unsigned NumTZ = CountTrailingZeros_32(Mask);
529 assert(NumTZ <= 3 && "Invalid IT mask!");
530 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
531 bool T = ((Mask >> Pos) & 1) == CondBit0;
539 void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
541 const MCOperand &MO1 = MI->getOperand(Op);
542 const MCOperand &MO2 = MI->getOperand(Op + 1);
544 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
545 printOperand(MI, Op, O);
549 O << "[" << getRegisterName(MO1.getReg());
550 if (unsigned RegNum = MO2.getReg())
551 O << ", " << getRegisterName(RegNum);
555 void ARMInstPrinter::printThumbAddrModeImm5SOperand(const MCInst *MI,
559 const MCOperand &MO1 = MI->getOperand(Op);
560 const MCOperand &MO2 = MI->getOperand(Op + 1);
562 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
563 printOperand(MI, Op, O);
567 O << "[" << getRegisterName(MO1.getReg());
568 if (unsigned ImmOffs = MO2.getImm())
569 O << ", #" << ImmOffs * Scale;
573 void ARMInstPrinter::printThumbAddrModeImm5S1Operand(const MCInst *MI,
576 printThumbAddrModeImm5SOperand(MI, Op, O, 1);
579 void ARMInstPrinter::printThumbAddrModeImm5S2Operand(const MCInst *MI,
582 printThumbAddrModeImm5SOperand(MI, Op, O, 2);
585 void ARMInstPrinter::printThumbAddrModeImm5S4Operand(const MCInst *MI,
588 printThumbAddrModeImm5SOperand(MI, Op, O, 4);
591 void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
593 printThumbAddrModeImm5SOperand(MI, Op, O, 4);
596 // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
597 // register with shift forms.
599 // REG IMM, SH_OPC - e.g. R5, LSL #3
600 void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
602 const MCOperand &MO1 = MI->getOperand(OpNum);
603 const MCOperand &MO2 = MI->getOperand(OpNum+1);
605 unsigned Reg = MO1.getReg();
606 O << getRegisterName(Reg);
608 // Print the shift opc.
609 assert(MO2.isImm() && "Not a valid t2_so_reg value!");
610 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm());
611 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
612 if (ShOpc != ARM_AM::rrx)
613 O << " #" << ARM_AM::getSORegOffset(MO2.getImm());
616 void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
618 const MCOperand &MO1 = MI->getOperand(OpNum);
619 const MCOperand &MO2 = MI->getOperand(OpNum+1);
621 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
622 printOperand(MI, OpNum, O);
626 O << "[" << getRegisterName(MO1.getReg());
628 int32_t OffImm = (int32_t)MO2.getImm();
629 bool isSub = OffImm < 0;
630 // Special value for #-0. All others are normal.
631 if (OffImm == INT32_MIN)
634 O << ", #-" << -OffImm;
636 O << ", #" << OffImm;
640 void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
643 const MCOperand &MO1 = MI->getOperand(OpNum);
644 const MCOperand &MO2 = MI->getOperand(OpNum+1);
646 O << "[" << getRegisterName(MO1.getReg());
648 int32_t OffImm = (int32_t)MO2.getImm();
651 O << ", #-" << -OffImm;
653 O << ", #" << OffImm;
657 void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
660 const MCOperand &MO1 = MI->getOperand(OpNum);
661 const MCOperand &MO2 = MI->getOperand(OpNum+1);
663 O << "[" << getRegisterName(MO1.getReg());
665 int32_t OffImm = (int32_t)MO2.getImm() / 4;
668 O << ", #-" << -OffImm * 4;
670 O << ", #" << OffImm * 4;
674 void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
677 const MCOperand &MO1 = MI->getOperand(OpNum);
678 int32_t OffImm = (int32_t)MO1.getImm();
681 O << "#-" << -OffImm;
686 void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
689 const MCOperand &MO1 = MI->getOperand(OpNum);
690 int32_t OffImm = (int32_t)MO1.getImm() / 4;
693 O << "#-" << -OffImm * 4;
695 O << "#" << OffImm * 4;
698 void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
701 const MCOperand &MO1 = MI->getOperand(OpNum);
702 const MCOperand &MO2 = MI->getOperand(OpNum+1);
703 const MCOperand &MO3 = MI->getOperand(OpNum+2);
705 O << "[" << getRegisterName(MO1.getReg());
707 assert(MO2.getReg() && "Invalid so_reg load / store address!");
708 O << ", " << getRegisterName(MO2.getReg());
710 unsigned ShAmt = MO3.getImm();
712 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
713 O << ", lsl #" << ShAmt;
718 void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum,
720 const MCOperand &MO = MI->getOperand(OpNum);
723 O << (float)MO.getFPImm();
730 FPUnion.I = MO.getImm();
735 void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum,
737 const MCOperand &MO = MI->getOperand(OpNum);
742 // We expect the binary encoding of a floating point number here.
748 FPUnion.I = MO.getImm();
753 void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
755 unsigned EncodedImm = MI->getOperand(OpNum).getImm();
757 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
758 O << "#0x" << utohexstr(Val);