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