AMDGPUInstPrinter.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
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
16using namespace llvm;
17
18void AMDGPUInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
19                             StringRef Annot) {
20  OS.flush();
21  printInstruction(MI, OS);
22
23  printAnnotation(OS, Annot);
24}
25
26void AMDGPUInstPrinter::printRegOperand(unsigned reg, raw_ostream &O) {
27  switch (reg) {
28  case AMDGPU::VCC:
29    O << "vcc";
30    return;
31  case AMDGPU::SCC:
32    O << "scc";
33    return;
34  case AMDGPU::EXEC:
35    O << "exec";
36    return;
37  case AMDGPU::M0:
38    O << "m0";
39    return;
40  default:
41    break;
42  }
43
44  // It's seems there's no way to use SIRegisterInfo here, and dealing with the
45  // giant enum of all the different shifted sets of registers is pretty
46  // unmanagable, so parse the name and reformat it to be prettier.
47  StringRef Name(getRegisterName(reg));
48
49  std::pair<StringRef, StringRef> Split = Name.split('_');
50  StringRef SubRegName = Split.first;
51  StringRef Rest = Split.second;
52
53  if (SubRegName.size() <= 4) { // Must at least be as long as "SGPR"/"VGPR".
54    O << Name;
55    return;
56  }
57
58  unsigned RegIndex;
59  StringRef RegIndexStr = SubRegName.drop_front(4);
60
61  if (RegIndexStr.getAsInteger(10, RegIndex)) {
62    O << Name;
63    return;
64  }
65
66  if (SubRegName.front() == 'V')
67    O << 'v';
68  else if (SubRegName.front() == 'S')
69    O << 's';
70  else {
71    O << Name;
72    return;
73  }
74
75  if (Rest.empty()) // Only 1 32-bit register
76    O << RegIndex;
77  else {
78    unsigned NumReg = Rest.count('_') + 2;
79    O << '[' << RegIndex << ':' << (RegIndex + NumReg - 1) << ']';
80  }
81}
82
83void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
84                                     raw_ostream &O) {
85
86  const MCOperand &Op = MI->getOperand(OpNo);
87  if (Op.isReg()) {
88    switch (Op.getReg()) {
89    // This is the default predicate state, so we don't need to print it.
90    case AMDGPU::PRED_SEL_OFF:
91      break;
92
93    default:
94      printRegOperand(Op.getReg(), O);
95      break;
96    }
97  } else if (Op.isImm()) {
98    O << Op.getImm();
99  } else if (Op.isFPImm()) {
100    O << Op.getFPImm();
101  } else if (Op.isExpr()) {
102    const MCExpr *Exp = Op.getExpr();
103    Exp->print(O);
104  } else {
105    assert(!"unknown operand type in printOperand");
106  }
107}
108
109void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum,
110                                        raw_ostream &O) {
111  unsigned Imm = MI->getOperand(OpNum).getImm();
112
113  if (Imm == 2) {
114    O << "P0";
115  } else if (Imm == 1) {
116    O << "P20";
117  } else if (Imm == 0) {
118    O << "P10";
119  } else {
120    assert(!"Invalid interpolation parameter slot");
121  }
122}
123
124void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
125                                        raw_ostream &O) {
126  printOperand(MI, OpNo, O);
127  O  << ", ";
128  printOperand(MI, OpNo + 1, O);
129}
130
131void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
132                                   raw_ostream &O, StringRef Asm,
133                                   StringRef Default) {
134  const MCOperand &Op = MI->getOperand(OpNo);
135  assert(Op.isImm());
136  if (Op.getImm() == 1) {
137    O << Asm;
138  } else {
139    O << Default;
140  }
141}
142
143void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo,
144                                 raw_ostream &O) {
145  printIfSet(MI, OpNo, O, "|");
146}
147
148void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo,
149                                   raw_ostream &O) {
150  printIfSet(MI, OpNo, O, "_SAT");
151}
152
153void AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo,
154                                     raw_ostream &O) {
155  union Literal {
156    float f;
157    int32_t i;
158  } L;
159
160  L.i = MI->getOperand(OpNo).getImm();
161  O << L.i << "(" << L.f << ")";
162}
163
164void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo,
165                                  raw_ostream &O) {
166  printIfSet(MI, OpNo, O.indent(25 - O.GetNumBytesInBuffer()), "*", " ");
167}
168
169void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo,
170                                 raw_ostream &O) {
171  printIfSet(MI, OpNo, O, "-");
172}
173
174void AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo,
175                                  raw_ostream &O) {
176  switch (MI->getOperand(OpNo).getImm()) {
177  default: break;
178  case 1:
179    O << " * 2.0";
180    break;
181  case 2:
182    O << " * 4.0";
183    break;
184  case 3:
185    O << " / 2.0";
186    break;
187  }
188}
189
190void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo,
191                                 raw_ostream &O) {
192  printIfSet(MI, OpNo, O, "+");
193}
194
195void AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo,
196                                            raw_ostream &O) {
197  printIfSet(MI, OpNo, O, "ExecMask,");
198}
199
200void AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo,
201                                        raw_ostream &O) {
202  printIfSet(MI, OpNo, O, "Pred,");
203}
204
205void AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo,
206                                       raw_ostream &O) {
207  const MCOperand &Op = MI->getOperand(OpNo);
208  if (Op.getImm() == 0) {
209    O << " (MASKED)";
210  }
211}
212
213void AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo,
214                                  raw_ostream &O) {
215  const char * chans = "XYZW";
216  int sel = MI->getOperand(OpNo).getImm();
217
218  int chan = sel & 3;
219  sel >>= 2;
220
221  if (sel >= 512) {
222    sel -= 512;
223    int cb = sel >> 12;
224    sel &= 4095;
225    O << cb << "[" << sel << "]";
226  } else if (sel >= 448) {
227    sel -= 448;
228    O << sel;
229  } else if (sel >= 0){
230    O << sel;
231  }
232
233  if (sel >= 0)
234    O << "." << chans[chan];
235}
236
237void AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo,
238                                         raw_ostream &O) {
239  int BankSwizzle = MI->getOperand(OpNo).getImm();
240  switch (BankSwizzle) {
241  case 1:
242    O << "BS:VEC_021/SCL_122";
243    break;
244  case 2:
245    O << "BS:VEC_120/SCL_212";
246    break;
247  case 3:
248    O << "BS:VEC_102/SCL_221";
249    break;
250  case 4:
251    O << "BS:VEC_201";
252    break;
253  case 5:
254    O << "BS:VEC_210";
255    break;
256  default:
257    break;
258  }
259  return;
260}
261
262void AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo,
263                                  raw_ostream &O) {
264  unsigned Sel = MI->getOperand(OpNo).getImm();
265  switch (Sel) {
266  case 0:
267    O << "X";
268    break;
269  case 1:
270    O << "Y";
271    break;
272  case 2:
273    O << "Z";
274    break;
275  case 3:
276    O << "W";
277    break;
278  case 4:
279    O << "0";
280    break;
281  case 5:
282    O << "1";
283    break;
284  case 7:
285    O << "_";
286    break;
287  default:
288    break;
289  }
290}
291
292void AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo,
293                                  raw_ostream &O) {
294  unsigned CT = MI->getOperand(OpNo).getImm();
295  switch (CT) {
296  case 0:
297    O << "U";
298    break;
299  case 1:
300    O << "N";
301    break;
302  default:
303    break;
304  }
305}
306
307void AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo,
308                                    raw_ostream &O) {
309  int KCacheMode = MI->getOperand(OpNo).getImm();
310  if (KCacheMode > 0) {
311    int KCacheBank = MI->getOperand(OpNo - 2).getImm();
312    O << "CB" << KCacheBank <<":";
313    int KCacheAddr = MI->getOperand(OpNo + 2).getImm();
314    int LineSize = (KCacheMode == 1)?16:32;
315    O << KCacheAddr * 16 << "-" << KCacheAddr * 16 + LineSize;
316  }
317}
318
319void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo,
320                                     raw_ostream &O) {
321  unsigned SImm16 = MI->getOperand(OpNo).getImm();
322  unsigned Msg = SImm16 & 0xF;
323  if (Msg == 2 || Msg == 3) {
324    unsigned Op = (SImm16 >> 4) & 0xF;
325    if (Msg == 3)
326      O << "Gs_done(";
327    else
328      O << "Gs(";
329    if (Op == 0) {
330      O << "nop";
331    } else {
332      unsigned Stream = (SImm16 >> 8) & 0x3;
333      if (Op == 1)
334	O << "cut";
335      else if (Op == 2)
336	O << "emit";
337      else if (Op == 3)
338	O << "emit-cut";
339      O << " stream " << Stream;
340    }
341    O << "), [m0] ";
342  } else if (Msg == 1)
343    O << "interrupt ";
344  else if (Msg == 15)
345    O << "system ";
346  else
347    O << "unknown(" << Msg << ") ";
348}
349
350void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo,
351                                      raw_ostream &O) {
352  // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs
353  // SIInsertWaits.cpp bits usage does not match ISA docs description but it
354  // works so it might be a misprint in docs.
355  unsigned SImm16 = MI->getOperand(OpNo).getImm();
356  unsigned Vmcnt = SImm16 & 0xF;
357  unsigned Expcnt = (SImm16 >> 4) & 0xF;
358  unsigned Lgkmcnt = (SImm16 >> 8) & 0xF;
359  if (Vmcnt != 0xF)
360    O << "vmcnt(" << Vmcnt << ") ";
361  if (Expcnt != 0x7)
362    O << "expcnt(" << Expcnt << ") ";
363  if (Lgkmcnt != 0x7)
364    O << "lgkmcnt(" << Lgkmcnt << ")";
365}
366
367#include "AMDGPUGenAsmWriter.inc"
368