db653a733ca882650e2977f0018b5a4a3c5db369
[oota-llvm.git] / lib / Target / CellSPU / AsmPrinter / SPUAsmPrinter.cpp
1 //===-- SPUAsmPrinter.cpp - Print machine instrs to Cell SPU assembly -------=//
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 file contains a printer that converts from our internal representation
11 // of machine-dependent LLVM code to Cell SPU assembly language. This printer
12 // is the output mechanism used by `llc'.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #define DEBUG_TYPE "asmprinter"
17 #include "SPU.h"
18 #include "SPUTargetMachine.h"
19 #include "llvm/Constants.h"
20 #include "llvm/DerivedTypes.h"
21 #include "llvm/Module.h"
22 #include "llvm/CodeGen/AsmPrinter.h"
23 #include "llvm/CodeGen/MachineModuleInfo.h"
24 #include "llvm/MC/MCStreamer.h"
25 #include "llvm/MC/MCAsmInfo.h"
26 #include "llvm/MC/MCSymbol.h"
27 #include "llvm/Target/TargetLoweringObjectFile.h"
28 #include "llvm/Target/TargetInstrInfo.h"
29 #include "llvm/Target/TargetOptions.h"
30 #include "llvm/Target/TargetRegisterInfo.h"
31 #include "llvm/Target/TargetRegistry.h"
32 #include "llvm/ADT/StringExtras.h"
33 #include "llvm/Support/ErrorHandling.h"
34 #include "llvm/Support/FormattedStream.h"
35 using namespace llvm;
36
37 namespace {
38   class SPUAsmPrinter : public AsmPrinter {
39   public:
40     explicit SPUAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
41                            MCContext &Ctx, MCStreamer &Streamer,
42                            const MCAsmInfo *T) :
43       AsmPrinter(O, TM, Ctx, Streamer, T) {}
44
45     virtual const char *getPassName() const {
46       return "STI CBEA SPU Assembly Printer";
47     }
48
49     SPUTargetMachine &getTM() {
50       return static_cast<SPUTargetMachine&>(TM);
51     }
52
53     /// printInstruction - This method is automatically generated by tablegen
54     /// from the instruction set description.
55     void printInstruction(const MachineInstr *MI);
56     static const char *getRegisterName(unsigned RegNo);
57
58
59     void EmitInstruction(const MachineInstr *MI) {
60       printInstruction(MI);
61       O << '\n';
62     }
63     void printOp(const MachineOperand &MO);
64
65     /// printRegister - Print register according to target requirements.
66     ///
67     void printRegister(const MachineOperand &MO, bool R0AsZero) {
68       unsigned RegNo = MO.getReg();
69       assert(TargetRegisterInfo::isPhysicalRegister(RegNo) &&
70              "Not physreg??");
71       O << getRegisterName(RegNo);
72     }
73
74     void printOperand(const MachineInstr *MI, unsigned OpNo) {
75       const MachineOperand &MO = MI->getOperand(OpNo);
76       if (MO.isReg()) {
77         O << getRegisterName(MO.getReg());
78       } else if (MO.isImm()) {
79         O << MO.getImm();
80       } else {
81         printOp(MO);
82       }
83     }
84
85     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
86                          unsigned AsmVariant, const char *ExtraCode);
87     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
88                                unsigned AsmVariant, const char *ExtraCode);
89
90
91     void
92     printS7ImmOperand(const MachineInstr *MI, unsigned OpNo)
93     {
94       int value = MI->getOperand(OpNo).getImm();
95       value = (value << (32 - 7)) >> (32 - 7);
96
97       assert((value >= -(1 << 8) && value <= (1 << 7) - 1)
98              && "Invalid s7 argument");
99       O << value;
100     }
101
102     void
103     printU7ImmOperand(const MachineInstr *MI, unsigned OpNo)
104     {
105       unsigned int value = MI->getOperand(OpNo).getImm();
106       assert(value < (1 << 8) && "Invalid u7 argument");
107       O << value;
108     }
109
110     void
111     printShufAddr(const MachineInstr *MI, unsigned OpNo)
112     {
113       char value = MI->getOperand(OpNo).getImm();
114       O << (int) value;
115       O << "(";
116       printOperand(MI, OpNo+1);
117       O << ")";
118     }
119
120     void
121     printS16ImmOperand(const MachineInstr *MI, unsigned OpNo)
122     {
123       O << (short) MI->getOperand(OpNo).getImm();
124     }
125
126     void
127     printU16ImmOperand(const MachineInstr *MI, unsigned OpNo)
128     {
129       O << (unsigned short)MI->getOperand(OpNo).getImm();
130     }
131
132     void
133     printU32ImmOperand(const MachineInstr *MI, unsigned OpNo)
134     {
135       O << (unsigned)MI->getOperand(OpNo).getImm();
136     }
137
138     void
139     printMemRegReg(const MachineInstr *MI, unsigned OpNo) {
140       // When used as the base register, r0 reads constant zero rather than
141       // the value contained in the register.  For this reason, the darwin
142       // assembler requires that we print r0 as 0 (no r) when used as the base.
143       const MachineOperand &MO = MI->getOperand(OpNo);
144       O << getRegisterName(MO.getReg()) << ", ";
145       printOperand(MI, OpNo+1);
146     }
147
148     void
149     printU18ImmOperand(const MachineInstr *MI, unsigned OpNo)
150     {
151       unsigned int value = MI->getOperand(OpNo).getImm();
152       assert(value <= (1 << 19) - 1 && "Invalid u18 argument");
153       O << value;
154     }
155
156     void
157     printS10ImmOperand(const MachineInstr *MI, unsigned OpNo)
158     {
159       short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
160                              >> 16);
161       assert((value >= -(1 << 9) && value <= (1 << 9) - 1)
162              && "Invalid s10 argument");
163       O << value;
164     }
165
166     void
167     printU10ImmOperand(const MachineInstr *MI, unsigned OpNo)
168     {
169       short value = (short) (((int) MI->getOperand(OpNo).getImm() << 16)
170                              >> 16);
171       assert((value <= (1 << 10) - 1) && "Invalid u10 argument");
172       O << value;
173     }
174
175     void
176     printDFormAddr(const MachineInstr *MI, unsigned OpNo)
177     {
178       assert(MI->getOperand(OpNo).isImm() &&
179              "printDFormAddr first operand is not immediate");
180       int64_t value = int64_t(MI->getOperand(OpNo).getImm());
181       int16_t value16 = int16_t(value);
182       assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1)
183              && "Invalid dform s10 offset argument");
184       O << (value16 & ~0xf) << "(";
185       printOperand(MI, OpNo+1);
186       O << ")";
187     }
188
189     void
190     printAddr256K(const MachineInstr *MI, unsigned OpNo)
191     {
192       /* Note: operand 1 is an offset or symbol name. */
193       if (MI->getOperand(OpNo).isImm()) {
194         printS16ImmOperand(MI, OpNo);
195       } else {
196         printOp(MI->getOperand(OpNo));
197         if (MI->getOperand(OpNo+1).isImm()) {
198           int displ = int(MI->getOperand(OpNo+1).getImm());
199           if (displ > 0)
200             O << "+" << displ;
201           else if (displ < 0)
202             O << displ;
203         }
204       }
205     }
206
207     void printCallOperand(const MachineInstr *MI, unsigned OpNo) {
208       printOp(MI->getOperand(OpNo));
209     }
210
211     void printPCRelativeOperand(const MachineInstr *MI, unsigned OpNo) {
212       // Used to generate a ".-<target>", but it turns out that the assembler
213       // really wants the target.
214       //
215       // N.B.: This operand is used for call targets. Branch hints are another
216       // animal entirely.
217       printOp(MI->getOperand(OpNo));
218     }
219
220     void printHBROperand(const MachineInstr *MI, unsigned OpNo) {
221       // HBR operands are generated in front of branches, hence, the
222       // program counter plus the target.
223       O << ".+";
224       printOp(MI->getOperand(OpNo));
225     }
226
227     void printSymbolHi(const MachineInstr *MI, unsigned OpNo) {
228       if (MI->getOperand(OpNo).isImm()) {
229         printS16ImmOperand(MI, OpNo);
230       } else {
231         printOp(MI->getOperand(OpNo));
232         O << "@h";
233       }
234     }
235
236     void printSymbolLo(const MachineInstr *MI, unsigned OpNo) {
237       if (MI->getOperand(OpNo).isImm()) {
238         printS16ImmOperand(MI, OpNo);
239       } else {
240         printOp(MI->getOperand(OpNo));
241         O << "@l";
242       }
243     }
244
245     /// Print local store address
246     void printSymbolLSA(const MachineInstr *MI, unsigned OpNo) {
247       printOp(MI->getOperand(OpNo));
248     }
249
250     void printROTHNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
251       if (MI->getOperand(OpNo).isImm()) {
252         int value = (int) MI->getOperand(OpNo).getImm();
253         assert((value >= 0 && value < 16)
254                && "Invalid negated immediate rotate 7-bit argument");
255         O << -value;
256       } else {
257         llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
258       }
259     }
260
261     void printROTNeg7Imm(const MachineInstr *MI, unsigned OpNo) {
262       if (MI->getOperand(OpNo).isImm()) {
263         int value = (int) MI->getOperand(OpNo).getImm();
264         assert((value >= 0 && value <= 32)
265                && "Invalid negated immediate rotate 7-bit argument");
266         O << -value;
267       } else {
268         llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
269       }
270     }
271   };
272 } // end of anonymous namespace
273
274 // Include the auto-generated portion of the assembly writer
275 #include "SPUGenAsmWriter.inc"
276
277 void SPUAsmPrinter::printOp(const MachineOperand &MO) {
278   switch (MO.getType()) {
279   case MachineOperand::MO_Immediate:
280     llvm_report_error("printOp() does not handle immediate values");
281     return;
282
283   case MachineOperand::MO_MachineBasicBlock:
284     O << *MO.getMBB()->getSymbol(OutContext);
285     return;
286   case MachineOperand::MO_JumpTableIndex:
287     O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
288       << '_' << MO.getIndex();
289     return;
290   case MachineOperand::MO_ConstantPoolIndex:
291     O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
292       << '_' << MO.getIndex();
293     return;
294   case MachineOperand::MO_ExternalSymbol:
295     // Computing the address of an external symbol, not calling it.
296     if (TM.getRelocationModel() != Reloc::Static) {
297       O << "L" << MAI->getGlobalPrefix() << MO.getSymbolName()
298         << "$non_lazy_ptr";
299       return;
300     }
301     O << *GetExternalSymbolSymbol(MO.getSymbolName());
302     return;
303   case MachineOperand::MO_GlobalAddress:
304     // External or weakly linked global variables need non-lazily-resolved
305     // stubs
306     if (TM.getRelocationModel() != Reloc::Static) {
307       GlobalValue *GV = MO.getGlobal();
308       if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
309             GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
310         O << *GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
311         return;
312       }
313     }
314     O << *GetGlobalValueSymbol(MO.getGlobal());
315     return;
316   default:
317     O << "<unknown operand type: " << MO.getType() << ">";
318     return;
319   }
320 }
321
322 /// PrintAsmOperand - Print out an operand for an inline asm expression.
323 ///
324 bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
325                                     unsigned AsmVariant,
326                                     const char *ExtraCode) {
327   // Does this asm operand have a single letter operand modifier?
328   if (ExtraCode && ExtraCode[0]) {
329     if (ExtraCode[1] != 0) return true; // Unknown modifier.
330
331     switch (ExtraCode[0]) {
332     default: return true;  // Unknown modifier.
333     case 'L': // Write second word of DImode reference.
334       // Verify that this operand has two consecutive registers.
335       if (!MI->getOperand(OpNo).isReg() ||
336           OpNo+1 == MI->getNumOperands() ||
337           !MI->getOperand(OpNo+1).isReg())
338         return true;
339       ++OpNo;   // Return the high-part.
340       break;
341     }
342   }
343
344   printOperand(MI, OpNo);
345   return false;
346 }
347
348 bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
349                                           unsigned OpNo,
350                                           unsigned AsmVariant,
351                                           const char *ExtraCode) {
352   if (ExtraCode && ExtraCode[0])
353     return true; // Unknown modifier.
354   printMemRegReg(MI, OpNo);
355   return false;
356 }
357
358 // Force static initialization.
359 extern "C" void LLVMInitializeCellSPUAsmPrinter() { 
360   RegisterAsmPrinter<SPUAsmPrinter> X(TheCellSPUTarget);
361 }