PPCInstPrinter.cpp revision 0a2f793d6e24acd00d9209b46436b4899feb1cdb
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/PPCBaseInfo.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  if (!Modifier) {
91    unsigned CCReg = MI->getOperand(OpNo+1).getReg();
92    unsigned RegNo;
93    switch (CCReg) {
94    default: llvm_unreachable("Unknown CR register");
95    case PPC::CR0: RegNo = 0; break;
96    case PPC::CR1: RegNo = 1; break;
97    case PPC::CR2: RegNo = 2; break;
98    case PPC::CR3: RegNo = 3; break;
99    case PPC::CR4: RegNo = 4; break;
100    case PPC::CR5: RegNo = 5; break;
101    case PPC::CR6: RegNo = 6; break;
102    case PPC::CR7: RegNo = 7; break;
103    }
104
105    // Print the CR bit number. The Code is ((BI << 5) | BO) for a
106    // BCC, but we must have the positive form here (BO == 12)
107    unsigned BI = Code >> 5;
108    assert((Code & 0xF) == 12 &&
109           "BO in predicate bit must have the positive form");
110
111    unsigned Value = 4*RegNo + BI;
112    O << Value;
113    return;
114  }
115
116  if (StringRef(Modifier) == "cc") {
117    switch ((PPC::Predicate)Code) {
118    case PPC::PRED_ALWAYS: return; // Don't print anything for always.
119    case PPC::PRED_LT: O << "lt"; return;
120    case PPC::PRED_LE: O << "le"; return;
121    case PPC::PRED_EQ: O << "eq"; return;
122    case PPC::PRED_GE: O << "ge"; return;
123    case PPC::PRED_GT: O << "gt"; return;
124    case PPC::PRED_NE: O << "ne"; return;
125    case PPC::PRED_UN: O << "un"; return;
126    case PPC::PRED_NU: O << "nu"; return;
127    }
128  }
129
130  assert(StringRef(Modifier) == "reg" &&
131         "Need to specify 'cc' or 'reg' as predicate op modifier!");
132  // Don't print the register for 'always'.
133  if (Code == PPC::PRED_ALWAYS) return;
134  printOperand(MI, OpNo+1, O);
135}
136
137void PPCInstPrinter::printS5ImmOperand(const MCInst *MI, unsigned OpNo,
138                                       raw_ostream &O) {
139  char Value = MI->getOperand(OpNo).getImm();
140  Value = (Value << (32-5)) >> (32-5);
141  O << (int)Value;
142}
143
144void PPCInstPrinter::printU5ImmOperand(const MCInst *MI, unsigned OpNo,
145                                       raw_ostream &O) {
146  unsigned char Value = MI->getOperand(OpNo).getImm();
147  assert(Value <= 31 && "Invalid u5imm argument!");
148  O << (unsigned int)Value;
149}
150
151void PPCInstPrinter::printU6ImmOperand(const MCInst *MI, unsigned OpNo,
152                                       raw_ostream &O) {
153  unsigned char Value = MI->getOperand(OpNo).getImm();
154  assert(Value <= 63 && "Invalid u6imm argument!");
155  O << (unsigned int)Value;
156}
157
158void PPCInstPrinter::printS16ImmOperand(const MCInst *MI, unsigned OpNo,
159                                        raw_ostream &O) {
160  O << (short)MI->getOperand(OpNo).getImm();
161}
162
163void PPCInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
164                                        raw_ostream &O) {
165  O << (unsigned short)MI->getOperand(OpNo).getImm();
166}
167
168void PPCInstPrinter::printS16X4ImmOperand(const MCInst *MI, unsigned OpNo,
169                                          raw_ostream &O) {
170  if (MI->getOperand(OpNo).isImm())
171    O << (short)(MI->getOperand(OpNo).getImm()*4);
172  else
173    printOperand(MI, OpNo, O);
174}
175
176void PPCInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo,
177                                        raw_ostream &O) {
178  if (!MI->getOperand(OpNo).isImm())
179    return printOperand(MI, OpNo, O);
180
181  // Branches can take an immediate operand.  This is used by the branch
182  // selection pass to print $+8, an eight byte displacement from the PC.
183  O << "$+";
184  printAbsAddrOperand(MI, OpNo, O);
185}
186
187void PPCInstPrinter::printAbsAddrOperand(const MCInst *MI, unsigned OpNo,
188                                         raw_ostream &O) {
189  O << (int)MI->getOperand(OpNo).getImm()*4;
190}
191
192
193void PPCInstPrinter::printcrbitm(const MCInst *MI, unsigned OpNo,
194                                 raw_ostream &O) {
195  unsigned CCReg = MI->getOperand(OpNo).getReg();
196  unsigned RegNo;
197  switch (CCReg) {
198  default: llvm_unreachable("Unknown CR register");
199  case PPC::CR0: RegNo = 0; break;
200  case PPC::CR1: RegNo = 1; break;
201  case PPC::CR2: RegNo = 2; break;
202  case PPC::CR3: RegNo = 3; break;
203  case PPC::CR4: RegNo = 4; break;
204  case PPC::CR5: RegNo = 5; break;
205  case PPC::CR6: RegNo = 6; break;
206  case PPC::CR7: RegNo = 7; break;
207  }
208  O << (0x80 >> RegNo);
209}
210
211void PPCInstPrinter::printMemRegImm(const MCInst *MI, unsigned OpNo,
212                                    raw_ostream &O) {
213  printSymbolLo(MI, OpNo, O);
214  O << '(';
215  if (MI->getOperand(OpNo+1).getReg() == PPC::R0)
216    O << "0";
217  else
218    printOperand(MI, OpNo+1, O);
219  O << ')';
220}
221
222void PPCInstPrinter::printMemRegImmShifted(const MCInst *MI, unsigned OpNo,
223                                           raw_ostream &O) {
224  if (MI->getOperand(OpNo).isImm())
225    printS16X4ImmOperand(MI, OpNo, O);
226  else
227    printSymbolLo(MI, OpNo, O);
228  O << '(';
229
230  if (MI->getOperand(OpNo+1).getReg() == PPC::R0)
231    O << "0";
232  else
233    printOperand(MI, OpNo+1, O);
234  O << ')';
235}
236
237
238void PPCInstPrinter::printMemRegReg(const MCInst *MI, unsigned OpNo,
239                                    raw_ostream &O) {
240  // When used as the base register, r0 reads constant zero rather than
241  // the value contained in the register.  For this reason, the darwin
242  // assembler requires that we print r0 as 0 (no r) when used as the base.
243  if (MI->getOperand(OpNo).getReg() == PPC::R0)
244    O << "0";
245  else
246    printOperand(MI, OpNo, O);
247  O << ", ";
248  printOperand(MI, OpNo+1, O);
249}
250
251
252
253/// stripRegisterPrefix - This method strips the character prefix from a
254/// register name so that only the number is left.  Used by for linux asm.
255static const char *stripRegisterPrefix(const char *RegName) {
256  switch (RegName[0]) {
257  case 'r':
258  case 'f':
259  case 'v': return RegName + 1;
260  case 'c': if (RegName[1] == 'r') return RegName + 2;
261  }
262
263  return RegName;
264}
265
266void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
267                                  raw_ostream &O) {
268  const MCOperand &Op = MI->getOperand(OpNo);
269  if (Op.isReg()) {
270    const char *RegName = getRegisterName(Op.getReg());
271    // The linux and AIX assembler does not take register prefixes.
272    if (!isDarwinSyntax())
273      RegName = stripRegisterPrefix(RegName);
274
275    O << RegName;
276    return;
277  }
278
279  if (Op.isImm()) {
280    O << Op.getImm();
281    return;
282  }
283
284  assert(Op.isExpr() && "unknown operand kind in printOperand");
285  O << *Op.getExpr();
286}
287
288void PPCInstPrinter::printSymbolLo(const MCInst *MI, unsigned OpNo,
289                                   raw_ostream &O) {
290  if (MI->getOperand(OpNo).isImm())
291    return printS16ImmOperand(MI, OpNo, O);
292
293  // FIXME: This is a terrible hack because we can't encode lo16() as an operand
294  // flag of a subtraction.  See the FIXME in GetSymbolRef in PPCMCInstLower.
295  if (MI->getOperand(OpNo).isExpr() &&
296      isa<MCBinaryExpr>(MI->getOperand(OpNo).getExpr())) {
297    O << "lo16(";
298    printOperand(MI, OpNo, O);
299    O << ')';
300  } else {
301    printOperand(MI, OpNo, O);
302  }
303}
304
305void PPCInstPrinter::printSymbolHi(const MCInst *MI, unsigned OpNo,
306                                   raw_ostream &O) {
307  if (MI->getOperand(OpNo).isImm())
308    return printS16ImmOperand(MI, OpNo, O);
309
310  // FIXME: This is a terrible hack because we can't encode lo16() as an operand
311  // flag of a subtraction.  See the FIXME in GetSymbolRef in PPCMCInstLower.
312  if (MI->getOperand(OpNo).isExpr() &&
313      isa<MCBinaryExpr>(MI->getOperand(OpNo).getExpr())) {
314    O << "ha16(";
315    printOperand(MI, OpNo, O);
316    O << ')';
317  } else {
318    printOperand(MI, OpNo, O);
319  }
320}
321
322
323