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