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