]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/lib/Target/R600/InstPrinter/AMDGPUInstPrinter.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / 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
16 using namespace llvm;
17
18 void 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
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.
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
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,
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
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"