AMDGPUInstPrinter.cpp revision 263508
1272343Sngie//===-- AMDGPUInstPrinter.cpp - AMDGPU MC Inst -> ASM ---------------------===//
2272343Sngie//
3272343Sngie//                     The LLVM Compiler Infrastructure
4272343Sngie//
5272343Sngie// This file is distributed under the University of Illinois Open Source
6272343Sngie// License. See LICENSE.TXT for details.
7272343Sngie//
8272343Sngie// \file
9272343Sngie//===----------------------------------------------------------------------===//
10272343Sngie
11272343Sngie#include "AMDGPUInstPrinter.h"
12272343Sngie#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
13272343Sngie#include "llvm/MC/MCExpr.h"
14272343Sngie#include "llvm/MC/MCInst.h"
15272343Sngie
16272343Sngieusing namespace llvm;
17272343Sngie
18272343Sngievoid AMDGPUInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
19272343Sngie                             StringRef Annot) {
20272343Sngie  OS.flush();
21272343Sngie  printInstruction(MI, OS);
22272343Sngie
23272343Sngie  printAnnotation(OS, Annot);
24272343Sngie}
25272343Sngie
26272343Sngievoid AMDGPUInstPrinter::printRegOperand(unsigned reg, raw_ostream &O) {
27272343Sngie  switch (reg) {
28272343Sngie  case AMDGPU::VCC:
29272343Sngie    O << "vcc";
30272343Sngie    return;
31272343Sngie  case AMDGPU::SCC:
32272343Sngie    O << "scc";
33272343Sngie    return;
34272343Sngie  case AMDGPU::EXEC:
35272343Sngie    O << "exec";
36272343Sngie    return;
37272343Sngie  case AMDGPU::M0:
38272343Sngie    O << "m0";
39272343Sngie    return;
40272343Sngie  default:
41272343Sngie    break;
42272343Sngie  }
43272343Sngie
44272343Sngie  // It's seems there's no way to use SIRegisterInfo here, and dealing with the
45272343Sngie  // giant enum of all the different shifted sets of registers is pretty
46272343Sngie  // unmanagable, so parse the name and reformat it to be prettier.
47272343Sngie  StringRef Name(getRegisterName(reg));
48272343Sngie
49272343Sngie  std::pair<StringRef, StringRef> Split = Name.split('_');
50272343Sngie  StringRef SubRegName = Split.first;
51272343Sngie  StringRef Rest = Split.second;
52272343Sngie
53272343Sngie  if (SubRegName.size() <= 4) { // Must at least be as long as "SGPR"/"VGPR".
54272343Sngie    O << Name;
55272343Sngie    return;
56272343Sngie  }
57272343Sngie
58272343Sngie  unsigned RegIndex;
59272343Sngie  StringRef RegIndexStr = SubRegName.drop_front(4);
60272343Sngie
61272343Sngie  if (RegIndexStr.getAsInteger(10, RegIndex)) {
62272343Sngie    O << Name;
63272343Sngie    return;
64272343Sngie  }
65272343Sngie
66272343Sngie  if (SubRegName.front() == 'V')
67272343Sngie    O << 'v';
68272343Sngie  else if (SubRegName.front() == 'S')
69272343Sngie    O << 's';
70272343Sngie  else {
71272343Sngie    O << Name;
72272343Sngie    return;
73272343Sngie  }
74272343Sngie
75272343Sngie  if (Rest.empty()) // Only 1 32-bit register
76272343Sngie    O << RegIndex;
77272343Sngie  else {
78272343Sngie    unsigned NumReg = Rest.count('_') + 2;
79272343Sngie    O << '[' << RegIndex << ':' << (RegIndex + NumReg - 1) << ']';
80272343Sngie  }
81272343Sngie}
82272343Sngie
83272343Sngievoid AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
84272343Sngie                                     raw_ostream &O) {
85272343Sngie
86272343Sngie  const MCOperand &Op = MI->getOperand(OpNo);
87272343Sngie  if (Op.isReg()) {
88272343Sngie    switch (Op.getReg()) {
89272343Sngie    // This is the default predicate state, so we don't need to print it.
90272343Sngie    case AMDGPU::PRED_SEL_OFF:
91272343Sngie      break;
92272343Sngie
93272343Sngie    default:
94272343Sngie      printRegOperand(Op.getReg(), O);
95272343Sngie      break;
96272343Sngie    }
97272343Sngie  } else if (Op.isImm()) {
98272343Sngie    O << Op.getImm();
99272343Sngie  } else if (Op.isFPImm()) {
100272343Sngie    O << Op.getFPImm();
101272343Sngie  } else if (Op.isExpr()) {
102272343Sngie    const MCExpr *Exp = Op.getExpr();
103272343Sngie    Exp->print(O);
104272343Sngie  } else {
105272343Sngie    assert(!"unknown operand type in printOperand");
106272343Sngie  }
107272343Sngie}
108272343Sngie
109272343Sngievoid AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum,
110272343Sngie                                        raw_ostream &O) {
111272343Sngie  unsigned Imm = MI->getOperand(OpNum).getImm();
112272343Sngie
113272343Sngie  if (Imm == 2) {
114272343Sngie    O << "P0";
115272343Sngie  } else if (Imm == 1) {
116272343Sngie    O << "P20";
117272343Sngie  } else if (Imm == 0) {
118272343Sngie    O << "P10";
119272343Sngie  } else {
120272343Sngie    assert(!"Invalid interpolation parameter slot");
121272343Sngie  }
122272343Sngie}
123272343Sngie
124272343Sngievoid AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
125272343Sngie                                        raw_ostream &O) {
126272343Sngie  printOperand(MI, OpNo, O);
127272343Sngie  O  << ", ";
128272343Sngie  printOperand(MI, OpNo + 1, O);
129272343Sngie}
130272343Sngie
131272343Sngievoid AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
132272343Sngie                                   raw_ostream &O, StringRef Asm,
133272343Sngie                                   StringRef Default) {
134272343Sngie  const MCOperand &Op = MI->getOperand(OpNo);
135272343Sngie  assert(Op.isImm());
136272343Sngie  if (Op.getImm() == 1) {
137272343Sngie    O << Asm;
138272343Sngie  } else {
139272343Sngie    O << Default;
140272343Sngie  }
141272343Sngie}
142272343Sngie
143272343Sngievoid 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::printWaitFlag(const MCInst *MI, unsigned OpNo,
320                                      raw_ostream &O) {
321  // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs
322  // SIInsertWaits.cpp bits usage does not match ISA docs description but it
323  // works so it might be a misprint in docs.
324  unsigned SImm16 = MI->getOperand(OpNo).getImm();
325  unsigned Vmcnt = SImm16 & 0xF;
326  unsigned Expcnt = (SImm16 >> 4) & 0xF;
327  unsigned Lgkmcnt = (SImm16 >> 8) & 0xF;
328  if (Vmcnt != 0xF)
329    O << "vmcnt(" << Vmcnt << ") ";
330  if (Expcnt != 0x7)
331    O << "expcnt(" << Expcnt << ") ";
332  if (Lgkmcnt != 0x7)
333    O << "lgkmcnt(" << Lgkmcnt << ")";
334}
335
336#include "AMDGPUGenAsmWriter.inc"
337