1218885Sdim//===-- PPCInstPrinter.cpp - Convert PPC MCInst to assembly syntax --------===//
2218885Sdim//
3218885Sdim//                     The LLVM Compiler Infrastructure
4218885Sdim//
5218885Sdim// This file is distributed under the University of Illinois Open Source
6218885Sdim// License. See LICENSE.TXT for details.
7218885Sdim//
8218885Sdim//===----------------------------------------------------------------------===//
9218885Sdim//
10218885Sdim// This class prints an PPC MCInst to a .s file.
11218885Sdim//
12218885Sdim//===----------------------------------------------------------------------===//
13218885Sdim
14218885Sdim#define DEBUG_TYPE "asm-printer"
15218885Sdim#include "PPCInstPrinter.h"
16249423Sdim#include "MCTargetDesc/PPCMCTargetDesc.h"
17226633Sdim#include "MCTargetDesc/PPCPredicates.h"
18218885Sdim#include "llvm/MC/MCExpr.h"
19218885Sdim#include "llvm/MC/MCInst.h"
20234353Sdim#include "llvm/MC/MCInstrInfo.h"
21263508Sdim#include "llvm/Support/CommandLine.h"
22218885Sdim#include "llvm/Support/raw_ostream.h"
23263508Sdim#include "llvm/Target/TargetOpcodes.h"
24218885Sdimusing namespace llvm;
25218885Sdim
26263508Sdim// FIXME: Once the integrated assembler supports full register names, tie this
27263508Sdim// to the verbose-asm setting.
28263508Sdimstatic cl::opt<bool>
29263508SdimFullRegNames("ppc-asm-full-reg-names", cl::Hidden, cl::init(false),
30263508Sdim             cl::desc("Use full register names when printing assembly"));
31263508Sdim
32218885Sdim#include "PPCGenAsmWriter.inc"
33218885Sdim
34223017Sdimvoid PPCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
35223017Sdim  OS << getRegisterName(RegNo);
36223017Sdim}
37218885Sdim
38226633Sdimvoid PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
39226633Sdim                               StringRef Annot) {
40218885Sdim  // Check for slwi/srwi mnemonics.
41218885Sdim  if (MI->getOpcode() == PPC::RLWINM) {
42218885Sdim    unsigned char SH = MI->getOperand(2).getImm();
43218885Sdim    unsigned char MB = MI->getOperand(3).getImm();
44218885Sdim    unsigned char ME = MI->getOperand(4).getImm();
45218885Sdim    bool useSubstituteMnemonic = false;
46218885Sdim    if (SH <= 31 && MB == 0 && ME == (31-SH)) {
47218885Sdim      O << "\tslwi "; useSubstituteMnemonic = true;
48218885Sdim    }
49218885Sdim    if (SH <= 31 && MB == (32-SH) && ME == 31) {
50218885Sdim      O << "\tsrwi "; useSubstituteMnemonic = true;
51218885Sdim      SH = 32-SH;
52218885Sdim    }
53218885Sdim    if (useSubstituteMnemonic) {
54218885Sdim      printOperand(MI, 0, O);
55218885Sdim      O << ", ";
56218885Sdim      printOperand(MI, 1, O);
57218885Sdim      O << ", " << (unsigned int)SH;
58226633Sdim
59226633Sdim      printAnnotation(O, Annot);
60218885Sdim      return;
61218885Sdim    }
62218885Sdim  }
63218885Sdim
64218885Sdim  if ((MI->getOpcode() == PPC::OR || MI->getOpcode() == PPC::OR8) &&
65218885Sdim      MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) {
66218885Sdim    O << "\tmr ";
67218885Sdim    printOperand(MI, 0, O);
68218885Sdim    O << ", ";
69218885Sdim    printOperand(MI, 1, O);
70226633Sdim    printAnnotation(O, Annot);
71218885Sdim    return;
72218885Sdim  }
73218885Sdim
74218885Sdim  if (MI->getOpcode() == PPC::RLDICR) {
75218885Sdim    unsigned char SH = MI->getOperand(2).getImm();
76218885Sdim    unsigned char ME = MI->getOperand(3).getImm();
77218885Sdim    // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH
78218885Sdim    if (63-SH == ME) {
79218885Sdim      O << "\tsldi ";
80218885Sdim      printOperand(MI, 0, O);
81218885Sdim      O << ", ";
82218885Sdim      printOperand(MI, 1, O);
83218885Sdim      O << ", " << (unsigned int)SH;
84226633Sdim      printAnnotation(O, Annot);
85218885Sdim      return;
86218885Sdim    }
87218885Sdim  }
88218885Sdim
89263508Sdim  // For fast-isel, a COPY_TO_REGCLASS may survive this long.  This is
90263508Sdim  // used when converting a 32-bit float to a 64-bit float as part of
91263508Sdim  // conversion to an integer (see PPCFastISel.cpp:SelectFPToI()),
92263508Sdim  // as otherwise we have problems with incorrect register classes
93263508Sdim  // in machine instruction verification.  For now, just avoid trying
94263508Sdim  // to print it as such an instruction has no effect (a 32-bit float
95263508Sdim  // in a register is already in 64-bit form, just with lower
96263508Sdim  // precision).  FIXME: Is there a better solution?
97263508Sdim  if (MI->getOpcode() == TargetOpcode::COPY_TO_REGCLASS)
98263508Sdim    return;
99263508Sdim
100218885Sdim  printInstruction(MI, O);
101226633Sdim  printAnnotation(O, Annot);
102218885Sdim}
103218885Sdim
104218885Sdim
105218885Sdimvoid PPCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
106218885Sdim                                           raw_ostream &O,
107218885Sdim                                           const char *Modifier) {
108218885Sdim  unsigned Code = MI->getOperand(OpNo).getImm();
109239462Sdim
110218885Sdim  if (StringRef(Modifier) == "cc") {
111218885Sdim    switch ((PPC::Predicate)Code) {
112263508Sdim    case PPC::PRED_LT_MINUS:
113263508Sdim    case PPC::PRED_LT_PLUS:
114263508Sdim    case PPC::PRED_LT:
115263508Sdim      O << "lt";
116263508Sdim      return;
117263508Sdim    case PPC::PRED_LE_MINUS:
118263508Sdim    case PPC::PRED_LE_PLUS:
119263508Sdim    case PPC::PRED_LE:
120263508Sdim      O << "le";
121263508Sdim      return;
122263508Sdim    case PPC::PRED_EQ_MINUS:
123263508Sdim    case PPC::PRED_EQ_PLUS:
124263508Sdim    case PPC::PRED_EQ:
125263508Sdim      O << "eq";
126263508Sdim      return;
127263508Sdim    case PPC::PRED_GE_MINUS:
128263508Sdim    case PPC::PRED_GE_PLUS:
129263508Sdim    case PPC::PRED_GE:
130263508Sdim      O << "ge";
131263508Sdim      return;
132263508Sdim    case PPC::PRED_GT_MINUS:
133263508Sdim    case PPC::PRED_GT_PLUS:
134263508Sdim    case PPC::PRED_GT:
135263508Sdim      O << "gt";
136263508Sdim      return;
137263508Sdim    case PPC::PRED_NE_MINUS:
138263508Sdim    case PPC::PRED_NE_PLUS:
139263508Sdim    case PPC::PRED_NE:
140263508Sdim      O << "ne";
141263508Sdim      return;
142263508Sdim    case PPC::PRED_UN_MINUS:
143263508Sdim    case PPC::PRED_UN_PLUS:
144263508Sdim    case PPC::PRED_UN:
145263508Sdim      O << "un";
146263508Sdim      return;
147263508Sdim    case PPC::PRED_NU_MINUS:
148263508Sdim    case PPC::PRED_NU_PLUS:
149263508Sdim    case PPC::PRED_NU:
150263508Sdim      O << "nu";
151263508Sdim      return;
152218885Sdim    }
153263508Sdim    llvm_unreachable("Invalid predicate code");
154218885Sdim  }
155263508Sdim
156263508Sdim  if (StringRef(Modifier) == "pm") {
157263508Sdim    switch ((PPC::Predicate)Code) {
158263508Sdim    case PPC::PRED_LT:
159263508Sdim    case PPC::PRED_LE:
160263508Sdim    case PPC::PRED_EQ:
161263508Sdim    case PPC::PRED_GE:
162263508Sdim    case PPC::PRED_GT:
163263508Sdim    case PPC::PRED_NE:
164263508Sdim    case PPC::PRED_UN:
165263508Sdim    case PPC::PRED_NU:
166263508Sdim      return;
167263508Sdim    case PPC::PRED_LT_MINUS:
168263508Sdim    case PPC::PRED_LE_MINUS:
169263508Sdim    case PPC::PRED_EQ_MINUS:
170263508Sdim    case PPC::PRED_GE_MINUS:
171263508Sdim    case PPC::PRED_GT_MINUS:
172263508Sdim    case PPC::PRED_NE_MINUS:
173263508Sdim    case PPC::PRED_UN_MINUS:
174263508Sdim    case PPC::PRED_NU_MINUS:
175263508Sdim      O << "-";
176263508Sdim      return;
177263508Sdim    case PPC::PRED_LT_PLUS:
178263508Sdim    case PPC::PRED_LE_PLUS:
179263508Sdim    case PPC::PRED_EQ_PLUS:
180263508Sdim    case PPC::PRED_GE_PLUS:
181263508Sdim    case PPC::PRED_GT_PLUS:
182263508Sdim    case PPC::PRED_NE_PLUS:
183263508Sdim    case PPC::PRED_UN_PLUS:
184263508Sdim    case PPC::PRED_NU_PLUS:
185263508Sdim      O << "+";
186263508Sdim      return;
187263508Sdim    }
188263508Sdim    llvm_unreachable("Invalid predicate code");
189263508Sdim  }
190218885Sdim
191218885Sdim  assert(StringRef(Modifier) == "reg" &&
192263508Sdim         "Need to specify 'cc', 'pm' or 'reg' as predicate op modifier!");
193218885Sdim  printOperand(MI, OpNo+1, O);
194218885Sdim}
195218885Sdim
196218885Sdimvoid PPCInstPrinter::printS5ImmOperand(const MCInst *MI, unsigned OpNo,
197218885Sdim                                       raw_ostream &O) {
198243830Sdim  int Value = MI->getOperand(OpNo).getImm();
199243830Sdim  Value = SignExtend32<5>(Value);
200218885Sdim  O << (int)Value;
201218885Sdim}
202218885Sdim
203218885Sdimvoid PPCInstPrinter::printU5ImmOperand(const MCInst *MI, unsigned OpNo,
204218885Sdim                                       raw_ostream &O) {
205243830Sdim  unsigned int Value = MI->getOperand(OpNo).getImm();
206218885Sdim  assert(Value <= 31 && "Invalid u5imm argument!");
207218885Sdim  O << (unsigned int)Value;
208218885Sdim}
209218885Sdim
210218885Sdimvoid PPCInstPrinter::printU6ImmOperand(const MCInst *MI, unsigned OpNo,
211218885Sdim                                       raw_ostream &O) {
212243830Sdim  unsigned int Value = MI->getOperand(OpNo).getImm();
213218885Sdim  assert(Value <= 63 && "Invalid u6imm argument!");
214218885Sdim  O << (unsigned int)Value;
215218885Sdim}
216218885Sdim
217218885Sdimvoid PPCInstPrinter::printS16ImmOperand(const MCInst *MI, unsigned OpNo,
218218885Sdim                                        raw_ostream &O) {
219263508Sdim  if (MI->getOperand(OpNo).isImm())
220263508Sdim    O << (short)MI->getOperand(OpNo).getImm();
221263508Sdim  else
222263508Sdim    printOperand(MI, OpNo, O);
223218885Sdim}
224218885Sdim
225218885Sdimvoid PPCInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
226218885Sdim                                        raw_ostream &O) {
227218885Sdim  if (MI->getOperand(OpNo).isImm())
228263508Sdim    O << (unsigned short)MI->getOperand(OpNo).getImm();
229218885Sdim  else
230218885Sdim    printOperand(MI, OpNo, O);
231218885Sdim}
232218885Sdim
233218885Sdimvoid PPCInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo,
234218885Sdim                                        raw_ostream &O) {
235218885Sdim  if (!MI->getOperand(OpNo).isImm())
236218885Sdim    return printOperand(MI, OpNo, O);
237218885Sdim
238218885Sdim  // Branches can take an immediate operand.  This is used by the branch
239251662Sdim  // selection pass to print .+8, an eight byte displacement from the PC.
240251662Sdim  O << ".+";
241263508Sdim  printAbsBranchOperand(MI, OpNo, O);
242218885Sdim}
243218885Sdim
244263508Sdimvoid PPCInstPrinter::printAbsBranchOperand(const MCInst *MI, unsigned OpNo,
245263508Sdim                                           raw_ostream &O) {
246263508Sdim  if (!MI->getOperand(OpNo).isImm())
247263508Sdim    return printOperand(MI, OpNo, O);
248263508Sdim
249218885Sdim  O << (int)MI->getOperand(OpNo).getImm()*4;
250218885Sdim}
251218885Sdim
252218885Sdim
253218885Sdimvoid PPCInstPrinter::printcrbitm(const MCInst *MI, unsigned OpNo,
254218885Sdim                                 raw_ostream &O) {
255218885Sdim  unsigned CCReg = MI->getOperand(OpNo).getReg();
256218885Sdim  unsigned RegNo;
257218885Sdim  switch (CCReg) {
258234353Sdim  default: llvm_unreachable("Unknown CR register");
259218885Sdim  case PPC::CR0: RegNo = 0; break;
260218885Sdim  case PPC::CR1: RegNo = 1; break;
261218885Sdim  case PPC::CR2: RegNo = 2; break;
262218885Sdim  case PPC::CR3: RegNo = 3; break;
263218885Sdim  case PPC::CR4: RegNo = 4; break;
264218885Sdim  case PPC::CR5: RegNo = 5; break;
265218885Sdim  case PPC::CR6: RegNo = 6; break;
266218885Sdim  case PPC::CR7: RegNo = 7; break;
267218885Sdim  }
268218885Sdim  O << (0x80 >> RegNo);
269218885Sdim}
270218885Sdim
271218885Sdimvoid PPCInstPrinter::printMemRegImm(const MCInst *MI, unsigned OpNo,
272218885Sdim                                    raw_ostream &O) {
273263508Sdim  printS16ImmOperand(MI, OpNo, O);
274218885Sdim  O << '(';
275218885Sdim  if (MI->getOperand(OpNo+1).getReg() == PPC::R0)
276218885Sdim    O << "0";
277218885Sdim  else
278218885Sdim    printOperand(MI, OpNo+1, O);
279218885Sdim  O << ')';
280218885Sdim}
281218885Sdim
282218885Sdimvoid PPCInstPrinter::printMemRegReg(const MCInst *MI, unsigned OpNo,
283218885Sdim                                    raw_ostream &O) {
284218885Sdim  // When used as the base register, r0 reads constant zero rather than
285218885Sdim  // the value contained in the register.  For this reason, the darwin
286218885Sdim  // assembler requires that we print r0 as 0 (no r) when used as the base.
287218885Sdim  if (MI->getOperand(OpNo).getReg() == PPC::R0)
288218885Sdim    O << "0";
289218885Sdim  else
290218885Sdim    printOperand(MI, OpNo, O);
291218885Sdim  O << ", ";
292218885Sdim  printOperand(MI, OpNo+1, O);
293218885Sdim}
294218885Sdim
295263508Sdimvoid PPCInstPrinter::printTLSCall(const MCInst *MI, unsigned OpNo,
296263508Sdim                                  raw_ostream &O) {
297263508Sdim  printBranchOperand(MI, OpNo, O);
298263508Sdim  O << '(';
299263508Sdim  printOperand(MI, OpNo+1, O);
300263508Sdim  O << ')';
301263508Sdim}
302218885Sdim
303218885Sdim
304218885Sdim/// stripRegisterPrefix - This method strips the character prefix from a
305218885Sdim/// register name so that only the number is left.  Used by for linux asm.
306218885Sdimstatic const char *stripRegisterPrefix(const char *RegName) {
307263508Sdim  if (FullRegNames)
308263508Sdim    return RegName;
309263508Sdim
310218885Sdim  switch (RegName[0]) {
311218885Sdim  case 'r':
312218885Sdim  case 'f':
313218885Sdim  case 'v': return RegName + 1;
314218885Sdim  case 'c': if (RegName[1] == 'r') return RegName + 2;
315218885Sdim  }
316218885Sdim
317218885Sdim  return RegName;
318218885Sdim}
319218885Sdim
320218885Sdimvoid PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
321218885Sdim                                  raw_ostream &O) {
322218885Sdim  const MCOperand &Op = MI->getOperand(OpNo);
323218885Sdim  if (Op.isReg()) {
324218885Sdim    const char *RegName = getRegisterName(Op.getReg());
325218885Sdim    // The linux and AIX assembler does not take register prefixes.
326218885Sdim    if (!isDarwinSyntax())
327218885Sdim      RegName = stripRegisterPrefix(RegName);
328218885Sdim
329218885Sdim    O << RegName;
330218885Sdim    return;
331218885Sdim  }
332218885Sdim
333218885Sdim  if (Op.isImm()) {
334218885Sdim    O << Op.getImm();
335218885Sdim    return;
336218885Sdim  }
337218885Sdim
338218885Sdim  assert(Op.isExpr() && "unknown operand kind in printOperand");
339218885Sdim  O << *Op.getExpr();
340218885Sdim}
341218885Sdim
342