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"
17db17bf38SDimitry Andric #include "PPCInstrInfo.h"
182cab237bSDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h"
192754fe60SDimitry Andric #include "llvm/MC/MCExpr.h"
202754fe60SDimitry Andric #include "llvm/MC/MCInst.h"
21dff0c46cSDimitry Andric #include "llvm/MC/MCInstrInfo.h"
22ff0cc061SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
23ff0cc061SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
2426e25074SRoman Divacky #include "llvm/MC/MCSymbol.h"
25f785676fSDimitry Andric #include "llvm/Support/CommandLine.h"
262754fe60SDimitry Andric #include "llvm/Support/raw_ostream.h"
272754fe60SDimitry Andric using namespace llvm;
282754fe60SDimitry Andric 
2991bc56edSDimitry Andric #define DEBUG_TYPE "asm-printer"
3091bc56edSDimitry Andric 
31f785676fSDimitry Andric // FIXME: Once the integrated assembler supports full register names, tie this
32f785676fSDimitry Andric // to the verbose-asm setting.
33f785676fSDimitry Andric static cl::opt<bool>
34f785676fSDimitry Andric FullRegNames("ppc-asm-full-reg-names", cl::Hidden, cl::init(false),
35f785676fSDimitry Andric              cl::desc("Use full register names when printing assembly"));
36f785676fSDimitry Andric 
37d88c1a5aSDimitry Andric // Useful for testing purposes. Prints vs{31-63} as v{0-31} respectively.
38d88c1a5aSDimitry Andric static cl::opt<bool>
39d88c1a5aSDimitry Andric ShowVSRNumsAsVR("ppc-vsr-nums-as-vr", cl::Hidden, cl::init(false),
40d88c1a5aSDimitry Andric              cl::desc("Prints full register names with vs{31-63} as v{0-31}"));
41d88c1a5aSDimitry Andric 
422cab237bSDimitry Andric // Prints full register names with percent symbol.
432cab237bSDimitry Andric static cl::opt<bool>
442cab237bSDimitry Andric FullRegNamesWithPercent("ppc-reg-with-percent-prefix", cl::Hidden,
452cab237bSDimitry Andric                         cl::init(false),
462cab237bSDimitry Andric                         cl::desc("Prints full register names with percent"));
472cab237bSDimitry Andric 
48ff0cc061SDimitry Andric #define PRINT_ALIAS_INSTR
492754fe60SDimitry Andric #include "PPCGenAsmWriter.inc"
502754fe60SDimitry Andric 
printRegName(raw_ostream & OS,unsigned RegNo) const51bd5abe19SDimitry Andric void PPCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
52ff0cc061SDimitry Andric   const char *RegName = getRegisterName(RegNo);
53ff0cc061SDimitry Andric   if (RegName[0] == 'q' /* QPX */) {
54ff0cc061SDimitry Andric     // The system toolchain on the BG/Q does not understand QPX register names
55ff0cc061SDimitry Andric     // in .cfi_* directives, so print the name of the floating-point
56ff0cc061SDimitry Andric     // subregister instead.
57ff0cc061SDimitry Andric     std::string RN(RegName);
58ff0cc061SDimitry Andric 
59ff0cc061SDimitry Andric     RN[0] = 'f';
60ff0cc061SDimitry Andric     OS << RN;
61ff0cc061SDimitry Andric 
62ff0cc061SDimitry Andric     return;
63ff0cc061SDimitry Andric   }
64ff0cc061SDimitry Andric 
65ff0cc061SDimitry Andric   OS << RegName;
66bd5abe19SDimitry Andric }
672754fe60SDimitry Andric 
printInst(const MCInst * MI,raw_ostream & O,StringRef Annot,const MCSubtargetInfo & STI)686122f3e6SDimitry Andric void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
69ff0cc061SDimitry Andric                                StringRef Annot, const MCSubtargetInfo &STI) {
702754fe60SDimitry Andric   // Check for slwi/srwi mnemonics.
712754fe60SDimitry Andric   if (MI->getOpcode() == PPC::RLWINM) {
722754fe60SDimitry Andric     unsigned char SH = MI->getOperand(2).getImm();
732754fe60SDimitry Andric     unsigned char MB = MI->getOperand(3).getImm();
742754fe60SDimitry Andric     unsigned char ME = MI->getOperand(4).getImm();
752754fe60SDimitry Andric     bool useSubstituteMnemonic = false;
762754fe60SDimitry Andric     if (SH <= 31 && MB == 0 && ME == (31-SH)) {
772754fe60SDimitry Andric       O << "\tslwi "; useSubstituteMnemonic = true;
782754fe60SDimitry Andric     }
792754fe60SDimitry Andric     if (SH <= 31 && MB == (32-SH) && ME == 31) {
802754fe60SDimitry Andric       O << "\tsrwi "; useSubstituteMnemonic = true;
812754fe60SDimitry Andric       SH = 32-SH;
822754fe60SDimitry Andric     }
832754fe60SDimitry Andric     if (useSubstituteMnemonic) {
842754fe60SDimitry Andric       printOperand(MI, 0, O);
852754fe60SDimitry Andric       O << ", ";
862754fe60SDimitry Andric       printOperand(MI, 1, O);
872754fe60SDimitry Andric       O << ", " << (unsigned int)SH;
886122f3e6SDimitry Andric 
896122f3e6SDimitry Andric       printAnnotation(O, Annot);
902754fe60SDimitry Andric       return;
912754fe60SDimitry Andric     }
922754fe60SDimitry Andric   }
932754fe60SDimitry Andric 
942754fe60SDimitry Andric   if ((MI->getOpcode() == PPC::OR || MI->getOpcode() == PPC::OR8) &&
952754fe60SDimitry Andric       MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) {
962754fe60SDimitry Andric     O << "\tmr ";
972754fe60SDimitry Andric     printOperand(MI, 0, O);
982754fe60SDimitry Andric     O << ", ";
992754fe60SDimitry Andric     printOperand(MI, 1, O);
1006122f3e6SDimitry Andric     printAnnotation(O, Annot);
1012754fe60SDimitry Andric     return;
1022754fe60SDimitry Andric   }
1032754fe60SDimitry Andric 
1045517e702SDimitry Andric   if (MI->getOpcode() == PPC::RLDICR ||
1055517e702SDimitry Andric       MI->getOpcode() == PPC::RLDICR_32) {
1062754fe60SDimitry Andric     unsigned char SH = MI->getOperand(2).getImm();
1072754fe60SDimitry Andric     unsigned char ME = MI->getOperand(3).getImm();
1082754fe60SDimitry Andric     // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH
1092754fe60SDimitry Andric     if (63-SH == ME) {
1102754fe60SDimitry Andric       O << "\tsldi ";
1112754fe60SDimitry Andric       printOperand(MI, 0, O);
1122754fe60SDimitry Andric       O << ", ";
1132754fe60SDimitry Andric       printOperand(MI, 1, O);
1142754fe60SDimitry Andric       O << ", " << (unsigned int)SH;
1156122f3e6SDimitry Andric       printAnnotation(O, Annot);
1162754fe60SDimitry Andric       return;
1172754fe60SDimitry Andric     }
1182754fe60SDimitry Andric   }
1192754fe60SDimitry Andric 
120ff0cc061SDimitry Andric   // dcbt[st] is printed manually here because:
121ff0cc061SDimitry Andric   //  1. The assembly syntax is different between embedded and server targets
122ff0cc061SDimitry Andric   //  2. We must print the short mnemonics for TH == 0 because the
123ff0cc061SDimitry Andric   //     embedded/server syntax default will not be stable across assemblers
124ff0cc061SDimitry Andric   //  The syntax for dcbt is:
125ff0cc061SDimitry Andric   //    dcbt ra, rb, th [server]
126ff0cc061SDimitry Andric   //    dcbt th, ra, rb [embedded]
127ff0cc061SDimitry Andric   //  where th can be omitted when it is 0. dcbtst is the same.
128ff0cc061SDimitry Andric   if (MI->getOpcode() == PPC::DCBT || MI->getOpcode() == PPC::DCBTST) {
129ff0cc061SDimitry Andric     unsigned char TH = MI->getOperand(0).getImm();
130ff0cc061SDimitry Andric     O << "\tdcbt";
131ff0cc061SDimitry Andric     if (MI->getOpcode() == PPC::DCBTST)
132ff0cc061SDimitry Andric       O << "st";
133ff0cc061SDimitry Andric     if (TH == 16)
134ff0cc061SDimitry Andric       O << "t";
135ff0cc061SDimitry Andric     O << " ";
136ff0cc061SDimitry Andric 
137ff0cc061SDimitry Andric     bool IsBookE = STI.getFeatureBits()[PPC::FeatureBookE];
138ff0cc061SDimitry Andric     if (IsBookE && TH != 0 && TH != 16)
139ff0cc061SDimitry Andric       O << (unsigned int) TH << ", ";
140ff0cc061SDimitry Andric 
141ff0cc061SDimitry Andric     printOperand(MI, 1, O);
142ff0cc061SDimitry Andric     O << ", ";
143ff0cc061SDimitry Andric     printOperand(MI, 2, O);
144ff0cc061SDimitry Andric 
145ff0cc061SDimitry Andric     if (!IsBookE && TH != 0 && TH != 16)
146ff0cc061SDimitry Andric       O << ", " << (unsigned int) TH;
147ff0cc061SDimitry Andric 
148ff0cc061SDimitry Andric     printAnnotation(O, Annot);
149ff0cc061SDimitry Andric     return;
150ff0cc061SDimitry Andric   }
151ff0cc061SDimitry Andric 
152d88c1a5aSDimitry Andric   if (MI->getOpcode() == PPC::DCBF) {
153d88c1a5aSDimitry Andric     unsigned char L = MI->getOperand(0).getImm();
154d88c1a5aSDimitry Andric     if (!L || L == 1 || L == 3) {
155d88c1a5aSDimitry Andric       O << "\tdcbf";
156d88c1a5aSDimitry Andric       if (L == 1 || L == 3)
157d88c1a5aSDimitry Andric         O << "l";
158d88c1a5aSDimitry Andric       if (L == 3)
159d88c1a5aSDimitry Andric         O << "p";
160d88c1a5aSDimitry Andric       O << " ";
161d88c1a5aSDimitry Andric 
162d88c1a5aSDimitry Andric       printOperand(MI, 1, O);
163d88c1a5aSDimitry Andric       O << ", ";
164d88c1a5aSDimitry Andric       printOperand(MI, 2, O);
165d88c1a5aSDimitry Andric 
166d88c1a5aSDimitry Andric       printAnnotation(O, Annot);
167d88c1a5aSDimitry Andric       return;
168d88c1a5aSDimitry Andric     }
169d88c1a5aSDimitry Andric   }
170d88c1a5aSDimitry Andric 
171ff0cc061SDimitry Andric   if (!printAliasInstr(MI, O))
1722754fe60SDimitry Andric     printInstruction(MI, O);
1736122f3e6SDimitry Andric   printAnnotation(O, Annot);
1742754fe60SDimitry Andric }
1752754fe60SDimitry Andric 
1762754fe60SDimitry Andric 
printPredicateOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O,const char * Modifier)1772754fe60SDimitry Andric void PPCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
1782754fe60SDimitry Andric                                            raw_ostream &O,
1792754fe60SDimitry Andric                                            const char *Modifier) {
1802754fe60SDimitry Andric   unsigned Code = MI->getOperand(OpNo).getImm();
1817ae0e2c9SDimitry Andric 
1822754fe60SDimitry Andric   if (StringRef(Modifier) == "cc") {
1832754fe60SDimitry Andric     switch ((PPC::Predicate)Code) {
184f785676fSDimitry Andric     case PPC::PRED_LT_MINUS:
185f785676fSDimitry Andric     case PPC::PRED_LT_PLUS:
186f785676fSDimitry Andric     case PPC::PRED_LT:
187f785676fSDimitry Andric       O << "lt";
188f785676fSDimitry Andric       return;
189f785676fSDimitry Andric     case PPC::PRED_LE_MINUS:
190f785676fSDimitry Andric     case PPC::PRED_LE_PLUS:
191f785676fSDimitry Andric     case PPC::PRED_LE:
192f785676fSDimitry Andric       O << "le";
193f785676fSDimitry Andric       return;
194f785676fSDimitry Andric     case PPC::PRED_EQ_MINUS:
195f785676fSDimitry Andric     case PPC::PRED_EQ_PLUS:
196f785676fSDimitry Andric     case PPC::PRED_EQ:
197f785676fSDimitry Andric       O << "eq";
198f785676fSDimitry Andric       return;
199f785676fSDimitry Andric     case PPC::PRED_GE_MINUS:
200f785676fSDimitry Andric     case PPC::PRED_GE_PLUS:
201f785676fSDimitry Andric     case PPC::PRED_GE:
202f785676fSDimitry Andric       O << "ge";
203f785676fSDimitry Andric       return;
204f785676fSDimitry Andric     case PPC::PRED_GT_MINUS:
205f785676fSDimitry Andric     case PPC::PRED_GT_PLUS:
206f785676fSDimitry Andric     case PPC::PRED_GT:
207f785676fSDimitry Andric       O << "gt";
208f785676fSDimitry Andric       return;
209f785676fSDimitry Andric     case PPC::PRED_NE_MINUS:
210f785676fSDimitry Andric     case PPC::PRED_NE_PLUS:
211f785676fSDimitry Andric     case PPC::PRED_NE:
212f785676fSDimitry Andric       O << "ne";
213f785676fSDimitry Andric       return;
214f785676fSDimitry Andric     case PPC::PRED_UN_MINUS:
215f785676fSDimitry Andric     case PPC::PRED_UN_PLUS:
216f785676fSDimitry Andric     case PPC::PRED_UN:
217f785676fSDimitry Andric       O << "un";
218f785676fSDimitry Andric       return;
219f785676fSDimitry Andric     case PPC::PRED_NU_MINUS:
220f785676fSDimitry Andric     case PPC::PRED_NU_PLUS:
221f785676fSDimitry Andric     case PPC::PRED_NU:
222f785676fSDimitry Andric       O << "nu";
223f785676fSDimitry Andric       return;
22491bc56edSDimitry Andric     case PPC::PRED_BIT_SET:
22591bc56edSDimitry Andric     case PPC::PRED_BIT_UNSET:
22691bc56edSDimitry Andric       llvm_unreachable("Invalid use of bit predicate code");
2272754fe60SDimitry Andric     }
228f785676fSDimitry Andric     llvm_unreachable("Invalid predicate code");
229f785676fSDimitry Andric   }
230f785676fSDimitry Andric 
231f785676fSDimitry Andric   if (StringRef(Modifier) == "pm") {
232f785676fSDimitry Andric     switch ((PPC::Predicate)Code) {
233f785676fSDimitry Andric     case PPC::PRED_LT:
234f785676fSDimitry Andric     case PPC::PRED_LE:
235f785676fSDimitry Andric     case PPC::PRED_EQ:
236f785676fSDimitry Andric     case PPC::PRED_GE:
237f785676fSDimitry Andric     case PPC::PRED_GT:
238f785676fSDimitry Andric     case PPC::PRED_NE:
239f785676fSDimitry Andric     case PPC::PRED_UN:
240f785676fSDimitry Andric     case PPC::PRED_NU:
241f785676fSDimitry Andric       return;
242f785676fSDimitry Andric     case PPC::PRED_LT_MINUS:
243f785676fSDimitry Andric     case PPC::PRED_LE_MINUS:
244f785676fSDimitry Andric     case PPC::PRED_EQ_MINUS:
245f785676fSDimitry Andric     case PPC::PRED_GE_MINUS:
246f785676fSDimitry Andric     case PPC::PRED_GT_MINUS:
247f785676fSDimitry Andric     case PPC::PRED_NE_MINUS:
248f785676fSDimitry Andric     case PPC::PRED_UN_MINUS:
249f785676fSDimitry Andric     case PPC::PRED_NU_MINUS:
250f785676fSDimitry Andric       O << "-";
251f785676fSDimitry Andric       return;
252f785676fSDimitry Andric     case PPC::PRED_LT_PLUS:
253f785676fSDimitry Andric     case PPC::PRED_LE_PLUS:
254f785676fSDimitry Andric     case PPC::PRED_EQ_PLUS:
255f785676fSDimitry Andric     case PPC::PRED_GE_PLUS:
256f785676fSDimitry Andric     case PPC::PRED_GT_PLUS:
257f785676fSDimitry Andric     case PPC::PRED_NE_PLUS:
258f785676fSDimitry Andric     case PPC::PRED_UN_PLUS:
259f785676fSDimitry Andric     case PPC::PRED_NU_PLUS:
260f785676fSDimitry Andric       O << "+";
261f785676fSDimitry Andric       return;
26291bc56edSDimitry Andric     case PPC::PRED_BIT_SET:
26391bc56edSDimitry Andric     case PPC::PRED_BIT_UNSET:
26491bc56edSDimitry Andric       llvm_unreachable("Invalid use of bit predicate code");
265f785676fSDimitry Andric     }
266f785676fSDimitry Andric     llvm_unreachable("Invalid predicate code");
2672754fe60SDimitry Andric   }
2682754fe60SDimitry Andric 
2692754fe60SDimitry Andric   assert(StringRef(Modifier) == "reg" &&
270f785676fSDimitry Andric          "Need to specify 'cc', 'pm' or 'reg' as predicate op modifier!");
2712754fe60SDimitry Andric   printOperand(MI, OpNo+1, O);
2722754fe60SDimitry Andric }
2732754fe60SDimitry Andric 
printATBitsAsHint(const MCInst * MI,unsigned OpNo,raw_ostream & O)274d88c1a5aSDimitry Andric void PPCInstPrinter::printATBitsAsHint(const MCInst *MI, unsigned OpNo,
275d88c1a5aSDimitry Andric                                        raw_ostream &O) {
276d88c1a5aSDimitry Andric   unsigned Code = MI->getOperand(OpNo).getImm();
277d88c1a5aSDimitry Andric   if (Code == 2)
278d88c1a5aSDimitry Andric     O << "-";
279d88c1a5aSDimitry Andric   else if (Code == 3)
280d88c1a5aSDimitry Andric     O << "+";
281d88c1a5aSDimitry Andric }
282d88c1a5aSDimitry Andric 
printU1ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)283ff0cc061SDimitry Andric void PPCInstPrinter::printU1ImmOperand(const MCInst *MI, unsigned OpNo,
284ff0cc061SDimitry Andric                                        raw_ostream &O) {
285ff0cc061SDimitry Andric   unsigned int Value = MI->getOperand(OpNo).getImm();
286ff0cc061SDimitry Andric   assert(Value <= 1 && "Invalid u1imm argument!");
287ff0cc061SDimitry Andric   O << (unsigned int)Value;
288ff0cc061SDimitry Andric }
289ff0cc061SDimitry Andric 
printU2ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)29091bc56edSDimitry Andric void PPCInstPrinter::printU2ImmOperand(const MCInst *MI, unsigned OpNo,
29191bc56edSDimitry Andric                                        raw_ostream &O) {
29291bc56edSDimitry Andric   unsigned int Value = MI->getOperand(OpNo).getImm();
29391bc56edSDimitry Andric   assert(Value <= 3 && "Invalid u2imm argument!");
29491bc56edSDimitry Andric   O << (unsigned int)Value;
29591bc56edSDimitry Andric }
29691bc56edSDimitry Andric 
printU3ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)297ff0cc061SDimitry Andric void PPCInstPrinter::printU3ImmOperand(const MCInst *MI, unsigned OpNo,
298ff0cc061SDimitry Andric                                        raw_ostream &O) {
299ff0cc061SDimitry Andric   unsigned int Value = MI->getOperand(OpNo).getImm();
300ff0cc061SDimitry Andric   assert(Value <= 8 && "Invalid u3imm argument!");
301ff0cc061SDimitry Andric   O << (unsigned int)Value;
302ff0cc061SDimitry Andric }
303ff0cc061SDimitry Andric 
printU4ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)30439d628a0SDimitry Andric void PPCInstPrinter::printU4ImmOperand(const MCInst *MI, unsigned OpNo,
30539d628a0SDimitry Andric                                        raw_ostream &O) {
30639d628a0SDimitry Andric   unsigned int Value = MI->getOperand(OpNo).getImm();
30739d628a0SDimitry Andric   assert(Value <= 15 && "Invalid u4imm argument!");
30839d628a0SDimitry Andric   O << (unsigned int)Value;
30939d628a0SDimitry Andric }
31039d628a0SDimitry Andric 
printS5ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)3112754fe60SDimitry Andric void PPCInstPrinter::printS5ImmOperand(const MCInst *MI, unsigned OpNo,
3122754fe60SDimitry Andric                                        raw_ostream &O) {
3133861d79fSDimitry Andric   int Value = MI->getOperand(OpNo).getImm();
3143861d79fSDimitry Andric   Value = SignExtend32<5>(Value);
3152754fe60SDimitry Andric   O << (int)Value;
3162754fe60SDimitry Andric }
3172754fe60SDimitry Andric 
printU5ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)3182754fe60SDimitry Andric void PPCInstPrinter::printU5ImmOperand(const MCInst *MI, unsigned OpNo,
3192754fe60SDimitry Andric                                        raw_ostream &O) {
3203861d79fSDimitry Andric   unsigned int Value = MI->getOperand(OpNo).getImm();
3212754fe60SDimitry Andric   assert(Value <= 31 && "Invalid u5imm argument!");
3222754fe60SDimitry Andric   O << (unsigned int)Value;
3232754fe60SDimitry Andric }
3242754fe60SDimitry Andric 
printU6ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)3252754fe60SDimitry Andric void PPCInstPrinter::printU6ImmOperand(const MCInst *MI, unsigned OpNo,
3262754fe60SDimitry Andric                                        raw_ostream &O) {
3273861d79fSDimitry Andric   unsigned int Value = MI->getOperand(OpNo).getImm();
3282754fe60SDimitry Andric   assert(Value <= 63 && "Invalid u6imm argument!");
3292754fe60SDimitry Andric   O << (unsigned int)Value;
3302754fe60SDimitry Andric }
3312754fe60SDimitry Andric 
printU7ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)3323ca95b02SDimitry Andric void PPCInstPrinter::printU7ImmOperand(const MCInst *MI, unsigned OpNo,
3333ca95b02SDimitry Andric                                        raw_ostream &O) {
3343ca95b02SDimitry Andric   unsigned int Value = MI->getOperand(OpNo).getImm();
3353ca95b02SDimitry Andric   assert(Value <= 127 && "Invalid u7imm argument!");
3363ca95b02SDimitry Andric   O << (unsigned int)Value;
3373ca95b02SDimitry Andric }
3383ca95b02SDimitry Andric 
339d88c1a5aSDimitry Andric // Operands of BUILD_VECTOR are signed and we use this to print operands
340d88c1a5aSDimitry Andric // of XXSPLTIB which are unsigned. So we simply truncate to 8 bits and
341d88c1a5aSDimitry Andric // print as unsigned.
printU8ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)3423ca95b02SDimitry Andric void PPCInstPrinter::printU8ImmOperand(const MCInst *MI, unsigned OpNo,
3433ca95b02SDimitry Andric                                        raw_ostream &O) {
344d88c1a5aSDimitry Andric   unsigned char Value = MI->getOperand(OpNo).getImm();
3453ca95b02SDimitry Andric   O << (unsigned int)Value;
3463ca95b02SDimitry Andric }
3473ca95b02SDimitry Andric 
printU10ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)348ff0cc061SDimitry Andric void PPCInstPrinter::printU10ImmOperand(const MCInst *MI, unsigned OpNo,
349ff0cc061SDimitry Andric                                         raw_ostream &O) {
350ff0cc061SDimitry Andric   unsigned short Value = MI->getOperand(OpNo).getImm();
351ff0cc061SDimitry Andric   assert(Value <= 1023 && "Invalid u10imm argument!");
352ff0cc061SDimitry Andric   O << (unsigned short)Value;
353ff0cc061SDimitry Andric }
354ff0cc061SDimitry Andric 
printU12ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)355ff0cc061SDimitry Andric void PPCInstPrinter::printU12ImmOperand(const MCInst *MI, unsigned OpNo,
356ff0cc061SDimitry Andric                                         raw_ostream &O) {
357ff0cc061SDimitry Andric   unsigned short Value = MI->getOperand(OpNo).getImm();
358ff0cc061SDimitry Andric   assert(Value <= 4095 && "Invalid u12imm argument!");
359ff0cc061SDimitry Andric   O << (unsigned short)Value;
360ff0cc061SDimitry Andric }
361ff0cc061SDimitry Andric 
printS16ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)3622754fe60SDimitry Andric void PPCInstPrinter::printS16ImmOperand(const MCInst *MI, unsigned OpNo,
3632754fe60SDimitry Andric                                         raw_ostream &O) {
364f785676fSDimitry Andric   if (MI->getOperand(OpNo).isImm())
3652754fe60SDimitry Andric     O << (short)MI->getOperand(OpNo).getImm();
366f785676fSDimitry Andric   else
367f785676fSDimitry Andric     printOperand(MI, OpNo, O);
3682754fe60SDimitry Andric }
3692754fe60SDimitry Andric 
printU16ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)3702754fe60SDimitry Andric void PPCInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
3712754fe60SDimitry Andric                                         raw_ostream &O) {
3722754fe60SDimitry Andric   if (MI->getOperand(OpNo).isImm())
373f785676fSDimitry Andric     O << (unsigned short)MI->getOperand(OpNo).getImm();
3742754fe60SDimitry Andric   else
3752754fe60SDimitry Andric     printOperand(MI, OpNo, O);
3762754fe60SDimitry Andric }
3772754fe60SDimitry Andric 
printBranchOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)3782754fe60SDimitry Andric void PPCInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo,
3792754fe60SDimitry Andric                                         raw_ostream &O) {
3802754fe60SDimitry Andric   if (!MI->getOperand(OpNo).isImm())
3812754fe60SDimitry Andric     return printOperand(MI, OpNo, O);
3822754fe60SDimitry Andric 
3832754fe60SDimitry Andric   // Branches can take an immediate operand.  This is used by the branch
384284c1978SDimitry Andric   // selection pass to print .+8, an eight byte displacement from the PC.
385*85573313SDimitry Andric   O << ".";
386*85573313SDimitry Andric   int32_t Imm = SignExtend32<32>((unsigned)MI->getOperand(OpNo).getImm() << 2);
387*85573313SDimitry Andric   if (Imm >= 0)
388*85573313SDimitry Andric     O << "+";
389*85573313SDimitry Andric   O << Imm;
3902754fe60SDimitry Andric }
3912754fe60SDimitry Andric 
printAbsBranchOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)392f785676fSDimitry Andric void PPCInstPrinter::printAbsBranchOperand(const MCInst *MI, unsigned OpNo,
3932754fe60SDimitry Andric                                            raw_ostream &O) {
394f785676fSDimitry Andric   if (!MI->getOperand(OpNo).isImm())
395f785676fSDimitry Andric     return printOperand(MI, OpNo, O);
396f785676fSDimitry Andric 
3979cac79b3SDimitry Andric   O << SignExtend32<32>((unsigned)MI->getOperand(OpNo).getImm() << 2);
3982754fe60SDimitry Andric }
3992754fe60SDimitry Andric 
4002754fe60SDimitry Andric 
printcrbitm(const MCInst * MI,unsigned OpNo,raw_ostream & O)4012754fe60SDimitry Andric void PPCInstPrinter::printcrbitm(const MCInst *MI, unsigned OpNo,
4022754fe60SDimitry Andric                                  raw_ostream &O) {
4032754fe60SDimitry Andric   unsigned CCReg = MI->getOperand(OpNo).getReg();
4042754fe60SDimitry Andric   unsigned RegNo;
4052754fe60SDimitry Andric   switch (CCReg) {
406dff0c46cSDimitry Andric   default: llvm_unreachable("Unknown CR register");
4072754fe60SDimitry Andric   case PPC::CR0: RegNo = 0; break;
4082754fe60SDimitry Andric   case PPC::CR1: RegNo = 1; break;
4092754fe60SDimitry Andric   case PPC::CR2: RegNo = 2; break;
4102754fe60SDimitry Andric   case PPC::CR3: RegNo = 3; break;
4112754fe60SDimitry Andric   case PPC::CR4: RegNo = 4; break;
4122754fe60SDimitry Andric   case PPC::CR5: RegNo = 5; break;
4132754fe60SDimitry Andric   case PPC::CR6: RegNo = 6; break;
4142754fe60SDimitry Andric   case PPC::CR7: RegNo = 7; break;
4152754fe60SDimitry Andric   }
4162754fe60SDimitry Andric   O << (0x80 >> RegNo);
4172754fe60SDimitry Andric }
4182754fe60SDimitry Andric 
printMemRegImm(const MCInst * MI,unsigned OpNo,raw_ostream & O)4192754fe60SDimitry Andric void PPCInstPrinter::printMemRegImm(const MCInst *MI, unsigned OpNo,
4202754fe60SDimitry Andric                                     raw_ostream &O) {
421f785676fSDimitry Andric   printS16ImmOperand(MI, OpNo, O);
4222754fe60SDimitry Andric   O << '(';
4232754fe60SDimitry Andric   if (MI->getOperand(OpNo+1).getReg() == PPC::R0)
4242754fe60SDimitry Andric     O << "0";
4252754fe60SDimitry Andric   else
4262754fe60SDimitry Andric     printOperand(MI, OpNo+1, O);
4272754fe60SDimitry Andric   O << ')';
4282754fe60SDimitry Andric }
4292754fe60SDimitry Andric 
printMemRegReg(const MCInst * MI,unsigned OpNo,raw_ostream & O)4302754fe60SDimitry Andric void PPCInstPrinter::printMemRegReg(const MCInst *MI, unsigned OpNo,
4312754fe60SDimitry Andric                                     raw_ostream &O) {
4322754fe60SDimitry Andric   // When used as the base register, r0 reads constant zero rather than
4332754fe60SDimitry Andric   // the value contained in the register.  For this reason, the darwin
4342754fe60SDimitry Andric   // assembler requires that we print r0 as 0 (no r) when used as the base.
4352754fe60SDimitry Andric   if (MI->getOperand(OpNo).getReg() == PPC::R0)
4362754fe60SDimitry Andric     O << "0";
4372754fe60SDimitry Andric   else
4382754fe60SDimitry Andric     printOperand(MI, OpNo, O);
4392754fe60SDimitry Andric   O << ", ";
4402754fe60SDimitry Andric   printOperand(MI, OpNo+1, O);
4412754fe60SDimitry Andric }
4422754fe60SDimitry Andric 
printTLSCall(const MCInst * MI,unsigned OpNo,raw_ostream & O)443f785676fSDimitry Andric void PPCInstPrinter::printTLSCall(const MCInst *MI, unsigned OpNo,
444f785676fSDimitry Andric                                   raw_ostream &O) {
44526e25074SRoman Divacky   // On PPC64, VariantKind is VK_None, but on PPC32, it's VK_PLT, and it must
44626e25074SRoman Divacky   // come at the _end_ of the expression.
44726e25074SRoman Divacky   const MCOperand &Op = MI->getOperand(OpNo);
44826e25074SRoman Divacky   const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*Op.getExpr());
44926e25074SRoman Divacky   O << refExp.getSymbol().getName();
450f785676fSDimitry Andric   O << '(';
451f785676fSDimitry Andric   printOperand(MI, OpNo+1, O);
452f785676fSDimitry Andric   O << ')';
45326e25074SRoman Divacky   if (refExp.getKind() != MCSymbolRefExpr::VK_None)
45426e25074SRoman Divacky     O << '@' << MCSymbolRefExpr::getVariantKindName(refExp.getKind());
455f785676fSDimitry Andric }
4562754fe60SDimitry Andric 
4572cab237bSDimitry Andric /// showRegistersWithPercentPrefix - Check if this register name should be
4582cab237bSDimitry Andric /// printed with a percentage symbol as prefix.
showRegistersWithPercentPrefix(const char * RegName) const4592cab237bSDimitry Andric bool PPCInstPrinter::showRegistersWithPercentPrefix(const char *RegName) const {
4602cab237bSDimitry Andric   if (!FullRegNamesWithPercent || TT.isOSDarwin() || TT.getOS() == Triple::AIX)
4612cab237bSDimitry Andric     return false;
4622cab237bSDimitry Andric 
4632cab237bSDimitry Andric   switch (RegName[0]) {
4642cab237bSDimitry Andric   default:
4652cab237bSDimitry Andric     return false;
4662cab237bSDimitry Andric   case 'r':
4672cab237bSDimitry Andric   case 'f':
4682cab237bSDimitry Andric   case 'q':
4692cab237bSDimitry Andric   case 'v':
4702cab237bSDimitry Andric   case 'c':
4712cab237bSDimitry Andric     return true;
4722cab237bSDimitry Andric   }
4732cab237bSDimitry Andric }
4742cab237bSDimitry Andric 
4752cab237bSDimitry Andric /// getVerboseConditionalRegName - This method expands the condition register
4762cab237bSDimitry Andric /// when requested explicitly or targetting Darwin.
getVerboseConditionRegName(unsigned RegNum,unsigned RegEncoding) const4772cab237bSDimitry Andric const char *PPCInstPrinter::getVerboseConditionRegName(unsigned RegNum,
4782cab237bSDimitry Andric                                                        unsigned RegEncoding)
4792cab237bSDimitry Andric                                                        const {
4802cab237bSDimitry Andric   if (!TT.isOSDarwin() && !FullRegNames)
4812cab237bSDimitry Andric     return nullptr;
4822cab237bSDimitry Andric   if (RegNum < PPC::CR0EQ || RegNum > PPC::CR7UN)
4832cab237bSDimitry Andric     return nullptr;
4842cab237bSDimitry Andric   const char *CRBits[] = {
4852cab237bSDimitry Andric     "lt", "gt", "eq", "un",
4862cab237bSDimitry Andric     "4*cr1+lt", "4*cr1+gt", "4*cr1+eq", "4*cr1+un",
4872cab237bSDimitry Andric     "4*cr2+lt", "4*cr2+gt", "4*cr2+eq", "4*cr2+un",
4882cab237bSDimitry Andric     "4*cr3+lt", "4*cr3+gt", "4*cr3+eq", "4*cr3+un",
4892cab237bSDimitry Andric     "4*cr4+lt", "4*cr4+gt", "4*cr4+eq", "4*cr4+un",
4902cab237bSDimitry Andric     "4*cr5+lt", "4*cr5+gt", "4*cr5+eq", "4*cr5+un",
4912cab237bSDimitry Andric     "4*cr6+lt", "4*cr6+gt", "4*cr6+eq", "4*cr6+un",
4922cab237bSDimitry Andric     "4*cr7+lt", "4*cr7+gt", "4*cr7+eq", "4*cr7+un"
4932cab237bSDimitry Andric   };
4942cab237bSDimitry Andric   return CRBits[RegEncoding];
4952cab237bSDimitry Andric }
4962cab237bSDimitry Andric 
4972cab237bSDimitry Andric // showRegistersWithPrefix - This method determines whether registers
4982cab237bSDimitry Andric // should be number-only or include the prefix.
showRegistersWithPrefix() const4992cab237bSDimitry Andric bool PPCInstPrinter::showRegistersWithPrefix() const {
5002cab237bSDimitry Andric   if (TT.getOS() == Triple::AIX)
5012cab237bSDimitry Andric     return false;
5022cab237bSDimitry Andric   return TT.isOSDarwin() || FullRegNamesWithPercent || FullRegNames;
5032cab237bSDimitry Andric }
5042754fe60SDimitry Andric 
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)5052754fe60SDimitry Andric void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
5062754fe60SDimitry Andric                                   raw_ostream &O) {
5072754fe60SDimitry Andric   const MCOperand &Op = MI->getOperand(OpNo);
5082754fe60SDimitry Andric   if (Op.isReg()) {
509d88c1a5aSDimitry Andric     unsigned Reg = Op.getReg();
510b5893f02SDimitry Andric     if (!ShowVSRNumsAsVR)
511b5893f02SDimitry Andric       Reg = PPCInstrInfo::getRegNumForOperand(MII.get(MI->getOpcode()),
512b5893f02SDimitry Andric                                               Reg, OpNo);
513d88c1a5aSDimitry Andric 
5142cab237bSDimitry Andric     const char *RegName;
5152cab237bSDimitry Andric     RegName = getVerboseConditionRegName(Reg, MRI.getEncodingValue(Reg));
5162cab237bSDimitry Andric     if (RegName == nullptr)
5172cab237bSDimitry Andric      RegName = getRegisterName(Reg);
5182cab237bSDimitry Andric     if (showRegistersWithPercentPrefix(RegName))
5192cab237bSDimitry Andric       O << "%";
5202cab237bSDimitry Andric     if (!showRegistersWithPrefix())
521b5893f02SDimitry Andric       RegName = PPCRegisterInfo::stripRegisterPrefix(RegName);
5222754fe60SDimitry Andric 
5232754fe60SDimitry Andric     O << RegName;
5242754fe60SDimitry Andric     return;
5252754fe60SDimitry Andric   }
5262754fe60SDimitry Andric 
5272754fe60SDimitry Andric   if (Op.isImm()) {
5282754fe60SDimitry Andric     O << Op.getImm();
5292754fe60SDimitry Andric     return;
5302754fe60SDimitry Andric   }
5312754fe60SDimitry Andric 
5322754fe60SDimitry Andric   assert(Op.isExpr() && "unknown operand kind in printOperand");
53397bc6c73SDimitry Andric   Op.getExpr()->print(O, &MAI);
5342754fe60SDimitry Andric }
5352754fe60SDimitry Andric 
536