PPCInstPrinter.cpp revision cde4ce411b1ace4a80ea1dd38df97e8508aed0c9
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 "PPCPredicates.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCInst.h"
19#include "llvm/Support/raw_ostream.h"
20using namespace llvm;
21
22#define GET_INSTRUCTION_NAME
23#include "PPCGenAsmWriter.inc"
24
25StringRef PPCInstPrinter::getOpcodeName(unsigned Opcode) const {
26  return getInstructionName(Opcode);
27}
28
29void PPCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
30  OS << getRegisterName(RegNo);
31}
32
33void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
34  // Check for slwi/srwi mnemonics.
35  if (MI->getOpcode() == PPC::RLWINM) {
36    unsigned char SH = MI->getOperand(2).getImm();
37    unsigned char MB = MI->getOperand(3).getImm();
38    unsigned char ME = MI->getOperand(4).getImm();
39    bool useSubstituteMnemonic = false;
40    if (SH <= 31 && MB == 0 && ME == (31-SH)) {
41      O << "\tslwi "; useSubstituteMnemonic = true;
42    }
43    if (SH <= 31 && MB == (32-SH) && ME == 31) {
44      O << "\tsrwi "; useSubstituteMnemonic = true;
45      SH = 32-SH;
46    }
47    if (useSubstituteMnemonic) {
48      printOperand(MI, 0, O);
49      O << ", ";
50      printOperand(MI, 1, O);
51      O << ", " << (unsigned int)SH;
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    return;
63  }
64
65  if (MI->getOpcode() == PPC::RLDICR) {
66    unsigned char SH = MI->getOperand(2).getImm();
67    unsigned char ME = MI->getOperand(3).getImm();
68    // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH
69    if (63-SH == ME) {
70      O << "\tsldi ";
71      printOperand(MI, 0, O);
72      O << ", ";
73      printOperand(MI, 1, O);
74      O << ", " << (unsigned int)SH;
75      return;
76    }
77  }
78
79  printInstruction(MI, O);
80}
81
82
83void PPCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
84                                           raw_ostream &O,
85                                           const char *Modifier) {
86  assert(Modifier && "Must specify 'cc' or 'reg' as predicate op modifier!");
87  unsigned Code = MI->getOperand(OpNo).getImm();
88  if (StringRef(Modifier) == "cc") {
89    switch ((PPC::Predicate)Code) {
90    default: assert(0 && "Invalid predicate");
91    case PPC::PRED_ALWAYS: return; // Don't print anything for always.
92    case PPC::PRED_LT: O << "lt"; return;
93    case PPC::PRED_LE: O << "le"; return;
94    case PPC::PRED_EQ: O << "eq"; return;
95    case PPC::PRED_GE: O << "ge"; return;
96    case PPC::PRED_GT: O << "gt"; return;
97    case PPC::PRED_NE: O << "ne"; return;
98    case PPC::PRED_UN: O << "un"; return;
99    case PPC::PRED_NU: O << "nu"; return;
100    }
101  }
102
103  assert(StringRef(Modifier) == "reg" &&
104         "Need to specify 'cc' or 'reg' as predicate op modifier!");
105  // Don't print the register for 'always'.
106  if (Code == PPC::PRED_ALWAYS) return;
107  printOperand(MI, OpNo+1, O);
108}
109
110void PPCInstPrinter::printS5ImmOperand(const MCInst *MI, unsigned OpNo,
111                                       raw_ostream &O) {
112  char Value = MI->getOperand(OpNo).getImm();
113  Value = (Value << (32-5)) >> (32-5);
114  O << (int)Value;
115}
116
117void PPCInstPrinter::printU5ImmOperand(const MCInst *MI, unsigned OpNo,
118                                       raw_ostream &O) {
119  unsigned char Value = MI->getOperand(OpNo).getImm();
120  assert(Value <= 31 && "Invalid u5imm argument!");
121  O << (unsigned int)Value;
122}
123
124void PPCInstPrinter::printU6ImmOperand(const MCInst *MI, unsigned OpNo,
125                                       raw_ostream &O) {
126  unsigned char Value = MI->getOperand(OpNo).getImm();
127  assert(Value <= 63 && "Invalid u6imm argument!");
128  O << (unsigned int)Value;
129}
130
131void PPCInstPrinter::printS16ImmOperand(const MCInst *MI, unsigned OpNo,
132                                        raw_ostream &O) {
133  O << (short)MI->getOperand(OpNo).getImm();
134}
135
136void PPCInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
137                                        raw_ostream &O) {
138  O << (unsigned short)MI->getOperand(OpNo).getImm();
139}
140
141void PPCInstPrinter::printS16X4ImmOperand(const MCInst *MI, unsigned OpNo,
142                                          raw_ostream &O) {
143  if (MI->getOperand(OpNo).isImm())
144    O << (short)(MI->getOperand(OpNo).getImm()*4);
145  else
146    printOperand(MI, OpNo, O);
147}
148
149void PPCInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo,
150                                        raw_ostream &O) {
151  if (!MI->getOperand(OpNo).isImm())
152    return printOperand(MI, OpNo, O);
153
154  // Branches can take an immediate operand.  This is used by the branch
155  // selection pass to print $+8, an eight byte displacement from the PC.
156  O << "$+";
157  printAbsAddrOperand(MI, OpNo, O);
158}
159
160void PPCInstPrinter::printAbsAddrOperand(const MCInst *MI, unsigned OpNo,
161                                         raw_ostream &O) {
162  O << (int)MI->getOperand(OpNo).getImm()*4;
163}
164
165
166void PPCInstPrinter::printcrbitm(const MCInst *MI, unsigned OpNo,
167                                 raw_ostream &O) {
168  unsigned CCReg = MI->getOperand(OpNo).getReg();
169  unsigned RegNo;
170  switch (CCReg) {
171  default: assert(0 && "Unknown CR register");
172  case PPC::CR0: RegNo = 0; break;
173  case PPC::CR1: RegNo = 1; break;
174  case PPC::CR2: RegNo = 2; break;
175  case PPC::CR3: RegNo = 3; break;
176  case PPC::CR4: RegNo = 4; break;
177  case PPC::CR5: RegNo = 5; break;
178  case PPC::CR6: RegNo = 6; break;
179  case PPC::CR7: RegNo = 7; break;
180  }
181  O << (0x80 >> RegNo);
182}
183
184void PPCInstPrinter::printMemRegImm(const MCInst *MI, unsigned OpNo,
185                                    raw_ostream &O) {
186  printSymbolLo(MI, OpNo, O);
187  O << '(';
188  if (MI->getOperand(OpNo+1).getReg() == PPC::R0)
189    O << "0";
190  else
191    printOperand(MI, OpNo+1, O);
192  O << ')';
193}
194
195void PPCInstPrinter::printMemRegImmShifted(const MCInst *MI, unsigned OpNo,
196                                           raw_ostream &O) {
197  if (MI->getOperand(OpNo).isImm())
198    printS16X4ImmOperand(MI, OpNo, O);
199  else
200    printSymbolLo(MI, OpNo, O);
201  O << '(';
202
203  if (MI->getOperand(OpNo+1).getReg() == PPC::R0)
204    O << "0";
205  else
206    printOperand(MI, OpNo+1, O);
207  O << ')';
208}
209
210
211void PPCInstPrinter::printMemRegReg(const MCInst *MI, unsigned OpNo,
212                                    raw_ostream &O) {
213  // When used as the base register, r0 reads constant zero rather than
214  // the value contained in the register.  For this reason, the darwin
215  // assembler requires that we print r0 as 0 (no r) when used as the base.
216  if (MI->getOperand(OpNo).getReg() == PPC::R0)
217    O << "0";
218  else
219    printOperand(MI, OpNo, O);
220  O << ", ";
221  printOperand(MI, OpNo+1, O);
222}
223
224
225
226/// stripRegisterPrefix - This method strips the character prefix from a
227/// register name so that only the number is left.  Used by for linux asm.
228static const char *stripRegisterPrefix(const char *RegName) {
229  switch (RegName[0]) {
230  case 'r':
231  case 'f':
232  case 'v': return RegName + 1;
233  case 'c': if (RegName[1] == 'r') return RegName + 2;
234  }
235
236  return RegName;
237}
238
239void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
240                                  raw_ostream &O) {
241  const MCOperand &Op = MI->getOperand(OpNo);
242  if (Op.isReg()) {
243    const char *RegName = getRegisterName(Op.getReg());
244    // The linux and AIX assembler does not take register prefixes.
245    if (!isDarwinSyntax())
246      RegName = stripRegisterPrefix(RegName);
247
248    O << RegName;
249    return;
250  }
251
252  if (Op.isImm()) {
253    O << Op.getImm();
254    return;
255  }
256
257  assert(Op.isExpr() && "unknown operand kind in printOperand");
258  O << *Op.getExpr();
259}
260
261void PPCInstPrinter::printSymbolLo(const MCInst *MI, unsigned OpNo,
262                                   raw_ostream &O) {
263  if (MI->getOperand(OpNo).isImm())
264    return printS16ImmOperand(MI, OpNo, O);
265
266  // FIXME: This is a terrible hack because we can't encode lo16() as an operand
267  // flag of a subtraction.  See the FIXME in GetSymbolRef in PPCMCInstLower.
268  if (MI->getOperand(OpNo).isExpr() &&
269      isa<MCBinaryExpr>(MI->getOperand(OpNo).getExpr())) {
270    O << "lo16(";
271    printOperand(MI, OpNo, O);
272    O << ')';
273  } else {
274    printOperand(MI, OpNo, O);
275  }
276}
277
278void PPCInstPrinter::printSymbolHi(const MCInst *MI, unsigned OpNo,
279                                   raw_ostream &O) {
280  if (MI->getOperand(OpNo).isImm())
281    return printS16ImmOperand(MI, OpNo, O);
282
283  // FIXME: This is a terrible hack because we can't encode lo16() as an operand
284  // flag of a subtraction.  See the FIXME in GetSymbolRef in PPCMCInstLower.
285  if (MI->getOperand(OpNo).isExpr() &&
286      isa<MCBinaryExpr>(MI->getOperand(OpNo).getExpr())) {
287    O << "ha16(";
288    printOperand(MI, OpNo, O);
289    O << ')';
290  } else {
291    printOperand(MI, OpNo, O);
292  }
293}
294
295
296