Use helper function
[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::printOperandAndMods(const MCInst *MI, unsigned OpNo,
162                                             raw_ostream &O) {
163   unsigned InputModifiers = MI->getOperand(OpNo).getImm();
164   if (InputModifiers & 0x1)
165     O << "-";
166   if (InputModifiers & 0x2)
167     O << "|";
168   printOperand(MI, OpNo + 1, O);
169   if (InputModifiers & 0x2)
170     O << "|";
171 }
172
173 void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum,
174                                         raw_ostream &O) {
175   unsigned Imm = MI->getOperand(OpNum).getImm();
176
177   if (Imm == 2) {
178     O << "P0";
179   } else if (Imm == 1) {
180     O << "P20";
181   } else if (Imm == 0) {
182     O << "P10";
183   } else {
184     assert(!"Invalid interpolation parameter slot");
185   }
186 }
187
188 void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
189                                         raw_ostream &O) {
190   printOperand(MI, OpNo, O);
191   O  << ", ";
192   printOperand(MI, OpNo + 1, O);
193 }
194
195 void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
196                                    raw_ostream &O, StringRef Asm,
197                                    StringRef Default) {
198   const MCOperand &Op = MI->getOperand(OpNo);
199   assert(Op.isImm());
200   if (Op.getImm() == 1) {
201     O << Asm;
202   } else {
203     O << Default;
204   }
205 }
206
207 void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo,
208                                  raw_ostream &O) {
209   printIfSet(MI, OpNo, O, "|");
210 }
211
212 void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo,
213                                    raw_ostream &O) {
214   printIfSet(MI, OpNo, O, "_SAT");
215 }
216
217 void AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo,
218                                      raw_ostream &O) {
219   int32_t Imm = MI->getOperand(OpNo).getImm();
220   O << Imm << '(' << BitsToFloat(Imm) << ')';
221 }
222
223 void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo,
224                                   raw_ostream &O) {
225   printIfSet(MI, OpNo, O.indent(25 - O.GetNumBytesInBuffer()), "*", " ");
226 }
227
228 void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo,
229                                  raw_ostream &O) {
230   printIfSet(MI, OpNo, O, "-");
231 }
232
233 void AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo,
234                                   raw_ostream &O) {
235   switch (MI->getOperand(OpNo).getImm()) {
236   default: break;
237   case 1:
238     O << " * 2.0";
239     break;
240   case 2:
241     O << " * 4.0";
242     break;
243   case 3:
244     O << " / 2.0";
245     break;
246   }
247 }
248
249 void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo,
250                                  raw_ostream &O) {
251   printIfSet(MI, OpNo, O, "+");
252 }
253
254 void AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo,
255                                             raw_ostream &O) {
256   printIfSet(MI, OpNo, O, "ExecMask,");
257 }
258
259 void AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo,
260                                         raw_ostream &O) {
261   printIfSet(MI, OpNo, O, "Pred,");
262 }
263
264 void AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo,
265                                        raw_ostream &O) {
266   const MCOperand &Op = MI->getOperand(OpNo);
267   if (Op.getImm() == 0) {
268     O << " (MASKED)";
269   }
270 }
271
272 void AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo,
273                                   raw_ostream &O) {
274   const char * chans = "XYZW";
275   int sel = MI->getOperand(OpNo).getImm();
276
277   int chan = sel & 3;
278   sel >>= 2;
279
280   if (sel >= 512) {
281     sel -= 512;
282     int cb = sel >> 12;
283     sel &= 4095;
284     O << cb << "[" << sel << "]";
285   } else if (sel >= 448) {
286     sel -= 448;
287     O << sel;
288   } else if (sel >= 0){
289     O << sel;
290   }
291
292   if (sel >= 0)
293     O << "." << chans[chan];
294 }
295
296 void AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo,
297                                          raw_ostream &O) {
298   int BankSwizzle = MI->getOperand(OpNo).getImm();
299   switch (BankSwizzle) {
300   case 1:
301     O << "BS:VEC_021/SCL_122";
302     break;
303   case 2:
304     O << "BS:VEC_120/SCL_212";
305     break;
306   case 3:
307     O << "BS:VEC_102/SCL_221";
308     break;
309   case 4:
310     O << "BS:VEC_201";
311     break;
312   case 5:
313     O << "BS:VEC_210";
314     break;
315   default:
316     break;
317   }
318   return;
319 }
320
321 void AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo,
322                                   raw_ostream &O) {
323   unsigned Sel = MI->getOperand(OpNo).getImm();
324   switch (Sel) {
325   case 0:
326     O << "X";
327     break;
328   case 1:
329     O << "Y";
330     break;
331   case 2:
332     O << "Z";
333     break;
334   case 3:
335     O << "W";
336     break;
337   case 4:
338     O << "0";
339     break;
340   case 5:
341     O << "1";
342     break;
343   case 7:
344     O << "_";
345     break;
346   default:
347     break;
348   }
349 }
350
351 void AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo,
352                                   raw_ostream &O) {
353   unsigned CT = MI->getOperand(OpNo).getImm();
354   switch (CT) {
355   case 0:
356     O << "U";
357     break;
358   case 1:
359     O << "N";
360     break;
361   default:
362     break;
363   }
364 }
365
366 void AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo,
367                                     raw_ostream &O) {
368   int KCacheMode = MI->getOperand(OpNo).getImm();
369   if (KCacheMode > 0) {
370     int KCacheBank = MI->getOperand(OpNo - 2).getImm();
371     O << "CB" << KCacheBank <<":";
372     int KCacheAddr = MI->getOperand(OpNo + 2).getImm();
373     int LineSize = (KCacheMode == 1)?16:32;
374     O << KCacheAddr * 16 << "-" << KCacheAddr * 16 + LineSize;
375   }
376 }
377
378 void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo,
379                                      raw_ostream &O) {
380   unsigned SImm16 = MI->getOperand(OpNo).getImm();
381   unsigned Msg = SImm16 & 0xF;
382   if (Msg == 2 || Msg == 3) {
383     unsigned Op = (SImm16 >> 4) & 0xF;
384     if (Msg == 3)
385       O << "Gs_done(";
386     else
387       O << "Gs(";
388     if (Op == 0) {
389       O << "nop";
390     } else {
391       unsigned Stream = (SImm16 >> 8) & 0x3;
392       if (Op == 1)
393         O << "cut";
394       else if (Op == 2)
395         O << "emit";
396       else if (Op == 3)
397         O << "emit-cut";
398       O << " stream " << Stream;
399     }
400     O << "), [m0] ";
401   } else if (Msg == 1)
402     O << "interrupt ";
403   else if (Msg == 15)
404     O << "system ";
405   else
406     O << "unknown(" << Msg << ") ";
407 }
408
409 void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo,
410                                       raw_ostream &O) {
411   // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs
412   // SIInsertWaits.cpp bits usage does not match ISA docs description but it
413   // works so it might be a misprint in docs.
414   unsigned SImm16 = MI->getOperand(OpNo).getImm();
415   unsigned Vmcnt = SImm16 & 0xF;
416   unsigned Expcnt = (SImm16 >> 4) & 0xF;
417   unsigned Lgkmcnt = (SImm16 >> 8) & 0xF;
418   if (Vmcnt != 0xF)
419     O << "vmcnt(" << Vmcnt << ") ";
420   if (Expcnt != 0x7)
421     O << "expcnt(" << Expcnt << ") ";
422   if (Lgkmcnt != 0x7)
423     O << "lgkmcnt(" << Lgkmcnt << ")";
424 }
425
426 #include "AMDGPUGenAsmWriter.inc"