R600/SI: Update MUBUF assembly string to match AMD proprietary compiler
[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   default:
102     break;
103   }
104
105   char Type;
106   unsigned NumRegs;
107
108   if (MRI.getRegClass(AMDGPU::VGPR_32RegClassID).contains(reg)) {
109     Type = 'v';
110     NumRegs = 1;
111   } else  if (MRI.getRegClass(AMDGPU::SGPR_32RegClassID).contains(reg)) {
112     Type = 's';
113     NumRegs = 1;
114   } else if (MRI.getRegClass(AMDGPU::VReg_64RegClassID).contains(reg)) {
115     Type = 'v';
116     NumRegs = 2;
117   } else  if (MRI.getRegClass(AMDGPU::SReg_64RegClassID).contains(reg)) {
118     Type = 's';
119     NumRegs = 2;
120   } else if (MRI.getRegClass(AMDGPU::VReg_128RegClassID).contains(reg)) {
121     Type = 'v';
122     NumRegs = 4;
123   } else  if (MRI.getRegClass(AMDGPU::SReg_128RegClassID).contains(reg)) {
124     Type = 's';
125     NumRegs = 4;
126   } else if (MRI.getRegClass(AMDGPU::VReg_96RegClassID).contains(reg)) {
127     Type = 'v';
128     NumRegs = 3;
129   } else if (MRI.getRegClass(AMDGPU::VReg_256RegClassID).contains(reg)) {
130     Type = 'v';
131     NumRegs = 8;
132   } else if (MRI.getRegClass(AMDGPU::SReg_256RegClassID).contains(reg)) {
133     Type = 's';
134     NumRegs = 8;
135   } else if (MRI.getRegClass(AMDGPU::VReg_512RegClassID).contains(reg)) {
136     Type = 'v';
137     NumRegs = 16;
138   } else if (MRI.getRegClass(AMDGPU::SReg_512RegClassID).contains(reg)) {
139     Type = 's';
140     NumRegs = 16;
141   } else {
142     O << getRegisterName(reg);
143     return;
144   }
145
146   // The low 8 bits of the encoding value is the register index, for both VGPRs
147   // and SGPRs.
148   unsigned RegIdx = MRI.getEncodingValue(reg) & ((1 << 8) - 1);
149   if (NumRegs == 1) {
150     O << Type << RegIdx;
151     return;
152   }
153
154   O << Type << '[' << RegIdx << ':' << (RegIdx + NumRegs - 1) << ']';
155 }
156
157 void AMDGPUInstPrinter::printImmediate(uint32_t Imm, raw_ostream &O) {
158   int32_t SImm = static_cast<int32_t>(Imm);
159   if (SImm >= -16 && SImm <= 64) {
160     O << SImm;
161     return;
162   }
163
164   if (Imm == FloatToBits(1.0f) ||
165       Imm == FloatToBits(-1.0f) ||
166       Imm == FloatToBits(0.5f) ||
167       Imm == FloatToBits(-0.5f) ||
168       Imm == FloatToBits(2.0f) ||
169       Imm == FloatToBits(-2.0f) ||
170       Imm == FloatToBits(4.0f) ||
171       Imm == FloatToBits(-4.0f)) {
172     O << BitsToFloat(Imm);
173     return;
174   }
175
176   O << formatHex(static_cast<uint64_t>(Imm));
177 }
178
179 void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
180                                      raw_ostream &O) {
181
182   const MCOperand &Op = MI->getOperand(OpNo);
183   if (Op.isReg()) {
184     switch (Op.getReg()) {
185     // This is the default predicate state, so we don't need to print it.
186     case AMDGPU::PRED_SEL_OFF:
187       break;
188
189     default:
190       printRegOperand(Op.getReg(), O);
191       break;
192     }
193   } else if (Op.isImm()) {
194     printImmediate(Op.getImm(), O);
195   } else if (Op.isFPImm()) {
196     O << Op.getFPImm();
197   } else if (Op.isExpr()) {
198     const MCExpr *Exp = Op.getExpr();
199     Exp->print(O);
200   } else {
201     assert(!"unknown operand type in printOperand");
202   }
203 }
204
205 void AMDGPUInstPrinter::printOperandAndMods(const MCInst *MI, unsigned OpNo,
206                                             raw_ostream &O) {
207   unsigned InputModifiers = MI->getOperand(OpNo).getImm();
208   if (InputModifiers & 0x1)
209     O << "-";
210   if (InputModifiers & 0x2)
211     O << "|";
212   printOperand(MI, OpNo + 1, O);
213   if (InputModifiers & 0x2)
214     O << "|";
215 }
216
217 void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum,
218                                         raw_ostream &O) {
219   unsigned Imm = MI->getOperand(OpNum).getImm();
220
221   if (Imm == 2) {
222     O << "P0";
223   } else if (Imm == 1) {
224     O << "P20";
225   } else if (Imm == 0) {
226     O << "P10";
227   } else {
228     assert(!"Invalid interpolation parameter slot");
229   }
230 }
231
232 void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
233                                         raw_ostream &O) {
234   printOperand(MI, OpNo, O);
235   O  << ", ";
236   printOperand(MI, OpNo + 1, O);
237 }
238
239 void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
240                                    raw_ostream &O, StringRef Asm,
241                                    StringRef Default) {
242   const MCOperand &Op = MI->getOperand(OpNo);
243   assert(Op.isImm());
244   if (Op.getImm() == 1) {
245     O << Asm;
246   } else {
247     O << Default;
248   }
249 }
250
251 void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo,
252                                  raw_ostream &O) {
253   printIfSet(MI, OpNo, O, "|");
254 }
255
256 void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo,
257                                    raw_ostream &O) {
258   printIfSet(MI, OpNo, O, "_SAT");
259 }
260
261 void AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo,
262                                      raw_ostream &O) {
263   int32_t Imm = MI->getOperand(OpNo).getImm();
264   O << Imm << '(' << BitsToFloat(Imm) << ')';
265 }
266
267 void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo,
268                                   raw_ostream &O) {
269   printIfSet(MI, OpNo, O.indent(25 - O.GetNumBytesInBuffer()), "*", " ");
270 }
271
272 void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo,
273                                  raw_ostream &O) {
274   printIfSet(MI, OpNo, O, "-");
275 }
276
277 void AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo,
278                                   raw_ostream &O) {
279   switch (MI->getOperand(OpNo).getImm()) {
280   default: break;
281   case 1:
282     O << " * 2.0";
283     break;
284   case 2:
285     O << " * 4.0";
286     break;
287   case 3:
288     O << " / 2.0";
289     break;
290   }
291 }
292
293 void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo,
294                                  raw_ostream &O) {
295   printIfSet(MI, OpNo, O, "+");
296 }
297
298 void AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo,
299                                             raw_ostream &O) {
300   printIfSet(MI, OpNo, O, "ExecMask,");
301 }
302
303 void AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo,
304                                         raw_ostream &O) {
305   printIfSet(MI, OpNo, O, "Pred,");
306 }
307
308 void AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo,
309                                        raw_ostream &O) {
310   const MCOperand &Op = MI->getOperand(OpNo);
311   if (Op.getImm() == 0) {
312     O << " (MASKED)";
313   }
314 }
315
316 void AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo,
317                                   raw_ostream &O) {
318   const char * chans = "XYZW";
319   int sel = MI->getOperand(OpNo).getImm();
320
321   int chan = sel & 3;
322   sel >>= 2;
323
324   if (sel >= 512) {
325     sel -= 512;
326     int cb = sel >> 12;
327     sel &= 4095;
328     O << cb << "[" << sel << "]";
329   } else if (sel >= 448) {
330     sel -= 448;
331     O << sel;
332   } else if (sel >= 0){
333     O << sel;
334   }
335
336   if (sel >= 0)
337     O << "." << chans[chan];
338 }
339
340 void AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo,
341                                          raw_ostream &O) {
342   int BankSwizzle = MI->getOperand(OpNo).getImm();
343   switch (BankSwizzle) {
344   case 1:
345     O << "BS:VEC_021/SCL_122";
346     break;
347   case 2:
348     O << "BS:VEC_120/SCL_212";
349     break;
350   case 3:
351     O << "BS:VEC_102/SCL_221";
352     break;
353   case 4:
354     O << "BS:VEC_201";
355     break;
356   case 5:
357     O << "BS:VEC_210";
358     break;
359   default:
360     break;
361   }
362   return;
363 }
364
365 void AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo,
366                                   raw_ostream &O) {
367   unsigned Sel = MI->getOperand(OpNo).getImm();
368   switch (Sel) {
369   case 0:
370     O << "X";
371     break;
372   case 1:
373     O << "Y";
374     break;
375   case 2:
376     O << "Z";
377     break;
378   case 3:
379     O << "W";
380     break;
381   case 4:
382     O << "0";
383     break;
384   case 5:
385     O << "1";
386     break;
387   case 7:
388     O << "_";
389     break;
390   default:
391     break;
392   }
393 }
394
395 void AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo,
396                                   raw_ostream &O) {
397   unsigned CT = MI->getOperand(OpNo).getImm();
398   switch (CT) {
399   case 0:
400     O << "U";
401     break;
402   case 1:
403     O << "N";
404     break;
405   default:
406     break;
407   }
408 }
409
410 void AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo,
411                                     raw_ostream &O) {
412   int KCacheMode = MI->getOperand(OpNo).getImm();
413   if (KCacheMode > 0) {
414     int KCacheBank = MI->getOperand(OpNo - 2).getImm();
415     O << "CB" << KCacheBank <<":";
416     int KCacheAddr = MI->getOperand(OpNo + 2).getImm();
417     int LineSize = (KCacheMode == 1)?16:32;
418     O << KCacheAddr * 16 << "-" << KCacheAddr * 16 + LineSize;
419   }
420 }
421
422 void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo,
423                                      raw_ostream &O) {
424   unsigned SImm16 = MI->getOperand(OpNo).getImm();
425   unsigned Msg = SImm16 & 0xF;
426   if (Msg == 2 || Msg == 3) {
427     unsigned Op = (SImm16 >> 4) & 0xF;
428     if (Msg == 3)
429       O << "Gs_done(";
430     else
431       O << "Gs(";
432     if (Op == 0) {
433       O << "nop";
434     } else {
435       unsigned Stream = (SImm16 >> 8) & 0x3;
436       if (Op == 1)
437         O << "cut";
438       else if (Op == 2)
439         O << "emit";
440       else if (Op == 3)
441         O << "emit-cut";
442       O << " stream " << Stream;
443     }
444     O << "), [m0] ";
445   } else if (Msg == 1)
446     O << "interrupt ";
447   else if (Msg == 15)
448     O << "system ";
449   else
450     O << "unknown(" << Msg << ") ";
451 }
452
453 void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo,
454                                       raw_ostream &O) {
455   // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs
456   // SIInsertWaits.cpp bits usage does not match ISA docs description but it
457   // works so it might be a misprint in docs.
458   unsigned SImm16 = MI->getOperand(OpNo).getImm();
459   unsigned Vmcnt = SImm16 & 0xF;
460   unsigned Expcnt = (SImm16 >> 4) & 0xF;
461   unsigned Lgkmcnt = (SImm16 >> 8) & 0xF;
462   if (Vmcnt != 0xF)
463     O << "vmcnt(" << Vmcnt << ") ";
464   if (Expcnt != 0x7)
465     O << "expcnt(" << Expcnt << ") ";
466   if (Lgkmcnt != 0x7)
467     O << "lgkmcnt(" << Lgkmcnt << ")";
468 }
469
470 #include "AMDGPUGenAsmWriter.inc"