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 "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCInst.h"
16 #include "llvm/MC/MCInstrInfo.h"
17 #include "llvm/MC/MCRegisterInfo.h"
18 #include "llvm/Support/MathExtras.h"
19
20 using namespace llvm;
21
printInst(const MCInst * MI,raw_ostream & OS,StringRef Annot,const MCSubtargetInfo & STI)22 void AMDGPUInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
23 StringRef Annot, const MCSubtargetInfo &STI) {
24 OS.flush();
25 printInstruction(MI, OS);
26
27 printAnnotation(OS, Annot);
28 }
29
printU8ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)30 void AMDGPUInstPrinter::printU8ImmOperand(const MCInst *MI, unsigned OpNo,
31 raw_ostream &O) {
32 O << formatHex(MI->getOperand(OpNo).getImm() & 0xff);
33 }
34
printU16ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)35 void AMDGPUInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
36 raw_ostream &O) {
37 O << formatHex(MI->getOperand(OpNo).getImm() & 0xffff);
38 }
39
printU32ImmOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)40 void AMDGPUInstPrinter::printU32ImmOperand(const MCInst *MI, unsigned OpNo,
41 raw_ostream &O) {
42 O << formatHex(MI->getOperand(OpNo).getImm() & 0xffffffff);
43 }
44
printU8ImmDecOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)45 void AMDGPUInstPrinter::printU8ImmDecOperand(const MCInst *MI, unsigned OpNo,
46 raw_ostream &O) {
47 O << formatDec(MI->getOperand(OpNo).getImm() & 0xff);
48 }
49
printU16ImmDecOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)50 void AMDGPUInstPrinter::printU16ImmDecOperand(const MCInst *MI, unsigned OpNo,
51 raw_ostream &O) {
52 O << formatDec(MI->getOperand(OpNo).getImm() & 0xffff);
53 }
54
printOffen(const MCInst * MI,unsigned OpNo,raw_ostream & O)55 void AMDGPUInstPrinter::printOffen(const MCInst *MI, unsigned OpNo,
56 raw_ostream &O) {
57 if (MI->getOperand(OpNo).getImm())
58 O << " offen";
59 }
60
printIdxen(const MCInst * MI,unsigned OpNo,raw_ostream & O)61 void AMDGPUInstPrinter::printIdxen(const MCInst *MI, unsigned OpNo,
62 raw_ostream &O) {
63 if (MI->getOperand(OpNo).getImm())
64 O << " idxen";
65 }
66
printAddr64(const MCInst * MI,unsigned OpNo,raw_ostream & O)67 void AMDGPUInstPrinter::printAddr64(const MCInst *MI, unsigned OpNo,
68 raw_ostream &O) {
69 if (MI->getOperand(OpNo).getImm())
70 O << " addr64";
71 }
72
printMBUFOffset(const MCInst * MI,unsigned OpNo,raw_ostream & O)73 void AMDGPUInstPrinter::printMBUFOffset(const MCInst *MI, unsigned OpNo,
74 raw_ostream &O) {
75 if (MI->getOperand(OpNo).getImm()) {
76 O << " offset:";
77 printU16ImmDecOperand(MI, OpNo, O);
78 }
79 }
80
printDSOffset(const MCInst * MI,unsigned OpNo,raw_ostream & O)81 void AMDGPUInstPrinter::printDSOffset(const MCInst *MI, unsigned OpNo,
82 raw_ostream &O) {
83 uint16_t Imm = MI->getOperand(OpNo).getImm();
84 if (Imm != 0) {
85 O << " offset:";
86 printU16ImmDecOperand(MI, OpNo, O);
87 }
88 }
89
printDSOffset0(const MCInst * MI,unsigned OpNo,raw_ostream & O)90 void AMDGPUInstPrinter::printDSOffset0(const MCInst *MI, unsigned OpNo,
91 raw_ostream &O) {
92 if (MI->getOperand(OpNo).getImm()) {
93 O << " offset0:";
94 printU8ImmDecOperand(MI, OpNo, O);
95 }
96 }
97
printDSOffset1(const MCInst * MI,unsigned OpNo,raw_ostream & O)98 void AMDGPUInstPrinter::printDSOffset1(const MCInst *MI, unsigned OpNo,
99 raw_ostream &O) {
100 if (MI->getOperand(OpNo).getImm()) {
101 O << " offset1:";
102 printU8ImmDecOperand(MI, OpNo, O);
103 }
104 }
105
printGDS(const MCInst * MI,unsigned OpNo,raw_ostream & O)106 void AMDGPUInstPrinter::printGDS(const MCInst *MI, unsigned OpNo,
107 raw_ostream &O) {
108 if (MI->getOperand(OpNo).getImm())
109 O << " gds";
110 }
111
printGLC(const MCInst * MI,unsigned OpNo,raw_ostream & O)112 void AMDGPUInstPrinter::printGLC(const MCInst *MI, unsigned OpNo,
113 raw_ostream &O) {
114 if (MI->getOperand(OpNo).getImm())
115 O << " glc";
116 }
117
printSLC(const MCInst * MI,unsigned OpNo,raw_ostream & O)118 void AMDGPUInstPrinter::printSLC(const MCInst *MI, unsigned OpNo,
119 raw_ostream &O) {
120 if (MI->getOperand(OpNo).getImm())
121 O << " slc";
122 }
123
printTFE(const MCInst * MI,unsigned OpNo,raw_ostream & O)124 void AMDGPUInstPrinter::printTFE(const MCInst *MI, unsigned OpNo,
125 raw_ostream &O) {
126 if (MI->getOperand(OpNo).getImm())
127 O << " tfe";
128 }
129
printRegOperand(unsigned reg,raw_ostream & O,const MCRegisterInfo & MRI)130 void AMDGPUInstPrinter::printRegOperand(unsigned reg, raw_ostream &O,
131 const MCRegisterInfo &MRI) {
132 switch (reg) {
133 case AMDGPU::VCC:
134 O << "vcc";
135 return;
136 case AMDGPU::SCC:
137 O << "scc";
138 return;
139 case AMDGPU::EXEC:
140 O << "exec";
141 return;
142 case AMDGPU::M0:
143 O << "m0";
144 return;
145 case AMDGPU::FLAT_SCR:
146 O << "flat_scratch";
147 return;
148 case AMDGPU::VCC_LO:
149 O << "vcc_lo";
150 return;
151 case AMDGPU::VCC_HI:
152 O << "vcc_hi";
153 return;
154 case AMDGPU::EXEC_LO:
155 O << "exec_lo";
156 return;
157 case AMDGPU::EXEC_HI:
158 O << "exec_hi";
159 return;
160 case AMDGPU::FLAT_SCR_LO:
161 O << "flat_scratch_lo";
162 return;
163 case AMDGPU::FLAT_SCR_HI:
164 O << "flat_scratch_hi";
165 return;
166 default:
167 break;
168 }
169
170 char Type;
171 unsigned NumRegs;
172
173 if (MRI.getRegClass(AMDGPU::VGPR_32RegClassID).contains(reg)) {
174 Type = 'v';
175 NumRegs = 1;
176 } else if (MRI.getRegClass(AMDGPU::SGPR_32RegClassID).contains(reg)) {
177 Type = 's';
178 NumRegs = 1;
179 } else if (MRI.getRegClass(AMDGPU::VReg_64RegClassID).contains(reg)) {
180 Type = 'v';
181 NumRegs = 2;
182 } else if (MRI.getRegClass(AMDGPU::SReg_64RegClassID).contains(reg)) {
183 Type = 's';
184 NumRegs = 2;
185 } else if (MRI.getRegClass(AMDGPU::VReg_128RegClassID).contains(reg)) {
186 Type = 'v';
187 NumRegs = 4;
188 } else if (MRI.getRegClass(AMDGPU::SReg_128RegClassID).contains(reg)) {
189 Type = 's';
190 NumRegs = 4;
191 } else if (MRI.getRegClass(AMDGPU::VReg_96RegClassID).contains(reg)) {
192 Type = 'v';
193 NumRegs = 3;
194 } else if (MRI.getRegClass(AMDGPU::VReg_256RegClassID).contains(reg)) {
195 Type = 'v';
196 NumRegs = 8;
197 } else if (MRI.getRegClass(AMDGPU::SReg_256RegClassID).contains(reg)) {
198 Type = 's';
199 NumRegs = 8;
200 } else if (MRI.getRegClass(AMDGPU::VReg_512RegClassID).contains(reg)) {
201 Type = 'v';
202 NumRegs = 16;
203 } else if (MRI.getRegClass(AMDGPU::SReg_512RegClassID).contains(reg)) {
204 Type = 's';
205 NumRegs = 16;
206 } else {
207 O << getRegisterName(reg);
208 return;
209 }
210
211 // The low 8 bits of the encoding value is the register index, for both VGPRs
212 // and SGPRs.
213 unsigned RegIdx = MRI.getEncodingValue(reg) & ((1 << 8) - 1);
214 if (NumRegs == 1) {
215 O << Type << RegIdx;
216 return;
217 }
218
219 O << Type << '[' << RegIdx << ':' << (RegIdx + NumRegs - 1) << ']';
220 }
221
printVOPDst(const MCInst * MI,unsigned OpNo,raw_ostream & O)222 void AMDGPUInstPrinter::printVOPDst(const MCInst *MI, unsigned OpNo,
223 raw_ostream &O) {
224 if (MII.get(MI->getOpcode()).TSFlags & SIInstrFlags::VOP3)
225 O << "_e64 ";
226 else
227 O << "_e32 ";
228
229 printOperand(MI, OpNo, O);
230 }
231
printImmediate32(uint32_t Imm,raw_ostream & O)232 void AMDGPUInstPrinter::printImmediate32(uint32_t Imm, raw_ostream &O) {
233 int32_t SImm = static_cast<int32_t>(Imm);
234 if (SImm >= -16 && SImm <= 64) {
235 O << SImm;
236 return;
237 }
238
239 if (Imm == FloatToBits(0.0f))
240 O << "0.0";
241 else if (Imm == FloatToBits(1.0f))
242 O << "1.0";
243 else if (Imm == FloatToBits(-1.0f))
244 O << "-1.0";
245 else if (Imm == FloatToBits(0.5f))
246 O << "0.5";
247 else if (Imm == FloatToBits(-0.5f))
248 O << "-0.5";
249 else if (Imm == FloatToBits(2.0f))
250 O << "2.0";
251 else if (Imm == FloatToBits(-2.0f))
252 O << "-2.0";
253 else if (Imm == FloatToBits(4.0f))
254 O << "4.0";
255 else if (Imm == FloatToBits(-4.0f))
256 O << "-4.0";
257 else
258 O << formatHex(static_cast<uint64_t>(Imm));
259 }
260
printImmediate64(uint64_t Imm,raw_ostream & O)261 void AMDGPUInstPrinter::printImmediate64(uint64_t Imm, raw_ostream &O) {
262 int64_t SImm = static_cast<int64_t>(Imm);
263 if (SImm >= -16 && SImm <= 64) {
264 O << SImm;
265 return;
266 }
267
268 if (Imm == DoubleToBits(0.0))
269 O << "0.0";
270 else if (Imm == DoubleToBits(1.0))
271 O << "1.0";
272 else if (Imm == DoubleToBits(-1.0))
273 O << "-1.0";
274 else if (Imm == DoubleToBits(0.5))
275 O << "0.5";
276 else if (Imm == DoubleToBits(-0.5))
277 O << "-0.5";
278 else if (Imm == DoubleToBits(2.0))
279 O << "2.0";
280 else if (Imm == DoubleToBits(-2.0))
281 O << "-2.0";
282 else if (Imm == DoubleToBits(4.0))
283 O << "4.0";
284 else if (Imm == DoubleToBits(-4.0))
285 O << "-4.0";
286 else {
287 assert(isUInt<32>(Imm));
288
289 // In rare situations, we will have a 32-bit literal in a 64-bit
290 // operand. This is technically allowed for the encoding of s_mov_b64.
291 O << formatHex(static_cast<uint64_t>(Imm));
292 }
293 }
294
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)295 void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
296 raw_ostream &O) {
297
298 const MCOperand &Op = MI->getOperand(OpNo);
299 if (Op.isReg()) {
300 switch (Op.getReg()) {
301 // This is the default predicate state, so we don't need to print it.
302 case AMDGPU::PRED_SEL_OFF:
303 break;
304
305 default:
306 printRegOperand(Op.getReg(), O, MRI);
307 break;
308 }
309 } else if (Op.isImm()) {
310 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
311 int RCID = Desc.OpInfo[OpNo].RegClass;
312 if (RCID != -1) {
313 const MCRegisterClass &ImmRC = MRI.getRegClass(RCID);
314 if (ImmRC.getSize() == 4)
315 printImmediate32(Op.getImm(), O);
316 else if (ImmRC.getSize() == 8)
317 printImmediate64(Op.getImm(), O);
318 else
319 llvm_unreachable("Invalid register class size");
320 } else if (Desc.OpInfo[OpNo].OperandType == MCOI::OPERAND_IMMEDIATE) {
321 printImmediate32(Op.getImm(), O);
322 } else {
323 // We hit this for the immediate instruction bits that don't yet have a
324 // custom printer.
325 // TODO: Eventually this should be unnecessary.
326 O << formatDec(Op.getImm());
327 }
328 } else if (Op.isFPImm()) {
329 // We special case 0.0 because otherwise it will be printed as an integer.
330 if (Op.getFPImm() == 0.0)
331 O << "0.0";
332 else {
333 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
334 const MCRegisterClass &ImmRC = MRI.getRegClass(Desc.OpInfo[OpNo].RegClass);
335
336 if (ImmRC.getSize() == 4)
337 printImmediate32(FloatToBits(Op.getFPImm()), O);
338 else if (ImmRC.getSize() == 8)
339 printImmediate64(DoubleToBits(Op.getFPImm()), O);
340 else
341 llvm_unreachable("Invalid register class size");
342 }
343 } else if (Op.isExpr()) {
344 const MCExpr *Exp = Op.getExpr();
345 Exp->print(O, &MAI);
346 } else {
347 llvm_unreachable("unknown operand type in printOperand");
348 }
349 }
350
printOperandAndMods(const MCInst * MI,unsigned OpNo,raw_ostream & O)351 void AMDGPUInstPrinter::printOperandAndMods(const MCInst *MI, unsigned OpNo,
352 raw_ostream &O) {
353 unsigned InputModifiers = MI->getOperand(OpNo).getImm();
354 if (InputModifiers & SISrcMods::NEG)
355 O << '-';
356 if (InputModifiers & SISrcMods::ABS)
357 O << '|';
358 printOperand(MI, OpNo + 1, O);
359 if (InputModifiers & SISrcMods::ABS)
360 O << '|';
361 }
362
printInterpSlot(const MCInst * MI,unsigned OpNum,raw_ostream & O)363 void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum,
364 raw_ostream &O) {
365 unsigned Imm = MI->getOperand(OpNum).getImm();
366
367 if (Imm == 2) {
368 O << "P0";
369 } else if (Imm == 1) {
370 O << "P20";
371 } else if (Imm == 0) {
372 O << "P10";
373 } else {
374 llvm_unreachable("Invalid interpolation parameter slot");
375 }
376 }
377
printMemOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)378 void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
379 raw_ostream &O) {
380 printOperand(MI, OpNo, O);
381 O << ", ";
382 printOperand(MI, OpNo + 1, O);
383 }
384
printIfSet(const MCInst * MI,unsigned OpNo,raw_ostream & O,StringRef Asm,StringRef Default)385 void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
386 raw_ostream &O, StringRef Asm,
387 StringRef Default) {
388 const MCOperand &Op = MI->getOperand(OpNo);
389 assert(Op.isImm());
390 if (Op.getImm() == 1) {
391 O << Asm;
392 } else {
393 O << Default;
394 }
395 }
396
printAbs(const MCInst * MI,unsigned OpNo,raw_ostream & O)397 void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo,
398 raw_ostream &O) {
399 printIfSet(MI, OpNo, O, "|");
400 }
401
printClamp(const MCInst * MI,unsigned OpNo,raw_ostream & O)402 void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo,
403 raw_ostream &O) {
404 printIfSet(MI, OpNo, O, "_SAT");
405 }
406
printClampSI(const MCInst * MI,unsigned OpNo,raw_ostream & O)407 void AMDGPUInstPrinter::printClampSI(const MCInst *MI, unsigned OpNo,
408 raw_ostream &O) {
409 if (MI->getOperand(OpNo).getImm())
410 O << " clamp";
411 }
412
printOModSI(const MCInst * MI,unsigned OpNo,raw_ostream & O)413 void AMDGPUInstPrinter::printOModSI(const MCInst *MI, unsigned OpNo,
414 raw_ostream &O) {
415 int Imm = MI->getOperand(OpNo).getImm();
416 if (Imm == SIOutMods::MUL2)
417 O << " mul:2";
418 else if (Imm == SIOutMods::MUL4)
419 O << " mul:4";
420 else if (Imm == SIOutMods::DIV2)
421 O << " div:2";
422 }
423
printLiteral(const MCInst * MI,unsigned OpNo,raw_ostream & O)424 void AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo,
425 raw_ostream &O) {
426 int32_t Imm = MI->getOperand(OpNo).getImm();
427 O << Imm << '(' << BitsToFloat(Imm) << ')';
428 }
429
printLast(const MCInst * MI,unsigned OpNo,raw_ostream & O)430 void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo,
431 raw_ostream &O) {
432 printIfSet(MI, OpNo, O, "*", " ");
433 }
434
printNeg(const MCInst * MI,unsigned OpNo,raw_ostream & O)435 void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo,
436 raw_ostream &O) {
437 printIfSet(MI, OpNo, O, "-");
438 }
439
printOMOD(const MCInst * MI,unsigned OpNo,raw_ostream & O)440 void AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo,
441 raw_ostream &O) {
442 switch (MI->getOperand(OpNo).getImm()) {
443 default: break;
444 case 1:
445 O << " * 2.0";
446 break;
447 case 2:
448 O << " * 4.0";
449 break;
450 case 3:
451 O << " / 2.0";
452 break;
453 }
454 }
455
printRel(const MCInst * MI,unsigned OpNo,raw_ostream & O)456 void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo,
457 raw_ostream &O) {
458 printIfSet(MI, OpNo, O, "+");
459 }
460
printUpdateExecMask(const MCInst * MI,unsigned OpNo,raw_ostream & O)461 void AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo,
462 raw_ostream &O) {
463 printIfSet(MI, OpNo, O, "ExecMask,");
464 }
465
printUpdatePred(const MCInst * MI,unsigned OpNo,raw_ostream & O)466 void AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo,
467 raw_ostream &O) {
468 printIfSet(MI, OpNo, O, "Pred,");
469 }
470
printWrite(const MCInst * MI,unsigned OpNo,raw_ostream & O)471 void AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo,
472 raw_ostream &O) {
473 const MCOperand &Op = MI->getOperand(OpNo);
474 if (Op.getImm() == 0) {
475 O << " (MASKED)";
476 }
477 }
478
printSel(const MCInst * MI,unsigned OpNo,raw_ostream & O)479 void AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo,
480 raw_ostream &O) {
481 const char * chans = "XYZW";
482 int sel = MI->getOperand(OpNo).getImm();
483
484 int chan = sel & 3;
485 sel >>= 2;
486
487 if (sel >= 512) {
488 sel -= 512;
489 int cb = sel >> 12;
490 sel &= 4095;
491 O << cb << '[' << sel << ']';
492 } else if (sel >= 448) {
493 sel -= 448;
494 O << sel;
495 } else if (sel >= 0){
496 O << sel;
497 }
498
499 if (sel >= 0)
500 O << '.' << chans[chan];
501 }
502
printBankSwizzle(const MCInst * MI,unsigned OpNo,raw_ostream & O)503 void AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo,
504 raw_ostream &O) {
505 int BankSwizzle = MI->getOperand(OpNo).getImm();
506 switch (BankSwizzle) {
507 case 1:
508 O << "BS:VEC_021/SCL_122";
509 break;
510 case 2:
511 O << "BS:VEC_120/SCL_212";
512 break;
513 case 3:
514 O << "BS:VEC_102/SCL_221";
515 break;
516 case 4:
517 O << "BS:VEC_201";
518 break;
519 case 5:
520 O << "BS:VEC_210";
521 break;
522 default:
523 break;
524 }
525 return;
526 }
527
printRSel(const MCInst * MI,unsigned OpNo,raw_ostream & O)528 void AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo,
529 raw_ostream &O) {
530 unsigned Sel = MI->getOperand(OpNo).getImm();
531 switch (Sel) {
532 case 0:
533 O << 'X';
534 break;
535 case 1:
536 O << 'Y';
537 break;
538 case 2:
539 O << 'Z';
540 break;
541 case 3:
542 O << 'W';
543 break;
544 case 4:
545 O << '0';
546 break;
547 case 5:
548 O << '1';
549 break;
550 case 7:
551 O << '_';
552 break;
553 default:
554 break;
555 }
556 }
557
printCT(const MCInst * MI,unsigned OpNo,raw_ostream & O)558 void AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo,
559 raw_ostream &O) {
560 unsigned CT = MI->getOperand(OpNo).getImm();
561 switch (CT) {
562 case 0:
563 O << 'U';
564 break;
565 case 1:
566 O << 'N';
567 break;
568 default:
569 break;
570 }
571 }
572
printKCache(const MCInst * MI,unsigned OpNo,raw_ostream & O)573 void AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo,
574 raw_ostream &O) {
575 int KCacheMode = MI->getOperand(OpNo).getImm();
576 if (KCacheMode > 0) {
577 int KCacheBank = MI->getOperand(OpNo - 2).getImm();
578 O << "CB" << KCacheBank << ':';
579 int KCacheAddr = MI->getOperand(OpNo + 2).getImm();
580 int LineSize = (KCacheMode == 1) ? 16 : 32;
581 O << KCacheAddr * 16 << '-' << KCacheAddr * 16 + LineSize;
582 }
583 }
584
printSendMsg(const MCInst * MI,unsigned OpNo,raw_ostream & O)585 void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo,
586 raw_ostream &O) {
587 unsigned SImm16 = MI->getOperand(OpNo).getImm();
588 unsigned Msg = SImm16 & 0xF;
589 if (Msg == 2 || Msg == 3) {
590 unsigned Op = (SImm16 >> 4) & 0xF;
591 if (Msg == 3)
592 O << "Gs_done(";
593 else
594 O << "Gs(";
595 if (Op == 0) {
596 O << "nop";
597 } else {
598 unsigned Stream = (SImm16 >> 8) & 0x3;
599 if (Op == 1)
600 O << "cut";
601 else if (Op == 2)
602 O << "emit";
603 else if (Op == 3)
604 O << "emit-cut";
605 O << " stream " << Stream;
606 }
607 O << "), [m0] ";
608 } else if (Msg == 1)
609 O << "interrupt ";
610 else if (Msg == 15)
611 O << "system ";
612 else
613 O << "unknown(" << Msg << ") ";
614 }
615
printWaitFlag(const MCInst * MI,unsigned OpNo,raw_ostream & O)616 void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo,
617 raw_ostream &O) {
618 // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs
619 // SIInsertWaits.cpp bits usage does not match ISA docs description but it
620 // works so it might be a misprint in docs.
621 unsigned SImm16 = MI->getOperand(OpNo).getImm();
622 unsigned Vmcnt = SImm16 & 0xF;
623 unsigned Expcnt = (SImm16 >> 4) & 0xF;
624 unsigned Lgkmcnt = (SImm16 >> 8) & 0xF;
625
626 bool NeedSpace = false;
627
628 if (Vmcnt != 0xF) {
629 O << "vmcnt(" << Vmcnt << ')';
630 NeedSpace = true;
631 }
632
633 if (Expcnt != 0x7) {
634 if (NeedSpace)
635 O << ' ';
636 O << "expcnt(" << Expcnt << ')';
637 NeedSpace = true;
638 }
639
640 if (Lgkmcnt != 0x7) {
641 if (NeedSpace)
642 O << ' ';
643 O << "lgkmcnt(" << Lgkmcnt << ')';
644 }
645 }
646
647 #include "AMDGPUGenAsmWriter.inc"
648