R600/SI: Add preliminary support for flat address space
[oota-llvm.git] / lib / Target / R600 / InstPrinter / AMDGPUInstPrinter.cpp
1 //===-- AMDGPUInstPrinter.cpp - AMDGPU MC Inst -> ASM ---------------------===//
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 // \file
9 //===----------------------------------------------------------------------===//
10
11 #include "AMDGPUInstPrinter.h"
12 #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
13 #include "llvm/MC/MCExpr.h"
14 #include "llvm/MC/MCInst.h"
15 #include "llvm/MC/MCRegisterInfo.h"
16 #include "llvm/Support/MathExtras.h"
17
18 using namespace llvm;
19
20 void AMDGPUInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
21                              StringRef Annot) {
22   OS.flush();
23   printInstruction(MI, OS);
24
25   printAnnotation(OS, Annot);
26 }
27
28 void AMDGPUInstPrinter::printU8ImmOperand(const MCInst *MI, unsigned OpNo,
29                                            raw_ostream &O) {
30   O << formatHex(MI->getOperand(OpNo).getImm() & 0xff);
31 }
32
33 void AMDGPUInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
34                                            raw_ostream &O) {
35   O << formatHex(MI->getOperand(OpNo).getImm() & 0xffff);
36 }
37
38 void AMDGPUInstPrinter::printU32ImmOperand(const MCInst *MI, unsigned OpNo,
39                                            raw_ostream &O) {
40   O << formatHex(MI->getOperand(OpNo).getImm() & 0xffffffff);
41 }
42
43 void AMDGPUInstPrinter::printOffen(const MCInst *MI, unsigned OpNo,
44                                    raw_ostream &O) {
45   if (MI->getOperand(OpNo).getImm())
46     O << " offen";
47 }
48
49 void AMDGPUInstPrinter::printIdxen(const MCInst *MI, unsigned OpNo,
50                                    raw_ostream &O) {
51   if (MI->getOperand(OpNo).getImm())
52     O << " idxen";
53 }
54
55 void AMDGPUInstPrinter::printAddr64(const MCInst *MI, unsigned OpNo,
56                                     raw_ostream &O) {
57   if (MI->getOperand(OpNo).getImm())
58     O << " addr64";
59 }
60
61 void AMDGPUInstPrinter::printMBUFOffset(const MCInst *MI, unsigned OpNo,
62                                         raw_ostream &O) {
63   if (MI->getOperand(OpNo).getImm()) {
64     O << " offset:";
65     printU16ImmOperand(MI, OpNo, O);
66   }
67 }
68
69 void AMDGPUInstPrinter::printGLC(const MCInst *MI, unsigned OpNo,
70                                  raw_ostream &O) {
71   if (MI->getOperand(OpNo).getImm())
72     O << " glc";
73 }
74
75 void AMDGPUInstPrinter::printSLC(const MCInst *MI, unsigned OpNo,
76                                  raw_ostream &O) {
77   if (MI->getOperand(OpNo).getImm())
78     O << " slc";
79 }
80
81 void AMDGPUInstPrinter::printTFE(const MCInst *MI, unsigned OpNo,
82                                  raw_ostream &O) {
83   if (MI->getOperand(OpNo).getImm())
84     O << " tfe";
85 }
86
87 void AMDGPUInstPrinter::printRegOperand(unsigned reg, raw_ostream &O) {
88   switch (reg) {
89   case AMDGPU::VCC:
90     O << "vcc";
91     return;
92   case AMDGPU::SCC:
93     O << "scc";
94     return;
95   case AMDGPU::EXEC:
96     O << "exec";
97     return;
98   case AMDGPU::M0:
99     O << "m0";
100     return;
101   case AMDGPU::FLAT_SCR:
102     O << "flat_scratch";
103     return;
104   case AMDGPU::VCC_LO:
105     O << "vcc_lo";
106     return;
107   case AMDGPU::VCC_HI:
108     O << "vcc_hi";
109     return;
110   case AMDGPU::EXEC_LO:
111     O << "exec_lo";
112     return;
113   case AMDGPU::EXEC_HI:
114     O << "exec_hi";
115     return;
116   case AMDGPU::FLAT_SCR_LO:
117     O << "flat_scratch_lo";
118     return;
119   case AMDGPU::FLAT_SCR_HI:
120     O << "flat_scratch_hi";
121     return;
122   default:
123     break;
124   }
125
126   char Type;
127   unsigned NumRegs;
128
129   if (MRI.getRegClass(AMDGPU::VGPR_32RegClassID).contains(reg)) {
130     Type = 'v';
131     NumRegs = 1;
132   } else  if (MRI.getRegClass(AMDGPU::SGPR_32RegClassID).contains(reg)) {
133     Type = 's';
134     NumRegs = 1;
135   } else if (MRI.getRegClass(AMDGPU::VReg_64RegClassID).contains(reg)) {
136     Type = 'v';
137     NumRegs = 2;
138   } else  if (MRI.getRegClass(AMDGPU::SReg_64RegClassID).contains(reg)) {
139     Type = 's';
140     NumRegs = 2;
141   } else if (MRI.getRegClass(AMDGPU::VReg_128RegClassID).contains(reg)) {
142     Type = 'v';
143     NumRegs = 4;
144   } else  if (MRI.getRegClass(AMDGPU::SReg_128RegClassID).contains(reg)) {
145     Type = 's';
146     NumRegs = 4;
147   } else if (MRI.getRegClass(AMDGPU::VReg_96RegClassID).contains(reg)) {
148     Type = 'v';
149     NumRegs = 3;
150   } else if (MRI.getRegClass(AMDGPU::VReg_256RegClassID).contains(reg)) {
151     Type = 'v';
152     NumRegs = 8;
153   } else if (MRI.getRegClass(AMDGPU::SReg_256RegClassID).contains(reg)) {
154     Type = 's';
155     NumRegs = 8;
156   } else if (MRI.getRegClass(AMDGPU::VReg_512RegClassID).contains(reg)) {
157     Type = 'v';
158     NumRegs = 16;
159   } else if (MRI.getRegClass(AMDGPU::SReg_512RegClassID).contains(reg)) {
160     Type = 's';
161     NumRegs = 16;
162   } else {
163     O << getRegisterName(reg);
164     return;
165   }
166
167   // The low 8 bits of the encoding value is the register index, for both VGPRs
168   // and SGPRs.
169   unsigned RegIdx = MRI.getEncodingValue(reg) & ((1 << 8) - 1);
170   if (NumRegs == 1) {
171     O << Type << RegIdx;
172     return;
173   }
174
175   O << Type << '[' << RegIdx << ':' << (RegIdx + NumRegs - 1) << ']';
176 }
177
178 void AMDGPUInstPrinter::printImmediate(uint32_t Imm, raw_ostream &O) {
179   int32_t SImm = static_cast<int32_t>(Imm);
180   if (SImm >= -16 && SImm <= 64) {
181     O << SImm;
182     return;
183   }
184
185   if (Imm == FloatToBits(1.0f) ||
186       Imm == FloatToBits(-1.0f) ||
187       Imm == FloatToBits(0.5f) ||
188       Imm == FloatToBits(-0.5f) ||
189       Imm == FloatToBits(2.0f) ||
190       Imm == FloatToBits(-2.0f) ||
191       Imm == FloatToBits(4.0f) ||
192       Imm == FloatToBits(-4.0f)) {
193     O << BitsToFloat(Imm);
194     return;
195   }
196
197   O << formatHex(static_cast<uint64_t>(Imm));
198 }
199
200 void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
201                                      raw_ostream &O) {
202
203   const MCOperand &Op = MI->getOperand(OpNo);
204   if (Op.isReg()) {
205     switch (Op.getReg()) {
206     // This is the default predicate state, so we don't need to print it.
207     case AMDGPU::PRED_SEL_OFF:
208       break;
209
210     default:
211       printRegOperand(Op.getReg(), O);
212       break;
213     }
214   } else if (Op.isImm()) {
215     printImmediate(Op.getImm(), O);
216   } else if (Op.isFPImm()) {
217     O << Op.getFPImm();
218   } else if (Op.isExpr()) {
219     const MCExpr *Exp = Op.getExpr();
220     Exp->print(O);
221   } else {
222     assert(!"unknown operand type in printOperand");
223   }
224 }
225
226 void AMDGPUInstPrinter::printOperandAndMods(const MCInst *MI, unsigned OpNo,
227                                             raw_ostream &O) {
228   unsigned InputModifiers = MI->getOperand(OpNo).getImm();
229   if (InputModifiers & 0x1)
230     O << "-";
231   if (InputModifiers & 0x2)
232     O << "|";
233   printOperand(MI, OpNo + 1, O);
234   if (InputModifiers & 0x2)
235     O << "|";
236 }
237
238 void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum,
239                                         raw_ostream &O) {
240   unsigned Imm = MI->getOperand(OpNum).getImm();
241
242   if (Imm == 2) {
243     O << "P0";
244   } else if (Imm == 1) {
245     O << "P20";
246   } else if (Imm == 0) {
247     O << "P10";
248   } else {
249     assert(!"Invalid interpolation parameter slot");
250   }
251 }
252
253 void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
254                                         raw_ostream &O) {
255   printOperand(MI, OpNo, O);
256   O  << ", ";
257   printOperand(MI, OpNo + 1, O);
258 }
259
260 void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
261                                    raw_ostream &O, StringRef Asm,
262                                    StringRef Default) {
263   const MCOperand &Op = MI->getOperand(OpNo);
264   assert(Op.isImm());
265   if (Op.getImm() == 1) {
266     O << Asm;
267   } else {
268     O << Default;
269   }
270 }
271
272 void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo,
273                                  raw_ostream &O) {
274   printIfSet(MI, OpNo, O, "|");
275 }
276
277 void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo,
278                                    raw_ostream &O) {
279   printIfSet(MI, OpNo, O, "_SAT");
280 }
281
282 void AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo,
283                                      raw_ostream &O) {
284   int32_t Imm = MI->getOperand(OpNo).getImm();
285   O << Imm << '(' << BitsToFloat(Imm) << ')';
286 }
287
288 void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo,
289                                   raw_ostream &O) {
290   printIfSet(MI, OpNo, O.indent(25 - O.GetNumBytesInBuffer()), "*", " ");
291 }
292
293 void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo,
294                                  raw_ostream &O) {
295   printIfSet(MI, OpNo, O, "-");
296 }
297
298 void AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo,
299                                   raw_ostream &O) {
300   switch (MI->getOperand(OpNo).getImm()) {
301   default: break;
302   case 1:
303     O << " * 2.0";
304     break;
305   case 2:
306     O << " * 4.0";
307     break;
308   case 3:
309     O << " / 2.0";
310     break;
311   }
312 }
313
314 void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo,
315                                  raw_ostream &O) {
316   printIfSet(MI, OpNo, O, "+");
317 }
318
319 void AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo,
320                                             raw_ostream &O) {
321   printIfSet(MI, OpNo, O, "ExecMask,");
322 }
323
324 void AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo,
325                                         raw_ostream &O) {
326   printIfSet(MI, OpNo, O, "Pred,");
327 }
328
329 void AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo,
330                                        raw_ostream &O) {
331   const MCOperand &Op = MI->getOperand(OpNo);
332   if (Op.getImm() == 0) {
333     O << " (MASKED)";
334   }
335 }
336
337 void AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo,
338                                   raw_ostream &O) {
339   const char * chans = "XYZW";
340   int sel = MI->getOperand(OpNo).getImm();
341
342   int chan = sel & 3;
343   sel >>= 2;
344
345   if (sel >= 512) {
346     sel -= 512;
347     int cb = sel >> 12;
348     sel &= 4095;
349     O << cb << "[" << sel << "]";
350   } else if (sel >= 448) {
351     sel -= 448;
352     O << sel;
353   } else if (sel >= 0){
354     O << sel;
355   }
356
357   if (sel >= 0)
358     O << "." << chans[chan];
359 }
360
361 void AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo,
362                                          raw_ostream &O) {
363   int BankSwizzle = MI->getOperand(OpNo).getImm();
364   switch (BankSwizzle) {
365   case 1:
366     O << "BS:VEC_021/SCL_122";
367     break;
368   case 2:
369     O << "BS:VEC_120/SCL_212";
370     break;
371   case 3:
372     O << "BS:VEC_102/SCL_221";
373     break;
374   case 4:
375     O << "BS:VEC_201";
376     break;
377   case 5:
378     O << "BS:VEC_210";
379     break;
380   default:
381     break;
382   }
383   return;
384 }
385
386 void AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo,
387                                   raw_ostream &O) {
388   unsigned Sel = MI->getOperand(OpNo).getImm();
389   switch (Sel) {
390   case 0:
391     O << "X";
392     break;
393   case 1:
394     O << "Y";
395     break;
396   case 2:
397     O << "Z";
398     break;
399   case 3:
400     O << "W";
401     break;
402   case 4:
403     O << "0";
404     break;
405   case 5:
406     O << "1";
407     break;
408   case 7:
409     O << "_";
410     break;
411   default:
412     break;
413   }
414 }
415
416 void AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo,
417                                   raw_ostream &O) {
418   unsigned CT = MI->getOperand(OpNo).getImm();
419   switch (CT) {
420   case 0:
421     O << "U";
422     break;
423   case 1:
424     O << "N";
425     break;
426   default:
427     break;
428   }
429 }
430
431 void AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo,
432                                     raw_ostream &O) {
433   int KCacheMode = MI->getOperand(OpNo).getImm();
434   if (KCacheMode > 0) {
435     int KCacheBank = MI->getOperand(OpNo - 2).getImm();
436     O << "CB" << KCacheBank <<":";
437     int KCacheAddr = MI->getOperand(OpNo + 2).getImm();
438     int LineSize = (KCacheMode == 1)?16:32;
439     O << KCacheAddr * 16 << "-" << KCacheAddr * 16 + LineSize;
440   }
441 }
442
443 void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo,
444                                      raw_ostream &O) {
445   unsigned SImm16 = MI->getOperand(OpNo).getImm();
446   unsigned Msg = SImm16 & 0xF;
447   if (Msg == 2 || Msg == 3) {
448     unsigned Op = (SImm16 >> 4) & 0xF;
449     if (Msg == 3)
450       O << "Gs_done(";
451     else
452       O << "Gs(";
453     if (Op == 0) {
454       O << "nop";
455     } else {
456       unsigned Stream = (SImm16 >> 8) & 0x3;
457       if (Op == 1)
458         O << "cut";
459       else if (Op == 2)
460         O << "emit";
461       else if (Op == 3)
462         O << "emit-cut";
463       O << " stream " << Stream;
464     }
465     O << "), [m0] ";
466   } else if (Msg == 1)
467     O << "interrupt ";
468   else if (Msg == 15)
469     O << "system ";
470   else
471     O << "unknown(" << Msg << ") ";
472 }
473
474 void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo,
475                                       raw_ostream &O) {
476   // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs
477   // SIInsertWaits.cpp bits usage does not match ISA docs description but it
478   // works so it might be a misprint in docs.
479   unsigned SImm16 = MI->getOperand(OpNo).getImm();
480   unsigned Vmcnt = SImm16 & 0xF;
481   unsigned Expcnt = (SImm16 >> 4) & 0xF;
482   unsigned Lgkmcnt = (SImm16 >> 8) & 0xF;
483   if (Vmcnt != 0xF)
484     O << "vmcnt(" << Vmcnt << ") ";
485   if (Expcnt != 0x7)
486     O << "expcnt(" << Expcnt << ") ";
487   if (Lgkmcnt != 0x7)
488     O << "lgkmcnt(" << Lgkmcnt << ")";
489 }
490
491 #include "AMDGPUGenAsmWriter.inc"