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 "SIDefines.h"
14 #include "Utils/AMDGPUAsmUtils.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCInst.h"
17 #include "llvm/MC/MCInstrInfo.h"
18 #include "llvm/MC/MCRegisterInfo.h"
19 #include "llvm/Support/MathExtras.h"
20 #include "llvm/Support/raw_ostream.h"
21
22 #include <string>
23
24 using namespace llvm;
25
printInst(const MCInst * MI,raw_ostream & OS,StringRef Annot,const MCSubtargetInfo & STI)26 void AMDGPUInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
27 StringRef Annot, const MCSubtargetInfo &STI) {
28 OS.flush();
29 printInstruction(MI, OS);
30
31 printAnnotation(OS, Annot);
32 }
33
printU4ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)34 void AMDGPUInstPrinter::printU4ImmOperand(const MCInst *MI, unsigned OpNo,
35 raw_ostream &O) {
36 O << formatHex(MI->getOperand(OpNo).getImm() & 0xf);
37 }
38
printU8ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)39 void AMDGPUInstPrinter::printU8ImmOperand(const MCInst *MI, unsigned OpNo,
40 raw_ostream &O) {
41 O << formatHex(MI->getOperand(OpNo).getImm() & 0xff);
42 }
43
printU16ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)44 void AMDGPUInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
45 raw_ostream &O) {
46 O << formatHex(MI->getOperand(OpNo).getImm() & 0xffff);
47 }
48
printU32ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)49 void AMDGPUInstPrinter::printU32ImmOperand(const MCInst *MI, unsigned OpNo,
50 raw_ostream &O) {
51 O << formatHex(MI->getOperand(OpNo).getImm() & 0xffffffff);
52 }
53
printU4ImmDecOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)54 void AMDGPUInstPrinter::printU4ImmDecOperand(const MCInst *MI, unsigned OpNo,
55 raw_ostream &O) {
56 O << formatDec(MI->getOperand(OpNo).getImm() & 0xf);
57 }
58
printU8ImmDecOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)59 void AMDGPUInstPrinter::printU8ImmDecOperand(const MCInst *MI, unsigned OpNo,
60 raw_ostream &O) {
61 O << formatDec(MI->getOperand(OpNo).getImm() & 0xff);
62 }
63
printU16ImmDecOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)64 void AMDGPUInstPrinter::printU16ImmDecOperand(const MCInst *MI, unsigned OpNo,
65 raw_ostream &O) {
66 O << formatDec(MI->getOperand(OpNo).getImm() & 0xffff);
67 }
68
printNamedBit(const MCInst * MI,unsigned OpNo,raw_ostream & O,StringRef BitName)69 void AMDGPUInstPrinter::printNamedBit(const MCInst* MI, unsigned OpNo,
70 raw_ostream& O, StringRef BitName) {
71 if (MI->getOperand(OpNo).getImm()) {
72 O << ' ' << BitName;
73 }
74 }
75
printOffen(const MCInst * MI,unsigned OpNo,raw_ostream & O)76 void AMDGPUInstPrinter::printOffen(const MCInst *MI, unsigned OpNo,
77 raw_ostream &O) {
78 printNamedBit(MI, OpNo, O, "offen");
79 }
80
printIdxen(const MCInst * MI,unsigned OpNo,raw_ostream & O)81 void AMDGPUInstPrinter::printIdxen(const MCInst *MI, unsigned OpNo,
82 raw_ostream &O) {
83 printNamedBit(MI, OpNo, O, "idxen");
84 }
85
printAddr64(const MCInst * MI,unsigned OpNo,raw_ostream & O)86 void AMDGPUInstPrinter::printAddr64(const MCInst *MI, unsigned OpNo,
87 raw_ostream &O) {
88 printNamedBit(MI, OpNo, O, "addr64");
89 }
90
printMBUFOffset(const MCInst * MI,unsigned OpNo,raw_ostream & O)91 void AMDGPUInstPrinter::printMBUFOffset(const MCInst *MI, unsigned OpNo,
92 raw_ostream &O) {
93 if (MI->getOperand(OpNo).getImm()) {
94 O << " offset:";
95 printU16ImmDecOperand(MI, OpNo, O);
96 }
97 }
98
printOffset(const MCInst * MI,unsigned OpNo,raw_ostream & O)99 void AMDGPUInstPrinter::printOffset(const MCInst *MI, unsigned OpNo,
100 raw_ostream &O) {
101 uint16_t Imm = MI->getOperand(OpNo).getImm();
102 if (Imm != 0) {
103 O << " offset:";
104 printU16ImmDecOperand(MI, OpNo, O);
105 }
106 }
107
printOffset0(const MCInst * MI,unsigned OpNo,raw_ostream & O)108 void AMDGPUInstPrinter::printOffset0(const MCInst *MI, unsigned OpNo,
109 raw_ostream &O) {
110 if (MI->getOperand(OpNo).getImm()) {
111 O << " offset0:";
112 printU8ImmDecOperand(MI, OpNo, O);
113 }
114 }
115
printOffset1(const MCInst * MI,unsigned OpNo,raw_ostream & O)116 void AMDGPUInstPrinter::printOffset1(const MCInst *MI, unsigned OpNo,
117 raw_ostream &O) {
118 if (MI->getOperand(OpNo).getImm()) {
119 O << " offset1:";
120 printU8ImmDecOperand(MI, OpNo, O);
121 }
122 }
123
printSMRDOffset(const MCInst * MI,unsigned OpNo,raw_ostream & O)124 void AMDGPUInstPrinter::printSMRDOffset(const MCInst *MI, unsigned OpNo,
125 raw_ostream &O) {
126 printU32ImmOperand(MI, OpNo, O);
127 }
128
printSMRDLiteralOffset(const MCInst * MI,unsigned OpNo,raw_ostream & O)129 void AMDGPUInstPrinter::printSMRDLiteralOffset(const MCInst *MI, unsigned OpNo,
130 raw_ostream &O) {
131 printU32ImmOperand(MI, OpNo, O);
132 }
133
printGDS(const MCInst * MI,unsigned OpNo,raw_ostream & O)134 void AMDGPUInstPrinter::printGDS(const MCInst *MI, unsigned OpNo,
135 raw_ostream &O) {
136 printNamedBit(MI, OpNo, O, "gds");
137 }
138
printGLC(const MCInst * MI,unsigned OpNo,raw_ostream & O)139 void AMDGPUInstPrinter::printGLC(const MCInst *MI, unsigned OpNo,
140 raw_ostream &O) {
141 printNamedBit(MI, OpNo, O, "glc");
142 }
143
printSLC(const MCInst * MI,unsigned OpNo,raw_ostream & O)144 void AMDGPUInstPrinter::printSLC(const MCInst *MI, unsigned OpNo,
145 raw_ostream &O) {
146 printNamedBit(MI, OpNo, O, "slc");
147 }
148
printTFE(const MCInst * MI,unsigned OpNo,raw_ostream & O)149 void AMDGPUInstPrinter::printTFE(const MCInst *MI, unsigned OpNo,
150 raw_ostream &O) {
151 printNamedBit(MI, OpNo, O, "tfe");
152 }
153
printDMask(const MCInst * MI,unsigned OpNo,raw_ostream & O)154 void AMDGPUInstPrinter::printDMask(const MCInst *MI, unsigned OpNo,
155 raw_ostream &O) {
156 if (MI->getOperand(OpNo).getImm()) {
157 O << " dmask:";
158 printU16ImmOperand(MI, OpNo, O);
159 }
160 }
161
printUNorm(const MCInst * MI,unsigned OpNo,raw_ostream & O)162 void AMDGPUInstPrinter::printUNorm(const MCInst *MI, unsigned OpNo,
163 raw_ostream &O) {
164 printNamedBit(MI, OpNo, O, "unorm");
165 }
166
printDA(const MCInst * MI,unsigned OpNo,raw_ostream & O)167 void AMDGPUInstPrinter::printDA(const MCInst *MI, unsigned OpNo,
168 raw_ostream &O) {
169 printNamedBit(MI, OpNo, O, "da");
170 }
171
printR128(const MCInst * MI,unsigned OpNo,raw_ostream & O)172 void AMDGPUInstPrinter::printR128(const MCInst *MI, unsigned OpNo,
173 raw_ostream &O) {
174 printNamedBit(MI, OpNo, O, "r128");
175 }
176
printLWE(const MCInst * MI,unsigned OpNo,raw_ostream & O)177 void AMDGPUInstPrinter::printLWE(const MCInst *MI, unsigned OpNo,
178 raw_ostream &O) {
179 printNamedBit(MI, OpNo, O, "lwe");
180 }
181
printRegOperand(unsigned reg,raw_ostream & O,const MCRegisterInfo & MRI)182 void AMDGPUInstPrinter::printRegOperand(unsigned reg, raw_ostream &O,
183 const MCRegisterInfo &MRI) {
184 switch (reg) {
185 case AMDGPU::VCC:
186 O << "vcc";
187 return;
188 case AMDGPU::SCC:
189 O << "scc";
190 return;
191 case AMDGPU::EXEC:
192 O << "exec";
193 return;
194 case AMDGPU::M0:
195 O << "m0";
196 return;
197 case AMDGPU::FLAT_SCR:
198 O << "flat_scratch";
199 return;
200 case AMDGPU::VCC_LO:
201 O << "vcc_lo";
202 return;
203 case AMDGPU::VCC_HI:
204 O << "vcc_hi";
205 return;
206 case AMDGPU::TBA_LO:
207 O << "tba_lo";
208 return;
209 case AMDGPU::TBA_HI:
210 O << "tba_hi";
211 return;
212 case AMDGPU::TMA_LO:
213 O << "tma_lo";
214 return;
215 case AMDGPU::TMA_HI:
216 O << "tma_hi";
217 return;
218 case AMDGPU::EXEC_LO:
219 O << "exec_lo";
220 return;
221 case AMDGPU::EXEC_HI:
222 O << "exec_hi";
223 return;
224 case AMDGPU::FLAT_SCR_LO:
225 O << "flat_scratch_lo";
226 return;
227 case AMDGPU::FLAT_SCR_HI:
228 O << "flat_scratch_hi";
229 return;
230 default:
231 break;
232 }
233
234 // The low 8 bits of the encoding value is the register index, for both VGPRs
235 // and SGPRs.
236 unsigned RegIdx = MRI.getEncodingValue(reg) & ((1 << 8) - 1);
237
238 unsigned NumRegs;
239 if (MRI.getRegClass(AMDGPU::VGPR_32RegClassID).contains(reg)) {
240 O << 'v';
241 NumRegs = 1;
242 } else if (MRI.getRegClass(AMDGPU::SGPR_32RegClassID).contains(reg)) {
243 O << 's';
244 NumRegs = 1;
245 } else if (MRI.getRegClass(AMDGPU::VReg_64RegClassID).contains(reg)) {
246 O <<'v';
247 NumRegs = 2;
248 } else if (MRI.getRegClass(AMDGPU::SGPR_64RegClassID).contains(reg)) {
249 O << 's';
250 NumRegs = 2;
251 } else if (MRI.getRegClass(AMDGPU::VReg_128RegClassID).contains(reg)) {
252 O << 'v';
253 NumRegs = 4;
254 } else if (MRI.getRegClass(AMDGPU::SGPR_128RegClassID).contains(reg)) {
255 O << 's';
256 NumRegs = 4;
257 } else if (MRI.getRegClass(AMDGPU::VReg_96RegClassID).contains(reg)) {
258 O << 'v';
259 NumRegs = 3;
260 } else if (MRI.getRegClass(AMDGPU::VReg_256RegClassID).contains(reg)) {
261 O << 'v';
262 NumRegs = 8;
263 } else if (MRI.getRegClass(AMDGPU::SReg_256RegClassID).contains(reg)) {
264 O << 's';
265 NumRegs = 8;
266 } else if (MRI.getRegClass(AMDGPU::VReg_512RegClassID).contains(reg)) {
267 O << 'v';
268 NumRegs = 16;
269 } else if (MRI.getRegClass(AMDGPU::SReg_512RegClassID).contains(reg)) {
270 O << 's';
271 NumRegs = 16;
272 } else if (MRI.getRegClass(AMDGPU::TTMP_64RegClassID).contains(reg)) {
273 O << "ttmp";
274 NumRegs = 2;
275 RegIdx -= 112; // Trap temps start at offset 112. TODO: Get this from tablegen.
276 } else if (MRI.getRegClass(AMDGPU::TTMP_128RegClassID).contains(reg)) {
277 O << "ttmp";
278 NumRegs = 4;
279 RegIdx -= 112; // Trap temps start at offset 112. TODO: Get this from tablegen.
280 } else {
281 O << getRegisterName(reg);
282 return;
283 }
284
285 if (NumRegs == 1) {
286 O << RegIdx;
287 return;
288 }
289
290 O << '[' << RegIdx << ':' << (RegIdx + NumRegs - 1) << ']';
291 }
292
printVOPDst(const MCInst * MI,unsigned OpNo,raw_ostream & O)293 void AMDGPUInstPrinter::printVOPDst(const MCInst *MI, unsigned OpNo,
294 raw_ostream &O) {
295 if (MII.get(MI->getOpcode()).TSFlags & SIInstrFlags::VOP3)
296 O << "_e64 ";
297 else if (MII.get(MI->getOpcode()).TSFlags & SIInstrFlags::DPP)
298 O << "_dpp ";
299 else if (MII.get(MI->getOpcode()).TSFlags & SIInstrFlags::SDWA)
300 O << "_sdwa ";
301 else
302 O << "_e32 ";
303
304 printOperand(MI, OpNo, O);
305 }
306
printImmediate32(uint32_t Imm,raw_ostream & O)307 void AMDGPUInstPrinter::printImmediate32(uint32_t Imm, raw_ostream &O) {
308 int32_t SImm = static_cast<int32_t>(Imm);
309 if (SImm >= -16 && SImm <= 64) {
310 O << SImm;
311 return;
312 }
313
314 if (Imm == FloatToBits(0.0f))
315 O << "0.0";
316 else if (Imm == FloatToBits(1.0f))
317 O << "1.0";
318 else if (Imm == FloatToBits(-1.0f))
319 O << "-1.0";
320 else if (Imm == FloatToBits(0.5f))
321 O << "0.5";
322 else if (Imm == FloatToBits(-0.5f))
323 O << "-0.5";
324 else if (Imm == FloatToBits(2.0f))
325 O << "2.0";
326 else if (Imm == FloatToBits(-2.0f))
327 O << "-2.0";
328 else if (Imm == FloatToBits(4.0f))
329 O << "4.0";
330 else if (Imm == FloatToBits(-4.0f))
331 O << "-4.0";
332 else
333 O << formatHex(static_cast<uint64_t>(Imm));
334 }
335
printImmediate64(uint64_t Imm,raw_ostream & O)336 void AMDGPUInstPrinter::printImmediate64(uint64_t Imm, raw_ostream &O) {
337 int64_t SImm = static_cast<int64_t>(Imm);
338 if (SImm >= -16 && SImm <= 64) {
339 O << SImm;
340 return;
341 }
342
343 if (Imm == DoubleToBits(0.0))
344 O << "0.0";
345 else if (Imm == DoubleToBits(1.0))
346 O << "1.0";
347 else if (Imm == DoubleToBits(-1.0))
348 O << "-1.0";
349 else if (Imm == DoubleToBits(0.5))
350 O << "0.5";
351 else if (Imm == DoubleToBits(-0.5))
352 O << "-0.5";
353 else if (Imm == DoubleToBits(2.0))
354 O << "2.0";
355 else if (Imm == DoubleToBits(-2.0))
356 O << "-2.0";
357 else if (Imm == DoubleToBits(4.0))
358 O << "4.0";
359 else if (Imm == DoubleToBits(-4.0))
360 O << "-4.0";
361 else {
362 assert(isUInt<32>(Imm));
363
364 // In rare situations, we will have a 32-bit literal in a 64-bit
365 // operand. This is technically allowed for the encoding of s_mov_b64.
366 O << formatHex(static_cast<uint64_t>(Imm));
367 }
368 }
369
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)370 void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
371 raw_ostream &O) {
372
373 const MCOperand &Op = MI->getOperand(OpNo);
374 if (Op.isReg()) {
375 switch (Op.getReg()) {
376 // This is the default predicate state, so we don't need to print it.
377 case AMDGPU::PRED_SEL_OFF:
378 break;
379
380 default:
381 printRegOperand(Op.getReg(), O, MRI);
382 break;
383 }
384 } else if (Op.isImm()) {
385 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
386 int RCID = Desc.OpInfo[OpNo].RegClass;
387 if (RCID != -1) {
388 const MCRegisterClass &ImmRC = MRI.getRegClass(RCID);
389 if (ImmRC.getSize() == 4)
390 printImmediate32(Op.getImm(), O);
391 else if (ImmRC.getSize() == 8)
392 printImmediate64(Op.getImm(), O);
393 else
394 llvm_unreachable("Invalid register class size");
395 } else if (Desc.OpInfo[OpNo].OperandType == MCOI::OPERAND_IMMEDIATE) {
396 printImmediate32(Op.getImm(), O);
397 } else {
398 // We hit this for the immediate instruction bits that don't yet have a
399 // custom printer.
400 // TODO: Eventually this should be unnecessary.
401 O << formatDec(Op.getImm());
402 }
403 } else if (Op.isFPImm()) {
404 // We special case 0.0 because otherwise it will be printed as an integer.
405 if (Op.getFPImm() == 0.0)
406 O << "0.0";
407 else {
408 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
409 const MCRegisterClass &ImmRC = MRI.getRegClass(Desc.OpInfo[OpNo].RegClass);
410
411 if (ImmRC.getSize() == 4)
412 printImmediate32(FloatToBits(Op.getFPImm()), O);
413 else if (ImmRC.getSize() == 8)
414 printImmediate64(DoubleToBits(Op.getFPImm()), O);
415 else
416 llvm_unreachable("Invalid register class size");
417 }
418 } else if (Op.isExpr()) {
419 const MCExpr *Exp = Op.getExpr();
420 Exp->print(O, &MAI);
421 } else {
422 O << "/*INV_OP*/";
423 }
424 }
425
printOperandAndFPInputMods(const MCInst * MI,unsigned OpNo,raw_ostream & O)426 void AMDGPUInstPrinter::printOperandAndFPInputMods(const MCInst *MI,
427 unsigned OpNo,
428 raw_ostream &O) {
429 unsigned InputModifiers = MI->getOperand(OpNo).getImm();
430 if (InputModifiers & SISrcMods::NEG)
431 O << '-';
432 if (InputModifiers & SISrcMods::ABS)
433 O << '|';
434 printOperand(MI, OpNo + 1, O);
435 if (InputModifiers & SISrcMods::ABS)
436 O << '|';
437 }
438
printOperandAndIntInputMods(const MCInst * MI,unsigned OpNo,raw_ostream & O)439 void AMDGPUInstPrinter::printOperandAndIntInputMods(const MCInst *MI,
440 unsigned OpNo,
441 raw_ostream &O) {
442 unsigned InputModifiers = MI->getOperand(OpNo).getImm();
443 if (InputModifiers & SISrcMods::SEXT)
444 O << "sext(";
445 printOperand(MI, OpNo + 1, O);
446 if (InputModifiers & SISrcMods::SEXT)
447 O << ')';
448 }
449
450
printDPPCtrl(const MCInst * MI,unsigned OpNo,raw_ostream & O)451 void AMDGPUInstPrinter::printDPPCtrl(const MCInst *MI, unsigned OpNo,
452 raw_ostream &O) {
453 unsigned Imm = MI->getOperand(OpNo).getImm();
454 if (Imm <= 0x0ff) {
455 O << " quad_perm:[";
456 O << formatDec(Imm & 0x3) << ',';
457 O << formatDec((Imm & 0xc) >> 2) << ',';
458 O << formatDec((Imm & 0x30) >> 4) << ',';
459 O << formatDec((Imm & 0xc0) >> 6) << ']';
460 } else if ((Imm >= 0x101) && (Imm <= 0x10f)) {
461 O << " row_shl:";
462 printU4ImmDecOperand(MI, OpNo, O);
463 } else if ((Imm >= 0x111) && (Imm <= 0x11f)) {
464 O << " row_shr:";
465 printU4ImmDecOperand(MI, OpNo, O);
466 } else if ((Imm >= 0x121) && (Imm <= 0x12f)) {
467 O << " row_ror:";
468 printU4ImmDecOperand(MI, OpNo, O);
469 } else if (Imm == 0x130) {
470 O << " wave_shl:1";
471 } else if (Imm == 0x134) {
472 O << " wave_rol:1";
473 } else if (Imm == 0x138) {
474 O << " wave_shr:1";
475 } else if (Imm == 0x13c) {
476 O << " wave_ror:1";
477 } else if (Imm == 0x140) {
478 O << " row_mirror";
479 } else if (Imm == 0x141) {
480 O << " row_half_mirror";
481 } else if (Imm == 0x142) {
482 O << " row_bcast:15";
483 } else if (Imm == 0x143) {
484 O << " row_bcast:31";
485 } else {
486 llvm_unreachable("Invalid dpp_ctrl value");
487 }
488 }
489
printRowMask(const MCInst * MI,unsigned OpNo,raw_ostream & O)490 void AMDGPUInstPrinter::printRowMask(const MCInst *MI, unsigned OpNo,
491 raw_ostream &O) {
492 O << " row_mask:";
493 printU4ImmOperand(MI, OpNo, O);
494 }
495
printBankMask(const MCInst * MI,unsigned OpNo,raw_ostream & O)496 void AMDGPUInstPrinter::printBankMask(const MCInst *MI, unsigned OpNo,
497 raw_ostream &O) {
498 O << " bank_mask:";
499 printU4ImmOperand(MI, OpNo, O);
500 }
501
printBoundCtrl(const MCInst * MI,unsigned OpNo,raw_ostream & O)502 void AMDGPUInstPrinter::printBoundCtrl(const MCInst *MI, unsigned OpNo,
503 raw_ostream &O) {
504 unsigned Imm = MI->getOperand(OpNo).getImm();
505 if (Imm) {
506 O << " bound_ctrl:0"; // XXX - this syntax is used in sp3
507 }
508 }
509
printSDWASel(const MCInst * MI,unsigned OpNo,raw_ostream & O)510 void AMDGPUInstPrinter::printSDWASel(const MCInst *MI, unsigned OpNo,
511 raw_ostream &O) {
512 unsigned Imm = MI->getOperand(OpNo).getImm();
513 switch (Imm) {
514 case 0: O << "BYTE_0"; break;
515 case 1: O << "BYTE_1"; break;
516 case 2: O << "BYTE_2"; break;
517 case 3: O << "BYTE_3"; break;
518 case 4: O << "WORD_0"; break;
519 case 5: O << "WORD_1"; break;
520 case 6: O << "DWORD"; break;
521 default: llvm_unreachable("Invalid SDWA data select operand");
522 }
523 }
524
printSDWADstSel(const MCInst * MI,unsigned OpNo,raw_ostream & O)525 void AMDGPUInstPrinter::printSDWADstSel(const MCInst *MI, unsigned OpNo,
526 raw_ostream &O) {
527 O << "dst_sel:";
528 printSDWASel(MI, OpNo, O);
529 }
530
printSDWASrc0Sel(const MCInst * MI,unsigned OpNo,raw_ostream & O)531 void AMDGPUInstPrinter::printSDWASrc0Sel(const MCInst *MI, unsigned OpNo,
532 raw_ostream &O) {
533 O << "src0_sel:";
534 printSDWASel(MI, OpNo, O);
535 }
536
printSDWASrc1Sel(const MCInst * MI,unsigned OpNo,raw_ostream & O)537 void AMDGPUInstPrinter::printSDWASrc1Sel(const MCInst *MI, unsigned OpNo,
538 raw_ostream &O) {
539 O << "src1_sel:";
540 printSDWASel(MI, OpNo, O);
541 }
542
printSDWADstUnused(const MCInst * MI,unsigned OpNo,raw_ostream & O)543 void AMDGPUInstPrinter::printSDWADstUnused(const MCInst *MI, unsigned OpNo,
544 raw_ostream &O) {
545 O << "dst_unused:";
546 unsigned Imm = MI->getOperand(OpNo).getImm();
547 switch (Imm) {
548 case 0: O << "UNUSED_PAD"; break;
549 case 1: O << "UNUSED_SEXT"; break;
550 case 2: O << "UNUSED_PRESERVE"; break;
551 default: llvm_unreachable("Invalid SDWA dest_unused operand");
552 }
553 }
554
printInterpSlot(const MCInst * MI,unsigned OpNum,raw_ostream & O)555 void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum,
556 raw_ostream &O) {
557 unsigned Imm = MI->getOperand(OpNum).getImm();
558
559 if (Imm == 2) {
560 O << "P0";
561 } else if (Imm == 1) {
562 O << "P20";
563 } else if (Imm == 0) {
564 O << "P10";
565 } else {
566 llvm_unreachable("Invalid interpolation parameter slot");
567 }
568 }
569
printMemOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)570 void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
571 raw_ostream &O) {
572 printOperand(MI, OpNo, O);
573 O << ", ";
574 printOperand(MI, OpNo + 1, O);
575 }
576
printIfSet(const MCInst * MI,unsigned OpNo,raw_ostream & O,StringRef Asm,StringRef Default)577 void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
578 raw_ostream &O, StringRef Asm,
579 StringRef Default) {
580 const MCOperand &Op = MI->getOperand(OpNo);
581 assert(Op.isImm());
582 if (Op.getImm() == 1) {
583 O << Asm;
584 } else {
585 O << Default;
586 }
587 }
588
printIfSet(const MCInst * MI,unsigned OpNo,raw_ostream & O,char Asm)589 void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
590 raw_ostream &O, char Asm) {
591 const MCOperand &Op = MI->getOperand(OpNo);
592 assert(Op.isImm());
593 if (Op.getImm() == 1)
594 O << Asm;
595 }
596
printAbs(const MCInst * MI,unsigned OpNo,raw_ostream & O)597 void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo,
598 raw_ostream &O) {
599 printIfSet(MI, OpNo, O, '|');
600 }
601
printClamp(const MCInst * MI,unsigned OpNo,raw_ostream & O)602 void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo,
603 raw_ostream &O) {
604 printIfSet(MI, OpNo, O, "_SAT");
605 }
606
printClampSI(const MCInst * MI,unsigned OpNo,raw_ostream & O)607 void AMDGPUInstPrinter::printClampSI(const MCInst *MI, unsigned OpNo,
608 raw_ostream &O) {
609 if (MI->getOperand(OpNo).getImm())
610 O << " clamp";
611 }
612
printOModSI(const MCInst * MI,unsigned OpNo,raw_ostream & O)613 void AMDGPUInstPrinter::printOModSI(const MCInst *MI, unsigned OpNo,
614 raw_ostream &O) {
615 int Imm = MI->getOperand(OpNo).getImm();
616 if (Imm == SIOutMods::MUL2)
617 O << " mul:2";
618 else if (Imm == SIOutMods::MUL4)
619 O << " mul:4";
620 else if (Imm == SIOutMods::DIV2)
621 O << " div:2";
622 }
623
printLiteral(const MCInst * MI,unsigned OpNo,raw_ostream & O)624 void AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo,
625 raw_ostream &O) {
626 const MCOperand &Op = MI->getOperand(OpNo);
627 assert(Op.isImm() || Op.isExpr());
628 if (Op.isImm()) {
629 int64_t Imm = Op.getImm();
630 O << Imm << '(' << BitsToFloat(Imm) << ')';
631 }
632 if (Op.isExpr()) {
633 Op.getExpr()->print(O << '@', &MAI);
634 }
635 }
636
printLast(const MCInst * MI,unsigned OpNo,raw_ostream & O)637 void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo,
638 raw_ostream &O) {
639 printIfSet(MI, OpNo, O, "*", " ");
640 }
641
printNeg(const MCInst * MI,unsigned OpNo,raw_ostream & O)642 void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo,
643 raw_ostream &O) {
644 printIfSet(MI, OpNo, O, '-');
645 }
646
printOMOD(const MCInst * MI,unsigned OpNo,raw_ostream & O)647 void AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo,
648 raw_ostream &O) {
649 switch (MI->getOperand(OpNo).getImm()) {
650 default: break;
651 case 1:
652 O << " * 2.0";
653 break;
654 case 2:
655 O << " * 4.0";
656 break;
657 case 3:
658 O << " / 2.0";
659 break;
660 }
661 }
662
printRel(const MCInst * MI,unsigned OpNo,raw_ostream & O)663 void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo,
664 raw_ostream &O) {
665 printIfSet(MI, OpNo, O, '+');
666 }
667
printUpdateExecMask(const MCInst * MI,unsigned OpNo,raw_ostream & O)668 void AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo,
669 raw_ostream &O) {
670 printIfSet(MI, OpNo, O, "ExecMask,");
671 }
672
printUpdatePred(const MCInst * MI,unsigned OpNo,raw_ostream & O)673 void AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo,
674 raw_ostream &O) {
675 printIfSet(MI, OpNo, O, "Pred,");
676 }
677
printWrite(const MCInst * MI,unsigned OpNo,raw_ostream & O)678 void AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo,
679 raw_ostream &O) {
680 const MCOperand &Op = MI->getOperand(OpNo);
681 if (Op.getImm() == 0) {
682 O << " (MASKED)";
683 }
684 }
685
printSel(const MCInst * MI,unsigned OpNo,raw_ostream & O)686 void AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo,
687 raw_ostream &O) {
688 const char * chans = "XYZW";
689 int sel = MI->getOperand(OpNo).getImm();
690
691 int chan = sel & 3;
692 sel >>= 2;
693
694 if (sel >= 512) {
695 sel -= 512;
696 int cb = sel >> 12;
697 sel &= 4095;
698 O << cb << '[' << sel << ']';
699 } else if (sel >= 448) {
700 sel -= 448;
701 O << sel;
702 } else if (sel >= 0){
703 O << sel;
704 }
705
706 if (sel >= 0)
707 O << '.' << chans[chan];
708 }
709
printBankSwizzle(const MCInst * MI,unsigned OpNo,raw_ostream & O)710 void AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo,
711 raw_ostream &O) {
712 int BankSwizzle = MI->getOperand(OpNo).getImm();
713 switch (BankSwizzle) {
714 case 1:
715 O << "BS:VEC_021/SCL_122";
716 break;
717 case 2:
718 O << "BS:VEC_120/SCL_212";
719 break;
720 case 3:
721 O << "BS:VEC_102/SCL_221";
722 break;
723 case 4:
724 O << "BS:VEC_201";
725 break;
726 case 5:
727 O << "BS:VEC_210";
728 break;
729 default:
730 break;
731 }
732 return;
733 }
734
printRSel(const MCInst * MI,unsigned OpNo,raw_ostream & O)735 void AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo,
736 raw_ostream &O) {
737 unsigned Sel = MI->getOperand(OpNo).getImm();
738 switch (Sel) {
739 case 0:
740 O << 'X';
741 break;
742 case 1:
743 O << 'Y';
744 break;
745 case 2:
746 O << 'Z';
747 break;
748 case 3:
749 O << 'W';
750 break;
751 case 4:
752 O << '0';
753 break;
754 case 5:
755 O << '1';
756 break;
757 case 7:
758 O << '_';
759 break;
760 default:
761 break;
762 }
763 }
764
printCT(const MCInst * MI,unsigned OpNo,raw_ostream & O)765 void AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo,
766 raw_ostream &O) {
767 unsigned CT = MI->getOperand(OpNo).getImm();
768 switch (CT) {
769 case 0:
770 O << 'U';
771 break;
772 case 1:
773 O << 'N';
774 break;
775 default:
776 break;
777 }
778 }
779
printKCache(const MCInst * MI,unsigned OpNo,raw_ostream & O)780 void AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo,
781 raw_ostream &O) {
782 int KCacheMode = MI->getOperand(OpNo).getImm();
783 if (KCacheMode > 0) {
784 int KCacheBank = MI->getOperand(OpNo - 2).getImm();
785 O << "CB" << KCacheBank << ':';
786 int KCacheAddr = MI->getOperand(OpNo + 2).getImm();
787 int LineSize = (KCacheMode == 1) ? 16 : 32;
788 O << KCacheAddr * 16 << '-' << KCacheAddr * 16 + LineSize;
789 }
790 }
791
printSendMsg(const MCInst * MI,unsigned OpNo,raw_ostream & O)792 void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo,
793 raw_ostream &O) {
794 using namespace llvm::AMDGPU::SendMsg;
795
796 const unsigned SImm16 = MI->getOperand(OpNo).getImm();
797 const unsigned Id = SImm16 & ID_MASK_;
798 do {
799 if (Id == ID_INTERRUPT) {
800 if ((SImm16 & ~ID_MASK_) != 0) // Unused/unknown bits must be 0.
801 break;
802 O << "sendmsg(" << IdSymbolic[Id] << ')';
803 return;
804 }
805 if (Id == ID_GS || Id == ID_GS_DONE) {
806 if ((SImm16 & ~(ID_MASK_|OP_GS_MASK_|STREAM_ID_MASK_)) != 0) // Unused/unknown bits must be 0.
807 break;
808 const unsigned OpGs = (SImm16 & OP_GS_MASK_) >> OP_SHIFT_;
809 const unsigned StreamId = (SImm16 & STREAM_ID_MASK_) >> STREAM_ID_SHIFT_;
810 if (OpGs == OP_GS_NOP && Id != ID_GS_DONE) // NOP to be used for GS_DONE only.
811 break;
812 if (OpGs == OP_GS_NOP && StreamId != 0) // NOP does not use/define stream id bits.
813 break;
814 O << "sendmsg(" << IdSymbolic[Id] << ", " << OpGsSymbolic[OpGs];
815 if (OpGs != OP_GS_NOP) { O << ", " << StreamId; }
816 O << ')';
817 return;
818 }
819 if (Id == ID_SYSMSG) {
820 if ((SImm16 & ~(ID_MASK_|OP_SYS_MASK_)) != 0) // Unused/unknown bits must be 0.
821 break;
822 const unsigned OpSys = (SImm16 & OP_SYS_MASK_) >> OP_SHIFT_;
823 if (! (OP_SYS_FIRST_ <= OpSys && OpSys < OP_SYS_LAST_)) // Unused/unknown.
824 break;
825 O << "sendmsg(" << IdSymbolic[Id] << ", " << OpSysSymbolic[OpSys] << ')';
826 return;
827 }
828 } while (0);
829 O << SImm16; // Unknown simm16 code.
830 }
831
printWaitFlag(const MCInst * MI,unsigned OpNo,raw_ostream & O)832 void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo,
833 raw_ostream &O) {
834 unsigned SImm16 = MI->getOperand(OpNo).getImm();
835 unsigned Vmcnt = SImm16 & 0xF;
836 unsigned Expcnt = (SImm16 >> 4) & 0x7;
837 unsigned Lgkmcnt = (SImm16 >> 8) & 0xF;
838
839 bool NeedSpace = false;
840
841 if (Vmcnt != 0xF) {
842 O << "vmcnt(" << Vmcnt << ')';
843 NeedSpace = true;
844 }
845
846 if (Expcnt != 0x7) {
847 if (NeedSpace)
848 O << ' ';
849 O << "expcnt(" << Expcnt << ')';
850 NeedSpace = true;
851 }
852
853 if (Lgkmcnt != 0xF) {
854 if (NeedSpace)
855 O << ' ';
856 O << "lgkmcnt(" << Lgkmcnt << ')';
857 }
858 }
859
printHwreg(const MCInst * MI,unsigned OpNo,raw_ostream & O)860 void AMDGPUInstPrinter::printHwreg(const MCInst *MI, unsigned OpNo,
861 raw_ostream &O) {
862 using namespace llvm::AMDGPU::Hwreg;
863
864 unsigned SImm16 = MI->getOperand(OpNo).getImm();
865 const unsigned Id = (SImm16 & ID_MASK_) >> ID_SHIFT_;
866 const unsigned Offset = (SImm16 & OFFSET_MASK_) >> OFFSET_SHIFT_;
867 const unsigned Width = ((SImm16 & WIDTH_M1_MASK_) >> WIDTH_M1_SHIFT_) + 1;
868
869 O << "hwreg(";
870 if (ID_SYMBOLIC_FIRST_ <= Id && Id < ID_SYMBOLIC_LAST_) {
871 O << IdSymbolic[Id];
872 } else {
873 O << Id;
874 }
875 if (Width != WIDTH_M1_DEFAULT_ + 1 || Offset != OFFSET_DEFAULT_) {
876 O << ", " << Offset << ", " << Width;
877 }
878 O << ')';
879 }
880
881 #include "AMDGPUGenAsmWriter.inc"
882