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