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 llvm_unreachable("64-bit literal constants not supported");
288 }
289
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)290 void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
291 raw_ostream &O) {
292
293 const MCOperand &Op = MI->getOperand(OpNo);
294 if (Op.isReg()) {
295 switch (Op.getReg()) {
296 // This is the default predicate state, so we don't need to print it.
297 case AMDGPU::PRED_SEL_OFF:
298 break;
299
300 default:
301 printRegOperand(Op.getReg(), O, MRI);
302 break;
303 }
304 } else if (Op.isImm()) {
305 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
306 int RCID = Desc.OpInfo[OpNo].RegClass;
307 if (RCID != -1) {
308 const MCRegisterClass &ImmRC = MRI.getRegClass(RCID);
309 if (ImmRC.getSize() == 4)
310 printImmediate32(Op.getImm(), O);
311 else if (ImmRC.getSize() == 8)
312 printImmediate64(Op.getImm(), O);
313 else
314 llvm_unreachable("Invalid register class size");
315 } else if (Desc.OpInfo[OpNo].OperandType == MCOI::OPERAND_IMMEDIATE) {
316 printImmediate32(Op.getImm(), O);
317 } else {
318 // We hit this for the immediate instruction bits that don't yet have a
319 // custom printer.
320 // TODO: Eventually this should be unnecessary.
321 O << formatDec(Op.getImm());
322 }
323 } else if (Op.isFPImm()) {
324 // We special case 0.0 because otherwise it will be printed as an integer.
325 if (Op.getFPImm() == 0.0)
326 O << "0.0";
327 else {
328 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
329 const MCRegisterClass &ImmRC = MRI.getRegClass(Desc.OpInfo[OpNo].RegClass);
330
331 if (ImmRC.getSize() == 4)
332 printImmediate32(FloatToBits(Op.getFPImm()), O);
333 else if (ImmRC.getSize() == 8)
334 printImmediate64(DoubleToBits(Op.getFPImm()), O);
335 else
336 llvm_unreachable("Invalid register class size");
337 }
338 } else if (Op.isExpr()) {
339 const MCExpr *Exp = Op.getExpr();
340 Exp->print(O);
341 } else {
342 llvm_unreachable("unknown operand type in printOperand");
343 }
344 }
345
printOperandAndMods(const MCInst * MI,unsigned OpNo,raw_ostream & O)346 void AMDGPUInstPrinter::printOperandAndMods(const MCInst *MI, unsigned OpNo,
347 raw_ostream &O) {
348 unsigned InputModifiers = MI->getOperand(OpNo).getImm();
349 if (InputModifiers & SISrcMods::NEG)
350 O << '-';
351 if (InputModifiers & SISrcMods::ABS)
352 O << '|';
353 printOperand(MI, OpNo + 1, O);
354 if (InputModifiers & SISrcMods::ABS)
355 O << '|';
356 }
357
printInterpSlot(const MCInst * MI,unsigned OpNum,raw_ostream & O)358 void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum,
359 raw_ostream &O) {
360 unsigned Imm = MI->getOperand(OpNum).getImm();
361
362 if (Imm == 2) {
363 O << "P0";
364 } else if (Imm == 1) {
365 O << "P20";
366 } else if (Imm == 0) {
367 O << "P10";
368 } else {
369 llvm_unreachable("Invalid interpolation parameter slot");
370 }
371 }
372
printMemOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)373 void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
374 raw_ostream &O) {
375 printOperand(MI, OpNo, O);
376 O << ", ";
377 printOperand(MI, OpNo + 1, O);
378 }
379
printIfSet(const MCInst * MI,unsigned OpNo,raw_ostream & O,StringRef Asm,StringRef Default)380 void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
381 raw_ostream &O, StringRef Asm,
382 StringRef Default) {
383 const MCOperand &Op = MI->getOperand(OpNo);
384 assert(Op.isImm());
385 if (Op.getImm() == 1) {
386 O << Asm;
387 } else {
388 O << Default;
389 }
390 }
391
printAbs(const MCInst * MI,unsigned OpNo,raw_ostream & O)392 void AMDGPUInstPrinter::printAbs(const MCInst *MI, unsigned OpNo,
393 raw_ostream &O) {
394 printIfSet(MI, OpNo, O, "|");
395 }
396
printClamp(const MCInst * MI,unsigned OpNo,raw_ostream & O)397 void AMDGPUInstPrinter::printClamp(const MCInst *MI, unsigned OpNo,
398 raw_ostream &O) {
399 printIfSet(MI, OpNo, O, "_SAT");
400 }
401
printClampSI(const MCInst * MI,unsigned OpNo,raw_ostream & O)402 void AMDGPUInstPrinter::printClampSI(const MCInst *MI, unsigned OpNo,
403 raw_ostream &O) {
404 if (MI->getOperand(OpNo).getImm())
405 O << " clamp";
406 }
407
printOModSI(const MCInst * MI,unsigned OpNo,raw_ostream & O)408 void AMDGPUInstPrinter::printOModSI(const MCInst *MI, unsigned OpNo,
409 raw_ostream &O) {
410 int Imm = MI->getOperand(OpNo).getImm();
411 if (Imm == SIOutMods::MUL2)
412 O << " mul:2";
413 else if (Imm == SIOutMods::MUL4)
414 O << " mul:4";
415 else if (Imm == SIOutMods::DIV2)
416 O << " div:2";
417 }
418
printLiteral(const MCInst * MI,unsigned OpNo,raw_ostream & O)419 void AMDGPUInstPrinter::printLiteral(const MCInst *MI, unsigned OpNo,
420 raw_ostream &O) {
421 int32_t Imm = MI->getOperand(OpNo).getImm();
422 O << Imm << '(' << BitsToFloat(Imm) << ')';
423 }
424
printLast(const MCInst * MI,unsigned OpNo,raw_ostream & O)425 void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo,
426 raw_ostream &O) {
427 printIfSet(MI, OpNo, O.indent(25 - O.GetNumBytesInBuffer()), "*", " ");
428 }
429
printNeg(const MCInst * MI,unsigned OpNo,raw_ostream & O)430 void AMDGPUInstPrinter::printNeg(const MCInst *MI, unsigned OpNo,
431 raw_ostream &O) {
432 printIfSet(MI, OpNo, O, "-");
433 }
434
printOMOD(const MCInst * MI,unsigned OpNo,raw_ostream & O)435 void AMDGPUInstPrinter::printOMOD(const MCInst *MI, unsigned OpNo,
436 raw_ostream &O) {
437 switch (MI->getOperand(OpNo).getImm()) {
438 default: break;
439 case 1:
440 O << " * 2.0";
441 break;
442 case 2:
443 O << " * 4.0";
444 break;
445 case 3:
446 O << " / 2.0";
447 break;
448 }
449 }
450
printRel(const MCInst * MI,unsigned OpNo,raw_ostream & O)451 void AMDGPUInstPrinter::printRel(const MCInst *MI, unsigned OpNo,
452 raw_ostream &O) {
453 printIfSet(MI, OpNo, O, "+");
454 }
455
printUpdateExecMask(const MCInst * MI,unsigned OpNo,raw_ostream & O)456 void AMDGPUInstPrinter::printUpdateExecMask(const MCInst *MI, unsigned OpNo,
457 raw_ostream &O) {
458 printIfSet(MI, OpNo, O, "ExecMask,");
459 }
460
printUpdatePred(const MCInst * MI,unsigned OpNo,raw_ostream & O)461 void AMDGPUInstPrinter::printUpdatePred(const MCInst *MI, unsigned OpNo,
462 raw_ostream &O) {
463 printIfSet(MI, OpNo, O, "Pred,");
464 }
465
printWrite(const MCInst * MI,unsigned OpNo,raw_ostream & O)466 void AMDGPUInstPrinter::printWrite(const MCInst *MI, unsigned OpNo,
467 raw_ostream &O) {
468 const MCOperand &Op = MI->getOperand(OpNo);
469 if (Op.getImm() == 0) {
470 O << " (MASKED)";
471 }
472 }
473
printSel(const MCInst * MI,unsigned OpNo,raw_ostream & O)474 void AMDGPUInstPrinter::printSel(const MCInst *MI, unsigned OpNo,
475 raw_ostream &O) {
476 const char * chans = "XYZW";
477 int sel = MI->getOperand(OpNo).getImm();
478
479 int chan = sel & 3;
480 sel >>= 2;
481
482 if (sel >= 512) {
483 sel -= 512;
484 int cb = sel >> 12;
485 sel &= 4095;
486 O << cb << '[' << sel << ']';
487 } else if (sel >= 448) {
488 sel -= 448;
489 O << sel;
490 } else if (sel >= 0){
491 O << sel;
492 }
493
494 if (sel >= 0)
495 O << '.' << chans[chan];
496 }
497
printBankSwizzle(const MCInst * MI,unsigned OpNo,raw_ostream & O)498 void AMDGPUInstPrinter::printBankSwizzle(const MCInst *MI, unsigned OpNo,
499 raw_ostream &O) {
500 int BankSwizzle = MI->getOperand(OpNo).getImm();
501 switch (BankSwizzle) {
502 case 1:
503 O << "BS:VEC_021/SCL_122";
504 break;
505 case 2:
506 O << "BS:VEC_120/SCL_212";
507 break;
508 case 3:
509 O << "BS:VEC_102/SCL_221";
510 break;
511 case 4:
512 O << "BS:VEC_201";
513 break;
514 case 5:
515 O << "BS:VEC_210";
516 break;
517 default:
518 break;
519 }
520 return;
521 }
522
printRSel(const MCInst * MI,unsigned OpNo,raw_ostream & O)523 void AMDGPUInstPrinter::printRSel(const MCInst *MI, unsigned OpNo,
524 raw_ostream &O) {
525 unsigned Sel = MI->getOperand(OpNo).getImm();
526 switch (Sel) {
527 case 0:
528 O << 'X';
529 break;
530 case 1:
531 O << 'Y';
532 break;
533 case 2:
534 O << 'Z';
535 break;
536 case 3:
537 O << 'W';
538 break;
539 case 4:
540 O << '0';
541 break;
542 case 5:
543 O << '1';
544 break;
545 case 7:
546 O << '_';
547 break;
548 default:
549 break;
550 }
551 }
552
printCT(const MCInst * MI,unsigned OpNo,raw_ostream & O)553 void AMDGPUInstPrinter::printCT(const MCInst *MI, unsigned OpNo,
554 raw_ostream &O) {
555 unsigned CT = MI->getOperand(OpNo).getImm();
556 switch (CT) {
557 case 0:
558 O << 'U';
559 break;
560 case 1:
561 O << 'N';
562 break;
563 default:
564 break;
565 }
566 }
567
printKCache(const MCInst * MI,unsigned OpNo,raw_ostream & O)568 void AMDGPUInstPrinter::printKCache(const MCInst *MI, unsigned OpNo,
569 raw_ostream &O) {
570 int KCacheMode = MI->getOperand(OpNo).getImm();
571 if (KCacheMode > 0) {
572 int KCacheBank = MI->getOperand(OpNo - 2).getImm();
573 O << "CB" << KCacheBank << ':';
574 int KCacheAddr = MI->getOperand(OpNo + 2).getImm();
575 int LineSize = (KCacheMode == 1) ? 16 : 32;
576 O << KCacheAddr * 16 << '-' << KCacheAddr * 16 + LineSize;
577 }
578 }
579
printSendMsg(const MCInst * MI,unsigned OpNo,raw_ostream & O)580 void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo,
581 raw_ostream &O) {
582 unsigned SImm16 = MI->getOperand(OpNo).getImm();
583 unsigned Msg = SImm16 & 0xF;
584 if (Msg == 2 || Msg == 3) {
585 unsigned Op = (SImm16 >> 4) & 0xF;
586 if (Msg == 3)
587 O << "Gs_done(";
588 else
589 O << "Gs(";
590 if (Op == 0) {
591 O << "nop";
592 } else {
593 unsigned Stream = (SImm16 >> 8) & 0x3;
594 if (Op == 1)
595 O << "cut";
596 else if (Op == 2)
597 O << "emit";
598 else if (Op == 3)
599 O << "emit-cut";
600 O << " stream " << Stream;
601 }
602 O << "), [m0] ";
603 } else if (Msg == 1)
604 O << "interrupt ";
605 else if (Msg == 15)
606 O << "system ";
607 else
608 O << "unknown(" << Msg << ") ";
609 }
610
printWaitFlag(const MCInst * MI,unsigned OpNo,raw_ostream & O)611 void AMDGPUInstPrinter::printWaitFlag(const MCInst *MI, unsigned OpNo,
612 raw_ostream &O) {
613 // Note: Mask values are taken from SIInsertWaits.cpp and not from ISA docs
614 // SIInsertWaits.cpp bits usage does not match ISA docs description but it
615 // works so it might be a misprint in docs.
616 unsigned SImm16 = MI->getOperand(OpNo).getImm();
617 unsigned Vmcnt = SImm16 & 0xF;
618 unsigned Expcnt = (SImm16 >> 4) & 0xF;
619 unsigned Lgkmcnt = (SImm16 >> 8) & 0xF;
620
621 bool NeedSpace = false;
622
623 if (Vmcnt != 0xF) {
624 O << "vmcnt(" << Vmcnt << ')';
625 NeedSpace = true;
626 }
627
628 if (Expcnt != 0x7) {
629 if (NeedSpace)
630 O << ' ';
631 O << "expcnt(" << Expcnt << ')';
632 NeedSpace = true;
633 }
634
635 if (Lgkmcnt != 0x7) {
636 if (NeedSpace)
637 O << ' ';
638 O << "lgkmcnt(" << Lgkmcnt << ')';
639 }
640 }
641
642 #include "AMDGPUGenAsmWriter.inc"
643