1 //===-- AMDGPUInstPrinter.cpp - AMDGPU MC Inst -> ASM ---------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 // \file
8 //===----------------------------------------------------------------------===//
9
10 #include "AMDGPUInstPrinter.h"
11 #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
12 #include "SIDefines.h"
13 #include "Utils/AMDGPUAsmUtils.h"
14 #include "Utils/AMDGPUBaseInfo.h"
15 #include "llvm/MC/MCAsmInfo.h"
16 #include "llvm/MC/MCExpr.h"
17 #include "llvm/MC/MCInst.h"
18 #include "llvm/MC/MCInstrDesc.h"
19 #include "llvm/MC/MCInstrInfo.h"
20 #include "llvm/MC/MCRegisterInfo.h"
21 #include "llvm/MC/MCSubtargetInfo.h"
22 #include "llvm/TargetParser/TargetParser.h"
23
24 using namespace llvm;
25 using namespace llvm::AMDGPU;
26
printRegName(raw_ostream & OS,MCRegister Reg)27 void AMDGPUInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
28 // FIXME: The current implementation of
29 // AsmParser::parseRegisterOrRegisterNumber in MC implies we either emit this
30 // as an integer or we provide a name which represents a physical register.
31 // For CFI instructions we really want to emit a name for the DWARF register
32 // instead, because there may be multiple DWARF registers corresponding to a
33 // single physical register. One case where this problem manifests is with
34 // wave32/wave64 where using the physical register name is ambiguous: if we
35 // write e.g. `.cfi_undefined v0` we lose information about the wavefront
36 // size which we need to encode the register in the final DWARF. Ideally we
37 // would extend MC to support parsing DWARF register names so we could do
38 // something like `.cfi_undefined dwarf_wave32_v0`. For now we just live with
39 // non-pretty DWARF register names in assembly text.
40 OS << Reg.id();
41 }
42
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & OS)43 void AMDGPUInstPrinter::printInst(const MCInst *MI, uint64_t Address,
44 StringRef Annot, const MCSubtargetInfo &STI,
45 raw_ostream &OS) {
46 printInstruction(MI, Address, STI, OS);
47 printAnnotation(OS, Annot);
48 }
49
printU16ImmOperand(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)50 void AMDGPUInstPrinter::printU16ImmOperand(const MCInst *MI, unsigned OpNo,
51 const MCSubtargetInfo &STI,
52 raw_ostream &O) {
53 const MCOperand &Op = MI->getOperand(OpNo);
54 if (Op.isExpr()) {
55 MAI.printExpr(O, *Op.getExpr());
56 return;
57 }
58
59 // It's possible to end up with a 32-bit literal used with a 16-bit operand
60 // with ignored high bits. Print as 32-bit anyway in that case.
61 int64_t Imm = Op.getImm();
62 if (isInt<16>(Imm) || isUInt<16>(Imm))
63 O << formatHex(static_cast<uint64_t>(Imm & 0xffff));
64 else
65 printU32ImmOperand(MI, OpNo, STI, O);
66 }
67
printU16ImmDecOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)68 void AMDGPUInstPrinter::printU16ImmDecOperand(const MCInst *MI, unsigned OpNo,
69 raw_ostream &O) {
70 O << formatDec(MI->getOperand(OpNo).getImm() & 0xffff);
71 }
72
printU32ImmOperand(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)73 void AMDGPUInstPrinter::printU32ImmOperand(const MCInst *MI, unsigned OpNo,
74 const MCSubtargetInfo &STI,
75 raw_ostream &O) {
76 O << formatHex(MI->getOperand(OpNo).getImm() & 0xffffffff);
77 }
78
printFP64ImmOperand(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)79 void AMDGPUInstPrinter::printFP64ImmOperand(const MCInst *MI, unsigned OpNo,
80 const MCSubtargetInfo &STI,
81 raw_ostream &O) {
82 // KIMM64
83 // This part needs to align with AMDGPUInstPrinter::printImmediate64.
84 uint64_t Imm = MI->getOperand(OpNo).getImm();
85 if (STI.hasFeature(AMDGPU::Feature64BitLiterals) && Lo_32(Imm))
86 O << "lit64(" << formatHex(static_cast<uint64_t>(Imm)) << ')';
87 else
88 O << formatHex(static_cast<uint64_t>(Hi_32(Imm)));
89 }
90
printNamedBit(const MCInst * MI,unsigned OpNo,raw_ostream & O,StringRef BitName)91 void AMDGPUInstPrinter::printNamedBit(const MCInst *MI, unsigned OpNo,
92 raw_ostream &O, StringRef BitName) {
93 if (MI->getOperand(OpNo).getImm()) {
94 O << ' ' << BitName;
95 }
96 }
97
printOffset(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)98 void AMDGPUInstPrinter::printOffset(const MCInst *MI, unsigned OpNo,
99 const MCSubtargetInfo &STI,
100 raw_ostream &O) {
101 uint32_t Imm = MI->getOperand(OpNo).getImm();
102 if (Imm != 0) {
103 O << " offset:";
104
105 // GFX12 uses a 24-bit signed offset for VBUFFER.
106 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
107 bool IsVBuffer = Desc.TSFlags & (SIInstrFlags::MUBUF | SIInstrFlags::MTBUF);
108 if (AMDGPU::isGFX12(STI) && IsVBuffer)
109 O << formatDec(SignExtend32<24>(Imm));
110 else
111 printU16ImmDecOperand(MI, OpNo, O);
112 }
113 }
114
printFlatOffset(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)115 void AMDGPUInstPrinter::printFlatOffset(const MCInst *MI, unsigned OpNo,
116 const MCSubtargetInfo &STI,
117 raw_ostream &O) {
118 uint32_t Imm = MI->getOperand(OpNo).getImm();
119 if (Imm != 0) {
120 O << " offset:";
121
122 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
123 bool AllowNegative = (Desc.TSFlags & (SIInstrFlags::FlatGlobal |
124 SIInstrFlags::FlatScratch)) ||
125 AMDGPU::isGFX12(STI);
126
127 if (AllowNegative) // Signed offset
128 O << formatDec(SignExtend32(Imm, AMDGPU::getNumFlatOffsetBits(STI)));
129 else // Unsigned offset
130 printU16ImmDecOperand(MI, OpNo, O);
131 }
132 }
133
printSMRDOffset8(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)134 void AMDGPUInstPrinter::printSMRDOffset8(const MCInst *MI, unsigned OpNo,
135 const MCSubtargetInfo &STI,
136 raw_ostream &O) {
137 printU32ImmOperand(MI, OpNo, STI, O);
138 }
139
printSMEMOffset(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)140 void AMDGPUInstPrinter::printSMEMOffset(const MCInst *MI, unsigned OpNo,
141 const MCSubtargetInfo &STI,
142 raw_ostream &O) {
143 O << formatHex(MI->getOperand(OpNo).getImm());
144 }
145
printSMRDLiteralOffset(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)146 void AMDGPUInstPrinter::printSMRDLiteralOffset(const MCInst *MI, unsigned OpNo,
147 const MCSubtargetInfo &STI,
148 raw_ostream &O) {
149 printU32ImmOperand(MI, OpNo, STI, O);
150 }
151
printCPol(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)152 void AMDGPUInstPrinter::printCPol(const MCInst *MI, unsigned OpNo,
153 const MCSubtargetInfo &STI, raw_ostream &O) {
154 auto Imm = MI->getOperand(OpNo).getImm();
155
156 if (AMDGPU::isGFX12Plus(STI)) {
157 const int64_t TH = Imm & CPol::TH;
158 const int64_t Scope = Imm & CPol::SCOPE;
159
160 printTH(MI, TH, Scope, O);
161 printScope(Scope, O);
162
163 return;
164 }
165
166 if (Imm & CPol::GLC)
167 O << ((AMDGPU::isGFX940(STI) &&
168 !(MII.get(MI->getOpcode()).TSFlags & SIInstrFlags::SMRD)) ? " sc0"
169 : " glc");
170 if (Imm & CPol::SLC)
171 O << (AMDGPU::isGFX940(STI) ? " nt" : " slc");
172 if ((Imm & CPol::DLC) && AMDGPU::isGFX10Plus(STI))
173 O << " dlc";
174 if ((Imm & CPol::SCC) && AMDGPU::isGFX90A(STI))
175 O << (AMDGPU::isGFX940(STI) ? " sc1" : " scc");
176 if (Imm & ~CPol::ALL_pregfx12)
177 O << " /* unexpected cache policy bit */";
178 }
179
printTH(const MCInst * MI,int64_t TH,int64_t Scope,raw_ostream & O)180 void AMDGPUInstPrinter::printTH(const MCInst *MI, int64_t TH, int64_t Scope,
181 raw_ostream &O) {
182 // For th = 0 do not print this field
183 if (TH == 0)
184 return;
185
186 const unsigned Opcode = MI->getOpcode();
187 const MCInstrDesc &TID = MII.get(Opcode);
188 unsigned THType = AMDGPU::getTemporalHintType(TID);
189 bool IsStore = (THType == AMDGPU::CPol::TH_TYPE_STORE);
190
191 O << " th:";
192
193 if (THType == AMDGPU::CPol::TH_TYPE_ATOMIC) {
194 O << "TH_ATOMIC_";
195 if (TH & AMDGPU::CPol::TH_ATOMIC_CASCADE) {
196 if (Scope >= AMDGPU::CPol::SCOPE_DEV)
197 O << "CASCADE" << (TH & AMDGPU::CPol::TH_ATOMIC_NT ? "_NT" : "_RT");
198 else
199 O << formatHex(TH);
200 } else if (TH & AMDGPU::CPol::TH_ATOMIC_NT)
201 O << "NT" << (TH & AMDGPU::CPol::TH_ATOMIC_RETURN ? "_RETURN" : "");
202 else if (TH & AMDGPU::CPol::TH_ATOMIC_RETURN)
203 O << "RETURN";
204 else
205 O << formatHex(TH);
206 } else {
207 if (!IsStore && TH == AMDGPU::CPol::TH_RESERVED)
208 O << formatHex(TH);
209 else {
210 O << (IsStore ? "TH_STORE_" : "TH_LOAD_");
211 switch (TH) {
212 case AMDGPU::CPol::TH_NT:
213 O << "NT";
214 break;
215 case AMDGPU::CPol::TH_HT:
216 O << "HT";
217 break;
218 case AMDGPU::CPol::TH_BYPASS: // or LU or WB
219 O << (Scope == AMDGPU::CPol::SCOPE_SYS ? "BYPASS"
220 : (IsStore ? "WB" : "LU"));
221 break;
222 case AMDGPU::CPol::TH_NT_RT:
223 O << "NT_RT";
224 break;
225 case AMDGPU::CPol::TH_RT_NT:
226 O << "RT_NT";
227 break;
228 case AMDGPU::CPol::TH_NT_HT:
229 O << "NT_HT";
230 break;
231 case AMDGPU::CPol::TH_NT_WB:
232 O << "NT_WB";
233 break;
234 default:
235 llvm_unreachable("unexpected th value");
236 }
237 }
238 }
239 }
240
printScope(int64_t Scope,raw_ostream & O)241 void AMDGPUInstPrinter::printScope(int64_t Scope, raw_ostream &O) {
242 if (Scope == CPol::SCOPE_CU)
243 return;
244
245 O << " scope:";
246
247 if (Scope == CPol::SCOPE_SE)
248 O << "SCOPE_SE";
249 else if (Scope == CPol::SCOPE_DEV)
250 O << "SCOPE_DEV";
251 else if (Scope == CPol::SCOPE_SYS)
252 O << "SCOPE_SYS";
253 else
254 llvm_unreachable("unexpected scope policy value");
255 }
256
printDim(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)257 void AMDGPUInstPrinter::printDim(const MCInst *MI, unsigned OpNo,
258 const MCSubtargetInfo &STI, raw_ostream &O) {
259 unsigned Dim = MI->getOperand(OpNo).getImm();
260 O << " dim:SQ_RSRC_IMG_";
261
262 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByEncoding(Dim);
263 if (DimInfo)
264 O << DimInfo->AsmSuffix;
265 else
266 O << Dim;
267 }
268
printR128A16(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)269 void AMDGPUInstPrinter::printR128A16(const MCInst *MI, unsigned OpNo,
270 const MCSubtargetInfo &STI, raw_ostream &O) {
271 if (STI.hasFeature(AMDGPU::FeatureR128A16))
272 printNamedBit(MI, OpNo, O, "a16");
273 else
274 printNamedBit(MI, OpNo, O, "r128");
275 }
276
printFORMAT(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)277 void AMDGPUInstPrinter::printFORMAT(const MCInst *MI, unsigned OpNo,
278 const MCSubtargetInfo &STI,
279 raw_ostream &O) {
280 }
281
printSymbolicFormat(const MCInst * MI,const MCSubtargetInfo & STI,raw_ostream & O)282 void AMDGPUInstPrinter::printSymbolicFormat(const MCInst *MI,
283 const MCSubtargetInfo &STI,
284 raw_ostream &O) {
285 using namespace llvm::AMDGPU::MTBUFFormat;
286
287 int OpNo =
288 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::format);
289 assert(OpNo != -1);
290
291 unsigned Val = MI->getOperand(OpNo).getImm();
292 if (AMDGPU::isGFX10Plus(STI)) {
293 if (Val == UFMT_DEFAULT)
294 return;
295 if (isValidUnifiedFormat(Val, STI)) {
296 O << " format:[" << getUnifiedFormatName(Val, STI) << ']';
297 } else {
298 O << " format:" << Val;
299 }
300 } else {
301 if (Val == DFMT_NFMT_DEFAULT)
302 return;
303 if (isValidDfmtNfmt(Val, STI)) {
304 unsigned Dfmt;
305 unsigned Nfmt;
306 decodeDfmtNfmt(Val, Dfmt, Nfmt);
307 O << " format:[";
308 if (Dfmt != DFMT_DEFAULT) {
309 O << getDfmtName(Dfmt);
310 if (Nfmt != NFMT_DEFAULT) {
311 O << ',';
312 }
313 }
314 if (Nfmt != NFMT_DEFAULT) {
315 O << getNfmtName(Nfmt, STI);
316 }
317 O << ']';
318 } else {
319 O << " format:" << Val;
320 }
321 }
322 }
323
printRegOperand(MCRegister Reg,raw_ostream & O,const MCRegisterInfo & MRI)324 void AMDGPUInstPrinter::printRegOperand(MCRegister Reg, raw_ostream &O,
325 const MCRegisterInfo &MRI) {
326 #if !defined(NDEBUG)
327 switch (Reg.id()) {
328 case AMDGPU::FP_REG:
329 case AMDGPU::SP_REG:
330 case AMDGPU::PRIVATE_RSRC_REG:
331 llvm_unreachable("pseudo-register should not ever be emitted");
332 default:
333 break;
334 }
335 #endif
336
337 O << getRegisterName(Reg);
338 }
339
printVOPDst(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)340 void AMDGPUInstPrinter::printVOPDst(const MCInst *MI, unsigned OpNo,
341 const MCSubtargetInfo &STI, raw_ostream &O) {
342 auto Opcode = MI->getOpcode();
343 auto Flags = MII.get(Opcode).TSFlags;
344 if (OpNo == 0) {
345 if (Flags & SIInstrFlags::VOP3 && Flags & SIInstrFlags::DPP)
346 O << "_e64_dpp";
347 else if (Flags & SIInstrFlags::VOP3) {
348 if (!getVOP3IsSingle(Opcode))
349 O << "_e64";
350 } else if (Flags & SIInstrFlags::DPP)
351 O << "_dpp";
352 else if (Flags & SIInstrFlags::SDWA)
353 O << "_sdwa";
354 else if (((Flags & SIInstrFlags::VOP1) && !getVOP1IsSingle(Opcode)) ||
355 ((Flags & SIInstrFlags::VOP2) && !getVOP2IsSingle(Opcode)))
356 O << "_e32";
357 O << " ";
358 }
359
360 printRegularOperand(MI, OpNo, STI, O);
361
362 // Print default vcc/vcc_lo operand.
363 switch (Opcode) {
364 default: break;
365
366 case AMDGPU::V_ADD_CO_CI_U32_e32_gfx10:
367 case AMDGPU::V_SUB_CO_CI_U32_e32_gfx10:
368 case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx10:
369 case AMDGPU::V_ADD_CO_CI_U32_sdwa_gfx10:
370 case AMDGPU::V_SUB_CO_CI_U32_sdwa_gfx10:
371 case AMDGPU::V_SUBREV_CO_CI_U32_sdwa_gfx10:
372 case AMDGPU::V_ADD_CO_CI_U32_dpp_gfx10:
373 case AMDGPU::V_SUB_CO_CI_U32_dpp_gfx10:
374 case AMDGPU::V_SUBREV_CO_CI_U32_dpp_gfx10:
375 case AMDGPU::V_ADD_CO_CI_U32_dpp8_gfx10:
376 case AMDGPU::V_SUB_CO_CI_U32_dpp8_gfx10:
377 case AMDGPU::V_SUBREV_CO_CI_U32_dpp8_gfx10:
378 case AMDGPU::V_ADD_CO_CI_U32_e32_gfx11:
379 case AMDGPU::V_SUB_CO_CI_U32_e32_gfx11:
380 case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx11:
381 case AMDGPU::V_ADD_CO_CI_U32_dpp_gfx11:
382 case AMDGPU::V_SUB_CO_CI_U32_dpp_gfx11:
383 case AMDGPU::V_SUBREV_CO_CI_U32_dpp_gfx11:
384 case AMDGPU::V_ADD_CO_CI_U32_dpp8_gfx11:
385 case AMDGPU::V_SUB_CO_CI_U32_dpp8_gfx11:
386 case AMDGPU::V_SUBREV_CO_CI_U32_dpp8_gfx11:
387 case AMDGPU::V_ADD_CO_CI_U32_e32_gfx12:
388 case AMDGPU::V_SUB_CO_CI_U32_e32_gfx12:
389 case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx12:
390 case AMDGPU::V_ADD_CO_CI_U32_dpp_gfx12:
391 case AMDGPU::V_SUB_CO_CI_U32_dpp_gfx12:
392 case AMDGPU::V_SUBREV_CO_CI_U32_dpp_gfx12:
393 case AMDGPU::V_ADD_CO_CI_U32_dpp8_gfx12:
394 case AMDGPU::V_SUB_CO_CI_U32_dpp8_gfx12:
395 case AMDGPU::V_SUBREV_CO_CI_U32_dpp8_gfx12:
396 printDefaultVccOperand(false, STI, O);
397 break;
398 }
399 }
400
printVINTRPDst(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)401 void AMDGPUInstPrinter::printVINTRPDst(const MCInst *MI, unsigned OpNo,
402 const MCSubtargetInfo &STI, raw_ostream &O) {
403 if (AMDGPU::isSI(STI) || AMDGPU::isCI(STI))
404 O << " ";
405 else
406 O << "_e32 ";
407
408 printRegularOperand(MI, OpNo, STI, O);
409 }
410
printImmediateInt16(uint32_t Imm,const MCSubtargetInfo & STI,raw_ostream & O)411 void AMDGPUInstPrinter::printImmediateInt16(uint32_t Imm,
412 const MCSubtargetInfo &STI,
413 raw_ostream &O) {
414 int32_t SImm = static_cast<int32_t>(Imm);
415 if (isInlinableIntLiteral(SImm)) {
416 O << SImm;
417 return;
418 }
419
420 if (printImmediateFloat32(Imm, STI, O))
421 return;
422
423 O << formatHex(static_cast<uint64_t>(Imm & 0xffff));
424 }
425
printImmediateFP16(uint32_t Imm,const MCSubtargetInfo & STI,raw_ostream & O)426 static bool printImmediateFP16(uint32_t Imm, const MCSubtargetInfo &STI,
427 raw_ostream &O) {
428 if (Imm == 0x3C00)
429 O << "1.0";
430 else if (Imm == 0xBC00)
431 O << "-1.0";
432 else if (Imm == 0x3800)
433 O << "0.5";
434 else if (Imm == 0xB800)
435 O << "-0.5";
436 else if (Imm == 0x4000)
437 O << "2.0";
438 else if (Imm == 0xC000)
439 O << "-2.0";
440 else if (Imm == 0x4400)
441 O << "4.0";
442 else if (Imm == 0xC400)
443 O << "-4.0";
444 else if (Imm == 0x3118 && STI.hasFeature(AMDGPU::FeatureInv2PiInlineImm))
445 O << "0.15915494";
446 else
447 return false;
448
449 return true;
450 }
451
printImmediateBFloat16(uint32_t Imm,const MCSubtargetInfo & STI,raw_ostream & O)452 static bool printImmediateBFloat16(uint32_t Imm, const MCSubtargetInfo &STI,
453 raw_ostream &O) {
454 if (Imm == 0x3F80)
455 O << "1.0";
456 else if (Imm == 0xBF80)
457 O << "-1.0";
458 else if (Imm == 0x3F00)
459 O << "0.5";
460 else if (Imm == 0xBF00)
461 O << "-0.5";
462 else if (Imm == 0x4000)
463 O << "2.0";
464 else if (Imm == 0xC000)
465 O << "-2.0";
466 else if (Imm == 0x4080)
467 O << "4.0";
468 else if (Imm == 0xC080)
469 O << "-4.0";
470 else if (Imm == 0x3E22 && STI.hasFeature(AMDGPU::FeatureInv2PiInlineImm))
471 O << "0.15915494";
472 else
473 return false;
474
475 return true;
476 }
477
printImmediateBF16(uint32_t Imm,const MCSubtargetInfo & STI,raw_ostream & O)478 void AMDGPUInstPrinter::printImmediateBF16(uint32_t Imm,
479 const MCSubtargetInfo &STI,
480 raw_ostream &O) {
481 int16_t SImm = static_cast<int16_t>(Imm);
482 if (isInlinableIntLiteral(SImm)) {
483 O << SImm;
484 return;
485 }
486
487 if (printImmediateBFloat16(static_cast<uint16_t>(Imm), STI, O))
488 return;
489
490 O << formatHex(static_cast<uint64_t>(Imm));
491 }
492
printImmediateF16(uint32_t Imm,const MCSubtargetInfo & STI,raw_ostream & O)493 void AMDGPUInstPrinter::printImmediateF16(uint32_t Imm,
494 const MCSubtargetInfo &STI,
495 raw_ostream &O) {
496 int16_t SImm = static_cast<int16_t>(Imm);
497 if (isInlinableIntLiteral(SImm)) {
498 O << SImm;
499 return;
500 }
501
502 uint16_t HImm = static_cast<uint16_t>(Imm);
503 if (printImmediateFP16(HImm, STI, O))
504 return;
505
506 uint64_t Imm16 = static_cast<uint16_t>(Imm);
507 O << formatHex(Imm16);
508 }
509
printImmediateV216(uint32_t Imm,uint8_t OpType,const MCSubtargetInfo & STI,raw_ostream & O)510 void AMDGPUInstPrinter::printImmediateV216(uint32_t Imm, uint8_t OpType,
511 const MCSubtargetInfo &STI,
512 raw_ostream &O) {
513 int32_t SImm = static_cast<int32_t>(Imm);
514 if (isInlinableIntLiteral(SImm)) {
515 O << SImm;
516 return;
517 }
518
519 switch (OpType) {
520 case AMDGPU::OPERAND_REG_IMM_V2INT16:
521 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
522 if (printImmediateFloat32(Imm, STI, O))
523 return;
524 break;
525 case AMDGPU::OPERAND_REG_IMM_V2FP16:
526 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
527 if (isUInt<16>(Imm) &&
528 printImmediateFP16(static_cast<uint16_t>(Imm), STI, O))
529 return;
530 break;
531 case AMDGPU::OPERAND_REG_IMM_V2BF16:
532 case AMDGPU::OPERAND_REG_INLINE_C_V2BF16:
533 if (isUInt<16>(Imm) &&
534 printImmediateBFloat16(static_cast<uint16_t>(Imm), STI, O))
535 return;
536 break;
537 default:
538 llvm_unreachable("bad operand type");
539 }
540
541 O << formatHex(static_cast<uint64_t>(Imm));
542 }
543
printImmediateFloat32(uint32_t Imm,const MCSubtargetInfo & STI,raw_ostream & O)544 bool AMDGPUInstPrinter::printImmediateFloat32(uint32_t Imm,
545 const MCSubtargetInfo &STI,
546 raw_ostream &O) {
547 if (Imm == llvm::bit_cast<uint32_t>(0.0f))
548 O << "0.0";
549 else if (Imm == llvm::bit_cast<uint32_t>(1.0f))
550 O << "1.0";
551 else if (Imm == llvm::bit_cast<uint32_t>(-1.0f))
552 O << "-1.0";
553 else if (Imm == llvm::bit_cast<uint32_t>(0.5f))
554 O << "0.5";
555 else if (Imm == llvm::bit_cast<uint32_t>(-0.5f))
556 O << "-0.5";
557 else if (Imm == llvm::bit_cast<uint32_t>(2.0f))
558 O << "2.0";
559 else if (Imm == llvm::bit_cast<uint32_t>(-2.0f))
560 O << "-2.0";
561 else if (Imm == llvm::bit_cast<uint32_t>(4.0f))
562 O << "4.0";
563 else if (Imm == llvm::bit_cast<uint32_t>(-4.0f))
564 O << "-4.0";
565 else if (Imm == 0x3e22f983 &&
566 STI.hasFeature(AMDGPU::FeatureInv2PiInlineImm))
567 O << "0.15915494";
568 else
569 return false;
570
571 return true;
572 }
573
printImmediate32(uint32_t Imm,const MCSubtargetInfo & STI,raw_ostream & O)574 void AMDGPUInstPrinter::printImmediate32(uint32_t Imm,
575 const MCSubtargetInfo &STI,
576 raw_ostream &O) {
577 int32_t SImm = static_cast<int32_t>(Imm);
578 if (isInlinableIntLiteral(SImm)) {
579 O << SImm;
580 return;
581 }
582
583 if (printImmediateFloat32(Imm, STI, O))
584 return;
585
586 O << formatHex(static_cast<uint64_t>(Imm));
587 }
588
printImmediate64(uint64_t Imm,const MCSubtargetInfo & STI,raw_ostream & O,bool IsFP)589 void AMDGPUInstPrinter::printImmediate64(uint64_t Imm,
590 const MCSubtargetInfo &STI,
591 raw_ostream &O, bool IsFP) {
592 int64_t SImm = static_cast<int64_t>(Imm);
593 if (SImm >= -16 && SImm <= 64) {
594 O << SImm;
595 return;
596 }
597
598 if (Imm == llvm::bit_cast<uint64_t>(0.0))
599 O << "0.0";
600 else if (Imm == llvm::bit_cast<uint64_t>(1.0))
601 O << "1.0";
602 else if (Imm == llvm::bit_cast<uint64_t>(-1.0))
603 O << "-1.0";
604 else if (Imm == llvm::bit_cast<uint64_t>(0.5))
605 O << "0.5";
606 else if (Imm == llvm::bit_cast<uint64_t>(-0.5))
607 O << "-0.5";
608 else if (Imm == llvm::bit_cast<uint64_t>(2.0))
609 O << "2.0";
610 else if (Imm == llvm::bit_cast<uint64_t>(-2.0))
611 O << "-2.0";
612 else if (Imm == llvm::bit_cast<uint64_t>(4.0))
613 O << "4.0";
614 else if (Imm == llvm::bit_cast<uint64_t>(-4.0))
615 O << "-4.0";
616 else if (Imm == 0x3fc45f306dc9c882 &&
617 STI.hasFeature(AMDGPU::FeatureInv2PiInlineImm))
618 O << "0.15915494309189532";
619 else {
620 // This part needs to align with AMDGPUOperand::addLiteralImmOperand.
621 if (IsFP) {
622 if (STI.hasFeature(AMDGPU::Feature64BitLiterals) && Lo_32(Imm))
623 O << "lit64(" << formatHex(static_cast<uint64_t>(Imm)) << ')';
624 else
625 O << formatHex(static_cast<uint64_t>(Hi_32(Imm)));
626 return;
627 }
628
629 if (STI.hasFeature(AMDGPU::Feature64BitLiterals) &&
630 (!isInt<32>(Imm) || !isUInt<32>(Imm)))
631 O << "lit64(" << formatHex(static_cast<uint64_t>(Imm)) << ')';
632 else
633 O << formatHex(static_cast<uint64_t>(Imm));
634 }
635 }
636
printBLGP(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)637 void AMDGPUInstPrinter::printBLGP(const MCInst *MI, unsigned OpNo,
638 const MCSubtargetInfo &STI,
639 raw_ostream &O) {
640 unsigned Imm = MI->getOperand(OpNo).getImm();
641 if (!Imm)
642 return;
643
644 if (AMDGPU::isGFX940(STI)) {
645 switch (MI->getOpcode()) {
646 case AMDGPU::V_MFMA_F64_16X16X4F64_gfx940_acd:
647 case AMDGPU::V_MFMA_F64_16X16X4F64_gfx940_vcd:
648 case AMDGPU::V_MFMA_F64_4X4X4F64_gfx940_acd:
649 case AMDGPU::V_MFMA_F64_4X4X4F64_gfx940_vcd:
650 O << " neg:[" << (Imm & 1) << ',' << ((Imm >> 1) & 1) << ','
651 << ((Imm >> 2) & 1) << ']';
652 return;
653 }
654 }
655
656 O << " blgp:" << Imm;
657 }
658
printDefaultVccOperand(bool FirstOperand,const MCSubtargetInfo & STI,raw_ostream & O)659 void AMDGPUInstPrinter::printDefaultVccOperand(bool FirstOperand,
660 const MCSubtargetInfo &STI,
661 raw_ostream &O) {
662 if (!FirstOperand)
663 O << ", ";
664 printRegOperand(STI.hasFeature(AMDGPU::FeatureWavefrontSize32)
665 ? AMDGPU::VCC_LO
666 : AMDGPU::VCC,
667 O, MRI);
668 if (FirstOperand)
669 O << ", ";
670 }
671
needsImpliedVcc(const MCInstrDesc & Desc,unsigned OpNo) const672 bool AMDGPUInstPrinter::needsImpliedVcc(const MCInstrDesc &Desc,
673 unsigned OpNo) const {
674 return OpNo == 0 && (Desc.TSFlags & SIInstrFlags::DPP) &&
675 (Desc.TSFlags & SIInstrFlags::VOPC) &&
676 !isVOPCAsmOnly(Desc.getOpcode()) &&
677 (Desc.hasImplicitDefOfPhysReg(AMDGPU::VCC) ||
678 Desc.hasImplicitDefOfPhysReg(AMDGPU::VCC_LO));
679 }
680
681 // Print default vcc/vcc_lo operand of VOPC.
printOperand(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)682 void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
683 const MCSubtargetInfo &STI,
684 raw_ostream &O) {
685 unsigned Opc = MI->getOpcode();
686 const MCInstrDesc &Desc = MII.get(Opc);
687 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers);
688 // 0, 1 and 2 are the first printed operands in different cases
689 // If there are printed modifiers, printOperandAndFPInputMods or
690 // printOperandAndIntInputMods will be called instead
691 if ((OpNo == 0 ||
692 (OpNo == 1 && (Desc.TSFlags & SIInstrFlags::DPP) && ModIdx != -1)) &&
693 (Desc.TSFlags & SIInstrFlags::VOPC) && !isVOPCAsmOnly(Desc.getOpcode()) &&
694 (Desc.hasImplicitDefOfPhysReg(AMDGPU::VCC) ||
695 Desc.hasImplicitDefOfPhysReg(AMDGPU::VCC_LO)))
696 printDefaultVccOperand(true, STI, O);
697
698 printRegularOperand(MI, OpNo, STI, O);
699 }
700
701 // Print operands after vcc or modifier handling.
printRegularOperand(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)702 void AMDGPUInstPrinter::printRegularOperand(const MCInst *MI, unsigned OpNo,
703 const MCSubtargetInfo &STI,
704 raw_ostream &O) {
705 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
706
707 if (OpNo >= MI->getNumOperands()) {
708 O << "/*Missing OP" << OpNo << "*/";
709 return;
710 }
711
712 const MCOperand &Op = MI->getOperand(OpNo);
713 if (Op.isReg()) {
714 printRegOperand(Op.getReg(), O, MRI);
715
716 // Check if operand register class contains register used.
717 // Intention: print disassembler message when invalid code is decoded,
718 // for example sgpr register used in VReg or VISrc(VReg or imm) operand.
719 int RCID = Desc.operands()[OpNo].RegClass;
720 if (RCID != -1) {
721 const MCRegisterClass RC = MRI.getRegClass(RCID);
722 auto Reg = mc2PseudoReg(Op.getReg());
723 if (!RC.contains(Reg) && !isInlineValue(Reg)) {
724 O << "/*Invalid register, operand has \'" << MRI.getRegClassName(&RC)
725 << "\' register class*/";
726 }
727 }
728 } else if (Op.isImm()) {
729 const uint8_t OpTy = Desc.operands()[OpNo].OperandType;
730 switch (OpTy) {
731 case AMDGPU::OPERAND_REG_IMM_INT32:
732 case AMDGPU::OPERAND_REG_IMM_FP32:
733 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
734 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
735 case AMDGPU::OPERAND_REG_INLINE_AC_INT32:
736 case AMDGPU::OPERAND_REG_INLINE_AC_FP32:
737 case AMDGPU::OPERAND_REG_IMM_V2INT32:
738 case AMDGPU::OPERAND_REG_IMM_V2FP32:
739 case MCOI::OPERAND_IMMEDIATE:
740 case AMDGPU::OPERAND_INLINE_SPLIT_BARRIER_INT32:
741 printImmediate32(Op.getImm(), STI, O);
742 break;
743 case AMDGPU::OPERAND_REG_IMM_INT64:
744 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
745 printImmediate64(Op.getImm(), STI, O, false);
746 break;
747 case AMDGPU::OPERAND_REG_IMM_FP64:
748 case AMDGPU::OPERAND_REG_INLINE_C_FP64:
749 case AMDGPU::OPERAND_REG_INLINE_AC_FP64:
750 printImmediate64(Op.getImm(), STI, O, true);
751 break;
752 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
753 case AMDGPU::OPERAND_REG_IMM_INT16:
754 printImmediateInt16(Op.getImm(), STI, O);
755 break;
756 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
757 case AMDGPU::OPERAND_REG_IMM_FP16:
758 printImmediateF16(Op.getImm(), STI, O);
759 break;
760 case AMDGPU::OPERAND_REG_INLINE_C_BF16:
761 case AMDGPU::OPERAND_REG_IMM_BF16:
762 printImmediateBF16(Op.getImm(), STI, O);
763 break;
764 case AMDGPU::OPERAND_REG_IMM_V2INT16:
765 case AMDGPU::OPERAND_REG_IMM_V2BF16:
766 case AMDGPU::OPERAND_REG_IMM_V2FP16:
767 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
768 case AMDGPU::OPERAND_REG_INLINE_C_V2BF16:
769 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
770 printImmediateV216(Op.getImm(), OpTy, STI, O);
771 break;
772 case MCOI::OPERAND_UNKNOWN:
773 case MCOI::OPERAND_PCREL:
774 O << formatDec(Op.getImm());
775 break;
776 case MCOI::OPERAND_REGISTER:
777 // Disassembler does not fail when operand should not allow immediate
778 // operands but decodes them into 32bit immediate operand.
779 printImmediate32(Op.getImm(), STI, O);
780 O << "/*Invalid immediate*/";
781 break;
782 default:
783 // We hit this for the immediate instruction bits that don't yet have a
784 // custom printer.
785 llvm_unreachable("unexpected immediate operand type");
786 }
787 } else if (Op.isDFPImm()) {
788 double Value = bit_cast<double>(Op.getDFPImm());
789 // We special case 0.0 because otherwise it will be printed as an integer.
790 if (Value == 0.0)
791 O << "0.0";
792 else {
793 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
794 int RCID = Desc.operands()[OpNo].RegClass;
795 unsigned RCBits = AMDGPU::getRegBitWidth(MRI.getRegClass(RCID));
796 if (RCBits == 32)
797 printImmediate32(llvm::bit_cast<uint32_t>((float)Value), STI, O);
798 else if (RCBits == 64)
799 printImmediate64(llvm::bit_cast<uint64_t>(Value), STI, O, true);
800 else
801 llvm_unreachable("Invalid register class size");
802 }
803 } else if (Op.isExpr()) {
804 const MCExpr *Exp = Op.getExpr();
805 MAI.printExpr(O, *Exp);
806 } else {
807 O << "/*INV_OP*/";
808 }
809
810 // Print default vcc/vcc_lo operand of v_cndmask_b32_e32.
811 switch (MI->getOpcode()) {
812 default: break;
813
814 case AMDGPU::V_CNDMASK_B32_e32_gfx10:
815 case AMDGPU::V_ADD_CO_CI_U32_e32_gfx10:
816 case AMDGPU::V_SUB_CO_CI_U32_e32_gfx10:
817 case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx10:
818 case AMDGPU::V_ADD_CO_CI_U32_dpp_gfx10:
819 case AMDGPU::V_SUB_CO_CI_U32_dpp_gfx10:
820 case AMDGPU::V_SUBREV_CO_CI_U32_dpp_gfx10:
821 case AMDGPU::V_CNDMASK_B32_dpp8_gfx10:
822 case AMDGPU::V_ADD_CO_CI_U32_dpp8_gfx10:
823 case AMDGPU::V_SUB_CO_CI_U32_dpp8_gfx10:
824 case AMDGPU::V_SUBREV_CO_CI_U32_dpp8_gfx10:
825 case AMDGPU::V_CNDMASK_B32_e32_gfx11:
826 case AMDGPU::V_ADD_CO_CI_U32_e32_gfx11:
827 case AMDGPU::V_SUB_CO_CI_U32_e32_gfx11:
828 case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx11:
829 case AMDGPU::V_ADD_CO_CI_U32_dpp_gfx11:
830 case AMDGPU::V_SUB_CO_CI_U32_dpp_gfx11:
831 case AMDGPU::V_SUBREV_CO_CI_U32_dpp_gfx11:
832 case AMDGPU::V_CNDMASK_B32_dpp8_gfx11:
833 case AMDGPU::V_ADD_CO_CI_U32_dpp8_gfx11:
834 case AMDGPU::V_SUB_CO_CI_U32_dpp8_gfx11:
835 case AMDGPU::V_SUBREV_CO_CI_U32_dpp8_gfx11:
836 case AMDGPU::V_CNDMASK_B32_e32_gfx12:
837 case AMDGPU::V_ADD_CO_CI_U32_e32_gfx12:
838 case AMDGPU::V_SUB_CO_CI_U32_e32_gfx12:
839 case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx12:
840 case AMDGPU::V_CNDMASK_B32_dpp_gfx12:
841 case AMDGPU::V_ADD_CO_CI_U32_dpp_gfx12:
842 case AMDGPU::V_SUB_CO_CI_U32_dpp_gfx12:
843 case AMDGPU::V_SUBREV_CO_CI_U32_dpp_gfx12:
844 case AMDGPU::V_CNDMASK_B32_dpp8_gfx12:
845 case AMDGPU::V_ADD_CO_CI_U32_dpp8_gfx12:
846 case AMDGPU::V_SUB_CO_CI_U32_dpp8_gfx12:
847 case AMDGPU::V_SUBREV_CO_CI_U32_dpp8_gfx12:
848
849 case AMDGPU::V_CNDMASK_B32_e32_gfx6_gfx7:
850 case AMDGPU::V_CNDMASK_B32_e32_vi:
851 if ((int)OpNo == AMDGPU::getNamedOperandIdx(MI->getOpcode(),
852 AMDGPU::OpName::src1))
853 printDefaultVccOperand(OpNo == 0, STI, O);
854 break;
855 }
856
857 if (Desc.TSFlags & SIInstrFlags::MTBUF) {
858 int SOffsetIdx =
859 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::soffset);
860 assert(SOffsetIdx != -1);
861 if ((int)OpNo == SOffsetIdx)
862 printSymbolicFormat(MI, STI, O);
863 }
864 }
865
printOperandAndFPInputMods(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)866 void AMDGPUInstPrinter::printOperandAndFPInputMods(const MCInst *MI,
867 unsigned OpNo,
868 const MCSubtargetInfo &STI,
869 raw_ostream &O) {
870 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
871 if (needsImpliedVcc(Desc, OpNo))
872 printDefaultVccOperand(true, STI, O);
873
874 unsigned InputModifiers = MI->getOperand(OpNo).getImm();
875
876 // Use 'neg(...)' instead of '-' to avoid ambiguity.
877 // This is important for integer literals because
878 // -1 is not the same value as neg(1).
879 bool NegMnemo = false;
880
881 if (InputModifiers & SISrcMods::NEG) {
882 if (OpNo + 1 < MI->getNumOperands() &&
883 (InputModifiers & SISrcMods::ABS) == 0) {
884 const MCOperand &Op = MI->getOperand(OpNo + 1);
885 NegMnemo = Op.isImm() || Op.isDFPImm();
886 }
887 if (NegMnemo) {
888 O << "neg(";
889 } else {
890 O << '-';
891 }
892 }
893
894 if (InputModifiers & SISrcMods::ABS)
895 O << '|';
896 printRegularOperand(MI, OpNo + 1, STI, O);
897 if (InputModifiers & SISrcMods::ABS)
898 O << '|';
899
900 if (NegMnemo) {
901 O << ')';
902 }
903
904 // Print default vcc/vcc_lo operand of VOP2b.
905 switch (MI->getOpcode()) {
906 default:
907 break;
908
909 case AMDGPU::V_CNDMASK_B32_sdwa_gfx10:
910 case AMDGPU::V_CNDMASK_B32_dpp_gfx10:
911 case AMDGPU::V_CNDMASK_B32_dpp_gfx11:
912 if ((int)OpNo + 1 ==
913 AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::src1))
914 printDefaultVccOperand(OpNo == 0, STI, O);
915 break;
916 }
917 }
918
printOperandAndIntInputMods(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)919 void AMDGPUInstPrinter::printOperandAndIntInputMods(const MCInst *MI,
920 unsigned OpNo,
921 const MCSubtargetInfo &STI,
922 raw_ostream &O) {
923 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
924 if (needsImpliedVcc(Desc, OpNo))
925 printDefaultVccOperand(true, STI, O);
926
927 unsigned InputModifiers = MI->getOperand(OpNo).getImm();
928 if (InputModifiers & SISrcMods::SEXT)
929 O << "sext(";
930 printRegularOperand(MI, OpNo + 1, STI, O);
931 if (InputModifiers & SISrcMods::SEXT)
932 O << ')';
933
934 // Print default vcc/vcc_lo operand of VOP2b.
935 switch (MI->getOpcode()) {
936 default: break;
937
938 case AMDGPU::V_ADD_CO_CI_U32_sdwa_gfx10:
939 case AMDGPU::V_SUB_CO_CI_U32_sdwa_gfx10:
940 case AMDGPU::V_SUBREV_CO_CI_U32_sdwa_gfx10:
941 if ((int)OpNo + 1 == AMDGPU::getNamedOperandIdx(MI->getOpcode(),
942 AMDGPU::OpName::src1))
943 printDefaultVccOperand(OpNo == 0, STI, O);
944 break;
945 }
946 }
947
printDPP8(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)948 void AMDGPUInstPrinter::printDPP8(const MCInst *MI, unsigned OpNo,
949 const MCSubtargetInfo &STI,
950 raw_ostream &O) {
951 if (!AMDGPU::isGFX10Plus(STI))
952 llvm_unreachable("dpp8 is not supported on ASICs earlier than GFX10");
953
954 unsigned Imm = MI->getOperand(OpNo).getImm();
955 O << "dpp8:[" << formatDec(Imm & 0x7);
956 for (size_t i = 1; i < 8; ++i) {
957 O << ',' << formatDec((Imm >> (3 * i)) & 0x7);
958 }
959 O << ']';
960 }
961
printDPPCtrl(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)962 void AMDGPUInstPrinter::printDPPCtrl(const MCInst *MI, unsigned OpNo,
963 const MCSubtargetInfo &STI,
964 raw_ostream &O) {
965 using namespace AMDGPU::DPP;
966
967 unsigned Imm = MI->getOperand(OpNo).getImm();
968 const MCInstrDesc &Desc = MII.get(MI->getOpcode());
969
970 if (!AMDGPU::isLegalDPALU_DPPControl(Imm) && AMDGPU::isDPALU_DPP(Desc)) {
971 O << " /* DP ALU dpp only supports row_newbcast */";
972 return;
973 }
974 if (Imm <= DppCtrl::QUAD_PERM_LAST) {
975 O << "quad_perm:[";
976 O << formatDec(Imm & 0x3) << ',';
977 O << formatDec((Imm & 0xc) >> 2) << ',';
978 O << formatDec((Imm & 0x30) >> 4) << ',';
979 O << formatDec((Imm & 0xc0) >> 6) << ']';
980 } else if ((Imm >= DppCtrl::ROW_SHL_FIRST) &&
981 (Imm <= DppCtrl::ROW_SHL_LAST)) {
982 O << "row_shl:" << formatDec(Imm - DppCtrl::ROW_SHL0);
983 } else if ((Imm >= DppCtrl::ROW_SHR_FIRST) &&
984 (Imm <= DppCtrl::ROW_SHR_LAST)) {
985 O << "row_shr:" << formatDec(Imm - DppCtrl::ROW_SHR0);
986 } else if ((Imm >= DppCtrl::ROW_ROR_FIRST) &&
987 (Imm <= DppCtrl::ROW_ROR_LAST)) {
988 O << "row_ror:" << formatDec(Imm - DppCtrl::ROW_ROR0);
989 } else if (Imm == DppCtrl::WAVE_SHL1) {
990 if (AMDGPU::isGFX10Plus(STI)) {
991 O << "/* wave_shl is not supported starting from GFX10 */";
992 return;
993 }
994 O << "wave_shl:1";
995 } else if (Imm == DppCtrl::WAVE_ROL1) {
996 if (AMDGPU::isGFX10Plus(STI)) {
997 O << "/* wave_rol is not supported starting from GFX10 */";
998 return;
999 }
1000 O << "wave_rol:1";
1001 } else if (Imm == DppCtrl::WAVE_SHR1) {
1002 if (AMDGPU::isGFX10Plus(STI)) {
1003 O << "/* wave_shr is not supported starting from GFX10 */";
1004 return;
1005 }
1006 O << "wave_shr:1";
1007 } else if (Imm == DppCtrl::WAVE_ROR1) {
1008 if (AMDGPU::isGFX10Plus(STI)) {
1009 O << "/* wave_ror is not supported starting from GFX10 */";
1010 return;
1011 }
1012 O << "wave_ror:1";
1013 } else if (Imm == DppCtrl::ROW_MIRROR) {
1014 O << "row_mirror";
1015 } else if (Imm == DppCtrl::ROW_HALF_MIRROR) {
1016 O << "row_half_mirror";
1017 } else if (Imm == DppCtrl::BCAST15) {
1018 if (AMDGPU::isGFX10Plus(STI)) {
1019 O << "/* row_bcast is not supported starting from GFX10 */";
1020 return;
1021 }
1022 O << "row_bcast:15";
1023 } else if (Imm == DppCtrl::BCAST31) {
1024 if (AMDGPU::isGFX10Plus(STI)) {
1025 O << "/* row_bcast is not supported starting from GFX10 */";
1026 return;
1027 }
1028 O << "row_bcast:31";
1029 } else if ((Imm >= DppCtrl::ROW_SHARE_FIRST) &&
1030 (Imm <= DppCtrl::ROW_SHARE_LAST)) {
1031 if (AMDGPU::isGFX90A(STI)) {
1032 O << "row_newbcast:";
1033 } else if (AMDGPU::isGFX10Plus(STI)) {
1034 O << "row_share:";
1035 } else {
1036 O << " /* row_newbcast/row_share is not supported on ASICs earlier "
1037 "than GFX90A/GFX10 */";
1038 return;
1039 }
1040 O << formatDec(Imm - DppCtrl::ROW_SHARE_FIRST);
1041 } else if ((Imm >= DppCtrl::ROW_XMASK_FIRST) &&
1042 (Imm <= DppCtrl::ROW_XMASK_LAST)) {
1043 if (!AMDGPU::isGFX10Plus(STI)) {
1044 O << "/* row_xmask is not supported on ASICs earlier than GFX10 */";
1045 return;
1046 }
1047 O << "row_xmask:" << formatDec(Imm - DppCtrl::ROW_XMASK_FIRST);
1048 } else {
1049 O << "/* Invalid dpp_ctrl value */";
1050 }
1051 }
1052
printDppBoundCtrl(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1053 void AMDGPUInstPrinter::printDppBoundCtrl(const MCInst *MI, unsigned OpNo,
1054 const MCSubtargetInfo &STI,
1055 raw_ostream &O) {
1056 unsigned Imm = MI->getOperand(OpNo).getImm();
1057 if (Imm) {
1058 O << " bound_ctrl:1";
1059 }
1060 }
1061
printDppFI(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1062 void AMDGPUInstPrinter::printDppFI(const MCInst *MI, unsigned OpNo,
1063 const MCSubtargetInfo &STI, raw_ostream &O) {
1064 using namespace llvm::AMDGPU::DPP;
1065 unsigned Imm = MI->getOperand(OpNo).getImm();
1066 if (Imm == DPP_FI_1 || Imm == DPP8_FI_1) {
1067 O << " fi:1";
1068 }
1069 }
1070
printSDWASel(const MCInst * MI,unsigned OpNo,raw_ostream & O)1071 void AMDGPUInstPrinter::printSDWASel(const MCInst *MI, unsigned OpNo,
1072 raw_ostream &O) {
1073 using namespace llvm::AMDGPU::SDWA;
1074
1075 unsigned Imm = MI->getOperand(OpNo).getImm();
1076 switch (Imm) {
1077 case SdwaSel::BYTE_0: O << "BYTE_0"; break;
1078 case SdwaSel::BYTE_1: O << "BYTE_1"; break;
1079 case SdwaSel::BYTE_2: O << "BYTE_2"; break;
1080 case SdwaSel::BYTE_3: O << "BYTE_3"; break;
1081 case SdwaSel::WORD_0: O << "WORD_0"; break;
1082 case SdwaSel::WORD_1: O << "WORD_1"; break;
1083 case SdwaSel::DWORD: O << "DWORD"; break;
1084 default: llvm_unreachable("Invalid SDWA data select operand");
1085 }
1086 }
1087
printSDWADstSel(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1088 void AMDGPUInstPrinter::printSDWADstSel(const MCInst *MI, unsigned OpNo,
1089 const MCSubtargetInfo &STI,
1090 raw_ostream &O) {
1091 O << "dst_sel:";
1092 printSDWASel(MI, OpNo, O);
1093 }
1094
printSDWASrc0Sel(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1095 void AMDGPUInstPrinter::printSDWASrc0Sel(const MCInst *MI, unsigned OpNo,
1096 const MCSubtargetInfo &STI,
1097 raw_ostream &O) {
1098 O << "src0_sel:";
1099 printSDWASel(MI, OpNo, O);
1100 }
1101
printSDWASrc1Sel(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1102 void AMDGPUInstPrinter::printSDWASrc1Sel(const MCInst *MI, unsigned OpNo,
1103 const MCSubtargetInfo &STI,
1104 raw_ostream &O) {
1105 O << "src1_sel:";
1106 printSDWASel(MI, OpNo, O);
1107 }
1108
printSDWADstUnused(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1109 void AMDGPUInstPrinter::printSDWADstUnused(const MCInst *MI, unsigned OpNo,
1110 const MCSubtargetInfo &STI,
1111 raw_ostream &O) {
1112 using namespace llvm::AMDGPU::SDWA;
1113
1114 O << "dst_unused:";
1115 unsigned Imm = MI->getOperand(OpNo).getImm();
1116 switch (Imm) {
1117 case DstUnused::UNUSED_PAD: O << "UNUSED_PAD"; break;
1118 case DstUnused::UNUSED_SEXT: O << "UNUSED_SEXT"; break;
1119 case DstUnused::UNUSED_PRESERVE: O << "UNUSED_PRESERVE"; break;
1120 default: llvm_unreachable("Invalid SDWA dest_unused operand");
1121 }
1122 }
1123
printExpSrcN(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O,unsigned N)1124 void AMDGPUInstPrinter::printExpSrcN(const MCInst *MI, unsigned OpNo,
1125 const MCSubtargetInfo &STI, raw_ostream &O,
1126 unsigned N) {
1127 unsigned Opc = MI->getOpcode();
1128 int EnIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::en);
1129 unsigned En = MI->getOperand(EnIdx).getImm();
1130
1131 int ComprIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::compr);
1132
1133 // If compr is set, print as src0, src0, src1, src1
1134 if (MI->getOperand(ComprIdx).getImm())
1135 OpNo = OpNo - N + N / 2;
1136
1137 if (En & (1 << N))
1138 printRegOperand(MI->getOperand(OpNo).getReg(), O, MRI);
1139 else
1140 O << "off";
1141 }
1142
printExpSrc0(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1143 void AMDGPUInstPrinter::printExpSrc0(const MCInst *MI, unsigned OpNo,
1144 const MCSubtargetInfo &STI,
1145 raw_ostream &O) {
1146 printExpSrcN(MI, OpNo, STI, O, 0);
1147 }
1148
printExpSrc1(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1149 void AMDGPUInstPrinter::printExpSrc1(const MCInst *MI, unsigned OpNo,
1150 const MCSubtargetInfo &STI,
1151 raw_ostream &O) {
1152 printExpSrcN(MI, OpNo, STI, O, 1);
1153 }
1154
printExpSrc2(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1155 void AMDGPUInstPrinter::printExpSrc2(const MCInst *MI, unsigned OpNo,
1156 const MCSubtargetInfo &STI,
1157 raw_ostream &O) {
1158 printExpSrcN(MI, OpNo, STI, O, 2);
1159 }
1160
printExpSrc3(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1161 void AMDGPUInstPrinter::printExpSrc3(const MCInst *MI, unsigned OpNo,
1162 const MCSubtargetInfo &STI,
1163 raw_ostream &O) {
1164 printExpSrcN(MI, OpNo, STI, O, 3);
1165 }
1166
printExpTgt(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1167 void AMDGPUInstPrinter::printExpTgt(const MCInst *MI, unsigned OpNo,
1168 const MCSubtargetInfo &STI,
1169 raw_ostream &O) {
1170 using namespace llvm::AMDGPU::Exp;
1171
1172 // This is really a 6 bit field.
1173 unsigned Id = MI->getOperand(OpNo).getImm() & ((1 << 6) - 1);
1174
1175 int Index;
1176 StringRef TgtName;
1177 if (getTgtName(Id, TgtName, Index) && isSupportedTgtId(Id, STI)) {
1178 O << ' ' << TgtName;
1179 if (Index >= 0)
1180 O << Index;
1181 } else {
1182 O << " invalid_target_" << Id;
1183 }
1184 }
1185
allOpsDefaultValue(const int * Ops,int NumOps,int Mod,bool IsPacked,bool HasDstSel)1186 static bool allOpsDefaultValue(const int* Ops, int NumOps, int Mod,
1187 bool IsPacked, bool HasDstSel) {
1188 int DefaultValue = IsPacked && (Mod == SISrcMods::OP_SEL_1);
1189
1190 for (int I = 0; I < NumOps; ++I) {
1191 if (!!(Ops[I] & Mod) != DefaultValue)
1192 return false;
1193 }
1194
1195 if (HasDstSel && (Ops[0] & SISrcMods::DST_OP_SEL) != 0)
1196 return false;
1197
1198 return true;
1199 }
1200
printPackedModifier(const MCInst * MI,StringRef Name,unsigned Mod,raw_ostream & O)1201 void AMDGPUInstPrinter::printPackedModifier(const MCInst *MI,
1202 StringRef Name,
1203 unsigned Mod,
1204 raw_ostream &O) {
1205 unsigned Opc = MI->getOpcode();
1206 int NumOps = 0;
1207 int Ops[3];
1208
1209 std::pair<AMDGPU::OpName, AMDGPU::OpName> MOps[] = {
1210 {AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src0},
1211 {AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src1},
1212 {AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::src2}};
1213 int DefaultValue = (Mod == SISrcMods::OP_SEL_1);
1214
1215 for (auto [SrcMod, Src] : MOps) {
1216 if (!AMDGPU::hasNamedOperand(Opc, Src))
1217 break;
1218
1219 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, SrcMod);
1220 Ops[NumOps++] =
1221 (ModIdx != -1) ? MI->getOperand(ModIdx).getImm() : DefaultValue;
1222 }
1223
1224 const bool HasDst =
1225 (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst) != -1) ||
1226 (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::sdst) != -1);
1227
1228 // Print three values of neg/opsel for wmma instructions (prints 0 when there
1229 // is no src_modifier operand instead of not printing anything).
1230 if (MII.get(MI->getOpcode()).TSFlags & SIInstrFlags::IsSWMMAC ||
1231 MII.get(MI->getOpcode()).TSFlags & SIInstrFlags::IsWMMA) {
1232 NumOps = 0;
1233 int DefaultValue = Mod == SISrcMods::OP_SEL_1;
1234 for (AMDGPU::OpName OpName :
1235 {AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
1236 AMDGPU::OpName::src2_modifiers}) {
1237 int Idx = AMDGPU::getNamedOperandIdx(Opc, OpName);
1238 if (Idx != -1)
1239 Ops[NumOps++] = MI->getOperand(Idx).getImm();
1240 else
1241 Ops[NumOps++] = DefaultValue;
1242 }
1243 }
1244
1245 const bool HasDstSel =
1246 HasDst && NumOps > 0 && Mod == SISrcMods::OP_SEL_0 &&
1247 MII.get(MI->getOpcode()).TSFlags & SIInstrFlags::VOP3_OPSEL;
1248
1249 const bool IsPacked =
1250 MII.get(MI->getOpcode()).TSFlags & SIInstrFlags::IsPacked;
1251
1252 if (allOpsDefaultValue(Ops, NumOps, Mod, IsPacked, HasDstSel))
1253 return;
1254
1255 O << Name;
1256 for (int I = 0; I < NumOps; ++I) {
1257 if (I != 0)
1258 O << ',';
1259
1260 O << !!(Ops[I] & Mod);
1261 }
1262
1263 if (HasDstSel) {
1264 O << ',' << !!(Ops[0] & SISrcMods::DST_OP_SEL);
1265 }
1266
1267 O << ']';
1268 }
1269
printOpSel(const MCInst * MI,unsigned,const MCSubtargetInfo & STI,raw_ostream & O)1270 void AMDGPUInstPrinter::printOpSel(const MCInst *MI, unsigned,
1271 const MCSubtargetInfo &STI,
1272 raw_ostream &O) {
1273 unsigned Opc = MI->getOpcode();
1274 if (isCvt_F32_Fp8_Bf8_e64(Opc)) {
1275 auto SrcMod =
1276 AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers);
1277 unsigned Mod = MI->getOperand(SrcMod).getImm();
1278 unsigned Index0 = !!(Mod & SISrcMods::OP_SEL_0);
1279 unsigned Index1 = !!(Mod & SISrcMods::OP_SEL_1);
1280 if (Index0 || Index1)
1281 O << " op_sel:[" << Index0 << ',' << Index1 << ']';
1282 return;
1283 }
1284 if (isPermlane16(Opc)) {
1285 auto FIN = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers);
1286 auto BCN = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1_modifiers);
1287 unsigned FI = !!(MI->getOperand(FIN).getImm() & SISrcMods::OP_SEL_0);
1288 unsigned BC = !!(MI->getOperand(BCN).getImm() & SISrcMods::OP_SEL_0);
1289 if (FI || BC)
1290 O << " op_sel:[" << FI << ',' << BC << ']';
1291 return;
1292 }
1293
1294 printPackedModifier(MI, " op_sel:[", SISrcMods::OP_SEL_0, O);
1295 }
1296
printOpSelHi(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1297 void AMDGPUInstPrinter::printOpSelHi(const MCInst *MI, unsigned OpNo,
1298 const MCSubtargetInfo &STI,
1299 raw_ostream &O) {
1300 printPackedModifier(MI, " op_sel_hi:[", SISrcMods::OP_SEL_1, O);
1301 }
1302
printNegLo(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1303 void AMDGPUInstPrinter::printNegLo(const MCInst *MI, unsigned OpNo,
1304 const MCSubtargetInfo &STI,
1305 raw_ostream &O) {
1306 printPackedModifier(MI, " neg_lo:[", SISrcMods::NEG, O);
1307 }
1308
printNegHi(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1309 void AMDGPUInstPrinter::printNegHi(const MCInst *MI, unsigned OpNo,
1310 const MCSubtargetInfo &STI,
1311 raw_ostream &O) {
1312 printPackedModifier(MI, " neg_hi:[", SISrcMods::NEG_HI, O);
1313 }
1314
printIndexKey8bit(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1315 void AMDGPUInstPrinter::printIndexKey8bit(const MCInst *MI, unsigned OpNo,
1316 const MCSubtargetInfo &STI,
1317 raw_ostream &O) {
1318 auto Imm = MI->getOperand(OpNo).getImm() & 0x7;
1319 if (Imm == 0)
1320 return;
1321
1322 O << " index_key:" << Imm;
1323 }
1324
printIndexKey16bit(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1325 void AMDGPUInstPrinter::printIndexKey16bit(const MCInst *MI, unsigned OpNo,
1326 const MCSubtargetInfo &STI,
1327 raw_ostream &O) {
1328 auto Imm = MI->getOperand(OpNo).getImm() & 0x7;
1329 if (Imm == 0)
1330 return;
1331
1332 O << " index_key:" << Imm;
1333 }
1334
printIndexKey32bit(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1335 void AMDGPUInstPrinter::printIndexKey32bit(const MCInst *MI, unsigned OpNo,
1336 const MCSubtargetInfo &STI,
1337 raw_ostream &O) {
1338 auto Imm = MI->getOperand(OpNo).getImm() & 0x7;
1339 if (Imm == 0)
1340 return;
1341
1342 O << " index_key:" << Imm;
1343 }
1344
printInterpSlot(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1345 void AMDGPUInstPrinter::printInterpSlot(const MCInst *MI, unsigned OpNum,
1346 const MCSubtargetInfo &STI,
1347 raw_ostream &O) {
1348 unsigned Imm = MI->getOperand(OpNum).getImm();
1349 switch (Imm) {
1350 case 0:
1351 O << "p10";
1352 break;
1353 case 1:
1354 O << "p20";
1355 break;
1356 case 2:
1357 O << "p0";
1358 break;
1359 default:
1360 O << "invalid_param_" << Imm;
1361 }
1362 }
1363
printInterpAttr(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1364 void AMDGPUInstPrinter::printInterpAttr(const MCInst *MI, unsigned OpNum,
1365 const MCSubtargetInfo &STI,
1366 raw_ostream &O) {
1367 unsigned Attr = MI->getOperand(OpNum).getImm();
1368 O << "attr" << Attr;
1369 }
1370
printInterpAttrChan(const MCInst * MI,unsigned OpNum,const MCSubtargetInfo & STI,raw_ostream & O)1371 void AMDGPUInstPrinter::printInterpAttrChan(const MCInst *MI, unsigned OpNum,
1372 const MCSubtargetInfo &STI,
1373 raw_ostream &O) {
1374 unsigned Chan = MI->getOperand(OpNum).getImm();
1375 O << '.' << "xyzw"[Chan & 0x3];
1376 }
1377
printGPRIdxMode(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1378 void AMDGPUInstPrinter::printGPRIdxMode(const MCInst *MI, unsigned OpNo,
1379 const MCSubtargetInfo &STI,
1380 raw_ostream &O) {
1381 using namespace llvm::AMDGPU::VGPRIndexMode;
1382 unsigned Val = MI->getOperand(OpNo).getImm();
1383
1384 if ((Val & ~ENABLE_MASK) != 0) {
1385 O << formatHex(static_cast<uint64_t>(Val));
1386 } else {
1387 O << "gpr_idx(";
1388 bool NeedComma = false;
1389 for (unsigned ModeId = ID_MIN; ModeId <= ID_MAX; ++ModeId) {
1390 if (Val & (1 << ModeId)) {
1391 if (NeedComma)
1392 O << ',';
1393 O << IdSymbolic[ModeId];
1394 NeedComma = true;
1395 }
1396 }
1397 O << ')';
1398 }
1399 }
1400
printMemOperand(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1401 void AMDGPUInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
1402 const MCSubtargetInfo &STI,
1403 raw_ostream &O) {
1404 printRegularOperand(MI, OpNo, STI, O);
1405 O << ", ";
1406 printRegularOperand(MI, OpNo + 1, STI, O);
1407 }
1408
printIfSet(const MCInst * MI,unsigned OpNo,raw_ostream & O,StringRef Asm,StringRef Default)1409 void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
1410 raw_ostream &O, StringRef Asm,
1411 StringRef Default) {
1412 const MCOperand &Op = MI->getOperand(OpNo);
1413 assert(Op.isImm());
1414 if (Op.getImm() == 1) {
1415 O << Asm;
1416 } else {
1417 O << Default;
1418 }
1419 }
1420
printIfSet(const MCInst * MI,unsigned OpNo,raw_ostream & O,char Asm)1421 void AMDGPUInstPrinter::printIfSet(const MCInst *MI, unsigned OpNo,
1422 raw_ostream &O, char Asm) {
1423 const MCOperand &Op = MI->getOperand(OpNo);
1424 assert(Op.isImm());
1425 if (Op.getImm() == 1)
1426 O << Asm;
1427 }
1428
printOModSI(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1429 void AMDGPUInstPrinter::printOModSI(const MCInst *MI, unsigned OpNo,
1430 const MCSubtargetInfo &STI,
1431 raw_ostream &O) {
1432 int Imm = MI->getOperand(OpNo).getImm();
1433 if (Imm == SIOutMods::MUL2)
1434 O << " mul:2";
1435 else if (Imm == SIOutMods::MUL4)
1436 O << " mul:4";
1437 else if (Imm == SIOutMods::DIV2)
1438 O << " div:2";
1439 }
1440
printSendMsg(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1441 void AMDGPUInstPrinter::printSendMsg(const MCInst *MI, unsigned OpNo,
1442 const MCSubtargetInfo &STI,
1443 raw_ostream &O) {
1444 using namespace llvm::AMDGPU::SendMsg;
1445
1446 const unsigned Imm16 = MI->getOperand(OpNo).getImm();
1447
1448 uint16_t MsgId;
1449 uint16_t OpId;
1450 uint16_t StreamId;
1451 decodeMsg(Imm16, MsgId, OpId, StreamId, STI);
1452
1453 StringRef MsgName = getMsgName(MsgId, STI);
1454
1455 if (!MsgName.empty() && isValidMsgOp(MsgId, OpId, STI) &&
1456 isValidMsgStream(MsgId, OpId, StreamId, STI)) {
1457 O << "sendmsg(" << MsgName;
1458 if (msgRequiresOp(MsgId, STI)) {
1459 O << ", " << getMsgOpName(MsgId, OpId, STI);
1460 if (msgSupportsStream(MsgId, OpId, STI)) {
1461 O << ", " << StreamId;
1462 }
1463 }
1464 O << ')';
1465 } else if (encodeMsg(MsgId, OpId, StreamId) == Imm16) {
1466 O << "sendmsg(" << MsgId << ", " << OpId << ", " << StreamId << ')';
1467 } else {
1468 O << Imm16; // Unknown imm16 code.
1469 }
1470 }
1471
printSwizzleBitmask(const uint16_t AndMask,const uint16_t OrMask,const uint16_t XorMask,raw_ostream & O)1472 static void printSwizzleBitmask(const uint16_t AndMask,
1473 const uint16_t OrMask,
1474 const uint16_t XorMask,
1475 raw_ostream &O) {
1476 using namespace llvm::AMDGPU::Swizzle;
1477
1478 uint16_t Probe0 = ((0 & AndMask) | OrMask) ^ XorMask;
1479 uint16_t Probe1 = ((BITMASK_MASK & AndMask) | OrMask) ^ XorMask;
1480
1481 O << "\"";
1482
1483 for (unsigned Mask = 1 << (BITMASK_WIDTH - 1); Mask > 0; Mask >>= 1) {
1484 uint16_t p0 = Probe0 & Mask;
1485 uint16_t p1 = Probe1 & Mask;
1486
1487 if (p0 == p1) {
1488 if (p0 == 0) {
1489 O << "0";
1490 } else {
1491 O << "1";
1492 }
1493 } else {
1494 if (p0 == 0) {
1495 O << "p";
1496 } else {
1497 O << "i";
1498 }
1499 }
1500 }
1501
1502 O << "\"";
1503 }
1504
printSwizzle(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1505 void AMDGPUInstPrinter::printSwizzle(const MCInst *MI, unsigned OpNo,
1506 const MCSubtargetInfo &STI,
1507 raw_ostream &O) {
1508 using namespace llvm::AMDGPU::Swizzle;
1509
1510 uint16_t Imm = MI->getOperand(OpNo).getImm();
1511 if (Imm == 0) {
1512 return;
1513 }
1514
1515 O << " offset:";
1516
1517 // Rotate and FFT modes
1518 if (Imm >= ROTATE_MODE_LO && AMDGPU::isGFX9Plus(STI)) {
1519 if (Imm >= FFT_MODE_LO) {
1520 O << "swizzle(" << IdSymbolic[ID_FFT] << ',' << (Imm & FFT_SWIZZLE_MASK)
1521 << ')';
1522 } else if (Imm >= ROTATE_MODE_LO) {
1523 O << "swizzle(" << IdSymbolic[ID_ROTATE] << ','
1524 << ((Imm >> ROTATE_DIR_SHIFT) & ROTATE_DIR_MASK) << ','
1525 << ((Imm >> ROTATE_SIZE_SHIFT) & ROTATE_SIZE_MASK) << ')';
1526 }
1527 return;
1528 }
1529
1530 // Basic mode
1531 if ((Imm & QUAD_PERM_ENC_MASK) == QUAD_PERM_ENC) {
1532 O << "swizzle(" << IdSymbolic[ID_QUAD_PERM];
1533 for (unsigned I = 0; I < LANE_NUM; ++I) {
1534 O << ",";
1535 O << formatDec(Imm & LANE_MASK);
1536 Imm >>= LANE_SHIFT;
1537 }
1538 O << ")";
1539
1540 } else if ((Imm & BITMASK_PERM_ENC_MASK) == BITMASK_PERM_ENC) {
1541
1542 uint16_t AndMask = (Imm >> BITMASK_AND_SHIFT) & BITMASK_MASK;
1543 uint16_t OrMask = (Imm >> BITMASK_OR_SHIFT) & BITMASK_MASK;
1544 uint16_t XorMask = (Imm >> BITMASK_XOR_SHIFT) & BITMASK_MASK;
1545
1546 if (AndMask == BITMASK_MAX && OrMask == 0 && llvm::popcount(XorMask) == 1) {
1547
1548 O << "swizzle(" << IdSymbolic[ID_SWAP];
1549 O << ",";
1550 O << formatDec(XorMask);
1551 O << ")";
1552
1553 } else if (AndMask == BITMASK_MAX && OrMask == 0 && XorMask > 0 &&
1554 isPowerOf2_64(XorMask + 1)) {
1555
1556 O << "swizzle(" << IdSymbolic[ID_REVERSE];
1557 O << ",";
1558 O << formatDec(XorMask + 1);
1559 O << ")";
1560
1561 } else {
1562
1563 uint16_t GroupSize = BITMASK_MAX - AndMask + 1;
1564 if (GroupSize > 1 &&
1565 isPowerOf2_64(GroupSize) &&
1566 OrMask < GroupSize &&
1567 XorMask == 0) {
1568
1569 O << "swizzle(" << IdSymbolic[ID_BROADCAST];
1570 O << ",";
1571 O << formatDec(GroupSize);
1572 O << ",";
1573 O << formatDec(OrMask);
1574 O << ")";
1575
1576 } else {
1577 O << "swizzle(" << IdSymbolic[ID_BITMASK_PERM];
1578 O << ",";
1579 printSwizzleBitmask(AndMask, OrMask, XorMask, O);
1580 O << ")";
1581 }
1582 }
1583 } else {
1584 printU16ImmDecOperand(MI, OpNo, O);
1585 }
1586 }
1587
printSWaitCnt(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1588 void AMDGPUInstPrinter::printSWaitCnt(const MCInst *MI, unsigned OpNo,
1589 const MCSubtargetInfo &STI,
1590 raw_ostream &O) {
1591 AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(STI.getCPU());
1592
1593 unsigned SImm16 = MI->getOperand(OpNo).getImm();
1594 unsigned Vmcnt, Expcnt, Lgkmcnt;
1595 decodeWaitcnt(ISA, SImm16, Vmcnt, Expcnt, Lgkmcnt);
1596
1597 bool IsDefaultVmcnt = Vmcnt == getVmcntBitMask(ISA);
1598 bool IsDefaultExpcnt = Expcnt == getExpcntBitMask(ISA);
1599 bool IsDefaultLgkmcnt = Lgkmcnt == getLgkmcntBitMask(ISA);
1600 bool PrintAll = IsDefaultVmcnt && IsDefaultExpcnt && IsDefaultLgkmcnt;
1601
1602 bool NeedSpace = false;
1603
1604 if (!IsDefaultVmcnt || PrintAll) {
1605 O << "vmcnt(" << Vmcnt << ')';
1606 NeedSpace = true;
1607 }
1608
1609 if (!IsDefaultExpcnt || PrintAll) {
1610 if (NeedSpace)
1611 O << ' ';
1612 O << "expcnt(" << Expcnt << ')';
1613 NeedSpace = true;
1614 }
1615
1616 if (!IsDefaultLgkmcnt || PrintAll) {
1617 if (NeedSpace)
1618 O << ' ';
1619 O << "lgkmcnt(" << Lgkmcnt << ')';
1620 }
1621 }
1622
printDepCtr(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1623 void AMDGPUInstPrinter::printDepCtr(const MCInst *MI, unsigned OpNo,
1624 const MCSubtargetInfo &STI,
1625 raw_ostream &O) {
1626 using namespace llvm::AMDGPU::DepCtr;
1627
1628 uint64_t Imm16 = MI->getOperand(OpNo).getImm() & 0xffff;
1629
1630 bool HasNonDefaultVal = false;
1631 if (isSymbolicDepCtrEncoding(Imm16, HasNonDefaultVal, STI)) {
1632 int Id = 0;
1633 StringRef Name;
1634 unsigned Val;
1635 bool IsDefault;
1636 bool NeedSpace = false;
1637 while (decodeDepCtr(Imm16, Id, Name, Val, IsDefault, STI)) {
1638 if (!IsDefault || !HasNonDefaultVal) {
1639 if (NeedSpace)
1640 O << ' ';
1641 O << Name << '(' << Val << ')';
1642 NeedSpace = true;
1643 }
1644 }
1645 } else {
1646 O << formatHex(Imm16);
1647 }
1648 }
1649
printSDelayALU(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1650 void AMDGPUInstPrinter::printSDelayALU(const MCInst *MI, unsigned OpNo,
1651 const MCSubtargetInfo &STI,
1652 raw_ostream &O) {
1653 const char *BadInstId = "/* invalid instid value */";
1654 static const std::array<const char *, 12> InstIds = {
1655 "NO_DEP", "VALU_DEP_1", "VALU_DEP_2",
1656 "VALU_DEP_3", "VALU_DEP_4", "TRANS32_DEP_1",
1657 "TRANS32_DEP_2", "TRANS32_DEP_3", "FMA_ACCUM_CYCLE_1",
1658 "SALU_CYCLE_1", "SALU_CYCLE_2", "SALU_CYCLE_3"};
1659
1660 const char *BadInstSkip = "/* invalid instskip value */";
1661 static const std::array<const char *, 6> InstSkips = {
1662 "SAME", "NEXT", "SKIP_1", "SKIP_2", "SKIP_3", "SKIP_4"};
1663
1664 unsigned SImm16 = MI->getOperand(OpNo).getImm();
1665 const char *Prefix = "";
1666
1667 unsigned Value = SImm16 & 0xF;
1668 if (Value) {
1669 const char *Name = Value < InstIds.size() ? InstIds[Value] : BadInstId;
1670 O << Prefix << "instid0(" << Name << ')';
1671 Prefix = " | ";
1672 }
1673
1674 Value = (SImm16 >> 4) & 7;
1675 if (Value) {
1676 const char *Name =
1677 Value < InstSkips.size() ? InstSkips[Value] : BadInstSkip;
1678 O << Prefix << "instskip(" << Name << ')';
1679 Prefix = " | ";
1680 }
1681
1682 Value = (SImm16 >> 7) & 0xF;
1683 if (Value) {
1684 const char *Name = Value < InstIds.size() ? InstIds[Value] : BadInstId;
1685 O << Prefix << "instid1(" << Name << ')';
1686 Prefix = " | ";
1687 }
1688
1689 if (!*Prefix)
1690 O << "0";
1691 }
1692
printHwreg(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1693 void AMDGPUInstPrinter::printHwreg(const MCInst *MI, unsigned OpNo,
1694 const MCSubtargetInfo &STI, raw_ostream &O) {
1695 using namespace llvm::AMDGPU::Hwreg;
1696 unsigned Val = MI->getOperand(OpNo).getImm();
1697 auto [Id, Offset, Width] = HwregEncoding::decode(Val);
1698 StringRef HwRegName = getHwreg(Id, STI);
1699
1700 O << "hwreg(";
1701 if (!HwRegName.empty()) {
1702 O << HwRegName;
1703 } else {
1704 O << Id;
1705 }
1706 if (Width != HwregSize::Default || Offset != HwregOffset::Default)
1707 O << ", " << Offset << ", " << Width;
1708 O << ')';
1709 }
1710
printEndpgm(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1711 void AMDGPUInstPrinter::printEndpgm(const MCInst *MI, unsigned OpNo,
1712 const MCSubtargetInfo &STI,
1713 raw_ostream &O) {
1714 uint16_t Imm = MI->getOperand(OpNo).getImm();
1715 if (Imm == 0) {
1716 return;
1717 }
1718
1719 O << ' ' << formatDec(Imm);
1720 }
1721
printNamedInt(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O,StringRef Prefix,bool PrintInHex,bool AlwaysPrint)1722 void AMDGPUInstPrinter::printNamedInt(const MCInst *MI, unsigned OpNo,
1723 const MCSubtargetInfo &STI,
1724 raw_ostream &O, StringRef Prefix,
1725 bool PrintInHex, bool AlwaysPrint) {
1726 int64_t V = MI->getOperand(OpNo).getImm();
1727 if (AlwaysPrint || V != 0)
1728 O << ' ' << Prefix << ':' << (PrintInHex ? formatHex(V) : formatDec(V));
1729 }
1730
printBitOp3(const MCInst * MI,unsigned OpNo,const MCSubtargetInfo & STI,raw_ostream & O)1731 void AMDGPUInstPrinter::printBitOp3(const MCInst *MI, unsigned OpNo,
1732 const MCSubtargetInfo &STI,
1733 raw_ostream &O) {
1734 uint8_t Imm = MI->getOperand(OpNo).getImm();
1735 if (!Imm)
1736 return;
1737
1738 O << " bitop3:";
1739 if (Imm <= 10)
1740 O << formatDec(Imm);
1741 else
1742 O << formatHex(static_cast<uint64_t>(Imm));
1743 }
1744
1745 #include "AMDGPUGenAsmWriter.inc"
1746