LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AMDGPUInstPrinter.cpp
Go to the documentation of this file.
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"
13 #include "llvm/MC/MCExpr.h"
14 #include "llvm/MC/MCInst.h"
15 
16 using namespace llvm;
17 
19  StringRef Annot) {
20  OS.flush();
21  printInstruction(MI, OS);
22 
23  printAnnotation(OS, Annot);
24 }
25 
26 void 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.
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 
83 void 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 
109 void 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 
124 void 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 
131 void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
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 
143 void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo,
144  raw_ostream &O) {
145  printIfSet(MI, OpNo, O, "|");
146 }
147 
148 void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo,
149  raw_ostream &O) {
150  printIfSet(MI, OpNo, O, "_SAT");
151 }
152 
153 void 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 
164 void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo,
165  raw_ostream &O) {
166  printIfSet(MI, OpNo, O.indent(25 - O.GetNumBytesInBuffer()), "*", " ");
167 }
168 
169 void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo,
170  raw_ostream &O) {
171  printIfSet(MI, OpNo, O, "-");
172 }
173 
174 void 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 
190 void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo,
191  raw_ostream &O) {
192  printIfSet(MI, OpNo, O, "+");
193 }
194 
195 void AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo,
196  raw_ostream &O) {
197  printIfSet(MI, OpNo, O, "ExecMask,");
198 }
199 
200 void AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo,
201  raw_ostream &O) {
202  printIfSet(MI, OpNo, O, "Pred,");
203 }
204 
205 void 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 
213 void 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 
237 void 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 
262 void 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 
292 void 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 
307 void 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 
319 void 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"
double getFPImm() const
Definition: MCInst.h:83
size_t size() const
size - Get the string size.
Definition: StringRef.h:113
bool isReg() const
Definition: MCInst.h:56
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot)
void printInstruction(const MCInst *MI, raw_ostream &O)
unsigned getReg() const
getReg - Returns the register number.
Definition: MCInst.h:63
static const char * getRegisterName(unsigned RegNo)
bool isImm() const
Definition: MCInst.h:57
const MCExpr * getExpr() const
Definition: MCInst.h:93
bool isFPImm() const
Definition: MCInst.h:58
size_t count(char C) const
Return the number of occurrences of C in the string.
Definition: StringRef.h:316
bool isExpr() const
Definition: MCInst.h:59
enable_if_c< std::numeric_limits< T >::is_signed, bool >::type getAsInteger(unsigned Radix, T &Result) const
Definition: StringRef.h:337
static void Split(std::vector< std::string > &V, const StringRef S)
StringRef drop_front(size_t N=1) const
Definition: StringRef.h:399
int64_t getImm() const
Definition: MCInst.h:74
Provides AMDGPU specific target descriptions.
void print(raw_ostream &OS) const
Definition: MCExpr.cpp:31
char front() const
front - Get the first character in the string.
Definition: StringRef.h:116
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:163
size_t GetNumBytesInBuffer() const
Definition: raw_ostream.h:121
bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:110