1//===-- PPCInstPrinter.cpp - Convert PPC MCInst to assembly syntax --------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This class prints an PPC MCInst to a .s file.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "asm-printer"
15#include "PPCInstPrinter.h"
16#include "MCTargetDesc/PPCMCTargetDesc.h"
17#include "MCTargetDesc/PPCPredicates.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCInst.h"
20#include "llvm/MC/MCInstrInfo.h"
21#include "llvm/Support/raw_ostream.h"
22using namespace llvm;
23
24#include "PPCGenAsmWriter.inc"
25
26void PPCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
27  OS << getRegisterName(RegNo);
28}
29
30void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
31                               StringRef Annot) {
32  // Check for slwi/srwi mnemonics.
33  if (MI->getOpcode() == PPC::RLWINM) {
34    unsigned char SH = MI->getOperand(2).getImm();
35    unsigned char MB = MI->getOperand(3).getImm();
36    unsigned char ME = MI->getOperand(4).getImm();
37    bool useSubstituteMnemonic = false;
38    if (SH <= 31 && MB == 0 && ME == (31-SH)) {
39      O << "\tslwi "; useSubstituteMnemonic = true;
40    }
41    if (SH <= 31 && MB == (32-SH) && ME == 31) {
42      O << "\tsrwi "; useSubstituteMnemonic = true;
43      SH = 32-SH;
44    }
45    if (useSubstituteMnemonic) {
46      printOperand(MI, 0, O);
47      O << ", ";
48      printOperand(MI, 1, O);
49      O << ", " << (unsigned int)SH;
50
51      printAnnotation(O, Annot);
52      return;
53    }
54  }
55
56  if ((MI->getOpcode() == PPC::OR || MI->getOpcode() == PPC::OR8) &&
57      MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) {
58    O << "\tmr ";
59    printOperand(MI, 0, O);
60    O << ", ";
61    printOperand(MI, 1, O);
62    printAnnotation(O, Annot);
63    return;
64  }
65
66  if (MI->getOpcode() == PPC::RLDICR) {
67    unsigned char SH = MI->getOperand(2).getImm();
68    unsigned char ME = MI->getOperand(3).getImm();
69    // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH
70    if (63-SH == ME) {
71      O << "\tsldi ";
72      printOperand(MI, 0, O);
73      O << ", ";
74      printOperand(MI, 1, O);
75      O << ", " << (unsigned int)SH;
76      printAnnotation(O, Annot);
77      return;
78    }
79  }
80
81  printInstruction(MI, O);
82  printAnnotation(O, Annot);
83}
84
85
86void PPCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
87                                           raw_ostream &O,
88                                           const char *Modifier) {
89  unsigned Code = MI->getOperand(OpNo).getImm();
90
91  if (StringRef(Modifier) == "cc") {
92    switch ((PPC::Predicate)Code) {
93    case PPC::PRED_LT_MINUS:
94    case PPC::PRED_LT_PLUS:
95    case PPC::PRED_LT:
96      O << "lt";
97      return;
98    case PPC::PRED_LE_MINUS:
99    case PPC::PRED_LE_PLUS:
100    case PPC::PRED_LE:
101      O << "le";
102      return;
103    case PPC::PRED_EQ_MINUS:
104    case PPC::PRED_EQ_PLUS:
105    case PPC::PRED_EQ:
106      O << "eq";
107      return;
108    case PPC::PRED_GE_MINUS:
109    case PPC::PRED_GE_PLUS:
110    case PPC::PRED_GE:
111      O << "ge";
112      return;
113    case PPC::PRED_GT_MINUS:
114    case PPC::PRED_GT_PLUS:
115    case PPC::PRED_GT:
116      O << "gt";
117      return;
118    case PPC::PRED_NE_MINUS:
119    case PPC::PRED_NE_PLUS:
120    case PPC::PRED_NE:
121      O << "ne";
122      return;
123    case PPC::PRED_UN_MINUS:
124    case PPC::PRED_UN_PLUS:
125    case PPC::PRED_UN:
126      O << "un";
127      return;
128    case PPC::PRED_NU_MINUS:
129    case PPC::PRED_NU_PLUS:
130    case PPC::PRED_NU:
131      O << "nu";
132      return;
133    }
134    llvm_unreachable("Invalid predicate code");
135  }
136
137  if (StringRef(Modifier) == "pm") {
138    switch ((PPC::Predicate)Code) {
139    case PPC::PRED_LT:
140    case PPC::PRED_LE:
141    case PPC::PRED_EQ:
142    case PPC::PRED_GE:
143    case PPC::PRED_GT:
144    case PPC::PRED_NE:
145    case PPC::PRED_UN:
146    case PPC::PRED_NU:
147      return;
148    case PPC::PRED_LT_MINUS:
149    case PPC::PRED_LE_MINUS:
150    case PPC::PRED_EQ_MINUS:
151    case PPC::PRED_GE_MINUS:
152    case PPC::PRED_GT_MINUS:
153    case PPC::PRED_NE_MINUS:
154    case PPC::PRED_UN_MINUS:
155    case PPC::PRED_NU_MINUS:
156      O << "-";
157      return;
158    case PPC::PRED_LT_PLUS:
159    case PPC::PRED_LE_PLUS:
160    case PPC::PRED_EQ_PLUS:
161    case PPC::PRED_GE_PLUS:
162    case PPC::PRED_GT_PLUS:
163    case PPC::PRED_NE_PLUS:
164    case PPC::PRED_UN_PLUS:
165    case PPC::PRED_NU_PLUS:
166      O << "+";
167      return;
168    }
169    llvm_unreachable("Invalid predicate code");
170  }
171
172  assert(StringRef(Modifier) == "reg" &&
173         "Need to specify 'cc', 'pm' or 'reg' as predicate op modifier!");
174  printOperand(MI, OpNo+1, O);
175}
176
177void PPCInstPrinter::printS5ImmOperand(const MCInst *MI, unsigned OpNo,
178                                       raw_ostream &O) {
179  int Value = MI->getOperand(OpNo).getImm();
180  Value = SignExtend32<5>(Value);
181  O << (int)Value;
182}
183
184void PPCInstPrinter::printU5ImmOperand(const MCInst *MI, unsigned OpNo,
185                                       raw_ostream &O) {
186  unsigned int Value = MI->getOperand(OpNo).getImm();
187  assert(Value <= 31 && "Invalid u5imm argument!");
188  O << (unsigned int)Value;
189}
190
191void PPCInstPrinter::printU6ImmOperand(const MCInst *MI, unsigned OpNo,
192                                       raw_ostream &O) {
193  unsigned int Value = MI->getOperand(OpNo).getImm();
194  assert(Value <= 63 && "Invalid u6imm argument!");
195  O << (unsigned int)Value;
196}
197
198void PPCInstPrinter::printS16ImmOperand(const MCInst *MI, unsigned OpNo,
199                                        raw_ostream &O) {
200  if (MI->getOperand(OpNo).isImm())
201    O << (short)MI->getOperand(OpNo).getImm();
202  else
203    printOperand(MI, OpNo, O);
204}
205
206void PPCInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
207                                        raw_ostream &O) {
208  if (MI->getOperand(OpNo).isImm())
209    O << (unsigned short)MI->getOperand(OpNo).getImm();
210  else
211    printOperand(MI, OpNo, O);
212}
213
214void PPCInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo,
215                                        raw_ostream &O) {
216  if (!MI->getOperand(OpNo).isImm())
217    return printOperand(MI, OpNo, O);
218
219  // Branches can take an immediate operand.  This is used by the branch
220  // selection pass to print .+8, an eight byte displacement from the PC.
221  O << ".+";
222  printAbsBranchOperand(MI, OpNo, O);
223}
224
225void PPCInstPrinter::printAbsBranchOperand(const MCInst *MI, unsigned OpNo,
226                                           raw_ostream &O) {
227  if (!MI->getOperand(OpNo).isImm())
228    return printOperand(MI, OpNo, O);
229
230  O << (int)MI->getOperand(OpNo).getImm()*4;
231}
232
233
234void PPCInstPrinter::printcrbitm(const MCInst *MI, unsigned OpNo,
235                                 raw_ostream &O) {
236  unsigned CCReg = MI->getOperand(OpNo).getReg();
237  unsigned RegNo;
238  switch (CCReg) {
239  default: llvm_unreachable("Unknown CR register");
240  case PPC::CR0: RegNo = 0; break;
241  case PPC::CR1: RegNo = 1; break;
242  case PPC::CR2: RegNo = 2; break;
243  case PPC::CR3: RegNo = 3; break;
244  case PPC::CR4: RegNo = 4; break;
245  case PPC::CR5: RegNo = 5; break;
246  case PPC::CR6: RegNo = 6; break;
247  case PPC::CR7: RegNo = 7; break;
248  }
249  O << (0x80 >> RegNo);
250}
251
252void PPCInstPrinter::printMemRegImm(const MCInst *MI, unsigned OpNo,
253                                    raw_ostream &O) {
254  printS16ImmOperand(MI, OpNo, O);
255  O << '(';
256  if (MI->getOperand(OpNo+1).getReg() == PPC::R0)
257    O << "0";
258  else
259    printOperand(MI, OpNo+1, O);
260  O << ')';
261}
262
263void PPCInstPrinter::printMemRegReg(const MCInst *MI, unsigned OpNo,
264                                    raw_ostream &O) {
265  // When used as the base register, r0 reads constant zero rather than
266  // the value contained in the register.  For this reason, the darwin
267  // assembler requires that we print r0 as 0 (no r) when used as the base.
268  if (MI->getOperand(OpNo).getReg() == PPC::R0)
269    O << "0";
270  else
271    printOperand(MI, OpNo, O);
272  O << ", ";
273  printOperand(MI, OpNo+1, O);
274}
275
276void PPCInstPrinter::printTLSCall(const MCInst *MI, unsigned OpNo,
277                                  raw_ostream &O) {
278  printBranchOperand(MI, OpNo, O);
279  O << '(';
280  printOperand(MI, OpNo+1, O);
281  O << ')';
282}
283
284
285/// stripRegisterPrefix - This method strips the character prefix from a
286/// register name so that only the number is left.  Used by for linux asm.
287static const char *stripRegisterPrefix(const char *RegName) {
288  switch (RegName[0]) {
289  case 'r':
290  case 'f':
291  case 'v': return RegName + 1;
292  case 'c': if (RegName[1] == 'r') return RegName + 2;
293  }
294
295  return RegName;
296}
297
298void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
299                                  raw_ostream &O) {
300  const MCOperand &Op = MI->getOperand(OpNo);
301  if (Op.isReg()) {
302    const char *RegName = getRegisterName(Op.getReg());
303    // The linux and AIX assembler does not take register prefixes.
304    if (!isDarwinSyntax())
305      RegName = stripRegisterPrefix(RegName);
306
307    O << RegName;
308    return;
309  }
310
311  if (Op.isImm()) {
312    O << Op.getImm();
313    return;
314  }
315
316  assert(Op.isExpr() && "unknown operand kind in printOperand");
317  O << *Op.getExpr();
318}
319
320