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);
33 void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
34 // Check for MOVs and print canonical forms, instead.
35 if (MI->getOpcode() == ARM::MOVs) {
36 // FIXME: Thumb variants?
37 const MCOperand &Dst = MI->getOperand(0);
38 const MCOperand &MO1 = MI->getOperand(1);
39 const MCOperand &MO2 = MI->getOperand(2);
40 const MCOperand &MO3 = MI->getOperand(3);
42 O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
43 printSBitModifierOperand(MI, 6, O);
44 printPredicateOperand(MI, 4, O);
46 O << '\t' << getRegisterName(Dst.getReg())
47 << ", " << getRegisterName(MO1.getReg());
49 if (ARM_AM::getSORegShOp(MO3.getImm()) == ARM_AM::rrx)
55 O << getRegisterName(MO2.getReg());
56 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
58 O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
64 if ((MI->getOpcode() == ARM::STM_UPD || MI->getOpcode() == ARM::t2STM_UPD) &&
65 MI->getOperand(0).getReg() == ARM::SP) {
66 const MCOperand &MO1 = MI->getOperand(2);
67 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) {
69 printPredicateOperand(MI, 3, O);
71 printRegisterList(MI, 5, O);
77 if ((MI->getOpcode() == ARM::LDM_UPD || MI->getOpcode() == ARM::t2LDM_UPD) &&
78 MI->getOperand(0).getReg() == ARM::SP) {
79 const MCOperand &MO1 = MI->getOperand(2);
80 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) {
82 printPredicateOperand(MI, 3, O);
84 printRegisterList(MI, 5, O);
90 if ((MI->getOpcode() == ARM::VSTMS_UPD || MI->getOpcode() ==ARM::VSTMD_UPD) &&
91 MI->getOperand(0).getReg() == ARM::SP) {
92 const MCOperand &MO1 = MI->getOperand(2);
93 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) {
95 printPredicateOperand(MI, 3, O);
97 printRegisterList(MI, 5, O);
103 if ((MI->getOpcode() == ARM::VLDMS_UPD || MI->getOpcode() ==ARM::VLDMD_UPD) &&
104 MI->getOperand(0).getReg() == ARM::SP) {
105 const MCOperand &MO1 = MI->getOperand(2);
106 if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) {
108 printPredicateOperand(MI, 3, O);
110 printRegisterList(MI, 5, O);
115 printInstruction(MI, O);
118 void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
120 const MCOperand &Op = MI->getOperand(OpNo);
122 unsigned Reg = Op.getReg();
123 O << getRegisterName(Reg);
124 } else if (Op.isImm()) {
125 O << '#' << Op.getImm();
127 assert(Op.isExpr() && "unknown operand kind in printOperand");
132 static void printSOImm(raw_ostream &O, int64_t V, raw_ostream *CommentStream,
133 const MCAsmInfo *MAI) {
134 // Break it up into two parts that make up a shifter immediate.
135 V = ARM_AM::getSOImmVal(V);
136 assert(V != -1 && "Not a valid so_imm value!");
138 unsigned Imm = ARM_AM::getSOImmValImm(V);
139 unsigned Rot = ARM_AM::getSOImmValRot(V);
141 // Print low-level immediate formation info, per
142 // A5.1.3: "Data-processing operands - Immediate".
144 O << "#" << Imm << ", " << Rot;
145 // Pretty printed version.
147 *CommentStream << (int)ARM_AM::rotr32(Imm, Rot) << "\n";
154 /// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
155 /// immediate in bits 0-7.
156 void ARMInstPrinter::printSOImmOperand(const MCInst *MI, unsigned OpNum,
158 const MCOperand &MO = MI->getOperand(OpNum);
159 assert(MO.isImm() && "Not a valid so_imm value!");
160 printSOImm(O, MO.getImm(), CommentStream, &MAI);
163 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
164 // "Addressing Mode 1 - Data-processing operands" forms. This includes:
166 // REG REG 0,SH_OPC - e.g. R5, ROR R3
167 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3
168 void ARMInstPrinter::printSORegOperand(const MCInst *MI, unsigned OpNum,
170 const MCOperand &MO1 = MI->getOperand(OpNum);
171 const MCOperand &MO2 = MI->getOperand(OpNum+1);
172 const MCOperand &MO3 = MI->getOperand(OpNum+2);
174 O << getRegisterName(MO1.getReg());
176 // Print the shift opc.
177 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO3.getImm());
178 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
180 O << ' ' << getRegisterName(MO2.getReg());
181 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
182 } else if (ShOpc != ARM_AM::rrx) {
183 O << " #" << ARM_AM::getSORegOffset(MO3.getImm());
188 void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op,
190 const MCOperand &MO1 = MI->getOperand(Op);
191 const MCOperand &MO2 = MI->getOperand(Op+1);
192 const MCOperand &MO3 = MI->getOperand(Op+2);
194 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
195 printOperand(MI, Op, O);
199 O << "[" << getRegisterName(MO1.getReg());
202 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
204 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
205 << ARM_AM::getAM2Offset(MO3.getImm());
211 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
212 << getRegisterName(MO2.getReg());
214 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
216 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
221 void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
224 const MCOperand &MO1 = MI->getOperand(OpNum);
225 const MCOperand &MO2 = MI->getOperand(OpNum+1);
228 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
230 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
235 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
236 << getRegisterName(MO1.getReg());
238 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
240 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
244 void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum,
246 const MCOperand &MO1 = MI->getOperand(OpNum);
247 const MCOperand &MO2 = MI->getOperand(OpNum+1);
248 const MCOperand &MO3 = MI->getOperand(OpNum+2);
250 O << '[' << getRegisterName(MO1.getReg());
253 O << ", " << (char)ARM_AM::getAM3Op(MO3.getImm())
254 << getRegisterName(MO2.getReg()) << ']';
258 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
260 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
265 void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
268 const MCOperand &MO1 = MI->getOperand(OpNum);
269 const MCOperand &MO2 = MI->getOperand(OpNum+1);
272 O << (char)ARM_AM::getAM3Op(MO2.getImm())
273 << getRegisterName(MO1.getReg());
277 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
279 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
283 void ARMInstPrinter::printLdStmModeOperand(const MCInst *MI, unsigned OpNum,
285 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(OpNum)
287 O << ARM_AM::getAMSubModeStr(Mode);
290 void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
292 const MCOperand &MO1 = MI->getOperand(OpNum);
293 const MCOperand &MO2 = MI->getOperand(OpNum+1);
295 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
296 printOperand(MI, OpNum, O);
300 O << "[" << getRegisterName(MO1.getReg());
302 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
304 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
310 void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
312 const MCOperand &MO1 = MI->getOperand(OpNum);
313 const MCOperand &MO2 = MI->getOperand(OpNum+1);
315 O << "[" << getRegisterName(MO1.getReg());
317 // FIXME: Both darwin as and GNU as violate ARM docs here.
318 O << ", :" << (MO2.getImm() << 3);
323 void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
326 const MCOperand &MO = MI->getOperand(OpNum);
327 if (MO.getReg() == 0)
330 O << ", " << getRegisterName(MO.getReg());
333 void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
336 const MCOperand &MO = MI->getOperand(OpNum);
337 uint32_t v = ~MO.getImm();
338 int32_t lsb = CountTrailingZeros_32(v);
339 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
340 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
341 O << '#' << lsb << ", #" << width;
344 void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum,
346 unsigned val = MI->getOperand(OpNum).getImm();
347 O << ARM_MB::MemBOptToString(val);
350 void ARMInstPrinter::printShiftImmOperand(const MCInst *MI, unsigned OpNum,
352 unsigned ShiftOp = MI->getOperand(OpNum).getImm();
353 ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp);
355 case ARM_AM::no_shift:
364 assert(0 && "unexpected shift opcode for shift immediate operand");
366 O << ARM_AM::getSORegOffset(ShiftOp);
369 void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
372 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
373 if (i != OpNum) O << ", ";
374 O << getRegisterName(MI->getOperand(i).getReg());
379 void ARMInstPrinter::printSetendOperand(const MCInst *MI, unsigned OpNum,
381 const MCOperand &Op = MI->getOperand(OpNum);
388 void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum,
390 const MCOperand &Op = MI->getOperand(OpNum);
391 unsigned option = Op.getImm();
392 unsigned mode = option & 31;
393 bool changemode = option >> 5 & 1;
394 unsigned AIF = option >> 6 & 7;
395 unsigned imod = option >> 9 & 3;
402 if (AIF & 4) O << 'a';
403 if (AIF & 2) O << 'i';
404 if (AIF & 1) O << 'f';
405 if (AIF > 0 && changemode) O << ", ";
411 void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
413 const MCOperand &Op = MI->getOperand(OpNum);
414 unsigned Mask = Op.getImm();
417 if (Mask & 8) O << 'f';
418 if (Mask & 4) O << 's';
419 if (Mask & 2) O << 'x';
420 if (Mask & 1) O << 'c';
424 void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum,
426 const MCOperand &Op = MI->getOperand(OpNum);
429 O << '-' << (-Op.getImm() - 1);
434 void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
436 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
438 O << ARMCondCodeToString(CC);
441 void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI,
444 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
445 O << ARMCondCodeToString(CC);
448 void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum,
450 if (MI->getOperand(OpNum).getReg()) {
451 assert(MI->getOperand(OpNum).getReg() == ARM::CPSR &&
452 "Expect ARM CPSR register!");
457 void ARMInstPrinter::printNoHashImmediate(const MCInst *MI, unsigned OpNum,
459 O << MI->getOperand(OpNum).getImm();
462 void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum,
464 llvm_unreachable("Unhandled PC-relative pseudo-instruction!");
467 void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum,
469 O << "#" << MI->getOperand(OpNum).getImm() * 4;
472 void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
474 // (3 - the number of trailing zeros) is the number of then / else.
475 unsigned Mask = MI->getOperand(OpNum).getImm();
476 unsigned CondBit0 = Mask >> 4 & 1;
477 unsigned NumTZ = CountTrailingZeros_32(Mask);
478 assert(NumTZ <= 3 && "Invalid IT mask!");
479 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
480 bool T = ((Mask >> Pos) & 1) == CondBit0;
488 void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op,
490 const MCOperand &MO1 = MI->getOperand(Op);
491 const MCOperand &MO2 = MI->getOperand(Op+1);
492 O << "[" << getRegisterName(MO1.getReg());
493 O << ", " << getRegisterName(MO2.getReg()) << "]";
496 void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op,
499 const MCOperand &MO1 = MI->getOperand(Op);
500 const MCOperand &MO2 = MI->getOperand(Op+1);
501 const MCOperand &MO3 = MI->getOperand(Op+2);
503 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
504 printOperand(MI, Op, O);
508 O << "[" << getRegisterName(MO1.getReg());
510 O << ", " << getRegisterName(MO3.getReg());
511 else if (unsigned ImmOffs = MO2.getImm())
512 O << ", #" << ImmOffs * Scale;
516 void ARMInstPrinter::printThumbAddrModeS1Operand(const MCInst *MI, unsigned Op,
518 printThumbAddrModeRI5Operand(MI, Op, O, 1);
521 void ARMInstPrinter::printThumbAddrModeS2Operand(const MCInst *MI, unsigned Op,
523 printThumbAddrModeRI5Operand(MI, Op, O, 2);
526 void ARMInstPrinter::printThumbAddrModeS4Operand(const MCInst *MI, unsigned Op,
528 printThumbAddrModeRI5Operand(MI, Op, O, 4);
531 void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI, unsigned Op,
533 const MCOperand &MO1 = MI->getOperand(Op);
534 const MCOperand &MO2 = MI->getOperand(Op+1);
535 O << "[" << getRegisterName(MO1.getReg());
536 if (unsigned ImmOffs = MO2.getImm())
537 O << ", #" << ImmOffs*4;
541 void ARMInstPrinter::printTBAddrMode(const MCInst *MI, unsigned OpNum,
543 O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg());
544 if (MI->getOpcode() == ARM::t2TBH)
549 // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
550 // register with shift forms.
552 // REG IMM, SH_OPC - e.g. R5, LSL #3
553 void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum,
555 const MCOperand &MO1 = MI->getOperand(OpNum);
556 const MCOperand &MO2 = MI->getOperand(OpNum+1);
558 unsigned Reg = MO1.getReg();
559 O << getRegisterName(Reg);
561 // Print the shift opc.
562 assert(MO2.isImm() && "Not a valid t2_so_reg value!");
563 ARM_AM::ShiftOpc ShOpc = ARM_AM::getSORegShOp(MO2.getImm());
564 O << ", " << ARM_AM::getShiftOpcStr(ShOpc);
565 if (ShOpc != ARM_AM::rrx)
566 O << " #" << ARM_AM::getSORegOffset(MO2.getImm());
569 void ARMInstPrinter::printAddrModeImm12Operand(const MCInst *MI, unsigned OpNum,
571 const MCOperand &MO1 = MI->getOperand(OpNum);
572 const MCOperand &MO2 = MI->getOperand(OpNum+1);
574 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
575 printOperand(MI, OpNum, O);
579 O << "[" << getRegisterName(MO1.getReg());
581 int32_t OffImm = (int32_t)MO2.getImm();
582 bool isSub = OffImm < 0;
583 // Special value for #-0. All others are normal.
584 if (OffImm == INT32_MIN)
587 O << ", #-" << -OffImm;
589 O << ", #" << OffImm;
593 void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
596 const MCOperand &MO1 = MI->getOperand(OpNum);
597 const MCOperand &MO2 = MI->getOperand(OpNum+1);
599 O << "[" << getRegisterName(MO1.getReg());
601 int32_t OffImm = (int32_t)MO2.getImm();
604 O << ", #-" << -OffImm;
606 O << ", #" << OffImm;
610 void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
613 const MCOperand &MO1 = MI->getOperand(OpNum);
614 const MCOperand &MO2 = MI->getOperand(OpNum+1);
616 O << "[" << getRegisterName(MO1.getReg());
618 int32_t OffImm = (int32_t)MO2.getImm() / 4;
621 O << ", #-" << -OffImm * 4;
623 O << ", #" << OffImm * 4;
627 void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
630 const MCOperand &MO1 = MI->getOperand(OpNum);
631 int32_t OffImm = (int32_t)MO1.getImm();
634 O << "#-" << -OffImm;
639 void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
642 const MCOperand &MO1 = MI->getOperand(OpNum);
643 int32_t OffImm = (int32_t)MO1.getImm() / 4;
646 O << "#-" << -OffImm * 4;
648 O << "#" << OffImm * 4;
651 void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
654 const MCOperand &MO1 = MI->getOperand(OpNum);
655 const MCOperand &MO2 = MI->getOperand(OpNum+1);
656 const MCOperand &MO3 = MI->getOperand(OpNum+2);
658 O << "[" << getRegisterName(MO1.getReg());
660 assert(MO2.getReg() && "Invalid so_reg load / store address!");
661 O << ", " << getRegisterName(MO2.getReg());
663 unsigned ShAmt = MO3.getImm();
665 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
666 O << ", lsl #" << ShAmt;
671 void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum,
673 O << '#' << (float)MI->getOperand(OpNum).getFPImm();
676 void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum,
678 O << '#' << MI->getOperand(OpNum).getFPImm();
681 void ARMInstPrinter::printNEONModImmOperand(const MCInst *MI, unsigned OpNum,
683 unsigned EncodedImm = MI->getOperand(OpNum).getImm();
685 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
686 O << "#0x" << utohexstr(Val);