implement pretty printing support for the various pseudo
[oota-llvm.git] / lib / Target / PowerPC / InstPrinter / PPCInstPrinter.cpp
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 "llvm/MC/MCExpr.h"
17 #include "llvm/MC/MCInst.h"
18 //#include "llvm/MC/MCAsmInfo.h"
19 //#include "llvm/ADT/StringExtras.h"
20 #include "llvm/Support/raw_ostream.h"
21
22 #include "PPCGenRegisterNames.inc"
23 #include "PPCGenInstrNames.inc"
24 using namespace llvm;
25
26 #define GET_INSTRUCTION_NAME
27 #define PPCAsmPrinter PPCInstPrinter
28 #define MachineInstr MCInst
29 #include "PPCGenAsmWriter.inc"
30
31 StringRef PPCInstPrinter::getOpcodeName(unsigned Opcode) const {
32   return getInstructionName(Opcode);
33 }
34
35
36 void PPCInstPrinter::printInst(const MCInst *MI, raw_ostream &O) {
37   // TODO: pseudo ops.
38   
39   // Check for slwi/srwi mnemonics.
40   if (MI->getOpcode() == PPC::RLWINM) {
41     unsigned char SH = MI->getOperand(2).getImm();
42     unsigned char MB = MI->getOperand(3).getImm();
43     unsigned char ME = MI->getOperand(4).getImm();
44     bool useSubstituteMnemonic = false;
45     if (SH <= 31 && MB == 0 && ME == (31-SH)) {
46       O << "\tslwi "; useSubstituteMnemonic = true;
47     }
48     if (SH <= 31 && MB == (32-SH) && ME == 31) {
49       O << "\tsrwi "; useSubstituteMnemonic = true;
50       SH = 32-SH;
51     }
52     if (useSubstituteMnemonic) {
53       printOperand(MI, 0, O);
54       O << ", ";
55       printOperand(MI, 1, O);
56       O << ", " << (unsigned int)SH;
57       return;
58     }
59   }
60   
61   if ((MI->getOpcode() == PPC::OR || MI->getOpcode() == PPC::OR8) &&
62       MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) {
63     O << "\tmr ";
64     printOperand(MI, 0, O);
65     O << ", ";
66     printOperand(MI, 1, O);
67     return;
68   }
69   
70   if (MI->getOpcode() == PPC::RLDICR) {
71     unsigned char SH = MI->getOperand(2).getImm();
72     unsigned char ME = MI->getOperand(3).getImm();
73     // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH
74     if (63-SH == ME) {
75       O << "\tsldi ";
76       printOperand(MI, 0, O);
77       O << ", ";
78       printOperand(MI, 1, O);
79       O << ", " << (unsigned int)SH;
80       return;
81     }
82   }
83   
84   printInstruction(MI, O);
85 }
86
87 void PPCInstPrinter::printS5ImmOperand(const MCInst *MI, unsigned OpNo,
88                                        raw_ostream &O) {
89   char Value = MI->getOperand(OpNo).getImm();
90   Value = (Value << (32-5)) >> (32-5);
91   O << (int)Value;
92 }
93
94 void PPCInstPrinter::printU5ImmOperand(const MCInst *MI, unsigned OpNo,
95                                        raw_ostream &O) {
96   unsigned char Value = MI->getOperand(OpNo).getImm();
97   assert(Value <= 31 && "Invalid u5imm argument!");
98   O << (unsigned int)Value;
99 }
100
101 void PPCInstPrinter::printU6ImmOperand(const MCInst *MI, unsigned OpNo,
102                                        raw_ostream &O) {
103   unsigned char Value = MI->getOperand(OpNo).getImm();
104   assert(Value <= 63 && "Invalid u6imm argument!");
105   O << (unsigned int)Value;
106 }
107
108 void PPCInstPrinter::printS16ImmOperand(const MCInst *MI, unsigned OpNo,
109                                         raw_ostream &O) {
110   O << (short)MI->getOperand(OpNo).getImm();
111 }
112
113 void PPCInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
114                                         raw_ostream &O) {
115   O << (unsigned short)MI->getOperand(OpNo).getImm();
116 }
117
118 void PPCInstPrinter::printS16X4ImmOperand(const MCInst *MI, unsigned OpNo,
119                                           raw_ostream &O) {
120   if (MI->getOperand(OpNo).isImm()) {
121     O << (short)(MI->getOperand(OpNo).getImm()*4);
122     return;
123   }
124   
125   assert(0 && "Unhandled operand");
126 #if 0
127   O << "lo16(";
128   printOp(MI->getOperand(OpNo), O);
129   if (TM.getRelocationModel() == Reloc::PIC_)
130     O << "-\"L" << getFunctionNumber() << "$pb\")";
131   else
132     O << ')';
133 #endif
134 }
135
136 void PPCInstPrinter::printBranchOperand(const MCInst *MI, unsigned OpNo,
137                                         raw_ostream &O) {
138   if (!MI->getOperand(OpNo).isImm())
139     return printOperand(MI, OpNo, O);
140
141   // Branches can take an immediate operand.  This is used by the branch
142   // selection pass to print $+8, an eight byte displacement from the PC.
143   O << "$+" << MI->getOperand(OpNo).getImm()*4;
144 }
145
146
147
148
149 void PPCInstPrinter::printcrbitm(const MCInst *MI, unsigned OpNo,
150                                  raw_ostream &O) {
151   unsigned CCReg = MI->getOperand(OpNo).getReg();
152   unsigned RegNo;
153   switch (CCReg) {
154   default: assert(0 && "Unknown CR register");
155   case PPC::CR0: RegNo = 0; break;
156   case PPC::CR1: RegNo = 1; break;
157   case PPC::CR2: RegNo = 2; break;
158   case PPC::CR3: RegNo = 3; break;
159   case PPC::CR4: RegNo = 4; break;
160   case PPC::CR5: RegNo = 5; break;
161   case PPC::CR6: RegNo = 6; break;
162   case PPC::CR7: RegNo = 7; break;
163   }
164   O << (0x80 >> RegNo);
165 }
166
167 void PPCInstPrinter::printMemRegImm(const MCInst *MI, unsigned OpNo,
168                                     raw_ostream &O) {
169   printSymbolLo(MI, OpNo, O);
170   O << '(';
171   assert(MI->getOperand(OpNo+1).isReg() && "Bad operand");
172   // FIXME: Simplify.
173   if (MI->getOperand(OpNo+1).isReg() &&
174       MI->getOperand(OpNo+1).getReg() == PPC::R0)
175     O << "0";
176   else
177     printOperand(MI, OpNo+1, O);
178   O << ')';
179 }
180
181 void PPCInstPrinter::printMemRegImmShifted(const MCInst *MI, unsigned OpNo,
182                                            raw_ostream &O) {
183   if (MI->getOperand(OpNo).isImm())
184     printS16X4ImmOperand(MI, OpNo, O);
185   else
186     printSymbolLo(MI, OpNo, O);
187   O << '(';
188   
189   assert(MI->getOperand(OpNo+1).isReg() && "Bad operand");
190   // FIXME: Simplify.
191   if (MI->getOperand(OpNo+1).isReg() &&
192       MI->getOperand(OpNo+1).getReg() == PPC::R0)
193     O << "0";
194   else
195     printOperand(MI, OpNo+1, O);
196   O << ')';
197 }
198
199
200 void PPCInstPrinter::printMemRegReg(const MCInst *MI, unsigned OpNo,
201                                     raw_ostream &O) {
202   // When used as the base register, r0 reads constant zero rather than
203   // the value contained in the register.  For this reason, the darwin
204   // assembler requires that we print r0 as 0 (no r) when used as the base.
205   if (MI->getOperand(OpNo).getReg() == PPC::R0)
206     O << "0";
207   else
208     printOperand(MI, OpNo, O);
209   O << ", ";
210   printOperand(MI, OpNo+1, O);
211 }
212
213
214
215 /// stripRegisterPrefix - This method strips the character prefix from a
216 /// register name so that only the number is left.  Used by for linux asm.
217 const char *stripRegisterPrefix(const char *RegName) {
218   switch (RegName[0]) {
219   case 'r':
220   case 'f':
221   case 'v': return RegName + 1;
222   case 'c': if (RegName[1] == 'r') return RegName + 2;
223   }
224   
225   return RegName;
226 }
227
228 void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
229                                   raw_ostream &O) {
230   const MCOperand &Op = MI->getOperand(OpNo);
231   if (Op.isReg()) {
232     const char *RegName = getRegisterName(Op.getReg());
233     // The linux and AIX assembler does not take register prefixes.
234     if (!isDarwinSyntax())
235       RegName = stripRegisterPrefix(RegName);
236     
237     O << RegName;
238     return;
239   }
240   
241   if (Op.isImm()) {
242     O << Op.getImm();
243     return;
244   }
245   
246   assert(Op.isExpr() && "unknown operand kind in printOperand");
247   O << *Op.getExpr();
248 }
249   
250 void PPCInstPrinter::printSymbolLo(const MCInst *MI, unsigned OpNo,
251                                    raw_ostream &O) {
252   if (MI->getOperand(OpNo).isImm())
253     printS16ImmOperand(MI, OpNo, O);
254   else
255     printOperand(MI, OpNo, O);
256 }
257
258 void PPCInstPrinter::printSymbolHi(const MCInst *MI, unsigned OpNo,
259                                    raw_ostream &O) {
260   if (MI->getOperand(OpNo).isImm())
261     printS16ImmOperand(MI, OpNo, O);
262   else
263     printOperand(MI, OpNo, O);
264 }