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