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
printInst(const MCInst * MI,raw_ostream & OS,StringRef Annot)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
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)26 void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
27 raw_ostream &O) {
28
29 const MCOperand &Op = MI->getOperand(OpNo);
30 if (Op.isReg()) {
31 switch (Op.getReg()) {
32 // This is the default predicate state, so we don't need to print it.
33 case AMDGPU::PRED_SEL_OFF: break;
34 default: O << getRegisterName(Op.getReg()); break;
35 }
36 } else if (Op.isImm()) {
37 O << Op.getImm();
38 } else if (Op.isFPImm()) {
39 O << Op.getFPImm();
40 } else if (Op.isExpr()) {
41 const MCExpr *Exp = Op.getExpr();
42 Exp->print(O);
43 } else {
44 assert(!"unknown operand type in printOperand");
45 }
46 }
47
printInterpSlot(const MCInst * MI,unsigned OpNum,raw_ostream & O)48 void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum,
49 raw_ostream &O) {
50 unsigned Imm = MI->getOperand(OpNum).getImm();
51
52 if (Imm == 2) {
53 O << "P0";
54 } else if (Imm == 1) {
55 O << "P20";
56 } else if (Imm == 0) {
57 O << "P10";
58 } else {
59 assert(!"Invalid interpolation parameter slot");
60 }
61 }
62
printMemOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)63 void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
64 raw_ostream &O) {
65 printOperand(MI, OpNo, O);
66 O << ", ";
67 printOperand(MI, OpNo + 1, O);
68 }
69
printIfSet(const MCInst * MI,unsigned OpNo,raw_ostream & O,StringRef Asm,StringRef Default)70 void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
71 raw_ostream &O, StringRef Asm,
72 StringRef Default) {
73 const MCOperand &Op = MI->getOperand(OpNo);
74 assert(Op.isImm());
75 if (Op.getImm() == 1) {
76 O << Asm;
77 } else {
78 O << Default;
79 }
80 }
81
printAbs(const MCInst * MI,unsigned OpNo,raw_ostream & O)82 void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo,
83 raw_ostream &O) {
84 printIfSet(MI, OpNo, O, "|");
85 }
86
printClamp(const MCInst * MI,unsigned OpNo,raw_ostream & O)87 void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo,
88 raw_ostream &O) {
89 printIfSet(MI, OpNo, O, "_SAT");
90 }
91
printLiteral(const MCInst * MI,unsigned OpNo,raw_ostream & O)92 void AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo,
93 raw_ostream &O) {
94 union Literal {
95 float f;
96 int32_t i;
97 } L;
98
99 L.i = MI->getOperand(OpNo).getImm();
100 O << L.i << "(" << L.f << ")";
101 }
102
printLast(const MCInst * MI,unsigned OpNo,raw_ostream & O)103 void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo,
104 raw_ostream &O) {
105 printIfSet(MI, OpNo, O.indent(25 - O.GetNumBytesInBuffer()), "*", " ");
106 }
107
printNeg(const MCInst * MI,unsigned OpNo,raw_ostream & O)108 void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo,
109 raw_ostream &O) {
110 printIfSet(MI, OpNo, O, "-");
111 }
112
printOMOD(const MCInst * MI,unsigned OpNo,raw_ostream & O)113 void AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo,
114 raw_ostream &O) {
115 switch (MI->getOperand(OpNo).getImm()) {
116 default: break;
117 case 1:
118 O << " * 2.0";
119 break;
120 case 2:
121 O << " * 4.0";
122 break;
123 case 3:
124 O << " / 2.0";
125 break;
126 }
127 }
128
printRel(const MCInst * MI,unsigned OpNo,raw_ostream & O)129 void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo,
130 raw_ostream &O) {
131 printIfSet(MI, OpNo, O, "+");
132 }
133
printUpdateExecMask(const MCInst * MI,unsigned OpNo,raw_ostream & O)134 void AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo,
135 raw_ostream &O) {
136 printIfSet(MI, OpNo, O, "ExecMask,");
137 }
138
printUpdatePred(const MCInst * MI,unsigned OpNo,raw_ostream & O)139 void AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo,
140 raw_ostream &O) {
141 printIfSet(MI, OpNo, O, "Pred,");
142 }
143
printWrite(const MCInst * MI,unsigned OpNo,raw_ostream & O)144 void AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo,
145 raw_ostream &O) {
146 const MCOperand &Op = MI->getOperand(OpNo);
147 if (Op.getImm() == 0) {
148 O << " (MASKED)";
149 }
150 }
151
printSel(const MCInst * MI,unsigned OpNo,raw_ostream & O)152 void AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo,
153 raw_ostream &O) {
154 const char * chans = "XYZW";
155 int sel = MI->getOperand(OpNo).getImm();
156
157 int chan = sel & 3;
158 sel >>= 2;
159
160 if (sel >= 512) {
161 sel -= 512;
162 int cb = sel >> 12;
163 sel &= 4095;
164 O << cb << "[" << sel << "]";
165 } else if (sel >= 448) {
166 sel -= 448;
167 O << sel;
168 } else if (sel >= 0){
169 O << sel;
170 }
171
172 if (sel >= 0)
173 O << "." << chans[chan];
174 }
175
printBankSwizzle(const MCInst * MI,unsigned OpNo,raw_ostream & O)176 void AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo,
177 raw_ostream &O) {
178 int BankSwizzle = MI->getOperand(OpNo).getImm();
179 switch (BankSwizzle) {
180 case 1:
181 O << "BS:VEC_021/SCL_122";
182 break;
183 case 2:
184 O << "BS:VEC_120/SCL_212";
185 break;
186 case 3:
187 O << "BS:VEC_102/SCL_221";
188 break;
189 case 4:
190 O << "BS:VEC_201";
191 break;
192 case 5:
193 O << "BS:VEC_210";
194 break;
195 default:
196 break;
197 }
198 return;
199 }
200
printRSel(const MCInst * MI,unsigned OpNo,raw_ostream & O)201 void AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo,
202 raw_ostream &O) {
203 unsigned Sel = MI->getOperand(OpNo).getImm();
204 switch (Sel) {
205 case 0:
206 O << "X";
207 break;
208 case 1:
209 O << "Y";
210 break;
211 case 2:
212 O << "Z";
213 break;
214 case 3:
215 O << "W";
216 break;
217 case 4:
218 O << "0";
219 break;
220 case 5:
221 O << "1";
222 break;
223 case 7:
224 O << "_";
225 break;
226 default:
227 break;
228 }
229 }
230
printCT(const MCInst * MI,unsigned OpNo,raw_ostream & O)231 void AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo,
232 raw_ostream &O) {
233 unsigned CT = MI->getOperand(OpNo).getImm();
234 switch (CT) {
235 case 0:
236 O << "U";
237 break;
238 case 1:
239 O << "N";
240 break;
241 default:
242 break;
243 }
244 }
245
printKCache(const MCInst * MI,unsigned OpNo,raw_ostream & O)246 void AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo,
247 raw_ostream &O) {
248 int KCacheMode = MI->getOperand(OpNo).getImm();
249 if (KCacheMode > 0) {
250 int KCacheBank = MI->getOperand(OpNo - 2).getImm();
251 O << "CB" << KCacheBank <<":";
252 int KCacheAddr = MI->getOperand(OpNo + 2).getImm();
253 int LineSize = (KCacheMode == 1)?16:32;
254 O << KCacheAddr * 16 << "-" << KCacheAddr * 16 + LineSize;
255 }
256 }
257
258 #include "AMDGPUGenAsmWriter.inc"
259