• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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