12754fe60SDimitry Andric //===-- PPCInstPrinter.cpp - Convert PPC MCInst to assembly syntax --------===// 22754fe60SDimitry Andric // 32754fe60SDimitry Andric // The LLVM Compiler Infrastructure 42754fe60SDimitry Andric // 52754fe60SDimitry Andric // This file is distributed under the University of Illinois Open Source 62754fe60SDimitry Andric // License. See LICENSE.TXT for details. 72754fe60SDimitry Andric // 82754fe60SDimitry Andric //===----------------------------------------------------------------------===// 92754fe60SDimitry Andric // 102754fe60SDimitry Andric // This class prints an PPC MCInst to a .s file. 112754fe60SDimitry Andric // 122754fe60SDimitry Andric //===----------------------------------------------------------------------===// 132754fe60SDimitry Andric 142754fe60SDimitry Andric #include "PPCInstPrinter.h" 15139f7f9bSDimitry Andric #include "MCTargetDesc/PPCMCTargetDesc.h" 166122f3e6SDimitry Andric #include "MCTargetDesc/PPCPredicates.h" 172754fe60SDimitry Andric #include "llvm/MC/MCExpr.h" 182754fe60SDimitry Andric #include "llvm/MC/MCInst.h" 19dff0c46cSDimitry Andric #include "llvm/MC/MCInstrInfo.h" 20*26e25074SRoman Divacky #include "llvm/MC/MCSymbol.h" 21f785676fSDimitry Andric #include "llvm/Support/CommandLine.h" 222754fe60SDimitry Andric #include "llvm/Support/raw_ostream.h" 23f785676fSDimitry Andric #include "llvm/Target/TargetOpcodes.h" 242754fe60SDimitry Andric using namespace llvm; 252754fe60SDimitry Andric 2691bc56edSDimitry Andric #define DEBUG_TYPE "asm-printer" 2791bc56edSDimitry Andric 28f785676fSDimitry Andric // FIXME: Once the integrated assembler supports full register names, tie this 29f785676fSDimitry Andric // to the verbose-asm setting. 30f785676fSDimitry Andric static cl::opt<bool> 31f785676fSDimitry Andric FullRegNames("ppc-asm-full-reg-names", cl::Hidden, cl::init(false), 32f785676fSDimitry Andric cl::desc("Use full register names when printing assembly")); 33f785676fSDimitry Andric 342754fe60SDimitry Andric #include "PPCGenAsmWriter.inc" 352754fe60SDimitry Andric 36bd5abe19SDimitry Andric void PPCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { 37bd5abe19SDimitry Andric OS << getRegisterName(RegNo); 38bd5abe19SDimitry Andric } 392754fe60SDimitry Andric 406122f3e6SDimitry Andric void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O, 416122f3e6SDimitry Andric StringRef Annot) { 422754fe60SDimitry Andric // Check for slwi/srwi mnemonics. 432754fe60SDimitry Andric if (MI->getOpcode() == PPC::RLWINM) { 442754fe60SDimitry Andric unsigned char SH = MI->getOperand(2).getImm(); 452754fe60SDimitry Andric unsigned char MB = MI->getOperand(3).getImm(); 462754fe60SDimitry Andric unsigned char ME = MI->getOperand(4).getImm(); 472754fe60SDimitry Andric bool useSubstituteMnemonic = false; 482754fe60SDimitry Andric if (SH <= 31 && MB == 0 && ME == (31-SH)) { 492754fe60SDimitry Andric O << "\tslwi "; useSubstituteMnemonic = true; 502754fe60SDimitry Andric } 512754fe60SDimitry Andric if (SH <= 31 && MB == (32-SH) && ME == 31) { 522754fe60SDimitry Andric O << "\tsrwi "; useSubstituteMnemonic = true; 532754fe60SDimitry Andric SH = 32-SH; 542754fe60SDimitry Andric } 552754fe60SDimitry Andric if (useSubstituteMnemonic) { 562754fe60SDimitry Andric printOperand(MI, 0, O); 572754fe60SDimitry Andric O << ", "; 582754fe60SDimitry Andric printOperand(MI, 1, O); 592754fe60SDimitry Andric O << ", " << (unsigned int)SH; 606122f3e6SDimitry Andric 616122f3e6SDimitry Andric printAnnotation(O, Annot); 622754fe60SDimitry Andric return; 632754fe60SDimitry Andric } 642754fe60SDimitry Andric } 652754fe60SDimitry Andric 662754fe60SDimitry Andric if ((MI->getOpcode() == PPC::OR || MI->getOpcode() == PPC::OR8) && 672754fe60SDimitry Andric MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) { 682754fe60SDimitry Andric O << "\tmr "; 692754fe60SDimitry Andric printOperand(MI, 0, O); 702754fe60SDimitry Andric O << ", "; 712754fe60SDimitry Andric printOperand(MI, 1, O); 726122f3e6SDimitry Andric printAnnotation(O, Annot); 732754fe60SDimitry Andric return; 742754fe60SDimitry Andric } 752754fe60SDimitry Andric 762754fe60SDimitry Andric if (MI->getOpcode() == PPC::RLDICR) { 772754fe60SDimitry Andric unsigned char SH = MI->getOperand(2).getImm(); 782754fe60SDimitry Andric unsigned char ME = MI->getOperand(3).getImm(); 792754fe60SDimitry Andric // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH 802754fe60SDimitry Andric if (63-SH == ME) { 812754fe60SDimitry Andric O << "\tsldi "; 822754fe60SDimitry Andric printOperand(MI, 0, O); 832754fe60SDimitry Andric O << ", "; 842754fe60SDimitry Andric printOperand(MI, 1, O); 852754fe60SDimitry Andric O << ", " << (unsigned int)SH; 866122f3e6SDimitry Andric printAnnotation(O, Annot); 872754fe60SDimitry Andric return; 882754fe60SDimitry Andric } 892754fe60SDimitry Andric } 902754fe60SDimitry Andric 91f785676fSDimitry Andric // For fast-isel, a COPY_TO_REGCLASS may survive this long. This is 92f785676fSDimitry Andric // used when converting a 32-bit float to a 64-bit float as part of 93f785676fSDimitry Andric // conversion to an integer (see PPCFastISel.cpp:SelectFPToI()), 94f785676fSDimitry Andric // as otherwise we have problems with incorrect register classes 95f785676fSDimitry Andric // in machine instruction verification. For now, just avoid trying 96f785676fSDimitry Andric // to print it as such an instruction has no effect (a 32-bit float 97f785676fSDimitry Andric // in a register is already in 64-bit form, just with lower 98f785676fSDimitry Andric // precision). FIXME: Is there a better solution? 99f785676fSDimitry Andric if (MI->getOpcode() == TargetOpcode::COPY_TO_REGCLASS) 100f785676fSDimitry Andric return; 101f785676fSDimitry Andric 1022754fe60SDimitry Andric printInstruction(MI, O); 1036122f3e6SDimitry Andric printAnnotation(O, Annot); 1042754fe60SDimitry Andric } 1052754fe60SDimitry Andric 1062754fe60SDimitry Andric 1072754fe60SDimitry Andric void PPCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo, 1082754fe60SDimitry Andric raw_ostream &O, 1092754fe60SDimitry Andric const char *Modifier) { 1102754fe60SDimitry Andric unsigned Code = MI->getOperand(OpNo).getImm(); 1117ae0e2c9SDimitry Andric 1122754fe60SDimitry Andric if (StringRef(Modifier) == "cc") { 1132754fe60SDimitry Andric switch ((PPC::Predicate)Code) { 114f785676fSDimitry Andric case PPC::PRED_LT_MINUS: 115f785676fSDimitry Andric case PPC::PRED_LT_PLUS: 116f785676fSDimitry Andric case PPC::PRED_LT: 117f785676fSDimitry Andric O << "lt"; 118f785676fSDimitry Andric return; 119f785676fSDimitry Andric case PPC::PRED_LE_MINUS: 120f785676fSDimitry Andric case PPC::PRED_LE_PLUS: 121f785676fSDimitry Andric case PPC::PRED_LE: 122f785676fSDimitry Andric O << "le"; 123f785676fSDimitry Andric return; 124f785676fSDimitry Andric case PPC::PRED_EQ_MINUS: 125f785676fSDimitry Andric case PPC::PRED_EQ_PLUS: 126f785676fSDimitry Andric case PPC::PRED_EQ: 127f785676fSDimitry Andric O << "eq"; 128f785676fSDimitry Andric return; 129f785676fSDimitry Andric case PPC::PRED_GE_MINUS: 130f785676fSDimitry Andric case PPC::PRED_GE_PLUS: 131f785676fSDimitry Andric case PPC::PRED_GE: 132f785676fSDimitry Andric O << "ge"; 133f785676fSDimitry Andric return; 134f785676fSDimitry Andric case PPC::PRED_GT_MINUS: 135f785676fSDimitry Andric case PPC::PRED_GT_PLUS: 136f785676fSDimitry Andric case PPC::PRED_GT: 137f785676fSDimitry Andric O << "gt"; 138f785676fSDimitry Andric return; 139f785676fSDimitry Andric case PPC::PRED_NE_MINUS: 140f785676fSDimitry Andric case PPC::PRED_NE_PLUS: 141f785676fSDimitry Andric case PPC::PRED_NE: 142f785676fSDimitry Andric O << "ne"; 143f785676fSDimitry Andric return; 144f785676fSDimitry Andric case PPC::PRED_UN_MINUS: 145f785676fSDimitry Andric case PPC::PRED_UN_PLUS: 146f785676fSDimitry Andric case PPC::PRED_UN: 147f785676fSDimitry Andric O << "un"; 148f785676fSDimitry Andric return; 149f785676fSDimitry Andric case PPC::PRED_NU_MINUS: 150f785676fSDimitry Andric case PPC::PRED_NU_PLUS: 151f785676fSDimitry Andric case PPC::PRED_NU: 152f785676fSDimitry Andric O << "nu"; 153f785676fSDimitry Andric return; 15491bc56edSDimitry Andric case PPC::PRED_BIT_SET: 15591bc56edSDimitry Andric case PPC::PRED_BIT_UNSET: 15691bc56edSDimitry Andric llvm_unreachable("Invalid use of bit predicate code"); 1572754fe60SDimitry Andric } 158f785676fSDimitry Andric llvm_unreachable("Invalid predicate code"); 159f785676fSDimitry Andric } 160f785676fSDimitry Andric 161f785676fSDimitry Andric if (StringRef(Modifier) == "pm") { 162f785676fSDimitry Andric switch ((PPC::Predicate)Code) { 163f785676fSDimitry Andric case PPC::PRED_LT: 164f785676fSDimitry Andric case PPC::PRED_LE: 165f785676fSDimitry Andric case PPC::PRED_EQ: 166f785676fSDimitry Andric case PPC::PRED_GE: 167f785676fSDimitry Andric case PPC::PRED_GT: 168f785676fSDimitry Andric case PPC::PRED_NE: 169f785676fSDimitry Andric case PPC::PRED_UN: 170f785676fSDimitry Andric case PPC::PRED_NU: 171f785676fSDimitry Andric return; 172f785676fSDimitry Andric case PPC::PRED_LT_MINUS: 173f785676fSDimitry Andric case PPC::PRED_LE_MINUS: 174f785676fSDimitry Andric case PPC::PRED_EQ_MINUS: 175f785676fSDimitry Andric case PPC::PRED_GE_MINUS: 176f785676fSDimitry Andric case PPC::PRED_GT_MINUS: 177f785676fSDimitry Andric case PPC::PRED_NE_MINUS: 178f785676fSDimitry Andric case PPC::PRED_UN_MINUS: 179f785676fSDimitry Andric case PPC::PRED_NU_MINUS: 180f785676fSDimitry Andric O << "-"; 181f785676fSDimitry Andric return; 182f785676fSDimitry Andric case PPC::PRED_LT_PLUS: 183f785676fSDimitry Andric case PPC::PRED_LE_PLUS: 184f785676fSDimitry Andric case PPC::PRED_EQ_PLUS: 185f785676fSDimitry Andric case PPC::PRED_GE_PLUS: 186f785676fSDimitry Andric case PPC::PRED_GT_PLUS: 187f785676fSDimitry Andric case PPC::PRED_NE_PLUS: 188f785676fSDimitry Andric case PPC::PRED_UN_PLUS: 189f785676fSDimitry Andric case PPC::PRED_NU_PLUS: 190f785676fSDimitry Andric O << "+"; 191f785676fSDimitry Andric return; 19291bc56edSDimitry Andric case PPC::PRED_BIT_SET: 19391bc56edSDimitry Andric case PPC::PRED_BIT_UNSET: 19491bc56edSDimitry Andric llvm_unreachable("Invalid use of bit predicate code"); 195f785676fSDimitry Andric } 196f785676fSDimitry Andric llvm_unreachable("Invalid predicate code"); 1972754fe60SDimitry Andric } 1982754fe60SDimitry Andric 1992754fe60SDimitry Andric assert(StringRef(Modifier) == "reg" && 200f785676fSDimitry Andric "Need to specify 'cc', 'pm' or 'reg' as predicate op modifier!"); 2012754fe60SDimitry Andric printOperand(MI, OpNo+1, O); 2022754fe60SDimitry Andric } 2032754fe60SDimitry Andric 20491bc56edSDimitry Andric void PPCInstPrinter::printU2ImmOperand(const MCInst *MI, unsigned OpNo, 20591bc56edSDimitry Andric raw_ostream &O) { 20691bc56edSDimitry Andric unsigned int Value = MI->getOperand(OpNo).getImm(); 20791bc56edSDimitry Andric assert(Value <= 3 && "Invalid u2imm argument!"); 20891bc56edSDimitry Andric O << (unsigned int)Value; 20991bc56edSDimitry Andric } 21091bc56edSDimitry Andric 2112754fe60SDimitry Andric void PPCInstPrinter::printS5ImmOperand(const MCInst *MI, unsigned OpNo, 2122754fe60SDimitry Andric raw_ostream &O) { 2133861d79fSDimitry Andric int Value = MI->getOperand(OpNo).getImm(); 2143861d79fSDimitry Andric Value = SignExtend32<5>(Value); 2152754fe60SDimitry Andric O << (int)Value; 2162754fe60SDimitry Andric } 2172754fe60SDimitry Andric 2182754fe60SDimitry Andric void PPCInstPrinter::printU5ImmOperand(const MCInst *MI, unsigned OpNo, 2192754fe60SDimitry Andric raw_ostream &O) { 2203861d79fSDimitry Andric unsigned int Value = MI->getOperand(OpNo).getImm(); 2212754fe60SDimitry Andric assert(Value <= 31 && "Invalid u5imm argument!"); 2222754fe60SDimitry Andric O << (unsigned int)Value; 2232754fe60SDimitry Andric } 2242754fe60SDimitry Andric 2252754fe60SDimitry Andric void PPCInstPrinter::printU6ImmOperand(const MCInst *MI, unsigned OpNo, 2262754fe60SDimitry Andric raw_ostream &O) { 2273861d79fSDimitry Andric unsigned int Value = MI->getOperand(OpNo).getImm(); 2282754fe60SDimitry Andric assert(Value <= 63 && "Invalid u6imm argument!"); 2292754fe60SDimitry Andric O << (unsigned int)Value; 2302754fe60SDimitry Andric } 2312754fe60SDimitry Andric 2322754fe60SDimitry Andric void PPCInstPrinter::printS16ImmOperand(const MCInst *MI, unsigned OpNo, 2332754fe60SDimitry Andric raw_ostream &O) { 234f785676fSDimitry Andric if (MI->getOperand(OpNo).isImm()) 2352754fe60SDimitry Andric O << (short)MI->getOperand(OpNo).getImm(); 236f785676fSDimitry Andric else 237f785676fSDimitry Andric printOperand(MI, OpNo, O); 2382754fe60SDimitry Andric } 2392754fe60SDimitry Andric 2402754fe60SDimitry Andric void PPCInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo, 2412754fe60SDimitry Andric raw_ostream &O) { 2422754fe60SDimitry Andric if (MI->getOperand(OpNo).isImm()) 243f785676fSDimitry Andric O << (unsigned short)MI->getOperand(OpNo).getImm(); 2442754fe60SDimitry Andric else 2452754fe60SDimitry Andric printOperand(MI, OpNo, O); 2462754fe60SDimitry Andric } 2472754fe60SDimitry Andric 2482754fe60SDimitry Andric void PPCInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo, 2492754fe60SDimitry Andric raw_ostream &O) { 2502754fe60SDimitry Andric if (!MI->getOperand(OpNo).isImm()) 2512754fe60SDimitry Andric return printOperand(MI, OpNo, O); 2522754fe60SDimitry Andric 2532754fe60SDimitry Andric // Branches can take an immediate operand. This is used by the branch 254284c1978SDimitry Andric // selection pass to print .+8, an eight byte displacement from the PC. 255284c1978SDimitry Andric O << ".+"; 256f785676fSDimitry Andric printAbsBranchOperand(MI, OpNo, O); 2572754fe60SDimitry Andric } 2582754fe60SDimitry Andric 259f785676fSDimitry Andric void PPCInstPrinter::printAbsBranchOperand(const MCInst *MI, unsigned OpNo, 2602754fe60SDimitry Andric raw_ostream &O) { 261f785676fSDimitry Andric if (!MI->getOperand(OpNo).isImm()) 262f785676fSDimitry Andric return printOperand(MI, OpNo, O); 263f785676fSDimitry Andric 2642754fe60SDimitry Andric O << (int)MI->getOperand(OpNo).getImm()*4; 2652754fe60SDimitry Andric } 2662754fe60SDimitry Andric 2672754fe60SDimitry Andric 2682754fe60SDimitry Andric void PPCInstPrinter::printcrbitm(const MCInst *MI, unsigned OpNo, 2692754fe60SDimitry Andric raw_ostream &O) { 2702754fe60SDimitry Andric unsigned CCReg = MI->getOperand(OpNo).getReg(); 2712754fe60SDimitry Andric unsigned RegNo; 2722754fe60SDimitry Andric switch (CCReg) { 273dff0c46cSDimitry Andric default: llvm_unreachable("Unknown CR register"); 2742754fe60SDimitry Andric case PPC::CR0: RegNo = 0; break; 2752754fe60SDimitry Andric case PPC::CR1: RegNo = 1; break; 2762754fe60SDimitry Andric case PPC::CR2: RegNo = 2; break; 2772754fe60SDimitry Andric case PPC::CR3: RegNo = 3; break; 2782754fe60SDimitry Andric case PPC::CR4: RegNo = 4; break; 2792754fe60SDimitry Andric case PPC::CR5: RegNo = 5; break; 2802754fe60SDimitry Andric case PPC::CR6: RegNo = 6; break; 2812754fe60SDimitry Andric case PPC::CR7: RegNo = 7; break; 2822754fe60SDimitry Andric } 2832754fe60SDimitry Andric O << (0x80 >> RegNo); 2842754fe60SDimitry Andric } 2852754fe60SDimitry Andric 2862754fe60SDimitry Andric void PPCInstPrinter::printMemRegImm(const MCInst *MI, unsigned OpNo, 2872754fe60SDimitry Andric raw_ostream &O) { 288f785676fSDimitry Andric printS16ImmOperand(MI, OpNo, O); 2892754fe60SDimitry Andric O << '('; 2902754fe60SDimitry Andric if (MI->getOperand(OpNo+1).getReg() == PPC::R0) 2912754fe60SDimitry Andric O << "0"; 2922754fe60SDimitry Andric else 2932754fe60SDimitry Andric printOperand(MI, OpNo+1, O); 2942754fe60SDimitry Andric O << ')'; 2952754fe60SDimitry Andric } 2962754fe60SDimitry Andric 2972754fe60SDimitry Andric void PPCInstPrinter::printMemRegReg(const MCInst *MI, unsigned OpNo, 2982754fe60SDimitry Andric raw_ostream &O) { 2992754fe60SDimitry Andric // When used as the base register, r0 reads constant zero rather than 3002754fe60SDimitry Andric // the value contained in the register. For this reason, the darwin 3012754fe60SDimitry Andric // assembler requires that we print r0 as 0 (no r) when used as the base. 3022754fe60SDimitry Andric if (MI->getOperand(OpNo).getReg() == PPC::R0) 3032754fe60SDimitry Andric O << "0"; 3042754fe60SDimitry Andric else 3052754fe60SDimitry Andric printOperand(MI, OpNo, O); 3062754fe60SDimitry Andric O << ", "; 3072754fe60SDimitry Andric printOperand(MI, OpNo+1, O); 3082754fe60SDimitry Andric } 3092754fe60SDimitry Andric 310f785676fSDimitry Andric void PPCInstPrinter::printTLSCall(const MCInst *MI, unsigned OpNo, 311f785676fSDimitry Andric raw_ostream &O) { 312*26e25074SRoman Divacky // On PPC64, VariantKind is VK_None, but on PPC32, it's VK_PLT, and it must 313*26e25074SRoman Divacky // come at the _end_ of the expression. 314*26e25074SRoman Divacky const MCOperand &Op = MI->getOperand(OpNo); 315*26e25074SRoman Divacky const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*Op.getExpr()); 316*26e25074SRoman Divacky O << refExp.getSymbol().getName(); 317f785676fSDimitry Andric O << '('; 318f785676fSDimitry Andric printOperand(MI, OpNo+1, O); 319f785676fSDimitry Andric O << ')'; 320*26e25074SRoman Divacky if (refExp.getKind() != MCSymbolRefExpr::VK_None) 321*26e25074SRoman Divacky O << '@' << MCSymbolRefExpr::getVariantKindName(refExp.getKind()); 322f785676fSDimitry Andric } 3232754fe60SDimitry Andric 3242754fe60SDimitry Andric 3252754fe60SDimitry Andric /// stripRegisterPrefix - This method strips the character prefix from a 3262754fe60SDimitry Andric /// register name so that only the number is left. Used by for linux asm. 3272754fe60SDimitry Andric static const char *stripRegisterPrefix(const char *RegName) { 328f785676fSDimitry Andric if (FullRegNames) 329f785676fSDimitry Andric return RegName; 330f785676fSDimitry Andric 3312754fe60SDimitry Andric switch (RegName[0]) { 3322754fe60SDimitry Andric case 'r': 3332754fe60SDimitry Andric case 'f': 33491bc56edSDimitry Andric case 'v': 33591bc56edSDimitry Andric if (RegName[1] == 's') 33691bc56edSDimitry Andric return RegName + 2; 33791bc56edSDimitry Andric return RegName + 1; 3382754fe60SDimitry Andric case 'c': if (RegName[1] == 'r') return RegName + 2; 3392754fe60SDimitry Andric } 3402754fe60SDimitry Andric 3412754fe60SDimitry Andric return RegName; 3422754fe60SDimitry Andric } 3432754fe60SDimitry Andric 3442754fe60SDimitry Andric void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 3452754fe60SDimitry Andric raw_ostream &O) { 3462754fe60SDimitry Andric const MCOperand &Op = MI->getOperand(OpNo); 3472754fe60SDimitry Andric if (Op.isReg()) { 3482754fe60SDimitry Andric const char *RegName = getRegisterName(Op.getReg()); 3492754fe60SDimitry Andric // The linux and AIX assembler does not take register prefixes. 3502754fe60SDimitry Andric if (!isDarwinSyntax()) 3512754fe60SDimitry Andric RegName = stripRegisterPrefix(RegName); 3522754fe60SDimitry Andric 3532754fe60SDimitry Andric O << RegName; 3542754fe60SDimitry Andric return; 3552754fe60SDimitry Andric } 3562754fe60SDimitry Andric 3572754fe60SDimitry Andric if (Op.isImm()) { 3582754fe60SDimitry Andric O << Op.getImm(); 3592754fe60SDimitry Andric return; 3602754fe60SDimitry Andric } 3612754fe60SDimitry Andric 3622754fe60SDimitry Andric assert(Op.isExpr() && "unknown operand kind in printOperand"); 3632754fe60SDimitry Andric O << *Op.getExpr(); 3642754fe60SDimitry Andric } 3652754fe60SDimitry Andric 366