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