1249259Sdim//===-- AMDGPUInstPrinter.cpp - AMDGPU MC Inst -> ASM ---------------------===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim// \file
9249259Sdim//===----------------------------------------------------------------------===//
10249259Sdim
11249259Sdim#include "AMDGPUInstPrinter.h"
12249259Sdim#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
13263508Sdim#include "llvm/MC/MCExpr.h"
14249259Sdim#include "llvm/MC/MCInst.h"
15249259Sdim
16249259Sdimusing namespace llvm;
17249259Sdim
18249259Sdimvoid AMDGPUInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
19249259Sdim                             StringRef Annot) {
20251662Sdim  OS.flush();
21249259Sdim  printInstruction(MI, OS);
22249259Sdim
23249259Sdim  printAnnotation(OS, Annot);
24249259Sdim}
25249259Sdim
26263508Sdimvoid AMDGPUInstPrinter::printRegOperand(unsigned reg, raw_ostream &O) {
27263508Sdim  switch (reg) {
28263508Sdim  case AMDGPU::VCC:
29263508Sdim    O << "vcc";
30263508Sdim    return;
31263508Sdim  case AMDGPU::SCC:
32263508Sdim    O << "scc";
33263508Sdim    return;
34263508Sdim  case AMDGPU::EXEC:
35263508Sdim    O << "exec";
36263508Sdim    return;
37263508Sdim  case AMDGPU::M0:
38263508Sdim    O << "m0";
39263508Sdim    return;
40263508Sdim  default:
41263508Sdim    break;
42263508Sdim  }
43263508Sdim
44263508Sdim  // It's seems there's no way to use SIRegisterInfo here, and dealing with the
45263508Sdim  // giant enum of all the different shifted sets of registers is pretty
46263508Sdim  // unmanagable, so parse the name and reformat it to be prettier.
47263508Sdim  StringRef Name(getRegisterName(reg));
48263508Sdim
49263508Sdim  std::pair<StringRef, StringRef> Split = Name.split('_');
50263508Sdim  StringRef SubRegName = Split.first;
51263508Sdim  StringRef Rest = Split.second;
52263508Sdim
53263508Sdim  if (SubRegName.size() <= 4) { // Must at least be as long as "SGPR"/"VGPR".
54263508Sdim    O << Name;
55263508Sdim    return;
56263508Sdim  }
57263508Sdim
58263508Sdim  unsigned RegIndex;
59263508Sdim  StringRef RegIndexStr = SubRegName.drop_front(4);
60263508Sdim
61263508Sdim  if (RegIndexStr.getAsInteger(10, RegIndex)) {
62263508Sdim    O << Name;
63263508Sdim    return;
64263508Sdim  }
65263508Sdim
66263508Sdim  if (SubRegName.front() == 'V')
67263508Sdim    O << 'v';
68263508Sdim  else if (SubRegName.front() == 'S')
69263508Sdim    O << 's';
70263508Sdim  else {
71263508Sdim    O << Name;
72263508Sdim    return;
73263508Sdim  }
74263508Sdim
75263508Sdim  if (Rest.empty()) // Only 1 32-bit register
76263508Sdim    O << RegIndex;
77263508Sdim  else {
78263508Sdim    unsigned NumReg = Rest.count('_') + 2;
79263508Sdim    O << '[' << RegIndex << ':' << (RegIndex + NumReg - 1) << ']';
80263508Sdim  }
81263508Sdim}
82263508Sdim
83249259Sdimvoid AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
84249259Sdim                                     raw_ostream &O) {
85249259Sdim
86249259Sdim  const MCOperand &Op = MI->getOperand(OpNo);
87249259Sdim  if (Op.isReg()) {
88249259Sdim    switch (Op.getReg()) {
89249259Sdim    // This is the default predicate state, so we don't need to print it.
90263508Sdim    case AMDGPU::PRED_SEL_OFF:
91263508Sdim      break;
92263508Sdim
93263508Sdim    default:
94263508Sdim      printRegOperand(Op.getReg(), O);
95263508Sdim      break;
96249259Sdim    }
97249259Sdim  } else if (Op.isImm()) {
98249259Sdim    O << Op.getImm();
99249259Sdim  } else if (Op.isFPImm()) {
100249259Sdim    O << Op.getFPImm();
101249259Sdim  } else if (Op.isExpr()) {
102249259Sdim    const MCExpr *Exp = Op.getExpr();
103249259Sdim    Exp->print(O);
104249259Sdim  } else {
105249259Sdim    assert(!"unknown operand type in printOperand");
106249259Sdim  }
107249259Sdim}
108249259Sdim
109249259Sdimvoid AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum,
110249259Sdim                                        raw_ostream &O) {
111249259Sdim  unsigned Imm = MI->getOperand(OpNum).getImm();
112249259Sdim
113249259Sdim  if (Imm == 2) {
114249259Sdim    O << "P0";
115249259Sdim  } else if (Imm == 1) {
116249259Sdim    O << "P20";
117249259Sdim  } else if (Imm == 0) {
118249259Sdim    O << "P10";
119249259Sdim  } else {
120249259Sdim    assert(!"Invalid interpolation parameter slot");
121249259Sdim  }
122249259Sdim}
123249259Sdim
124249259Sdimvoid AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
125249259Sdim                                        raw_ostream &O) {
126249259Sdim  printOperand(MI, OpNo, O);
127249259Sdim  O  << ", ";
128249259Sdim  printOperand(MI, OpNo + 1, O);
129249259Sdim}
130249259Sdim
131249259Sdimvoid AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
132251662Sdim                                   raw_ostream &O, StringRef Asm,
133251662Sdim                                   StringRef Default) {
134249259Sdim  const MCOperand &Op = MI->getOperand(OpNo);
135249259Sdim  assert(Op.isImm());
136249259Sdim  if (Op.getImm() == 1) {
137249259Sdim    O << Asm;
138251662Sdim  } else {
139251662Sdim    O << Default;
140249259Sdim  }
141249259Sdim}
142249259Sdim
143249259Sdimvoid AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo,
144249259Sdim                                 raw_ostream &O) {
145249259Sdim  printIfSet(MI, OpNo, O, "|");
146249259Sdim}
147249259Sdim
148249259Sdimvoid AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo,
149249259Sdim                                   raw_ostream &O) {
150249259Sdim  printIfSet(MI, OpNo, O, "_SAT");
151249259Sdim}
152249259Sdim
153249259Sdimvoid AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo,
154249259Sdim                                     raw_ostream &O) {
155249259Sdim  union Literal {
156249259Sdim    float f;
157249259Sdim    int32_t i;
158249259Sdim  } L;
159249259Sdim
160249259Sdim  L.i = MI->getOperand(OpNo).getImm();
161249259Sdim  O << L.i << "(" << L.f << ")";
162249259Sdim}
163249259Sdim
164249259Sdimvoid AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo,
165249259Sdim                                  raw_ostream &O) {
166263508Sdim  printIfSet(MI, OpNo, O.indent(25 - O.GetNumBytesInBuffer()), "*", " ");
167249259Sdim}
168249259Sdim
169249259Sdimvoid AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo,
170249259Sdim                                 raw_ostream &O) {
171249259Sdim  printIfSet(MI, OpNo, O, "-");
172249259Sdim}
173249259Sdim
174249259Sdimvoid AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo,
175249259Sdim                                  raw_ostream &O) {
176249259Sdim  switch (MI->getOperand(OpNo).getImm()) {
177249259Sdim  default: break;
178249259Sdim  case 1:
179249259Sdim    O << " * 2.0";
180249259Sdim    break;
181249259Sdim  case 2:
182249259Sdim    O << " * 4.0";
183249259Sdim    break;
184249259Sdim  case 3:
185249259Sdim    O << " / 2.0";
186249259Sdim    break;
187249259Sdim  }
188249259Sdim}
189249259Sdim
190249259Sdimvoid AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo,
191249259Sdim                                 raw_ostream &O) {
192249259Sdim  printIfSet(MI, OpNo, O, "+");
193249259Sdim}
194249259Sdim
195249259Sdimvoid AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo,
196249259Sdim                                            raw_ostream &O) {
197249259Sdim  printIfSet(MI, OpNo, O, "ExecMask,");
198249259Sdim}
199249259Sdim
200249259Sdimvoid AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo,
201249259Sdim                                        raw_ostream &O) {
202249259Sdim  printIfSet(MI, OpNo, O, "Pred,");
203249259Sdim}
204249259Sdim
205249259Sdimvoid AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo,
206249259Sdim                                       raw_ostream &O) {
207249259Sdim  const MCOperand &Op = MI->getOperand(OpNo);
208249259Sdim  if (Op.getImm() == 0) {
209249259Sdim    O << " (MASKED)";
210249259Sdim  }
211249259Sdim}
212249259Sdim
213249259Sdimvoid AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo,
214249259Sdim                                  raw_ostream &O) {
215249259Sdim  const char * chans = "XYZW";
216249259Sdim  int sel = MI->getOperand(OpNo).getImm();
217249259Sdim
218249259Sdim  int chan = sel & 3;
219249259Sdim  sel >>= 2;
220249259Sdim
221249259Sdim  if (sel >= 512) {
222249259Sdim    sel -= 512;
223249259Sdim    int cb = sel >> 12;
224249259Sdim    sel &= 4095;
225249259Sdim    O << cb << "[" << sel << "]";
226249259Sdim  } else if (sel >= 448) {
227249259Sdim    sel -= 448;
228249259Sdim    O << sel;
229249259Sdim  } else if (sel >= 0){
230249259Sdim    O << sel;
231249259Sdim  }
232249259Sdim
233249259Sdim  if (sel >= 0)
234249259Sdim    O << "." << chans[chan];
235249259Sdim}
236249259Sdim
237251662Sdimvoid AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo,
238251662Sdim                                         raw_ostream &O) {
239251662Sdim  int BankSwizzle = MI->getOperand(OpNo).getImm();
240251662Sdim  switch (BankSwizzle) {
241251662Sdim  case 1:
242263508Sdim    O << "BS:VEC_021/SCL_122";
243251662Sdim    break;
244251662Sdim  case 2:
245263508Sdim    O << "BS:VEC_120/SCL_212";
246251662Sdim    break;
247251662Sdim  case 3:
248263508Sdim    O << "BS:VEC_102/SCL_221";
249251662Sdim    break;
250251662Sdim  case 4:
251251662Sdim    O << "BS:VEC_201";
252251662Sdim    break;
253251662Sdim  case 5:
254251662Sdim    O << "BS:VEC_210";
255251662Sdim    break;
256251662Sdim  default:
257251662Sdim    break;
258251662Sdim  }
259251662Sdim  return;
260251662Sdim}
261251662Sdim
262263508Sdimvoid AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo,
263263508Sdim                                  raw_ostream &O) {
264263508Sdim  unsigned Sel = MI->getOperand(OpNo).getImm();
265263508Sdim  switch (Sel) {
266263508Sdim  case 0:
267263508Sdim    O << "X";
268263508Sdim    break;
269263508Sdim  case 1:
270263508Sdim    O << "Y";
271263508Sdim    break;
272263508Sdim  case 2:
273263508Sdim    O << "Z";
274263508Sdim    break;
275263508Sdim  case 3:
276263508Sdim    O << "W";
277263508Sdim    break;
278263508Sdim  case 4:
279263508Sdim    O << "0";
280263508Sdim    break;
281263508Sdim  case 5:
282263508Sdim    O << "1";
283263508Sdim    break;
284263508Sdim  case 7:
285263508Sdim    O << "_";
286263508Sdim    break;
287263508Sdim  default:
288263508Sdim    break;
289263508Sdim  }
290263508Sdim}
291263508Sdim
292263508Sdimvoid AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo,
293263508Sdim                                  raw_ostream &O) {
294263508Sdim  unsigned CT = MI->getOperand(OpNo).getImm();
295263508Sdim  switch (CT) {
296263508Sdim  case 0:
297263508Sdim    O << "U";
298263508Sdim    break;
299263508Sdim  case 1:
300263508Sdim    O << "N";
301263508Sdim    break;
302263508Sdim  default:
303263508Sdim    break;
304263508Sdim  }
305263508Sdim}
306263508Sdim
307251662Sdimvoid AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo,
308251662Sdim                                    raw_ostream &O) {
309251662Sdim  int KCacheMode = MI->getOperand(OpNo).getImm();
310251662Sdim  if (KCacheMode > 0) {
311251662Sdim    int KCacheBank = MI->getOperand(OpNo - 2).getImm();
312251662Sdim    O << "CB" << KCacheBank <<":";
313251662Sdim    int KCacheAddr = MI->getOperand(OpNo + 2).getImm();
314251662Sdim    int LineSize = (KCacheMode == 1)?16:32;
315251662Sdim    O << KCacheAddr * 16 << "-" << KCacheAddr * 16 + LineSize;
316251662Sdim  }
317251662Sdim}
318251662Sdim
319263508Sdimvoid AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo,
320263508Sdim                                      raw_ostream &O) {
321263508Sdim  // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs
322263508Sdim  // SIInsertWaits.cpp bits usage does not match ISA docs description but it
323263508Sdim  // works so it might be a misprint in docs.
324263508Sdim  unsigned SImm16 = MI->getOperand(OpNo).getImm();
325263508Sdim  unsigned Vmcnt = SImm16 & 0xF;
326263508Sdim  unsigned Expcnt = (SImm16 >> 4) & 0xF;
327263508Sdim  unsigned Lgkmcnt = (SImm16 >> 8) & 0xF;
328263508Sdim  if (Vmcnt != 0xF)
329263508Sdim    O << "vmcnt(" << Vmcnt << ") ";
330263508Sdim  if (Expcnt != 0x7)
331263508Sdim    O << "expcnt(" << Expcnt << ") ";
332263508Sdim  if (Lgkmcnt != 0x7)
333263508Sdim    O << "lgkmcnt(" << Lgkmcnt << ")";
334263508Sdim}
335263508Sdim
336249259Sdim#include "AMDGPUGenAsmWriter.inc"
337