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