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