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 #define DEBUG_TYPE "asm-printer" 152754fe60SDimitry Andric #include "PPCInstPrinter.h" 16139f7f9bSDimitry Andric #include "MCTargetDesc/PPCMCTargetDesc.h" 176122f3e6SDimitry Andric #include "MCTargetDesc/PPCPredicates.h" 182754fe60SDimitry Andric #include "llvm/MC/MCExpr.h" 192754fe60SDimitry Andric #include "llvm/MC/MCInst.h" 20dff0c46cSDimitry Andric #include "llvm/MC/MCInstrInfo.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 26f785676fSDimitry Andric // FIXME: Once the integrated assembler supports full register names, tie this 27f785676fSDimitry Andric // to the verbose-asm setting. 28f785676fSDimitry Andric static cl::opt<bool> 29f785676fSDimitry Andric FullRegNames("ppc-asm-full-reg-names", cl::Hidden, cl::init(false), 30f785676fSDimitry Andric cl::desc("Use full register names when printing assembly")); 31f785676fSDimitry Andric 322754fe60SDimitry Andric #include "PPCGenAsmWriter.inc" 332754fe60SDimitry Andric 34bd5abe19SDimitry Andric void PPCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { 35bd5abe19SDimitry Andric OS << getRegisterName(RegNo); 36bd5abe19SDimitry Andric } 372754fe60SDimitry Andric 386122f3e6SDimitry Andric void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O, 396122f3e6SDimitry Andric StringRef Annot) { 402754fe60SDimitry Andric // Check for slwi/srwi mnemonics. 412754fe60SDimitry Andric if (MI->getOpcode() == PPC::RLWINM) { 422754fe60SDimitry Andric unsigned char SH = MI->getOperand(2).getImm(); 432754fe60SDimitry Andric unsigned char MB = MI->getOperand(3).getImm(); 442754fe60SDimitry Andric unsigned char ME = MI->getOperand(4).getImm(); 452754fe60SDimitry Andric bool useSubstituteMnemonic = false; 462754fe60SDimitry Andric if (SH <= 31 && MB == 0 && ME == (31-SH)) { 472754fe60SDimitry Andric O << "\tslwi "; useSubstituteMnemonic = true; 482754fe60SDimitry Andric } 492754fe60SDimitry Andric if (SH <= 31 && MB == (32-SH) && ME == 31) { 502754fe60SDimitry Andric O << "\tsrwi "; useSubstituteMnemonic = true; 512754fe60SDimitry Andric SH = 32-SH; 522754fe60SDimitry Andric } 532754fe60SDimitry Andric if (useSubstituteMnemonic) { 542754fe60SDimitry Andric printOperand(MI, 0, O); 552754fe60SDimitry Andric O << ", "; 562754fe60SDimitry Andric printOperand(MI, 1, O); 572754fe60SDimitry Andric O << ", " << (unsigned int)SH; 586122f3e6SDimitry Andric 596122f3e6SDimitry Andric printAnnotation(O, Annot); 602754fe60SDimitry Andric return; 612754fe60SDimitry Andric } 622754fe60SDimitry Andric } 632754fe60SDimitry Andric 642754fe60SDimitry Andric if ((MI->getOpcode() == PPC::OR || MI->getOpcode() == PPC::OR8) && 652754fe60SDimitry Andric MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) { 662754fe60SDimitry Andric O << "\tmr "; 672754fe60SDimitry Andric printOperand(MI, 0, O); 682754fe60SDimitry Andric O << ", "; 692754fe60SDimitry Andric printOperand(MI, 1, O); 706122f3e6SDimitry Andric printAnnotation(O, Annot); 712754fe60SDimitry Andric return; 722754fe60SDimitry Andric } 732754fe60SDimitry Andric 742754fe60SDimitry Andric if (MI->getOpcode() == PPC::RLDICR) { 752754fe60SDimitry Andric unsigned char SH = MI->getOperand(2).getImm(); 762754fe60SDimitry Andric unsigned char ME = MI->getOperand(3).getImm(); 772754fe60SDimitry Andric // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH 782754fe60SDimitry Andric if (63-SH == ME) { 792754fe60SDimitry Andric O << "\tsldi "; 802754fe60SDimitry Andric printOperand(MI, 0, O); 812754fe60SDimitry Andric O << ", "; 822754fe60SDimitry Andric printOperand(MI, 1, O); 832754fe60SDimitry Andric O << ", " << (unsigned int)SH; 846122f3e6SDimitry Andric printAnnotation(O, Annot); 852754fe60SDimitry Andric return; 862754fe60SDimitry Andric } 872754fe60SDimitry Andric } 882754fe60SDimitry Andric 89f785676fSDimitry Andric // For fast-isel, a COPY_TO_REGCLASS may survive this long. This is 90f785676fSDimitry Andric // used when converting a 32-bit float to a 64-bit float as part of 91f785676fSDimitry Andric // conversion to an integer (see PPCFastISel.cpp:SelectFPToI()), 92f785676fSDimitry Andric // as otherwise we have problems with incorrect register classes 93f785676fSDimitry Andric // in machine instruction verification. For now, just avoid trying 94f785676fSDimitry Andric // to print it as such an instruction has no effect (a 32-bit float 95f785676fSDimitry Andric // in a register is already in 64-bit form, just with lower 96f785676fSDimitry Andric // precision). FIXME: Is there a better solution? 97f785676fSDimitry Andric if (MI->getOpcode() == TargetOpcode::COPY_TO_REGCLASS) 98f785676fSDimitry Andric return; 99f785676fSDimitry Andric 1002754fe60SDimitry Andric printInstruction(MI, O); 1016122f3e6SDimitry Andric printAnnotation(O, Annot); 1022754fe60SDimitry Andric } 1032754fe60SDimitry Andric 1042754fe60SDimitry Andric 1052754fe60SDimitry Andric void PPCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo, 1062754fe60SDimitry Andric raw_ostream &O, 1072754fe60SDimitry Andric const char *Modifier) { 1082754fe60SDimitry Andric unsigned Code = MI->getOperand(OpNo).getImm(); 1097ae0e2c9SDimitry Andric 1102754fe60SDimitry Andric if (StringRef(Modifier) == "cc") { 1112754fe60SDimitry Andric switch ((PPC::Predicate)Code) { 112f785676fSDimitry Andric case PPC::PRED_LT_MINUS: 113f785676fSDimitry Andric case PPC::PRED_LT_PLUS: 114f785676fSDimitry Andric case PPC::PRED_LT: 115f785676fSDimitry Andric O << "lt"; 116f785676fSDimitry Andric return; 117f785676fSDimitry Andric case PPC::PRED_LE_MINUS: 118f785676fSDimitry Andric case PPC::PRED_LE_PLUS: 119f785676fSDimitry Andric case PPC::PRED_LE: 120f785676fSDimitry Andric O << "le"; 121f785676fSDimitry Andric return; 122f785676fSDimitry Andric case PPC::PRED_EQ_MINUS: 123f785676fSDimitry Andric case PPC::PRED_EQ_PLUS: 124f785676fSDimitry Andric case PPC::PRED_EQ: 125f785676fSDimitry Andric O << "eq"; 126f785676fSDimitry Andric return; 127f785676fSDimitry Andric case PPC::PRED_GE_MINUS: 128f785676fSDimitry Andric case PPC::PRED_GE_PLUS: 129f785676fSDimitry Andric case PPC::PRED_GE: 130f785676fSDimitry Andric O << "ge"; 131f785676fSDimitry Andric return; 132f785676fSDimitry Andric case PPC::PRED_GT_MINUS: 133f785676fSDimitry Andric case PPC::PRED_GT_PLUS: 134f785676fSDimitry Andric case PPC::PRED_GT: 135f785676fSDimitry Andric O << "gt"; 136f785676fSDimitry Andric return; 137f785676fSDimitry Andric case PPC::PRED_NE_MINUS: 138f785676fSDimitry Andric case PPC::PRED_NE_PLUS: 139f785676fSDimitry Andric case PPC::PRED_NE: 140f785676fSDimitry Andric O << "ne"; 141f785676fSDimitry Andric return; 142f785676fSDimitry Andric case PPC::PRED_UN_MINUS: 143f785676fSDimitry Andric case PPC::PRED_UN_PLUS: 144f785676fSDimitry Andric case PPC::PRED_UN: 145f785676fSDimitry Andric O << "un"; 146f785676fSDimitry Andric return; 147f785676fSDimitry Andric case PPC::PRED_NU_MINUS: 148f785676fSDimitry Andric case PPC::PRED_NU_PLUS: 149f785676fSDimitry Andric case PPC::PRED_NU: 150f785676fSDimitry Andric O << "nu"; 151f785676fSDimitry Andric return; 1522754fe60SDimitry Andric } 153f785676fSDimitry Andric llvm_unreachable("Invalid predicate code"); 154f785676fSDimitry Andric } 155f785676fSDimitry Andric 156f785676fSDimitry Andric if (StringRef(Modifier) == "pm") { 157f785676fSDimitry Andric switch ((PPC::Predicate)Code) { 158f785676fSDimitry Andric case PPC::PRED_LT: 159f785676fSDimitry Andric case PPC::PRED_LE: 160f785676fSDimitry Andric case PPC::PRED_EQ: 161f785676fSDimitry Andric case PPC::PRED_GE: 162f785676fSDimitry Andric case PPC::PRED_GT: 163f785676fSDimitry Andric case PPC::PRED_NE: 164f785676fSDimitry Andric case PPC::PRED_UN: 165f785676fSDimitry Andric case PPC::PRED_NU: 166f785676fSDimitry Andric return; 167f785676fSDimitry Andric case PPC::PRED_LT_MINUS: 168f785676fSDimitry Andric case PPC::PRED_LE_MINUS: 169f785676fSDimitry Andric case PPC::PRED_EQ_MINUS: 170f785676fSDimitry Andric case PPC::PRED_GE_MINUS: 171f785676fSDimitry Andric case PPC::PRED_GT_MINUS: 172f785676fSDimitry Andric case PPC::PRED_NE_MINUS: 173f785676fSDimitry Andric case PPC::PRED_UN_MINUS: 174f785676fSDimitry Andric case PPC::PRED_NU_MINUS: 175f785676fSDimitry Andric O << "-"; 176f785676fSDimitry Andric return; 177f785676fSDimitry Andric case PPC::PRED_LT_PLUS: 178f785676fSDimitry Andric case PPC::PRED_LE_PLUS: 179f785676fSDimitry Andric case PPC::PRED_EQ_PLUS: 180f785676fSDimitry Andric case PPC::PRED_GE_PLUS: 181f785676fSDimitry Andric case PPC::PRED_GT_PLUS: 182f785676fSDimitry Andric case PPC::PRED_NE_PLUS: 183f785676fSDimitry Andric case PPC::PRED_UN_PLUS: 184f785676fSDimitry Andric case PPC::PRED_NU_PLUS: 185f785676fSDimitry Andric O << "+"; 186f785676fSDimitry Andric return; 187f785676fSDimitry Andric } 188f785676fSDimitry Andric llvm_unreachable("Invalid predicate code"); 1892754fe60SDimitry Andric } 1902754fe60SDimitry Andric 1912754fe60SDimitry Andric assert(StringRef(Modifier) == "reg" && 192f785676fSDimitry Andric "Need to specify 'cc', 'pm' or 'reg' as predicate op modifier!"); 1932754fe60SDimitry Andric printOperand(MI, OpNo+1, O); 1942754fe60SDimitry Andric } 1952754fe60SDimitry Andric 1962754fe60SDimitry Andric void PPCInstPrinter::printS5ImmOperand(const MCInst *MI, unsigned OpNo, 1972754fe60SDimitry Andric raw_ostream &O) { 1983861d79fSDimitry Andric int Value = MI->getOperand(OpNo).getImm(); 1993861d79fSDimitry Andric Value = SignExtend32<5>(Value); 2002754fe60SDimitry Andric O << (int)Value; 2012754fe60SDimitry Andric } 2022754fe60SDimitry Andric 2032754fe60SDimitry Andric void PPCInstPrinter::printU5ImmOperand(const MCInst *MI, unsigned OpNo, 2042754fe60SDimitry Andric raw_ostream &O) { 2053861d79fSDimitry Andric unsigned int Value = MI->getOperand(OpNo).getImm(); 2062754fe60SDimitry Andric assert(Value <= 31 && "Invalid u5imm argument!"); 2072754fe60SDimitry Andric O << (unsigned int)Value; 2082754fe60SDimitry Andric } 2092754fe60SDimitry Andric 2102754fe60SDimitry Andric void PPCInstPrinter::printU6ImmOperand(const MCInst *MI, unsigned OpNo, 2112754fe60SDimitry Andric raw_ostream &O) { 2123861d79fSDimitry Andric unsigned int Value = MI->getOperand(OpNo).getImm(); 2132754fe60SDimitry Andric assert(Value <= 63 && "Invalid u6imm argument!"); 2142754fe60SDimitry Andric O << (unsigned int)Value; 2152754fe60SDimitry Andric } 2162754fe60SDimitry Andric 2172754fe60SDimitry Andric void PPCInstPrinter::printS16ImmOperand(const MCInst *MI, unsigned OpNo, 2182754fe60SDimitry Andric raw_ostream &O) { 219f785676fSDimitry Andric if (MI->getOperand(OpNo).isImm()) 2202754fe60SDimitry Andric O << (short)MI->getOperand(OpNo).getImm(); 221f785676fSDimitry Andric else 222f785676fSDimitry Andric printOperand(MI, OpNo, O); 2232754fe60SDimitry Andric } 2242754fe60SDimitry Andric 2252754fe60SDimitry Andric void PPCInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo, 2262754fe60SDimitry Andric raw_ostream &O) { 2272754fe60SDimitry Andric if (MI->getOperand(OpNo).isImm()) 228f785676fSDimitry Andric O << (unsigned short)MI->getOperand(OpNo).getImm(); 2292754fe60SDimitry Andric else 2302754fe60SDimitry Andric printOperand(MI, OpNo, O); 2312754fe60SDimitry Andric } 2322754fe60SDimitry Andric 2332754fe60SDimitry Andric void PPCInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo, 2342754fe60SDimitry Andric raw_ostream &O) { 2352754fe60SDimitry Andric if (!MI->getOperand(OpNo).isImm()) 2362754fe60SDimitry Andric return printOperand(MI, OpNo, O); 2372754fe60SDimitry Andric 2382754fe60SDimitry Andric // Branches can take an immediate operand. This is used by the branch 239284c1978SDimitry Andric // selection pass to print .+8, an eight byte displacement from the PC. 240284c1978SDimitry Andric O << ".+"; 241f785676fSDimitry Andric printAbsBranchOperand(MI, OpNo, O); 2422754fe60SDimitry Andric } 2432754fe60SDimitry Andric 244f785676fSDimitry Andric void PPCInstPrinter::printAbsBranchOperand(const MCInst *MI, unsigned OpNo, 2452754fe60SDimitry Andric raw_ostream &O) { 246f785676fSDimitry Andric if (!MI->getOperand(OpNo).isImm()) 247f785676fSDimitry Andric return printOperand(MI, OpNo, O); 248f785676fSDimitry Andric 2492754fe60SDimitry Andric O << (int)MI->getOperand(OpNo).getImm()*4; 2502754fe60SDimitry Andric } 2512754fe60SDimitry Andric 2522754fe60SDimitry Andric 2532754fe60SDimitry Andric void PPCInstPrinter::printcrbitm(const MCInst *MI, unsigned OpNo, 2542754fe60SDimitry Andric raw_ostream &O) { 2552754fe60SDimitry Andric unsigned CCReg = MI->getOperand(OpNo).getReg(); 2562754fe60SDimitry Andric unsigned RegNo; 2572754fe60SDimitry Andric switch (CCReg) { 258dff0c46cSDimitry Andric default: llvm_unreachable("Unknown CR register"); 2592754fe60SDimitry Andric case PPC::CR0: RegNo = 0; break; 2602754fe60SDimitry Andric case PPC::CR1: RegNo = 1; break; 2612754fe60SDimitry Andric case PPC::CR2: RegNo = 2; break; 2622754fe60SDimitry Andric case PPC::CR3: RegNo = 3; break; 2632754fe60SDimitry Andric case PPC::CR4: RegNo = 4; break; 2642754fe60SDimitry Andric case PPC::CR5: RegNo = 5; break; 2652754fe60SDimitry Andric case PPC::CR6: RegNo = 6; break; 2662754fe60SDimitry Andric case PPC::CR7: RegNo = 7; break; 2672754fe60SDimitry Andric } 2682754fe60SDimitry Andric O << (0x80 >> RegNo); 2692754fe60SDimitry Andric } 2702754fe60SDimitry Andric 2712754fe60SDimitry Andric void PPCInstPrinter::printMemRegImm(const MCInst *MI, unsigned OpNo, 2722754fe60SDimitry Andric raw_ostream &O) { 273f785676fSDimitry Andric printS16ImmOperand(MI, OpNo, O); 2742754fe60SDimitry Andric O << '('; 2752754fe60SDimitry Andric if (MI->getOperand(OpNo+1).getReg() == PPC::R0) 2762754fe60SDimitry Andric O << "0"; 2772754fe60SDimitry Andric else 2782754fe60SDimitry Andric printOperand(MI, OpNo+1, O); 2792754fe60SDimitry Andric O << ')'; 2802754fe60SDimitry Andric } 2812754fe60SDimitry Andric 2822754fe60SDimitry Andric void PPCInstPrinter::printMemRegReg(const MCInst *MI, unsigned OpNo, 2832754fe60SDimitry Andric raw_ostream &O) { 2842754fe60SDimitry Andric // When used as the base register, r0 reads constant zero rather than 2852754fe60SDimitry Andric // the value contained in the register. For this reason, the darwin 2862754fe60SDimitry Andric // assembler requires that we print r0 as 0 (no r) when used as the base. 2872754fe60SDimitry Andric if (MI->getOperand(OpNo).getReg() == PPC::R0) 2882754fe60SDimitry Andric O << "0"; 2892754fe60SDimitry Andric else 2902754fe60SDimitry Andric printOperand(MI, OpNo, O); 2912754fe60SDimitry Andric O << ", "; 2922754fe60SDimitry Andric printOperand(MI, OpNo+1, O); 2932754fe60SDimitry Andric } 2942754fe60SDimitry Andric 295f785676fSDimitry Andric void PPCInstPrinter::printTLSCall(const MCInst *MI, unsigned OpNo, 296f785676fSDimitry Andric raw_ostream &O) { 297f785676fSDimitry Andric printBranchOperand(MI, OpNo, O); 298f785676fSDimitry Andric O << '('; 299f785676fSDimitry Andric printOperand(MI, OpNo+1, O); 300f785676fSDimitry Andric O << ')'; 301f785676fSDimitry Andric } 3022754fe60SDimitry Andric 3032754fe60SDimitry Andric 3042754fe60SDimitry Andric /// stripRegisterPrefix - This method strips the character prefix from a 3052754fe60SDimitry Andric /// register name so that only the number is left. Used by for linux asm. 3062754fe60SDimitry Andric static const char *stripRegisterPrefix(const char *RegName) { 307f785676fSDimitry Andric if (FullRegNames) 308f785676fSDimitry Andric return RegName; 309f785676fSDimitry Andric 3102754fe60SDimitry Andric switch (RegName[0]) { 3112754fe60SDimitry Andric case 'r': 3122754fe60SDimitry Andric case 'f': 3132754fe60SDimitry Andric case 'v': return RegName + 1; 3142754fe60SDimitry Andric case 'c': if (RegName[1] == 'r') return RegName + 2; 3152754fe60SDimitry Andric } 3162754fe60SDimitry Andric 3172754fe60SDimitry Andric return RegName; 3182754fe60SDimitry Andric } 3192754fe60SDimitry Andric 3202754fe60SDimitry Andric void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, 3212754fe60SDimitry Andric raw_ostream &O) { 3222754fe60SDimitry Andric const MCOperand &Op = MI->getOperand(OpNo); 3232754fe60SDimitry Andric if (Op.isReg()) { 3242754fe60SDimitry Andric const char *RegName = getRegisterName(Op.getReg()); 3252754fe60SDimitry Andric // The linux and AIX assembler does not take register prefixes. 3262754fe60SDimitry Andric if (!isDarwinSyntax()) 3272754fe60SDimitry Andric RegName = stripRegisterPrefix(RegName); 3282754fe60SDimitry Andric 3292754fe60SDimitry Andric O << RegName; 3302754fe60SDimitry Andric return; 3312754fe60SDimitry Andric } 3322754fe60SDimitry Andric 3332754fe60SDimitry Andric if (Op.isImm()) { 3342754fe60SDimitry Andric O << Op.getImm(); 3352754fe60SDimitry Andric return; 3362754fe60SDimitry Andric } 3372754fe60SDimitry Andric 3382754fe60SDimitry Andric assert(Op.isExpr() && "unknown operand kind in printOperand"); 3392754fe60SDimitry Andric O << *Op.getExpr(); 3402754fe60SDimitry Andric } 3412754fe60SDimitry Andric 342