Use llvm_unreachable instead of assert(!)
[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(0.0f))
186     O << "0.0";
187   else if (Imm == FloatToBits(1.0f))
188     O << "1.0";
189   else if (Imm == FloatToBits(-1.0f))
190     O << "-1.0";
191   else if (Imm == FloatToBits(0.5f))
192     O << "0.5";
193   else if (Imm == FloatToBits(-0.5f))
194     O << "-0.5";
195   else if (Imm == FloatToBits(2.0f))
196     O << "2.0";
197   else if (Imm == FloatToBits(-2.0f))
198     O << "-2.0";
199   else if (Imm == FloatToBits(4.0f))
200     O << "4.0";
201   else if (Imm == FloatToBits(-4.0f))
202     O << "-4.0";
203   else {
204     O << formatHex(static_cast<uint64_t>(Imm));
205   }
206 }
207
208 void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
209                                      raw_ostream &O) {
210
211   const MCOperand &Op = MI->getOperand(OpNo);
212   if (Op.isReg()) {
213     switch (Op.getReg()) {
214     // This is the default predicate state, so we don't need to print it.
215     case AMDGPU::PRED_SEL_OFF:
216       break;
217
218     default:
219       printRegOperand(Op.getReg(), O);
220       break;
221     }
222   } else if (Op.isImm()) {
223     printImmediate(Op.getImm(), O);
224   } else if (Op.isFPImm()) {
225
226     // We special case 0.0 because otherwise it will be printed as an integer.
227     if (Op.getFPImm() == 0.0)
228       O << "0.0";
229     else
230       printImmediate(FloatToBits(Op.getFPImm()), O);
231   } else if (Op.isExpr()) {
232     const MCExpr *Exp = Op.getExpr();
233     Exp->print(O);
234   } else {
235     llvm_unreachable("unknown operand type in printOperand");
236   }
237 }
238
239 void AMDGPUInstPrinter::printOperandAndMods(const MCInst *MI, unsigned OpNo,
240                                             raw_ostream &O) {
241   unsigned InputModifiers = MI->getOperand(OpNo).getImm();
242   if (InputModifiers & 0x1)
243     O << '-';
244   if (InputModifiers & 0x2)
245     O << '|';
246   printOperand(MI, OpNo + 1, O);
247   if (InputModifiers & 0x2)
248     O << '|';
249 }
250
251 void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum,
252                                         raw_ostream &O) {
253   unsigned Imm = MI->getOperand(OpNum).getImm();
254
255   if (Imm == 2) {
256     O << "P0";
257   } else if (Imm == 1) {
258     O << "P20";
259   } else if (Imm == 0) {
260     O << "P10";
261   } else {
262     llvm_unreachable("Invalid interpolation parameter slot");
263   }
264 }
265
266 void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
267                                         raw_ostream &O) {
268   printOperand(MI, OpNo, O);
269   O  << ", ";
270   printOperand(MI, OpNo + 1, O);
271 }
272
273 void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
274                                    raw_ostream &O, StringRef Asm,
275                                    StringRef Default) {
276   const MCOperand &Op = MI->getOperand(OpNo);
277   assert(Op.isImm());
278   if (Op.getImm() == 1) {
279     O << Asm;
280   } else {
281     O << Default;
282   }
283 }
284
285 void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo,
286                                  raw_ostream &O) {
287   printIfSet(MI, OpNo, O, "|");
288 }
289
290 void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo,
291                                    raw_ostream &O) {
292   printIfSet(MI, OpNo, O, "_SAT");
293 }
294
295 void AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo,
296                                      raw_ostream &O) {
297   int32_t Imm = MI->getOperand(OpNo).getImm();
298   O << Imm << '(' << BitsToFloat(Imm) << ')';
299 }
300
301 void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo,
302                                   raw_ostream &O) {
303   printIfSet(MI, OpNo, O.indent(25 - O.GetNumBytesInBuffer()), "*", " ");
304 }
305
306 void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo,
307                                  raw_ostream &O) {
308   printIfSet(MI, OpNo, O, "-");
309 }
310
311 void AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo,
312                                   raw_ostream &O) {
313   switch (MI->getOperand(OpNo).getImm()) {
314   default: break;
315   case 1:
316     O << " * 2.0";
317     break;
318   case 2:
319     O << " * 4.0";
320     break;
321   case 3:
322     O << " / 2.0";
323     break;
324   }
325 }
326
327 void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo,
328                                  raw_ostream &O) {
329   printIfSet(MI, OpNo, O, "+");
330 }
331
332 void AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo,
333                                             raw_ostream &O) {
334   printIfSet(MI, OpNo, O, "ExecMask,");
335 }
336
337 void AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo,
338                                         raw_ostream &O) {
339   printIfSet(MI, OpNo, O, "Pred,");
340 }
341
342 void AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo,
343                                        raw_ostream &O) {
344   const MCOperand &Op = MI->getOperand(OpNo);
345   if (Op.getImm() == 0) {
346     O << " (MASKED)";
347   }
348 }
349
350 void AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo,
351                                   raw_ostream &O) {
352   const char * chans = "XYZW";
353   int sel = MI->getOperand(OpNo).getImm();
354
355   int chan = sel & 3;
356   sel >>= 2;
357
358   if (sel >= 512) {
359     sel -= 512;
360     int cb = sel >> 12;
361     sel &= 4095;
362     O << cb << '[' << sel << ']';
363   } else if (sel >= 448) {
364     sel -= 448;
365     O << sel;
366   } else if (sel >= 0){
367     O << sel;
368   }
369
370   if (sel >= 0)
371     O << '.' << chans[chan];
372 }
373
374 void AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo,
375                                          raw_ostream &O) {
376   int BankSwizzle = MI->getOperand(OpNo).getImm();
377   switch (BankSwizzle) {
378   case 1:
379     O << "BS:VEC_021/SCL_122";
380     break;
381   case 2:
382     O << "BS:VEC_120/SCL_212";
383     break;
384   case 3:
385     O << "BS:VEC_102/SCL_221";
386     break;
387   case 4:
388     O << "BS:VEC_201";
389     break;
390   case 5:
391     O << "BS:VEC_210";
392     break;
393   default:
394     break;
395   }
396   return;
397 }
398
399 void AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo,
400                                   raw_ostream &O) {
401   unsigned Sel = MI->getOperand(OpNo).getImm();
402   switch (Sel) {
403   case 0:
404     O << 'X';
405     break;
406   case 1:
407     O << 'Y';
408     break;
409   case 2:
410     O << 'Z';
411     break;
412   case 3:
413     O << 'W';
414     break;
415   case 4:
416     O << '0';
417     break;
418   case 5:
419     O << '1';
420     break;
421   case 7:
422     O << '_';
423     break;
424   default:
425     break;
426   }
427 }
428
429 void AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo,
430                                   raw_ostream &O) {
431   unsigned CT = MI->getOperand(OpNo).getImm();
432   switch (CT) {
433   case 0:
434     O << 'U';
435     break;
436   case 1:
437     O << 'N';
438     break;
439   default:
440     break;
441   }
442 }
443
444 void AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo,
445                                     raw_ostream &O) {
446   int KCacheMode = MI->getOperand(OpNo).getImm();
447   if (KCacheMode > 0) {
448     int KCacheBank = MI->getOperand(OpNo - 2).getImm();
449     O << "CB" << KCacheBank << ':';
450     int KCacheAddr = MI->getOperand(OpNo + 2).getImm();
451     int LineSize = (KCacheMode == 1) ? 16 : 32;
452     O << KCacheAddr * 16 << '-' << KCacheAddr * 16 + LineSize;
453   }
454 }
455
456 void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo,
457                                      raw_ostream &O) {
458   unsigned SImm16 = MI->getOperand(OpNo).getImm();
459   unsigned Msg = SImm16 & 0xF;
460   if (Msg == 2 || Msg == 3) {
461     unsigned Op = (SImm16 >> 4) & 0xF;
462     if (Msg == 3)
463       O << "Gs_done(";
464     else
465       O << "Gs(";
466     if (Op == 0) {
467       O << "nop";
468     } else {
469       unsigned Stream = (SImm16 >> 8) & 0x3;
470       if (Op == 1)
471         O << "cut";
472       else if (Op == 2)
473         O << "emit";
474       else if (Op == 3)
475         O << "emit-cut";
476       O << " stream " << Stream;
477     }
478     O << "), [m0] ";
479   } else if (Msg == 1)
480     O << "interrupt ";
481   else if (Msg == 15)
482     O << "system ";
483   else
484     O << "unknown(" << Msg << ") ";
485 }
486
487 void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo,
488                                       raw_ostream &O) {
489   // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs
490   // SIInsertWaits.cpp bits usage does not match ISA docs description but it
491   // works so it might be a misprint in docs.
492   unsigned SImm16 = MI->getOperand(OpNo).getImm();
493   unsigned Vmcnt = SImm16 & 0xF;
494   unsigned Expcnt = (SImm16 >> 4) & 0xF;
495   unsigned Lgkmcnt = (SImm16 >> 8) & 0xF;
496   if (Vmcnt != 0xF)
497     O << "vmcnt(" << Vmcnt << ") ";
498   if (Expcnt != 0x7)
499     O << "expcnt(" << Expcnt << ") ";
500   if (Lgkmcnt != 0x7)
501     O << "lgkmcnt(" << Lgkmcnt << ')';
502 }
503
504 #include "AMDGPUGenAsmWriter.inc"