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