10b57cec5SDimitry Andric //===- AMDGPUDisassembler.cpp - Disassembler for AMDGPU ISA ---------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric /// \file 120b57cec5SDimitry Andric /// 130b57cec5SDimitry Andric /// This file contains definition for AMDGPU ISA disassembler 140b57cec5SDimitry Andric // 150b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric // ToDo: What to do with instruction suffixes (v_mov_b32 vs v_mov_b32_e32)? 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #include "Disassembler/AMDGPUDisassembler.h" 200b57cec5SDimitry Andric #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 2181ad6265SDimitry Andric #include "SIDefines.h" 2281ad6265SDimitry Andric #include "SIRegisterInfo.h" 230b57cec5SDimitry Andric #include "TargetInfo/AMDGPUTargetInfo.h" 24*0fca6ea1SDimitry Andric #include "Utils/AMDGPUAsmUtils.h" 250b57cec5SDimitry Andric #include "Utils/AMDGPUBaseInfo.h" 26e8d8bef9SDimitry Andric #include "llvm-c/DisassemblerTypes.h" 2781ad6265SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 280b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 290b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 3081ad6265SDimitry Andric #include "llvm/MC/MCDecoderOps.h" 310b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 32349cc55cSDimitry Andric #include "llvm/MC/MCInstrDesc.h" 3381ad6265SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 3481ad6265SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 3581ad6265SDimitry Andric #include "llvm/MC/TargetRegistry.h" 36e8d8bef9SDimitry Andric #include "llvm/Support/AMDHSAKernelDescriptor.h" 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric using namespace llvm; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric #define DEBUG_TYPE "amdgpu-disassembler" 410b57cec5SDimitry Andric 42e8d8bef9SDimitry Andric #define SGPR_MAX \ 43e8d8bef9SDimitry Andric (isGFX10Plus() ? AMDGPU::EncValues::SGPR_MAX_GFX10 \ 440b57cec5SDimitry Andric : AMDGPU::EncValues::SGPR_MAX_SI) 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric using DecodeStatus = llvm::MCDisassembler::DecodeStatus; 470b57cec5SDimitry Andric 48*0fca6ea1SDimitry Andric static const MCSubtargetInfo &addDefaultWaveSize(const MCSubtargetInfo &STI, 49*0fca6ea1SDimitry Andric MCContext &Ctx) { 50*0fca6ea1SDimitry Andric if (!STI.hasFeature(AMDGPU::FeatureWavefrontSize64) && 51*0fca6ea1SDimitry Andric !STI.hasFeature(AMDGPU::FeatureWavefrontSize32)) { 52*0fca6ea1SDimitry Andric MCSubtargetInfo &STICopy = Ctx.getSubtargetCopy(STI); 53*0fca6ea1SDimitry Andric // If there is no default wave size it must be a generation before gfx10, 54*0fca6ea1SDimitry Andric // these have FeatureWavefrontSize64 in their definition already. For gfx10+ 55*0fca6ea1SDimitry Andric // set wave32 as a default. 56*0fca6ea1SDimitry Andric STICopy.ToggleFeature(AMDGPU::FeatureWavefrontSize32); 57*0fca6ea1SDimitry Andric return STICopy; 58*0fca6ea1SDimitry Andric } 59*0fca6ea1SDimitry Andric 60*0fca6ea1SDimitry Andric return STI; 61*0fca6ea1SDimitry Andric } 62*0fca6ea1SDimitry Andric 630b57cec5SDimitry Andric AMDGPUDisassembler::AMDGPUDisassembler(const MCSubtargetInfo &STI, 6406c3fb27SDimitry Andric MCContext &Ctx, MCInstrInfo const *MCII) 65*0fca6ea1SDimitry Andric : MCDisassembler(addDefaultWaveSize(STI, Ctx), Ctx), MCII(MCII), 66*0fca6ea1SDimitry Andric MRI(*Ctx.getRegisterInfo()), MAI(*Ctx.getAsmInfo()), 67*0fca6ea1SDimitry Andric TargetMaxInstBytes(MAI.getMaxInstLength(&STI)), 68*0fca6ea1SDimitry Andric CodeObjectVersion(AMDGPU::getDefaultAMDHSACodeObjectVersion()) { 690b57cec5SDimitry Andric // ToDo: AMDGPUDisassembler supports only VI ISA. 7006c3fb27SDimitry Andric if (!STI.hasFeature(AMDGPU::FeatureGCN3Encoding) && !isGFX10Plus()) 710b57cec5SDimitry Andric report_fatal_error("Disassembly not yet supported for subtarget"); 72*0fca6ea1SDimitry Andric 73*0fca6ea1SDimitry Andric for (auto [Symbol, Code] : AMDGPU::UCVersion::getGFXVersions()) 74*0fca6ea1SDimitry Andric createConstantSymbolExpr(Symbol, Code); 75*0fca6ea1SDimitry Andric 76*0fca6ea1SDimitry Andric UCVersionW64Expr = createConstantSymbolExpr("UC_VERSION_W64_BIT", 0x2000); 77*0fca6ea1SDimitry Andric UCVersionW32Expr = createConstantSymbolExpr("UC_VERSION_W32_BIT", 0x4000); 78*0fca6ea1SDimitry Andric UCVersionMDPExpr = createConstantSymbolExpr("UC_VERSION_MDP_BIT", 0x8000); 79*0fca6ea1SDimitry Andric } 80*0fca6ea1SDimitry Andric 81*0fca6ea1SDimitry Andric void AMDGPUDisassembler::setABIVersion(unsigned Version) { 82*0fca6ea1SDimitry Andric CodeObjectVersion = AMDGPU::getAMDHSACodeObjectVersion(Version); 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric inline static MCDisassembler::DecodeStatus 860b57cec5SDimitry Andric addOperand(MCInst &Inst, const MCOperand& Opnd) { 870b57cec5SDimitry Andric Inst.addOperand(Opnd); 880b57cec5SDimitry Andric return Opnd.isValid() ? 890b57cec5SDimitry Andric MCDisassembler::Success : 90480093f4SDimitry Andric MCDisassembler::Fail; 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric static int insertNamedMCOperand(MCInst &MI, const MCOperand &Op, 940b57cec5SDimitry Andric uint16_t NameIdx) { 950b57cec5SDimitry Andric int OpIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), NameIdx); 960b57cec5SDimitry Andric if (OpIdx != -1) { 970b57cec5SDimitry Andric auto I = MI.begin(); 980b57cec5SDimitry Andric std::advance(I, OpIdx); 990b57cec5SDimitry Andric MI.insert(I, Op); 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric return OpIdx; 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric 10406c3fb27SDimitry Andric static DecodeStatus decodeSOPPBrTarget(MCInst &Inst, unsigned Imm, 10581ad6265SDimitry Andric uint64_t Addr, 10681ad6265SDimitry Andric const MCDisassembler *Decoder) { 1070b57cec5SDimitry Andric auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric // Our branches take a simm16, but we need two extra bits to account for the 1100b57cec5SDimitry Andric // factor of 4. 1110b57cec5SDimitry Andric APInt SignedOffset(18, Imm * 4, true); 1120b57cec5SDimitry Andric int64_t Offset = (SignedOffset.sext(64) + 4 + Addr).getSExtValue(); 1130b57cec5SDimitry Andric 11481ad6265SDimitry Andric if (DAsm->tryAddingSymbolicOperand(Inst, Offset, Addr, true, 2, 2, 0)) 1150b57cec5SDimitry Andric return MCDisassembler::Success; 1160b57cec5SDimitry Andric return addOperand(Inst, MCOperand::createImm(Imm)); 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric 11981ad6265SDimitry Andric static DecodeStatus decodeSMEMOffset(MCInst &Inst, unsigned Imm, uint64_t Addr, 12081ad6265SDimitry Andric const MCDisassembler *Decoder) { 1215ffd83dbSDimitry Andric auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); 1225ffd83dbSDimitry Andric int64_t Offset; 1235f757f3fSDimitry Andric if (DAsm->isGFX12Plus()) { // GFX12 supports 24-bit signed offsets. 1245f757f3fSDimitry Andric Offset = SignExtend64<24>(Imm); 1255f757f3fSDimitry Andric } else if (DAsm->isVI()) { // VI supports 20-bit unsigned offsets. 1265ffd83dbSDimitry Andric Offset = Imm & 0xFFFFF; 1275ffd83dbSDimitry Andric } else { // GFX9+ supports 21-bit signed offsets. 1285ffd83dbSDimitry Andric Offset = SignExtend64<21>(Imm); 1295ffd83dbSDimitry Andric } 1305ffd83dbSDimitry Andric return addOperand(Inst, MCOperand::createImm(Offset)); 1315ffd83dbSDimitry Andric } 1325ffd83dbSDimitry Andric 13381ad6265SDimitry Andric static DecodeStatus decodeBoolReg(MCInst &Inst, unsigned Val, uint64_t Addr, 13481ad6265SDimitry Andric const MCDisassembler *Decoder) { 1350b57cec5SDimitry Andric auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); 1360b57cec5SDimitry Andric return addOperand(Inst, DAsm->decodeBoolReg(Val)); 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric 1395f757f3fSDimitry Andric static DecodeStatus decodeSplitBarrier(MCInst &Inst, unsigned Val, 1405f757f3fSDimitry Andric uint64_t Addr, 1415f757f3fSDimitry Andric const MCDisassembler *Decoder) { 1425f757f3fSDimitry Andric auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); 1435f757f3fSDimitry Andric return addOperand(Inst, DAsm->decodeSplitBarrier(Val)); 1445f757f3fSDimitry Andric } 1455f757f3fSDimitry Andric 146*0fca6ea1SDimitry Andric static DecodeStatus decodeDpp8FI(MCInst &Inst, unsigned Val, uint64_t Addr, 147*0fca6ea1SDimitry Andric const MCDisassembler *Decoder) { 148*0fca6ea1SDimitry Andric auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); 149*0fca6ea1SDimitry Andric return addOperand(Inst, DAsm->decodeDpp8FI(Val)); 150*0fca6ea1SDimitry Andric } 151*0fca6ea1SDimitry Andric 1520b57cec5SDimitry Andric #define DECODE_OPERAND(StaticDecoderName, DecoderName) \ 15381ad6265SDimitry Andric static DecodeStatus StaticDecoderName(MCInst &Inst, unsigned Imm, \ 1540b57cec5SDimitry Andric uint64_t /*Addr*/, \ 15581ad6265SDimitry Andric const MCDisassembler *Decoder) { \ 1560b57cec5SDimitry Andric auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); \ 1570b57cec5SDimitry Andric return addOperand(Inst, DAsm->DecoderName(Imm)); \ 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric 16006c3fb27SDimitry Andric // Decoder for registers, decode directly using RegClassID. Imm(8-bit) is 16106c3fb27SDimitry Andric // number of register. Used by VGPR only and AGPR only operands. 16206c3fb27SDimitry Andric #define DECODE_OPERAND_REG_8(RegClass) \ 16306c3fb27SDimitry Andric static DecodeStatus Decode##RegClass##RegisterClass( \ 16406c3fb27SDimitry Andric MCInst &Inst, unsigned Imm, uint64_t /*Addr*/, \ 16506c3fb27SDimitry Andric const MCDisassembler *Decoder) { \ 16606c3fb27SDimitry Andric assert(Imm < (1 << 8) && "8-bit encoding"); \ 16706c3fb27SDimitry Andric auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); \ 16806c3fb27SDimitry Andric return addOperand( \ 16906c3fb27SDimitry Andric Inst, DAsm->createRegOperand(AMDGPU::RegClass##RegClassID, Imm)); \ 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric 17206c3fb27SDimitry Andric #define DECODE_SrcOp(Name, EncSize, OpWidth, EncImm, MandatoryLiteral, \ 17306c3fb27SDimitry Andric ImmWidth) \ 17406c3fb27SDimitry Andric static DecodeStatus Name(MCInst &Inst, unsigned Imm, uint64_t /*Addr*/, \ 17506c3fb27SDimitry Andric const MCDisassembler *Decoder) { \ 17606c3fb27SDimitry Andric assert(Imm < (1 << EncSize) && #EncSize "-bit encoding"); \ 17706c3fb27SDimitry Andric auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); \ 17806c3fb27SDimitry Andric return addOperand(Inst, \ 17906c3fb27SDimitry Andric DAsm->decodeSrcOp(AMDGPUDisassembler::OpWidth, EncImm, \ 18006c3fb27SDimitry Andric MandatoryLiteral, ImmWidth)); \ 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 183*0fca6ea1SDimitry Andric static DecodeStatus decodeSrcOp(MCInst &Inst, unsigned EncSize, 184*0fca6ea1SDimitry Andric AMDGPUDisassembler::OpWidthTy OpWidth, 185*0fca6ea1SDimitry Andric unsigned Imm, unsigned EncImm, 186*0fca6ea1SDimitry Andric bool MandatoryLiteral, unsigned ImmWidth, 187*0fca6ea1SDimitry Andric AMDGPU::OperandSemantics Sema, 188*0fca6ea1SDimitry Andric const MCDisassembler *Decoder) { 189*0fca6ea1SDimitry Andric assert(Imm < (1U << EncSize) && "Operand doesn't fit encoding!"); 190*0fca6ea1SDimitry Andric auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); 191*0fca6ea1SDimitry Andric return addOperand(Inst, DAsm->decodeSrcOp(OpWidth, EncImm, MandatoryLiteral, 192*0fca6ea1SDimitry Andric ImmWidth, Sema)); 193*0fca6ea1SDimitry Andric } 194*0fca6ea1SDimitry Andric 19506c3fb27SDimitry Andric // Decoder for registers. Imm(7-bit) is number of register, uses decodeSrcOp to 19606c3fb27SDimitry Andric // get register class. Used by SGPR only operands. 19706c3fb27SDimitry Andric #define DECODE_OPERAND_REG_7(RegClass, OpWidth) \ 19806c3fb27SDimitry Andric DECODE_SrcOp(Decode##RegClass##RegisterClass, 7, OpWidth, Imm, false, 0) 199fe6060f1SDimitry Andric 20006c3fb27SDimitry Andric // Decoder for registers. Imm(10-bit): Imm{7-0} is number of register, 20106c3fb27SDimitry Andric // Imm{9} is acc(agpr or vgpr) Imm{8} should be 0 (see VOP3Pe_SMFMAC). 20206c3fb27SDimitry Andric // Set Imm{8} to 1 (IS_VGPR) to decode using 'enum10' from decodeSrcOp. 20306c3fb27SDimitry Andric // Used by AV_ register classes (AGPR or VGPR only register operands). 204*0fca6ea1SDimitry Andric template <AMDGPUDisassembler::OpWidthTy OpWidth> 205*0fca6ea1SDimitry Andric static DecodeStatus decodeAV10(MCInst &Inst, unsigned Imm, uint64_t /* Addr */, 206*0fca6ea1SDimitry Andric const MCDisassembler *Decoder) { 207*0fca6ea1SDimitry Andric return decodeSrcOp(Inst, 10, OpWidth, Imm, Imm | AMDGPU::EncValues::IS_VGPR, 208*0fca6ea1SDimitry Andric false, 0, AMDGPU::OperandSemantics::INT, Decoder); 209*0fca6ea1SDimitry Andric } 2100b57cec5SDimitry Andric 21106c3fb27SDimitry Andric // Decoder for Src(9-bit encoding) registers only. 212*0fca6ea1SDimitry Andric template <AMDGPUDisassembler::OpWidthTy OpWidth> 213*0fca6ea1SDimitry Andric static DecodeStatus decodeSrcReg9(MCInst &Inst, unsigned Imm, 214*0fca6ea1SDimitry Andric uint64_t /* Addr */, 215*0fca6ea1SDimitry Andric const MCDisassembler *Decoder) { 216*0fca6ea1SDimitry Andric return decodeSrcOp(Inst, 9, OpWidth, Imm, Imm, false, 0, 217*0fca6ea1SDimitry Andric AMDGPU::OperandSemantics::INT, Decoder); 218*0fca6ea1SDimitry Andric } 2190b57cec5SDimitry Andric 22006c3fb27SDimitry Andric // Decoder for Src(9-bit encoding) AGPR, register number encoded in 9bits, set 22106c3fb27SDimitry Andric // Imm{9} to 1 (set acc) and decode using 'enum10' from decodeSrcOp, registers 22206c3fb27SDimitry Andric // only. 223*0fca6ea1SDimitry Andric template <AMDGPUDisassembler::OpWidthTy OpWidth> 224*0fca6ea1SDimitry Andric static DecodeStatus decodeSrcA9(MCInst &Inst, unsigned Imm, uint64_t /* Addr */, 225*0fca6ea1SDimitry Andric const MCDisassembler *Decoder) { 226*0fca6ea1SDimitry Andric return decodeSrcOp(Inst, 9, OpWidth, Imm, Imm | 512, false, 0, 227*0fca6ea1SDimitry Andric AMDGPU::OperandSemantics::INT, Decoder); 228*0fca6ea1SDimitry Andric } 229fe6060f1SDimitry Andric 23006c3fb27SDimitry Andric // Decoder for 'enum10' from decodeSrcOp, Imm{0-8} is 9-bit Src encoding 23106c3fb27SDimitry Andric // Imm{9} is acc, registers only. 232*0fca6ea1SDimitry Andric template <AMDGPUDisassembler::OpWidthTy OpWidth> 233*0fca6ea1SDimitry Andric static DecodeStatus decodeSrcAV10(MCInst &Inst, unsigned Imm, 234*0fca6ea1SDimitry Andric uint64_t /* Addr */, 235*0fca6ea1SDimitry Andric const MCDisassembler *Decoder) { 236*0fca6ea1SDimitry Andric return decodeSrcOp(Inst, 10, OpWidth, Imm, Imm, false, 0, 237*0fca6ea1SDimitry Andric AMDGPU::OperandSemantics::INT, Decoder); 238*0fca6ea1SDimitry Andric } 2390b57cec5SDimitry Andric 24006c3fb27SDimitry Andric // Decoder for RegisterOperands using 9-bit Src encoding. Operand can be 24106c3fb27SDimitry Andric // register from RegClass or immediate. Registers that don't belong to RegClass 24206c3fb27SDimitry Andric // will be decoded and InstPrinter will report warning. Immediate will be 24306c3fb27SDimitry Andric // decoded into constant of size ImmWidth, should match width of immediate used 24406c3fb27SDimitry Andric // by OperandType (important for floating point types). 245*0fca6ea1SDimitry Andric template <AMDGPUDisassembler::OpWidthTy OpWidth, unsigned ImmWidth, 246*0fca6ea1SDimitry Andric unsigned OperandSemantics> 247*0fca6ea1SDimitry Andric static DecodeStatus decodeSrcRegOrImm9(MCInst &Inst, unsigned Imm, 248*0fca6ea1SDimitry Andric uint64_t /* Addr */, 249*0fca6ea1SDimitry Andric const MCDisassembler *Decoder) { 250*0fca6ea1SDimitry Andric return decodeSrcOp(Inst, 9, OpWidth, Imm, Imm, false, ImmWidth, 251*0fca6ea1SDimitry Andric (AMDGPU::OperandSemantics)OperandSemantics, Decoder); 252*0fca6ea1SDimitry Andric } 2531db9f3b2SDimitry Andric 25406c3fb27SDimitry Andric // Decoder for Src(9-bit encoding) AGPR or immediate. Set Imm{9} to 1 (set acc) 25506c3fb27SDimitry Andric // and decode using 'enum10' from decodeSrcOp. 256*0fca6ea1SDimitry Andric template <AMDGPUDisassembler::OpWidthTy OpWidth, unsigned ImmWidth, 257*0fca6ea1SDimitry Andric unsigned OperandSemantics> 258*0fca6ea1SDimitry Andric static DecodeStatus decodeSrcRegOrImmA9(MCInst &Inst, unsigned Imm, 259*0fca6ea1SDimitry Andric uint64_t /* Addr */, 260*0fca6ea1SDimitry Andric const MCDisassembler *Decoder) { 261*0fca6ea1SDimitry Andric return decodeSrcOp(Inst, 9, OpWidth, Imm, Imm | 512, false, ImmWidth, 262*0fca6ea1SDimitry Andric (AMDGPU::OperandSemantics)OperandSemantics, Decoder); 263*0fca6ea1SDimitry Andric } 2640b57cec5SDimitry Andric 265*0fca6ea1SDimitry Andric template <AMDGPUDisassembler::OpWidthTy OpWidth, unsigned ImmWidth, 266*0fca6ea1SDimitry Andric unsigned OperandSemantics> 267*0fca6ea1SDimitry Andric static DecodeStatus decodeSrcRegOrImmDeferred9(MCInst &Inst, unsigned Imm, 268*0fca6ea1SDimitry Andric uint64_t /* Addr */, 269*0fca6ea1SDimitry Andric const MCDisassembler *Decoder) { 270*0fca6ea1SDimitry Andric return decodeSrcOp(Inst, 9, OpWidth, Imm, Imm, true, ImmWidth, 271*0fca6ea1SDimitry Andric (AMDGPU::OperandSemantics)OperandSemantics, Decoder); 272*0fca6ea1SDimitry Andric } 2730b57cec5SDimitry Andric 27406c3fb27SDimitry Andric // Default decoders generated by tablegen: 'Decode<RegClass>RegisterClass' 27506c3fb27SDimitry Andric // when RegisterClass is used as an operand. Most often used for destination 27606c3fb27SDimitry Andric // operands. 277fe6060f1SDimitry Andric 27806c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VGPR_32) 27906c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VGPR_32_Lo128) 28006c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_64) 28106c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_96) 28206c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_128) 28306c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_256) 28406c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_288) 28506c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_352) 28606c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_384) 28706c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_512) 28806c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_1024) 289fe6060f1SDimitry Andric 29006c3fb27SDimitry Andric DECODE_OPERAND_REG_7(SReg_32, OPW32) 2915f757f3fSDimitry Andric DECODE_OPERAND_REG_7(SReg_32_XEXEC, OPW32) 29206c3fb27SDimitry Andric DECODE_OPERAND_REG_7(SReg_32_XM0_XEXEC, OPW32) 29306c3fb27SDimitry Andric DECODE_OPERAND_REG_7(SReg_32_XEXEC_HI, OPW32) 29406c3fb27SDimitry Andric DECODE_OPERAND_REG_7(SReg_64, OPW64) 29506c3fb27SDimitry Andric DECODE_OPERAND_REG_7(SReg_64_XEXEC, OPW64) 2965f757f3fSDimitry Andric DECODE_OPERAND_REG_7(SReg_96, OPW96) 29706c3fb27SDimitry Andric DECODE_OPERAND_REG_7(SReg_128, OPW128) 29806c3fb27SDimitry Andric DECODE_OPERAND_REG_7(SReg_256, OPW256) 29906c3fb27SDimitry Andric DECODE_OPERAND_REG_7(SReg_512, OPW512) 300fe6060f1SDimitry Andric 30106c3fb27SDimitry Andric DECODE_OPERAND_REG_8(AGPR_32) 30206c3fb27SDimitry Andric DECODE_OPERAND_REG_8(AReg_64) 30306c3fb27SDimitry Andric DECODE_OPERAND_REG_8(AReg_128) 30406c3fb27SDimitry Andric DECODE_OPERAND_REG_8(AReg_256) 30506c3fb27SDimitry Andric DECODE_OPERAND_REG_8(AReg_512) 30606c3fb27SDimitry Andric DECODE_OPERAND_REG_8(AReg_1024) 307fe6060f1SDimitry Andric 3085f757f3fSDimitry Andric static DecodeStatus DecodeVGPR_16RegisterClass(MCInst &Inst, unsigned Imm, 3095f757f3fSDimitry Andric uint64_t /*Addr*/, 3105f757f3fSDimitry Andric const MCDisassembler *Decoder) { 3115f757f3fSDimitry Andric assert(isUInt<10>(Imm) && "10-bit encoding expected"); 3125f757f3fSDimitry Andric assert((Imm & (1 << 8)) == 0 && "Imm{8} should not be used"); 3135f757f3fSDimitry Andric 3145f757f3fSDimitry Andric bool IsHi = Imm & (1 << 9); 3155f757f3fSDimitry Andric unsigned RegIdx = Imm & 0xff; 3165f757f3fSDimitry Andric auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); 3175f757f3fSDimitry Andric return addOperand(Inst, DAsm->createVGPR16Operand(RegIdx, IsHi)); 3185f757f3fSDimitry Andric } 3195f757f3fSDimitry Andric 3205f757f3fSDimitry Andric static DecodeStatus 3215f757f3fSDimitry Andric DecodeVGPR_16_Lo128RegisterClass(MCInst &Inst, unsigned Imm, uint64_t /*Addr*/, 3225f757f3fSDimitry Andric const MCDisassembler *Decoder) { 3235f757f3fSDimitry Andric assert(isUInt<8>(Imm) && "8-bit encoding expected"); 3245f757f3fSDimitry Andric 3255f757f3fSDimitry Andric bool IsHi = Imm & (1 << 7); 3265f757f3fSDimitry Andric unsigned RegIdx = Imm & 0x7f; 3275f757f3fSDimitry Andric auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); 3285f757f3fSDimitry Andric return addOperand(Inst, DAsm->createVGPR16Operand(RegIdx, IsHi)); 3295f757f3fSDimitry Andric } 3305f757f3fSDimitry Andric 3315f757f3fSDimitry Andric static DecodeStatus decodeOperand_VSrcT16_Lo128(MCInst &Inst, unsigned Imm, 3325f757f3fSDimitry Andric uint64_t /*Addr*/, 3335f757f3fSDimitry Andric const MCDisassembler *Decoder) { 3345f757f3fSDimitry Andric assert(isUInt<9>(Imm) && "9-bit encoding expected"); 3355f757f3fSDimitry Andric 3365f757f3fSDimitry Andric const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); 3375f757f3fSDimitry Andric bool IsVGPR = Imm & (1 << 8); 3385f757f3fSDimitry Andric if (IsVGPR) { 3395f757f3fSDimitry Andric bool IsHi = Imm & (1 << 7); 3405f757f3fSDimitry Andric unsigned RegIdx = Imm & 0x7f; 3415f757f3fSDimitry Andric return addOperand(Inst, DAsm->createVGPR16Operand(RegIdx, IsHi)); 3425f757f3fSDimitry Andric } 3435f757f3fSDimitry Andric return addOperand(Inst, DAsm->decodeNonVGPRSrcOp(AMDGPUDisassembler::OPW16, 3445f757f3fSDimitry Andric Imm & 0xFF, false, 16)); 3455f757f3fSDimitry Andric } 3465f757f3fSDimitry Andric 3475f757f3fSDimitry Andric static DecodeStatus decodeOperand_VSrcT16(MCInst &Inst, unsigned Imm, 3485f757f3fSDimitry Andric uint64_t /*Addr*/, 3495f757f3fSDimitry Andric const MCDisassembler *Decoder) { 3505f757f3fSDimitry Andric assert(isUInt<10>(Imm) && "10-bit encoding expected"); 3515f757f3fSDimitry Andric 3525f757f3fSDimitry Andric const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); 3535f757f3fSDimitry Andric bool IsVGPR = Imm & (1 << 8); 3545f757f3fSDimitry Andric if (IsVGPR) { 3555f757f3fSDimitry Andric bool IsHi = Imm & (1 << 9); 3565f757f3fSDimitry Andric unsigned RegIdx = Imm & 0xff; 3575f757f3fSDimitry Andric return addOperand(Inst, DAsm->createVGPR16Operand(RegIdx, IsHi)); 3585f757f3fSDimitry Andric } 3595f757f3fSDimitry Andric return addOperand(Inst, DAsm->decodeNonVGPRSrcOp(AMDGPUDisassembler::OPW16, 3605f757f3fSDimitry Andric Imm & 0xFF, false, 16)); 3615f757f3fSDimitry Andric } 36206c3fb27SDimitry Andric 36306c3fb27SDimitry Andric static DecodeStatus decodeOperand_KImmFP(MCInst &Inst, unsigned Imm, 36481ad6265SDimitry Andric uint64_t Addr, 36581ad6265SDimitry Andric const MCDisassembler *Decoder) { 366349cc55cSDimitry Andric const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); 367349cc55cSDimitry Andric return addOperand(Inst, DAsm->decodeMandatoryLiteralConstant(Imm)); 368349cc55cSDimitry Andric } 369349cc55cSDimitry Andric 37081ad6265SDimitry Andric static DecodeStatus decodeOperandVOPDDstY(MCInst &Inst, unsigned Val, 37181ad6265SDimitry Andric uint64_t Addr, const void *Decoder) { 37281ad6265SDimitry Andric const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); 37381ad6265SDimitry Andric return addOperand(Inst, DAsm->decodeVOPDDstYOp(Inst, Val)); 37481ad6265SDimitry Andric } 37581ad6265SDimitry Andric 376fe6060f1SDimitry Andric static bool IsAGPROperand(const MCInst &Inst, int OpIdx, 377fe6060f1SDimitry Andric const MCRegisterInfo *MRI) { 378fe6060f1SDimitry Andric if (OpIdx < 0) 379fe6060f1SDimitry Andric return false; 380fe6060f1SDimitry Andric 381fe6060f1SDimitry Andric const MCOperand &Op = Inst.getOperand(OpIdx); 382fe6060f1SDimitry Andric if (!Op.isReg()) 383fe6060f1SDimitry Andric return false; 384fe6060f1SDimitry Andric 385fe6060f1SDimitry Andric unsigned Sub = MRI->getSubReg(Op.getReg(), AMDGPU::sub0); 386fe6060f1SDimitry Andric auto Reg = Sub ? Sub : Op.getReg(); 387fe6060f1SDimitry Andric return Reg >= AMDGPU::AGPR0 && Reg <= AMDGPU::AGPR255; 388fe6060f1SDimitry Andric } 389fe6060f1SDimitry Andric 390*0fca6ea1SDimitry Andric static DecodeStatus decodeAVLdSt(MCInst &Inst, unsigned Imm, 391fe6060f1SDimitry Andric AMDGPUDisassembler::OpWidthTy Opw, 39281ad6265SDimitry Andric const MCDisassembler *Decoder) { 393fe6060f1SDimitry Andric auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); 394fe6060f1SDimitry Andric if (!DAsm->isGFX90A()) { 395fe6060f1SDimitry Andric Imm &= 511; 396fe6060f1SDimitry Andric } else { 397fe6060f1SDimitry Andric // If atomic has both vdata and vdst their register classes are tied. 398fe6060f1SDimitry Andric // The bit is decoded along with the vdst, first operand. We need to 399fe6060f1SDimitry Andric // change register class to AGPR if vdst was AGPR. 400fe6060f1SDimitry Andric // If a DS instruction has both data0 and data1 their register classes 401fe6060f1SDimitry Andric // are also tied. 402fe6060f1SDimitry Andric unsigned Opc = Inst.getOpcode(); 403fe6060f1SDimitry Andric uint64_t TSFlags = DAsm->getMCII()->get(Opc).TSFlags; 404fe6060f1SDimitry Andric uint16_t DataNameIdx = (TSFlags & SIInstrFlags::DS) ? AMDGPU::OpName::data0 405fe6060f1SDimitry Andric : AMDGPU::OpName::vdata; 406fe6060f1SDimitry Andric const MCRegisterInfo *MRI = DAsm->getContext().getRegisterInfo(); 407fe6060f1SDimitry Andric int DataIdx = AMDGPU::getNamedOperandIdx(Opc, DataNameIdx); 408fe6060f1SDimitry Andric if ((int)Inst.getNumOperands() == DataIdx) { 409fe6060f1SDimitry Andric int DstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst); 410fe6060f1SDimitry Andric if (IsAGPROperand(Inst, DstIdx, MRI)) 411fe6060f1SDimitry Andric Imm |= 512; 412fe6060f1SDimitry Andric } 413fe6060f1SDimitry Andric 414fe6060f1SDimitry Andric if (TSFlags & SIInstrFlags::DS) { 415fe6060f1SDimitry Andric int Data2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1); 416fe6060f1SDimitry Andric if ((int)Inst.getNumOperands() == Data2Idx && 417fe6060f1SDimitry Andric IsAGPROperand(Inst, DataIdx, MRI)) 418fe6060f1SDimitry Andric Imm |= 512; 419fe6060f1SDimitry Andric } 420fe6060f1SDimitry Andric } 421fe6060f1SDimitry Andric return addOperand(Inst, DAsm->decodeSrcOp(Opw, Imm | 256)); 422fe6060f1SDimitry Andric } 423fe6060f1SDimitry Andric 424*0fca6ea1SDimitry Andric template <AMDGPUDisassembler::OpWidthTy Opw> 425*0fca6ea1SDimitry Andric static DecodeStatus decodeAVLdSt(MCInst &Inst, unsigned Imm, 426*0fca6ea1SDimitry Andric uint64_t /* Addr */, 427*0fca6ea1SDimitry Andric const MCDisassembler *Decoder) { 428*0fca6ea1SDimitry Andric return decodeAVLdSt(Inst, Imm, Opw, Decoder); 429*0fca6ea1SDimitry Andric } 430*0fca6ea1SDimitry Andric 4315f757f3fSDimitry Andric static DecodeStatus decodeOperand_VSrc_f64(MCInst &Inst, unsigned Imm, 4325f757f3fSDimitry Andric uint64_t Addr, 4335f757f3fSDimitry Andric const MCDisassembler *Decoder) { 4345f757f3fSDimitry Andric assert(Imm < (1 << 9) && "9-bit encoding"); 4355f757f3fSDimitry Andric auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); 436*0fca6ea1SDimitry Andric return addOperand(Inst, 437*0fca6ea1SDimitry Andric DAsm->decodeSrcOp(AMDGPUDisassembler::OPW64, Imm, false, 64, 438*0fca6ea1SDimitry Andric AMDGPU::OperandSemantics::FP64)); 439bdd1243dSDimitry Andric } 440bdd1243dSDimitry Andric 4410b57cec5SDimitry Andric #define DECODE_SDWA(DecName) \ 4420b57cec5SDimitry Andric DECODE_OPERAND(decodeSDWA##DecName, decodeSDWA##DecName) 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric DECODE_SDWA(Src32) 4450b57cec5SDimitry Andric DECODE_SDWA(Src16) 4460b57cec5SDimitry Andric DECODE_SDWA(VopcDst) 4470b57cec5SDimitry Andric 448*0fca6ea1SDimitry Andric static DecodeStatus decodeVersionImm(MCInst &Inst, unsigned Imm, 449*0fca6ea1SDimitry Andric uint64_t /* Addr */, 450*0fca6ea1SDimitry Andric const MCDisassembler *Decoder) { 451*0fca6ea1SDimitry Andric auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); 452*0fca6ea1SDimitry Andric return addOperand(Inst, DAsm->decodeVersionImm(Imm)); 453*0fca6ea1SDimitry Andric } 454*0fca6ea1SDimitry Andric 4550b57cec5SDimitry Andric #include "AMDGPUGenDisassemblerTables.inc" 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4580b57cec5SDimitry Andric // 4590b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric template <typename T> static inline T eatBytes(ArrayRef<uint8_t>& Bytes) { 4620b57cec5SDimitry Andric assert(Bytes.size() >= sizeof(T)); 4635f757f3fSDimitry Andric const auto Res = 4645f757f3fSDimitry Andric support::endian::read<T, llvm::endianness::little>(Bytes.data()); 4650b57cec5SDimitry Andric Bytes = Bytes.slice(sizeof(T)); 4660b57cec5SDimitry Andric return Res; 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric 46981ad6265SDimitry Andric static inline DecoderUInt128 eat12Bytes(ArrayRef<uint8_t> &Bytes) { 47081ad6265SDimitry Andric assert(Bytes.size() >= 12); 4715f757f3fSDimitry Andric uint64_t Lo = 4725f757f3fSDimitry Andric support::endian::read<uint64_t, llvm::endianness::little>(Bytes.data()); 47381ad6265SDimitry Andric Bytes = Bytes.slice(8); 4745f757f3fSDimitry Andric uint64_t Hi = 4755f757f3fSDimitry Andric support::endian::read<uint32_t, llvm::endianness::little>(Bytes.data()); 47681ad6265SDimitry Andric Bytes = Bytes.slice(4); 47781ad6265SDimitry Andric return DecoderUInt128(Lo, Hi); 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size, 4810b57cec5SDimitry Andric ArrayRef<uint8_t> Bytes_, 4820b57cec5SDimitry Andric uint64_t Address, 4830b57cec5SDimitry Andric raw_ostream &CS) const { 4840b57cec5SDimitry Andric unsigned MaxInstBytesNum = std::min((size_t)TargetMaxInstBytes, Bytes_.size()); 4850b57cec5SDimitry Andric Bytes = Bytes_.slice(0, MaxInstBytesNum); 4860b57cec5SDimitry Andric 487*0fca6ea1SDimitry Andric // In case the opcode is not recognized we'll assume a Size of 4 bytes (unless 488*0fca6ea1SDimitry Andric // there are fewer bytes left). This will be overridden on success. 489*0fca6ea1SDimitry Andric Size = std::min((size_t)4, Bytes_.size()); 490*0fca6ea1SDimitry Andric 4910b57cec5SDimitry Andric do { 4920b57cec5SDimitry Andric // ToDo: better to switch encoding length using some bit predicate 4930b57cec5SDimitry Andric // but it is unknown yet, so try all we can 4940b57cec5SDimitry Andric 4950b57cec5SDimitry Andric // Try to decode DPP and SDWA first to solve conflict with VOP1 and VOP2 4960b57cec5SDimitry Andric // encodings 49781ad6265SDimitry Andric if (isGFX11Plus() && Bytes.size() >= 12 ) { 49881ad6265SDimitry Andric DecoderUInt128 DecW = eat12Bytes(Bytes); 4995f757f3fSDimitry Andric 500*0fca6ea1SDimitry Andric if (isGFX11() && 501*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX1196, DecoderTableGFX11_FAKE1696, MI, 502*0fca6ea1SDimitry Andric DecW, Address, CS)) 50381ad6265SDimitry Andric break; 5045f757f3fSDimitry Andric 505*0fca6ea1SDimitry Andric if (isGFX12() && 506*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX1296, DecoderTableGFX12_FAKE1696, MI, 507*0fca6ea1SDimitry Andric DecW, Address, CS)) 5085f757f3fSDimitry Andric break; 5097a6dacacSDimitry Andric 510*0fca6ea1SDimitry Andric if (isGFX12() && 511*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX12W6496, MI, DecW, Address, CS)) 5127a6dacacSDimitry Andric break; 513*0fca6ea1SDimitry Andric 51481ad6265SDimitry Andric // Reinitialize Bytes 51581ad6265SDimitry Andric Bytes = Bytes_.slice(0, MaxInstBytesNum); 516*0fca6ea1SDimitry Andric } 51781ad6265SDimitry Andric 5180b57cec5SDimitry Andric if (Bytes.size() >= 8) { 5190b57cec5SDimitry Andric const uint64_t QW = eatBytes<uint64_t>(Bytes); 5200b57cec5SDimitry Andric 521*0fca6ea1SDimitry Andric if (STI.hasFeature(AMDGPU::FeatureGFX10_BEncoding) && 522*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX10_B64, MI, QW, Address, CS)) 5235ffd83dbSDimitry Andric break; 524*0fca6ea1SDimitry Andric 525*0fca6ea1SDimitry Andric if (STI.hasFeature(AMDGPU::FeatureUnpackedD16VMem) && 526*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX80_UNPACKED64, MI, QW, Address, CS)) 5275ffd83dbSDimitry Andric break; 5280b57cec5SDimitry Andric 5290b57cec5SDimitry Andric // Some GFX9 subtargets repurposed the v_mad_mix_f32, v_mad_mixlo_f16 and 5300b57cec5SDimitry Andric // v_mad_mixhi_f16 for FMA variants. Try to decode using this special 5310b57cec5SDimitry Andric // table first so we print the correct name. 532*0fca6ea1SDimitry Andric if (STI.hasFeature(AMDGPU::FeatureFmaMixInsts) && 533*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX9_DL64, MI, QW, Address, CS)) 5340b57cec5SDimitry Andric break; 5350b57cec5SDimitry Andric 536*0fca6ea1SDimitry Andric if (STI.hasFeature(AMDGPU::FeatureGFX940Insts) && 537*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX94064, MI, QW, Address, CS)) 538*0fca6ea1SDimitry Andric break; 539*0fca6ea1SDimitry Andric 540*0fca6ea1SDimitry Andric if (STI.hasFeature(AMDGPU::FeatureGFX90AInsts) && 541*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX90A64, MI, QW, Address, CS)) 542*0fca6ea1SDimitry Andric break; 543*0fca6ea1SDimitry Andric 544*0fca6ea1SDimitry Andric if ((isVI() || isGFX9()) && 545*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX864, MI, QW, Address, CS)) 546*0fca6ea1SDimitry Andric break; 547*0fca6ea1SDimitry Andric 548*0fca6ea1SDimitry Andric if (isGFX9() && tryDecodeInst(DecoderTableGFX964, MI, QW, Address, CS)) 549*0fca6ea1SDimitry Andric break; 550*0fca6ea1SDimitry Andric 551*0fca6ea1SDimitry Andric if (isGFX10() && tryDecodeInst(DecoderTableGFX1064, MI, QW, Address, CS)) 552*0fca6ea1SDimitry Andric break; 553*0fca6ea1SDimitry Andric 554*0fca6ea1SDimitry Andric if (isGFX12() && 555*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX1264, DecoderTableGFX12_FAKE1664, MI, QW, 556*0fca6ea1SDimitry Andric Address, CS)) 557*0fca6ea1SDimitry Andric break; 558*0fca6ea1SDimitry Andric 559*0fca6ea1SDimitry Andric if (isGFX11() && 560*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX1164, DecoderTableGFX11_FAKE1664, MI, QW, 561*0fca6ea1SDimitry Andric Address, CS)) 562*0fca6ea1SDimitry Andric break; 563*0fca6ea1SDimitry Andric 564*0fca6ea1SDimitry Andric if (isGFX11() && 565*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX11W6464, MI, QW, Address, CS)) 566*0fca6ea1SDimitry Andric break; 567*0fca6ea1SDimitry Andric 568*0fca6ea1SDimitry Andric if (isGFX12() && 569*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX12W6464, MI, QW, Address, CS)) 570*0fca6ea1SDimitry Andric break; 571*0fca6ea1SDimitry Andric 572*0fca6ea1SDimitry Andric // Reinitialize Bytes 5730b57cec5SDimitry Andric Bytes = Bytes_.slice(0, MaxInstBytesNum); 574*0fca6ea1SDimitry Andric } 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric // Try decode 32-bit instruction 577*0fca6ea1SDimitry Andric if (Bytes.size() >= 4) { 5780b57cec5SDimitry Andric const uint32_t DW = eatBytes<uint32_t>(Bytes); 5790b57cec5SDimitry Andric 580*0fca6ea1SDimitry Andric if ((isVI() || isGFX9()) && 581*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX832, MI, DW, Address, CS)) 582*0fca6ea1SDimitry Andric break; 5830b57cec5SDimitry Andric 584*0fca6ea1SDimitry Andric if (tryDecodeInst(DecoderTableAMDGPU32, MI, DW, Address, CS)) 585*0fca6ea1SDimitry Andric break; 5860b57cec5SDimitry Andric 587*0fca6ea1SDimitry Andric if (isGFX9() && tryDecodeInst(DecoderTableGFX932, MI, DW, Address, CS)) 588*0fca6ea1SDimitry Andric break; 589*0fca6ea1SDimitry Andric 590*0fca6ea1SDimitry Andric if (STI.hasFeature(AMDGPU::FeatureGFX90AInsts) && 591*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX90A32, MI, DW, Address, CS)) 592*0fca6ea1SDimitry Andric break; 593*0fca6ea1SDimitry Andric 594*0fca6ea1SDimitry Andric if (STI.hasFeature(AMDGPU::FeatureGFX10_BEncoding) && 595*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX10_B32, MI, DW, Address, CS)) 596*0fca6ea1SDimitry Andric break; 597*0fca6ea1SDimitry Andric 598*0fca6ea1SDimitry Andric if (isGFX10() && tryDecodeInst(DecoderTableGFX1032, MI, DW, Address, CS)) 599*0fca6ea1SDimitry Andric break; 600*0fca6ea1SDimitry Andric 601*0fca6ea1SDimitry Andric if (isGFX11() && 602*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX1132, DecoderTableGFX11_FAKE1632, MI, DW, 603*0fca6ea1SDimitry Andric Address, CS)) 604*0fca6ea1SDimitry Andric break; 605*0fca6ea1SDimitry Andric 606*0fca6ea1SDimitry Andric if (isGFX12() && 607*0fca6ea1SDimitry Andric tryDecodeInst(DecoderTableGFX1232, DecoderTableGFX12_FAKE1632, MI, DW, 608*0fca6ea1SDimitry Andric Address, CS)) 609fe6060f1SDimitry Andric break; 610fe6060f1SDimitry Andric } 611fe6060f1SDimitry Andric 612*0fca6ea1SDimitry Andric return MCDisassembler::Fail; 6130b57cec5SDimitry Andric } while (false); 6140b57cec5SDimitry Andric 615*0fca6ea1SDimitry Andric if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::DPP) { 616*0fca6ea1SDimitry Andric if (isMacDPP(MI)) 617*0fca6ea1SDimitry Andric convertMacDPPInst(MI); 618*0fca6ea1SDimitry Andric 619*0fca6ea1SDimitry Andric if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VOP3P) 620*0fca6ea1SDimitry Andric convertVOP3PDPPInst(MI); 621*0fca6ea1SDimitry Andric else if ((MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VOPC) || 622*0fca6ea1SDimitry Andric AMDGPU::isVOPC64DPP(MI.getOpcode())) 623*0fca6ea1SDimitry Andric convertVOPCDPPInst(MI); // Special VOP3 case 624*0fca6ea1SDimitry Andric else if (AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::dpp8) != 625*0fca6ea1SDimitry Andric -1) 626*0fca6ea1SDimitry Andric convertDPP8Inst(MI); 627*0fca6ea1SDimitry Andric else if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VOP3) 628*0fca6ea1SDimitry Andric convertVOP3DPPInst(MI); // Regular VOP3 case 629*0fca6ea1SDimitry Andric } 630*0fca6ea1SDimitry Andric 631*0fca6ea1SDimitry Andric if (AMDGPU::isMAC(MI.getOpcode())) { 6320b57cec5SDimitry Andric // Insert dummy unused src2_modifiers. 6330b57cec5SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(0), 6340b57cec5SDimitry Andric AMDGPU::OpName::src2_modifiers); 6350b57cec5SDimitry Andric } 6360b57cec5SDimitry Andric 637*0fca6ea1SDimitry Andric if (MI.getOpcode() == AMDGPU::V_CVT_SR_BF8_F32_e64_dpp || 638*0fca6ea1SDimitry Andric MI.getOpcode() == AMDGPU::V_CVT_SR_FP8_F32_e64_dpp) { 639b3edf446SDimitry Andric // Insert dummy unused src2_modifiers. 640b3edf446SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(0), 641b3edf446SDimitry Andric AMDGPU::OpName::src2_modifiers); 642b3edf446SDimitry Andric } 643b3edf446SDimitry Andric 644*0fca6ea1SDimitry Andric if ((MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::DS) && 645cb14a3feSDimitry Andric !AMDGPU::hasGDS(STI)) { 646cb14a3feSDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::gds); 647cb14a3feSDimitry Andric } 648cb14a3feSDimitry Andric 649*0fca6ea1SDimitry Andric if (MCII->get(MI.getOpcode()).TSFlags & 650*0fca6ea1SDimitry Andric (SIInstrFlags::MUBUF | SIInstrFlags::FLAT | SIInstrFlags::SMRD)) { 651fe6060f1SDimitry Andric int CPolPos = AMDGPU::getNamedOperandIdx(MI.getOpcode(), 652fe6060f1SDimitry Andric AMDGPU::OpName::cpol); 653fe6060f1SDimitry Andric if (CPolPos != -1) { 654fe6060f1SDimitry Andric unsigned CPol = 655fe6060f1SDimitry Andric (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::IsAtomicRet) ? 656fe6060f1SDimitry Andric AMDGPU::CPol::GLC : 0; 657fe6060f1SDimitry Andric if (MI.getNumOperands() <= (unsigned)CPolPos) { 658fe6060f1SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(CPol), 659fe6060f1SDimitry Andric AMDGPU::OpName::cpol); 660fe6060f1SDimitry Andric } else if (CPol) { 661fe6060f1SDimitry Andric MI.getOperand(CPolPos).setImm(MI.getOperand(CPolPos).getImm() | CPol); 662fe6060f1SDimitry Andric } 663fe6060f1SDimitry Andric } 664fe6060f1SDimitry Andric } 665fe6060f1SDimitry Andric 666*0fca6ea1SDimitry Andric if ((MCII->get(MI.getOpcode()).TSFlags & 667fe6060f1SDimitry Andric (SIInstrFlags::MTBUF | SIInstrFlags::MUBUF)) && 66806c3fb27SDimitry Andric (STI.hasFeature(AMDGPU::FeatureGFX90AInsts))) { 669fe6060f1SDimitry Andric // GFX90A lost TFE, its place is occupied by ACC. 670fe6060f1SDimitry Andric int TFEOpIdx = 671fe6060f1SDimitry Andric AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::tfe); 672fe6060f1SDimitry Andric if (TFEOpIdx != -1) { 673fe6060f1SDimitry Andric auto TFEIter = MI.begin(); 674fe6060f1SDimitry Andric std::advance(TFEIter, TFEOpIdx); 675fe6060f1SDimitry Andric MI.insert(TFEIter, MCOperand::createImm(0)); 676fe6060f1SDimitry Andric } 677fe6060f1SDimitry Andric } 678fe6060f1SDimitry Andric 679*0fca6ea1SDimitry Andric if (MCII->get(MI.getOpcode()).TSFlags & 680*0fca6ea1SDimitry Andric (SIInstrFlags::MTBUF | SIInstrFlags::MUBUF)) { 681fe6060f1SDimitry Andric int SWZOpIdx = 682fe6060f1SDimitry Andric AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::swz); 683fe6060f1SDimitry Andric if (SWZOpIdx != -1) { 684fe6060f1SDimitry Andric auto SWZIter = MI.begin(); 685fe6060f1SDimitry Andric std::advance(SWZIter, SWZOpIdx); 686fe6060f1SDimitry Andric MI.insert(SWZIter, MCOperand::createImm(0)); 687fe6060f1SDimitry Andric } 688e8d8bef9SDimitry Andric } 689e8d8bef9SDimitry Andric 690*0fca6ea1SDimitry Andric if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::MIMG) { 6910b57cec5SDimitry Andric int VAddr0Idx = 6920b57cec5SDimitry Andric AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vaddr0); 6930b57cec5SDimitry Andric int RsrcIdx = 6940b57cec5SDimitry Andric AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc); 6950b57cec5SDimitry Andric unsigned NSAArgs = RsrcIdx - VAddr0Idx - 1; 6960b57cec5SDimitry Andric if (VAddr0Idx >= 0 && NSAArgs > 0) { 6970b57cec5SDimitry Andric unsigned NSAWords = (NSAArgs + 3) / 4; 698*0fca6ea1SDimitry Andric if (Bytes.size() < 4 * NSAWords) 699*0fca6ea1SDimitry Andric return MCDisassembler::Fail; 7000b57cec5SDimitry Andric for (unsigned i = 0; i < NSAArgs; ++i) { 70181ad6265SDimitry Andric const unsigned VAddrIdx = VAddr0Idx + 1 + i; 702bdd1243dSDimitry Andric auto VAddrRCID = 703bdd1243dSDimitry Andric MCII->get(MI.getOpcode()).operands()[VAddrIdx].RegClass; 704*0fca6ea1SDimitry Andric MI.insert(MI.begin() + VAddrIdx, createRegOperand(VAddrRCID, Bytes[i])); 7050b57cec5SDimitry Andric } 7060b57cec5SDimitry Andric Bytes = Bytes.slice(4 * NSAWords); 7070b57cec5SDimitry Andric } 708*0fca6ea1SDimitry Andric 709*0fca6ea1SDimitry Andric convertMIMGInst(MI); 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric 712*0fca6ea1SDimitry Andric if (MCII->get(MI.getOpcode()).TSFlags & 713*0fca6ea1SDimitry Andric (SIInstrFlags::VIMAGE | SIInstrFlags::VSAMPLE)) 714*0fca6ea1SDimitry Andric convertMIMGInst(MI); 7150b57cec5SDimitry Andric 716*0fca6ea1SDimitry Andric if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::EXP) 717*0fca6ea1SDimitry Andric convertEXPInst(MI); 7185f757f3fSDimitry Andric 719*0fca6ea1SDimitry Andric if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VINTERP) 720*0fca6ea1SDimitry Andric convertVINTERPInst(MI); 72181ad6265SDimitry Andric 722*0fca6ea1SDimitry Andric if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::SDWA) 723*0fca6ea1SDimitry Andric convertSDWAInst(MI); 7240b57cec5SDimitry Andric 7250b57cec5SDimitry Andric int VDstIn_Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), 7260b57cec5SDimitry Andric AMDGPU::OpName::vdst_in); 7270b57cec5SDimitry Andric if (VDstIn_Idx != -1) { 7280b57cec5SDimitry Andric int Tied = MCII->get(MI.getOpcode()).getOperandConstraint(VDstIn_Idx, 7290b57cec5SDimitry Andric MCOI::OperandConstraint::TIED_TO); 7300b57cec5SDimitry Andric if (Tied != -1 && (MI.getNumOperands() <= (unsigned)VDstIn_Idx || 7310b57cec5SDimitry Andric !MI.getOperand(VDstIn_Idx).isReg() || 7320b57cec5SDimitry Andric MI.getOperand(VDstIn_Idx).getReg() != MI.getOperand(Tied).getReg())) { 7330b57cec5SDimitry Andric if (MI.getNumOperands() > (unsigned)VDstIn_Idx) 7340b57cec5SDimitry Andric MI.erase(&MI.getOperand(VDstIn_Idx)); 7350b57cec5SDimitry Andric insertNamedMCOperand(MI, 7360b57cec5SDimitry Andric MCOperand::createReg(MI.getOperand(Tied).getReg()), 7370b57cec5SDimitry Andric AMDGPU::OpName::vdst_in); 7380b57cec5SDimitry Andric } 7390b57cec5SDimitry Andric } 7400b57cec5SDimitry Andric 741349cc55cSDimitry Andric int ImmLitIdx = 742349cc55cSDimitry Andric AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::imm); 743bdd1243dSDimitry Andric bool IsSOPK = MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::SOPK; 744*0fca6ea1SDimitry Andric if (ImmLitIdx != -1 && !IsSOPK) 745*0fca6ea1SDimitry Andric convertFMAanyK(MI, ImmLitIdx); 746349cc55cSDimitry Andric 747*0fca6ea1SDimitry Andric Size = MaxInstBytesNum - Bytes.size(); 748*0fca6ea1SDimitry Andric return MCDisassembler::Success; 7490b57cec5SDimitry Andric } 7500b57cec5SDimitry Andric 751*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertEXPInst(MCInst &MI) const { 7525f757f3fSDimitry Andric if (STI.hasFeature(AMDGPU::FeatureGFX11Insts)) { 75381ad6265SDimitry Andric // The MCInst still has these fields even though they are no longer encoded 75481ad6265SDimitry Andric // in the GFX11 instruction. 75581ad6265SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::vm); 75681ad6265SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::compr); 75781ad6265SDimitry Andric } 75881ad6265SDimitry Andric } 75981ad6265SDimitry Andric 760*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertVINTERPInst(MCInst &MI) const { 76181ad6265SDimitry Andric if (MI.getOpcode() == AMDGPU::V_INTERP_P10_F16_F32_inreg_gfx11 || 7625f757f3fSDimitry Andric MI.getOpcode() == AMDGPU::V_INTERP_P10_F16_F32_inreg_gfx12 || 76381ad6265SDimitry Andric MI.getOpcode() == AMDGPU::V_INTERP_P10_RTZ_F16_F32_inreg_gfx11 || 7645f757f3fSDimitry Andric MI.getOpcode() == AMDGPU::V_INTERP_P10_RTZ_F16_F32_inreg_gfx12 || 76581ad6265SDimitry Andric MI.getOpcode() == AMDGPU::V_INTERP_P2_F16_F32_inreg_gfx11 || 7665f757f3fSDimitry Andric MI.getOpcode() == AMDGPU::V_INTERP_P2_F16_F32_inreg_gfx12 || 7675f757f3fSDimitry Andric MI.getOpcode() == AMDGPU::V_INTERP_P2_RTZ_F16_F32_inreg_gfx11 || 7685f757f3fSDimitry Andric MI.getOpcode() == AMDGPU::V_INTERP_P2_RTZ_F16_F32_inreg_gfx12) { 76981ad6265SDimitry Andric // The MCInst has this field that is not directly encoded in the 77081ad6265SDimitry Andric // instruction. 77181ad6265SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::op_sel); 77281ad6265SDimitry Andric } 77381ad6265SDimitry Andric } 77481ad6265SDimitry Andric 775*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertSDWAInst(MCInst &MI) const { 77606c3fb27SDimitry Andric if (STI.hasFeature(AMDGPU::FeatureGFX9) || 77706c3fb27SDimitry Andric STI.hasFeature(AMDGPU::FeatureGFX10)) { 778bdd1243dSDimitry Andric if (AMDGPU::hasNamedOperand(MI.getOpcode(), AMDGPU::OpName::sdst)) 7790b57cec5SDimitry Andric // VOPC - insert clamp 7800b57cec5SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::clamp); 78106c3fb27SDimitry Andric } else if (STI.hasFeature(AMDGPU::FeatureVolcanicIslands)) { 7820b57cec5SDimitry Andric int SDst = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sdst); 7830b57cec5SDimitry Andric if (SDst != -1) { 7840b57cec5SDimitry Andric // VOPC - insert VCC register as sdst 7850b57cec5SDimitry Andric insertNamedMCOperand(MI, createRegOperand(AMDGPU::VCC), 7860b57cec5SDimitry Andric AMDGPU::OpName::sdst); 7870b57cec5SDimitry Andric } else { 7880b57cec5SDimitry Andric // VOP1/2 - insert omod if present in instruction 7890b57cec5SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::omod); 7900b57cec5SDimitry Andric } 7910b57cec5SDimitry Andric } 7920b57cec5SDimitry Andric } 7930b57cec5SDimitry Andric 794fcaf7f86SDimitry Andric struct VOPModifiers { 795fcaf7f86SDimitry Andric unsigned OpSel = 0; 796fcaf7f86SDimitry Andric unsigned OpSelHi = 0; 797fcaf7f86SDimitry Andric unsigned NegLo = 0; 798fcaf7f86SDimitry Andric unsigned NegHi = 0; 799fcaf7f86SDimitry Andric }; 800fcaf7f86SDimitry Andric 801fcaf7f86SDimitry Andric // Reconstruct values of VOP3/VOP3P operands such as op_sel. 802fcaf7f86SDimitry Andric // Note that these values do not affect disassembler output, 803fcaf7f86SDimitry Andric // so this is only necessary for consistency with src_modifiers. 804fcaf7f86SDimitry Andric static VOPModifiers collectVOPModifiers(const MCInst &MI, 805fcaf7f86SDimitry Andric bool IsVOP3P = false) { 806fcaf7f86SDimitry Andric VOPModifiers Modifiers; 807fcaf7f86SDimitry Andric unsigned Opc = MI.getOpcode(); 808fcaf7f86SDimitry Andric const int ModOps[] = {AMDGPU::OpName::src0_modifiers, 809fcaf7f86SDimitry Andric AMDGPU::OpName::src1_modifiers, 810fcaf7f86SDimitry Andric AMDGPU::OpName::src2_modifiers}; 811fcaf7f86SDimitry Andric for (int J = 0; J < 3; ++J) { 812fcaf7f86SDimitry Andric int OpIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]); 813fcaf7f86SDimitry Andric if (OpIdx == -1) 814fcaf7f86SDimitry Andric continue; 815fcaf7f86SDimitry Andric 816fcaf7f86SDimitry Andric unsigned Val = MI.getOperand(OpIdx).getImm(); 817fcaf7f86SDimitry Andric 818fcaf7f86SDimitry Andric Modifiers.OpSel |= !!(Val & SISrcMods::OP_SEL_0) << J; 819fcaf7f86SDimitry Andric if (IsVOP3P) { 820fcaf7f86SDimitry Andric Modifiers.OpSelHi |= !!(Val & SISrcMods::OP_SEL_1) << J; 821fcaf7f86SDimitry Andric Modifiers.NegLo |= !!(Val & SISrcMods::NEG) << J; 822fcaf7f86SDimitry Andric Modifiers.NegHi |= !!(Val & SISrcMods::NEG_HI) << J; 823fcaf7f86SDimitry Andric } else if (J == 0) { 824fcaf7f86SDimitry Andric Modifiers.OpSel |= !!(Val & SISrcMods::DST_OP_SEL) << 3; 825fcaf7f86SDimitry Andric } 826fcaf7f86SDimitry Andric } 827fcaf7f86SDimitry Andric 828fcaf7f86SDimitry Andric return Modifiers; 829fcaf7f86SDimitry Andric } 830fcaf7f86SDimitry Andric 831*0fca6ea1SDimitry Andric // Instructions decode the op_sel/suffix bits into the src_modifier 832*0fca6ea1SDimitry Andric // operands. Copy those bits into the src operands for true16 VGPRs. 833*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertTrue16OpSel(MCInst &MI) const { 834*0fca6ea1SDimitry Andric const unsigned Opc = MI.getOpcode(); 835*0fca6ea1SDimitry Andric const MCRegisterClass &ConversionRC = 836*0fca6ea1SDimitry Andric MRI.getRegClass(AMDGPU::VGPR_16RegClassID); 837*0fca6ea1SDimitry Andric constexpr std::array<std::tuple<int, int, unsigned>, 4> OpAndOpMods = { 838*0fca6ea1SDimitry Andric {{AMDGPU::OpName::src0, AMDGPU::OpName::src0_modifiers, 839*0fca6ea1SDimitry Andric SISrcMods::OP_SEL_0}, 840*0fca6ea1SDimitry Andric {AMDGPU::OpName::src1, AMDGPU::OpName::src1_modifiers, 841*0fca6ea1SDimitry Andric SISrcMods::OP_SEL_0}, 842*0fca6ea1SDimitry Andric {AMDGPU::OpName::src2, AMDGPU::OpName::src2_modifiers, 843*0fca6ea1SDimitry Andric SISrcMods::OP_SEL_0}, 844*0fca6ea1SDimitry Andric {AMDGPU::OpName::vdst, AMDGPU::OpName::src0_modifiers, 845*0fca6ea1SDimitry Andric SISrcMods::DST_OP_SEL}}}; 846*0fca6ea1SDimitry Andric for (const auto &[OpName, OpModsName, OpSelMask] : OpAndOpMods) { 847*0fca6ea1SDimitry Andric int OpIdx = AMDGPU::getNamedOperandIdx(Opc, OpName); 848*0fca6ea1SDimitry Andric int OpModsIdx = AMDGPU::getNamedOperandIdx(Opc, OpModsName); 849*0fca6ea1SDimitry Andric if (OpIdx == -1 || OpModsIdx == -1) 850*0fca6ea1SDimitry Andric continue; 851*0fca6ea1SDimitry Andric MCOperand &Op = MI.getOperand(OpIdx); 852*0fca6ea1SDimitry Andric if (!Op.isReg()) 853*0fca6ea1SDimitry Andric continue; 854*0fca6ea1SDimitry Andric if (!ConversionRC.contains(Op.getReg())) 855*0fca6ea1SDimitry Andric continue; 856*0fca6ea1SDimitry Andric unsigned OpEnc = MRI.getEncodingValue(Op.getReg()); 857*0fca6ea1SDimitry Andric const MCOperand &OpMods = MI.getOperand(OpModsIdx); 858*0fca6ea1SDimitry Andric unsigned ModVal = OpMods.getImm(); 859*0fca6ea1SDimitry Andric if (ModVal & OpSelMask) { // isHi 860*0fca6ea1SDimitry Andric unsigned RegIdx = OpEnc & AMDGPU::HWEncoding::REG_IDX_MASK; 861*0fca6ea1SDimitry Andric Op.setReg(ConversionRC.getRegister(RegIdx * 2 + 1)); 862*0fca6ea1SDimitry Andric } 863*0fca6ea1SDimitry Andric } 864*0fca6ea1SDimitry Andric } 865*0fca6ea1SDimitry Andric 866bdd1243dSDimitry Andric // MAC opcodes have special old and src2 operands. 867bdd1243dSDimitry Andric // src2 is tied to dst, while old is not tied (but assumed to be). 868bdd1243dSDimitry Andric bool AMDGPUDisassembler::isMacDPP(MCInst &MI) const { 869bdd1243dSDimitry Andric constexpr int DST_IDX = 0; 870bdd1243dSDimitry Andric auto Opcode = MI.getOpcode(); 871bdd1243dSDimitry Andric const auto &Desc = MCII->get(Opcode); 872bdd1243dSDimitry Andric auto OldIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::old); 873bdd1243dSDimitry Andric 874bdd1243dSDimitry Andric if (OldIdx != -1 && Desc.getOperandConstraint( 875bdd1243dSDimitry Andric OldIdx, MCOI::OperandConstraint::TIED_TO) == -1) { 876bdd1243dSDimitry Andric assert(AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src2)); 877bdd1243dSDimitry Andric assert(Desc.getOperandConstraint( 878bdd1243dSDimitry Andric AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2), 879bdd1243dSDimitry Andric MCOI::OperandConstraint::TIED_TO) == DST_IDX); 880bdd1243dSDimitry Andric (void)DST_IDX; 881bdd1243dSDimitry Andric return true; 882bdd1243dSDimitry Andric } 883bdd1243dSDimitry Andric 884bdd1243dSDimitry Andric return false; 885bdd1243dSDimitry Andric } 886bdd1243dSDimitry Andric 887bdd1243dSDimitry Andric // Create dummy old operand and insert dummy unused src2_modifiers 888bdd1243dSDimitry Andric void AMDGPUDisassembler::convertMacDPPInst(MCInst &MI) const { 889bdd1243dSDimitry Andric assert(MI.getNumOperands() + 1 < MCII->get(MI.getOpcode()).getNumOperands()); 890bdd1243dSDimitry Andric insertNamedMCOperand(MI, MCOperand::createReg(0), AMDGPU::OpName::old); 891bdd1243dSDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(0), 892bdd1243dSDimitry Andric AMDGPU::OpName::src2_modifiers); 893bdd1243dSDimitry Andric } 894bdd1243dSDimitry Andric 895*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertDPP8Inst(MCInst &MI) const { 8960b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 897b3edf446SDimitry Andric 898b3edf446SDimitry Andric int VDstInIdx = 899b3edf446SDimitry Andric AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdst_in); 900b3edf446SDimitry Andric if (VDstInIdx != -1) 901b3edf446SDimitry Andric insertNamedMCOperand(MI, MI.getOperand(0), AMDGPU::OpName::vdst_in); 902b3edf446SDimitry Andric 903bdd1243dSDimitry Andric unsigned DescNumOps = MCII->get(Opc).getNumOperands(); 904bdd1243dSDimitry Andric if (MI.getNumOperands() < DescNumOps && 905bdd1243dSDimitry Andric AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) { 906*0fca6ea1SDimitry Andric convertTrue16OpSel(MI); 907fcaf7f86SDimitry Andric auto Mods = collectVOPModifiers(MI); 908fcaf7f86SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(Mods.OpSel), 909fcaf7f86SDimitry Andric AMDGPU::OpName::op_sel); 91081ad6265SDimitry Andric } else { 9110b57cec5SDimitry Andric // Insert dummy unused src modifiers. 9120b57cec5SDimitry Andric if (MI.getNumOperands() < DescNumOps && 913bdd1243dSDimitry Andric AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src0_modifiers)) 9140b57cec5SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(0), 9150b57cec5SDimitry Andric AMDGPU::OpName::src0_modifiers); 9160b57cec5SDimitry Andric 9170b57cec5SDimitry Andric if (MI.getNumOperands() < DescNumOps && 918bdd1243dSDimitry Andric AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src1_modifiers)) 9190b57cec5SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(0), 9200b57cec5SDimitry Andric AMDGPU::OpName::src1_modifiers); 92181ad6265SDimitry Andric } 922bdd1243dSDimitry Andric } 9230b57cec5SDimitry Andric 924*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertVOP3DPPInst(MCInst &MI) const { 925*0fca6ea1SDimitry Andric convertTrue16OpSel(MI); 926bdd1243dSDimitry Andric 927b3edf446SDimitry Andric int VDstInIdx = 928b3edf446SDimitry Andric AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdst_in); 929b3edf446SDimitry Andric if (VDstInIdx != -1) 930b3edf446SDimitry Andric insertNamedMCOperand(MI, MI.getOperand(0), AMDGPU::OpName::vdst_in); 931b3edf446SDimitry Andric 932fcaf7f86SDimitry Andric unsigned Opc = MI.getOpcode(); 933fcaf7f86SDimitry Andric unsigned DescNumOps = MCII->get(Opc).getNumOperands(); 934fcaf7f86SDimitry Andric if (MI.getNumOperands() < DescNumOps && 935bdd1243dSDimitry Andric AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) { 936fcaf7f86SDimitry Andric auto Mods = collectVOPModifiers(MI); 937fcaf7f86SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(Mods.OpSel), 938fcaf7f86SDimitry Andric AMDGPU::OpName::op_sel); 939fcaf7f86SDimitry Andric } 940fcaf7f86SDimitry Andric } 941fcaf7f86SDimitry Andric 9420b57cec5SDimitry Andric // Note that before gfx10, the MIMG encoding provided no information about 9430b57cec5SDimitry Andric // VADDR size. Consequently, decoded instructions always show address as if it 9440b57cec5SDimitry Andric // has 1 dword, which could be not really so. 945*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertMIMGInst(MCInst &MI) const { 9465f757f3fSDimitry Andric auto TSFlags = MCII->get(MI.getOpcode()).TSFlags; 9470b57cec5SDimitry Andric 9480b57cec5SDimitry Andric int VDstIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), 9490b57cec5SDimitry Andric AMDGPU::OpName::vdst); 9500b57cec5SDimitry Andric 9510b57cec5SDimitry Andric int VDataIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), 9520b57cec5SDimitry Andric AMDGPU::OpName::vdata); 9530b57cec5SDimitry Andric int VAddr0Idx = 9540b57cec5SDimitry Andric AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vaddr0); 955*0fca6ea1SDimitry Andric int RsrcOpName = (TSFlags & SIInstrFlags::MIMG) ? AMDGPU::OpName::srsrc 9565f757f3fSDimitry Andric : AMDGPU::OpName::rsrc; 9575f757f3fSDimitry Andric int RsrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), RsrcOpName); 9580b57cec5SDimitry Andric int DMaskIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), 9590b57cec5SDimitry Andric AMDGPU::OpName::dmask); 9600b57cec5SDimitry Andric 9610b57cec5SDimitry Andric int TFEIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), 9620b57cec5SDimitry Andric AMDGPU::OpName::tfe); 9630b57cec5SDimitry Andric int D16Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), 9640b57cec5SDimitry Andric AMDGPU::OpName::d16); 9650b57cec5SDimitry Andric 966349cc55cSDimitry Andric const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(MI.getOpcode()); 967349cc55cSDimitry Andric const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode = 968349cc55cSDimitry Andric AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode); 969349cc55cSDimitry Andric 9700b57cec5SDimitry Andric assert(VDataIdx != -1); 971349cc55cSDimitry Andric if (BaseOpcode->BVH) { 972349cc55cSDimitry Andric // Add A16 operand for intersect_ray instructions 97306c3fb27SDimitry Andric addOperand(MI, MCOperand::createImm(BaseOpcode->A16)); 974*0fca6ea1SDimitry Andric return; 975e8d8bef9SDimitry Andric } 9760b57cec5SDimitry Andric 9770b57cec5SDimitry Andric bool IsAtomic = (VDstIdx != -1); 9785f757f3fSDimitry Andric bool IsGather4 = TSFlags & SIInstrFlags::Gather4; 9795f757f3fSDimitry Andric bool IsVSample = TSFlags & SIInstrFlags::VSAMPLE; 9800b57cec5SDimitry Andric bool IsNSA = false; 98106c3fb27SDimitry Andric bool IsPartialNSA = false; 9820b57cec5SDimitry Andric unsigned AddrSize = Info->VAddrDwords; 9830b57cec5SDimitry Andric 98481ad6265SDimitry Andric if (isGFX10Plus()) { 9850b57cec5SDimitry Andric unsigned DimIdx = 9860b57cec5SDimitry Andric AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::dim); 987fe6060f1SDimitry Andric int A16Idx = 988fe6060f1SDimitry Andric AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::a16); 9890b57cec5SDimitry Andric const AMDGPU::MIMGDimInfo *Dim = 9900b57cec5SDimitry Andric AMDGPU::getMIMGDimInfoByEncoding(MI.getOperand(DimIdx).getImm()); 991fe6060f1SDimitry Andric const bool IsA16 = (A16Idx != -1 && MI.getOperand(A16Idx).getImm()); 9920b57cec5SDimitry Andric 993fe6060f1SDimitry Andric AddrSize = 994fe6060f1SDimitry Andric AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, AMDGPU::hasG16(STI)); 995fe6060f1SDimitry Andric 9965f757f3fSDimitry Andric // VSAMPLE insts that do not use vaddr3 behave the same as NSA forms. 9975f757f3fSDimitry Andric // VIMAGE insts other than BVH never use vaddr4. 99881ad6265SDimitry Andric IsNSA = Info->MIMGEncoding == AMDGPU::MIMGEncGfx10NSA || 9995f757f3fSDimitry Andric Info->MIMGEncoding == AMDGPU::MIMGEncGfx11NSA || 10005f757f3fSDimitry Andric Info->MIMGEncoding == AMDGPU::MIMGEncGfx12; 10010b57cec5SDimitry Andric if (!IsNSA) { 10025f757f3fSDimitry Andric if (!IsVSample && AddrSize > 12) 10030b57cec5SDimitry Andric AddrSize = 16; 10040b57cec5SDimitry Andric } else { 10050b57cec5SDimitry Andric if (AddrSize > Info->VAddrDwords) { 100606c3fb27SDimitry Andric if (!STI.hasFeature(AMDGPU::FeaturePartialNSAEncoding)) { 100706c3fb27SDimitry Andric // The NSA encoding does not contain enough operands for the 100806c3fb27SDimitry Andric // combination of base opcode / dimension. Should this be an error? 1009*0fca6ea1SDimitry Andric return; 10100b57cec5SDimitry Andric } 101106c3fb27SDimitry Andric IsPartialNSA = true; 101206c3fb27SDimitry Andric } 10130b57cec5SDimitry Andric } 10140b57cec5SDimitry Andric } 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric unsigned DMask = MI.getOperand(DMaskIdx).getImm() & 0xf; 1017bdd1243dSDimitry Andric unsigned DstSize = IsGather4 ? 4 : std::max(llvm::popcount(DMask), 1); 10180b57cec5SDimitry Andric 10190b57cec5SDimitry Andric bool D16 = D16Idx >= 0 && MI.getOperand(D16Idx).getImm(); 10200b57cec5SDimitry Andric if (D16 && AMDGPU::hasPackedD16(STI)) { 10210b57cec5SDimitry Andric DstSize = (DstSize + 1) / 2; 10220b57cec5SDimitry Andric } 10230b57cec5SDimitry Andric 1024fe6060f1SDimitry Andric if (TFEIdx != -1 && MI.getOperand(TFEIdx).getImm()) 1025e8d8bef9SDimitry Andric DstSize += 1; 10260b57cec5SDimitry Andric 10270b57cec5SDimitry Andric if (DstSize == Info->VDataDwords && AddrSize == Info->VAddrDwords) 1028*0fca6ea1SDimitry Andric return; 10290b57cec5SDimitry Andric 10300b57cec5SDimitry Andric int NewOpcode = 10310b57cec5SDimitry Andric AMDGPU::getMIMGOpcode(Info->BaseOpcode, Info->MIMGEncoding, DstSize, AddrSize); 10320b57cec5SDimitry Andric if (NewOpcode == -1) 1033*0fca6ea1SDimitry Andric return; 10340b57cec5SDimitry Andric 10350b57cec5SDimitry Andric // Widen the register to the correct number of enabled channels. 10360b57cec5SDimitry Andric unsigned NewVdata = AMDGPU::NoRegister; 10370b57cec5SDimitry Andric if (DstSize != Info->VDataDwords) { 1038bdd1243dSDimitry Andric auto DataRCID = MCII->get(NewOpcode).operands()[VDataIdx].RegClass; 10390b57cec5SDimitry Andric 10400b57cec5SDimitry Andric // Get first subregister of VData 10410b57cec5SDimitry Andric unsigned Vdata0 = MI.getOperand(VDataIdx).getReg(); 10420b57cec5SDimitry Andric unsigned VdataSub0 = MRI.getSubReg(Vdata0, AMDGPU::sub0); 10430b57cec5SDimitry Andric Vdata0 = (VdataSub0 != 0)? VdataSub0 : Vdata0; 10440b57cec5SDimitry Andric 10450b57cec5SDimitry Andric NewVdata = MRI.getMatchingSuperReg(Vdata0, AMDGPU::sub0, 10460b57cec5SDimitry Andric &MRI.getRegClass(DataRCID)); 10470b57cec5SDimitry Andric if (NewVdata == AMDGPU::NoRegister) { 10480b57cec5SDimitry Andric // It's possible to encode this such that the low register + enabled 10490b57cec5SDimitry Andric // components exceeds the register count. 1050*0fca6ea1SDimitry Andric return; 10510b57cec5SDimitry Andric } 10520b57cec5SDimitry Andric } 10530b57cec5SDimitry Andric 105406c3fb27SDimitry Andric // If not using NSA on GFX10+, widen vaddr0 address register to correct size. 105506c3fb27SDimitry Andric // If using partial NSA on GFX11+ widen last address register. 105606c3fb27SDimitry Andric int VAddrSAIdx = IsPartialNSA ? (RsrcIdx - 1) : VAddr0Idx; 105706c3fb27SDimitry Andric unsigned NewVAddrSA = AMDGPU::NoRegister; 105806c3fb27SDimitry Andric if (STI.hasFeature(AMDGPU::FeatureNSAEncoding) && (!IsNSA || IsPartialNSA) && 105906c3fb27SDimitry Andric AddrSize != Info->VAddrDwords) { 106006c3fb27SDimitry Andric unsigned VAddrSA = MI.getOperand(VAddrSAIdx).getReg(); 106106c3fb27SDimitry Andric unsigned VAddrSubSA = MRI.getSubReg(VAddrSA, AMDGPU::sub0); 106206c3fb27SDimitry Andric VAddrSA = VAddrSubSA ? VAddrSubSA : VAddrSA; 10630b57cec5SDimitry Andric 106406c3fb27SDimitry Andric auto AddrRCID = MCII->get(NewOpcode).operands()[VAddrSAIdx].RegClass; 106506c3fb27SDimitry Andric NewVAddrSA = MRI.getMatchingSuperReg(VAddrSA, AMDGPU::sub0, 10660b57cec5SDimitry Andric &MRI.getRegClass(AddrRCID)); 106706c3fb27SDimitry Andric if (!NewVAddrSA) 1068*0fca6ea1SDimitry Andric return; 10690b57cec5SDimitry Andric } 10700b57cec5SDimitry Andric 10710b57cec5SDimitry Andric MI.setOpcode(NewOpcode); 10720b57cec5SDimitry Andric 10730b57cec5SDimitry Andric if (NewVdata != AMDGPU::NoRegister) { 10740b57cec5SDimitry Andric MI.getOperand(VDataIdx) = MCOperand::createReg(NewVdata); 10750b57cec5SDimitry Andric 10760b57cec5SDimitry Andric if (IsAtomic) { 10770b57cec5SDimitry Andric // Atomic operations have an additional operand (a copy of data) 10780b57cec5SDimitry Andric MI.getOperand(VDstIdx) = MCOperand::createReg(NewVdata); 10790b57cec5SDimitry Andric } 10800b57cec5SDimitry Andric } 10810b57cec5SDimitry Andric 108206c3fb27SDimitry Andric if (NewVAddrSA) { 108306c3fb27SDimitry Andric MI.getOperand(VAddrSAIdx) = MCOperand::createReg(NewVAddrSA); 10840b57cec5SDimitry Andric } else if (IsNSA) { 10850b57cec5SDimitry Andric assert(AddrSize <= Info->VAddrDwords); 10860b57cec5SDimitry Andric MI.erase(MI.begin() + VAddr0Idx + AddrSize, 10870b57cec5SDimitry Andric MI.begin() + VAddr0Idx + Info->VAddrDwords); 10880b57cec5SDimitry Andric } 10890b57cec5SDimitry Andric } 10900b57cec5SDimitry Andric 109181ad6265SDimitry Andric // Opsel and neg bits are used in src_modifiers and standalone operands. Autogen 109281ad6265SDimitry Andric // decoder only adds to src_modifiers, so manually add the bits to the other 109381ad6265SDimitry Andric // operands. 1094*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertVOP3PDPPInst(MCInst &MI) const { 109581ad6265SDimitry Andric unsigned Opc = MI.getOpcode(); 109681ad6265SDimitry Andric unsigned DescNumOps = MCII->get(Opc).getNumOperands(); 1097fcaf7f86SDimitry Andric auto Mods = collectVOPModifiers(MI, true); 109881ad6265SDimitry Andric 109981ad6265SDimitry Andric if (MI.getNumOperands() < DescNumOps && 1100bdd1243dSDimitry Andric AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::vdst_in)) 110181ad6265SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::vdst_in); 110281ad6265SDimitry Andric 110381ad6265SDimitry Andric if (MI.getNumOperands() < DescNumOps && 1104bdd1243dSDimitry Andric AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) 1105fcaf7f86SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(Mods.OpSel), 110681ad6265SDimitry Andric AMDGPU::OpName::op_sel); 110781ad6265SDimitry Andric if (MI.getNumOperands() < DescNumOps && 1108bdd1243dSDimitry Andric AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel_hi)) 1109fcaf7f86SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(Mods.OpSelHi), 111081ad6265SDimitry Andric AMDGPU::OpName::op_sel_hi); 111181ad6265SDimitry Andric if (MI.getNumOperands() < DescNumOps && 1112bdd1243dSDimitry Andric AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::neg_lo)) 1113fcaf7f86SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(Mods.NegLo), 111481ad6265SDimitry Andric AMDGPU::OpName::neg_lo); 111581ad6265SDimitry Andric if (MI.getNumOperands() < DescNumOps && 1116bdd1243dSDimitry Andric AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::neg_hi)) 1117fcaf7f86SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(Mods.NegHi), 111881ad6265SDimitry Andric AMDGPU::OpName::neg_hi); 111981ad6265SDimitry Andric } 112081ad6265SDimitry Andric 112181ad6265SDimitry Andric // Create dummy old operand and insert optional operands 1122*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertVOPCDPPInst(MCInst &MI) const { 112381ad6265SDimitry Andric unsigned Opc = MI.getOpcode(); 112481ad6265SDimitry Andric unsigned DescNumOps = MCII->get(Opc).getNumOperands(); 112581ad6265SDimitry Andric 112681ad6265SDimitry Andric if (MI.getNumOperands() < DescNumOps && 1127bdd1243dSDimitry Andric AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::old)) 112881ad6265SDimitry Andric insertNamedMCOperand(MI, MCOperand::createReg(0), AMDGPU::OpName::old); 112981ad6265SDimitry Andric 113081ad6265SDimitry Andric if (MI.getNumOperands() < DescNumOps && 1131bdd1243dSDimitry Andric AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src0_modifiers)) 113281ad6265SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(0), 113381ad6265SDimitry Andric AMDGPU::OpName::src0_modifiers); 113481ad6265SDimitry Andric 113581ad6265SDimitry Andric if (MI.getNumOperands() < DescNumOps && 1136bdd1243dSDimitry Andric AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src1_modifiers)) 113781ad6265SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(0), 113881ad6265SDimitry Andric AMDGPU::OpName::src1_modifiers); 113981ad6265SDimitry Andric } 114081ad6265SDimitry Andric 1141*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertFMAanyK(MCInst &MI, int ImmLitIdx) const { 1142349cc55cSDimitry Andric assert(HasLiteral && "Should have decoded a literal"); 1143349cc55cSDimitry Andric const MCInstrDesc &Desc = MCII->get(MI.getOpcode()); 1144349cc55cSDimitry Andric unsigned DescNumOps = Desc.getNumOperands(); 114581ad6265SDimitry Andric insertNamedMCOperand(MI, MCOperand::createImm(Literal), 114681ad6265SDimitry Andric AMDGPU::OpName::immDeferred); 1147349cc55cSDimitry Andric assert(DescNumOps == MI.getNumOperands()); 1148349cc55cSDimitry Andric for (unsigned I = 0; I < DescNumOps; ++I) { 1149349cc55cSDimitry Andric auto &Op = MI.getOperand(I); 1150bdd1243dSDimitry Andric auto OpType = Desc.operands()[I].OperandType; 1151349cc55cSDimitry Andric bool IsDeferredOp = (OpType == AMDGPU::OPERAND_REG_IMM_FP32_DEFERRED || 1152349cc55cSDimitry Andric OpType == AMDGPU::OPERAND_REG_IMM_FP16_DEFERRED); 1153349cc55cSDimitry Andric if (Op.isImm() && Op.getImm() == AMDGPU::EncValues::LITERAL_CONST && 1154349cc55cSDimitry Andric IsDeferredOp) 1155349cc55cSDimitry Andric Op.setImm(Literal); 1156349cc55cSDimitry Andric } 1157349cc55cSDimitry Andric } 1158349cc55cSDimitry Andric 11590b57cec5SDimitry Andric const char* AMDGPUDisassembler::getRegClassName(unsigned RegClassID) const { 11600b57cec5SDimitry Andric return getContext().getRegisterInfo()-> 11610b57cec5SDimitry Andric getRegClassName(&AMDGPUMCRegisterClasses[RegClassID]); 11620b57cec5SDimitry Andric } 11630b57cec5SDimitry Andric 11640b57cec5SDimitry Andric inline 11650b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::errOperand(unsigned V, 11660b57cec5SDimitry Andric const Twine& ErrMsg) const { 11670b57cec5SDimitry Andric *CommentStream << "Error: " + ErrMsg; 11680b57cec5SDimitry Andric 11690b57cec5SDimitry Andric // ToDo: add support for error operands to MCInst.h 11700b57cec5SDimitry Andric // return MCOperand::createError(V); 11710b57cec5SDimitry Andric return MCOperand(); 11720b57cec5SDimitry Andric } 11730b57cec5SDimitry Andric 11740b57cec5SDimitry Andric inline 11750b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::createRegOperand(unsigned int RegId) const { 11760b57cec5SDimitry Andric return MCOperand::createReg(AMDGPU::getMCReg(RegId, STI)); 11770b57cec5SDimitry Andric } 11780b57cec5SDimitry Andric 11790b57cec5SDimitry Andric inline 11800b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::createRegOperand(unsigned RegClassID, 11810b57cec5SDimitry Andric unsigned Val) const { 11820b57cec5SDimitry Andric const auto& RegCl = AMDGPUMCRegisterClasses[RegClassID]; 11830b57cec5SDimitry Andric if (Val >= RegCl.getNumRegs()) 11840b57cec5SDimitry Andric return errOperand(Val, Twine(getRegClassName(RegClassID)) + 11850b57cec5SDimitry Andric ": unknown register " + Twine(Val)); 11860b57cec5SDimitry Andric return createRegOperand(RegCl.getRegister(Val)); 11870b57cec5SDimitry Andric } 11880b57cec5SDimitry Andric 11890b57cec5SDimitry Andric inline 11900b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::createSRegOperand(unsigned SRegClassID, 11910b57cec5SDimitry Andric unsigned Val) const { 11920b57cec5SDimitry Andric // ToDo: SI/CI have 104 SGPRs, VI - 102 11930b57cec5SDimitry Andric // Valery: here we accepting as much as we can, let assembler sort it out 11940b57cec5SDimitry Andric int shift = 0; 11950b57cec5SDimitry Andric switch (SRegClassID) { 11960b57cec5SDimitry Andric case AMDGPU::SGPR_32RegClassID: 11970b57cec5SDimitry Andric case AMDGPU::TTMP_32RegClassID: 11980b57cec5SDimitry Andric break; 11990b57cec5SDimitry Andric case AMDGPU::SGPR_64RegClassID: 12000b57cec5SDimitry Andric case AMDGPU::TTMP_64RegClassID: 12010b57cec5SDimitry Andric shift = 1; 12020b57cec5SDimitry Andric break; 12035f757f3fSDimitry Andric case AMDGPU::SGPR_96RegClassID: 12045f757f3fSDimitry Andric case AMDGPU::TTMP_96RegClassID: 12050b57cec5SDimitry Andric case AMDGPU::SGPR_128RegClassID: 12060b57cec5SDimitry Andric case AMDGPU::TTMP_128RegClassID: 12070b57cec5SDimitry Andric // ToDo: unclear if s[100:104] is available on VI. Can we use VCC as SGPR in 12080b57cec5SDimitry Andric // this bundle? 12090b57cec5SDimitry Andric case AMDGPU::SGPR_256RegClassID: 12100b57cec5SDimitry Andric case AMDGPU::TTMP_256RegClassID: 12110b57cec5SDimitry Andric // ToDo: unclear if s[96:104] is available on VI. Can we use VCC as SGPR in 12120b57cec5SDimitry Andric // this bundle? 1213bdd1243dSDimitry Andric case AMDGPU::SGPR_288RegClassID: 1214bdd1243dSDimitry Andric case AMDGPU::TTMP_288RegClassID: 1215bdd1243dSDimitry Andric case AMDGPU::SGPR_320RegClassID: 1216bdd1243dSDimitry Andric case AMDGPU::TTMP_320RegClassID: 1217bdd1243dSDimitry Andric case AMDGPU::SGPR_352RegClassID: 1218bdd1243dSDimitry Andric case AMDGPU::TTMP_352RegClassID: 1219bdd1243dSDimitry Andric case AMDGPU::SGPR_384RegClassID: 1220bdd1243dSDimitry Andric case AMDGPU::TTMP_384RegClassID: 12210b57cec5SDimitry Andric case AMDGPU::SGPR_512RegClassID: 12220b57cec5SDimitry Andric case AMDGPU::TTMP_512RegClassID: 12230b57cec5SDimitry Andric shift = 2; 12240b57cec5SDimitry Andric break; 12250b57cec5SDimitry Andric // ToDo: unclear if s[88:104] is available on VI. Can we use VCC as SGPR in 12260b57cec5SDimitry Andric // this bundle? 12270b57cec5SDimitry Andric default: 12280b57cec5SDimitry Andric llvm_unreachable("unhandled register class"); 12290b57cec5SDimitry Andric } 12300b57cec5SDimitry Andric 12310b57cec5SDimitry Andric if (Val % (1 << shift)) { 12320b57cec5SDimitry Andric *CommentStream << "Warning: " << getRegClassName(SRegClassID) 12330b57cec5SDimitry Andric << ": scalar reg isn't aligned " << Val; 12340b57cec5SDimitry Andric } 12350b57cec5SDimitry Andric 12360b57cec5SDimitry Andric return createRegOperand(SRegClassID, Val >> shift); 12370b57cec5SDimitry Andric } 12380b57cec5SDimitry Andric 12395f757f3fSDimitry Andric MCOperand AMDGPUDisassembler::createVGPR16Operand(unsigned RegIdx, 12405f757f3fSDimitry Andric bool IsHi) const { 1241647cbc5dSDimitry Andric unsigned RegIdxInVGPR16 = RegIdx * 2 + (IsHi ? 1 : 0); 1242647cbc5dSDimitry Andric return createRegOperand(AMDGPU::VGPR_16RegClassID, RegIdxInVGPR16); 12435f757f3fSDimitry Andric } 12445f757f3fSDimitry Andric 1245349cc55cSDimitry Andric // Decode Literals for insts which always have a literal in the encoding 1246349cc55cSDimitry Andric MCOperand 1247349cc55cSDimitry Andric AMDGPUDisassembler::decodeMandatoryLiteralConstant(unsigned Val) const { 1248349cc55cSDimitry Andric if (HasLiteral) { 124981ad6265SDimitry Andric assert( 125081ad6265SDimitry Andric AMDGPU::hasVOPD(STI) && 125181ad6265SDimitry Andric "Should only decode multiple kimm with VOPD, check VSrc operand types"); 1252349cc55cSDimitry Andric if (Literal != Val) 1253349cc55cSDimitry Andric return errOperand(Val, "More than one unique literal is illegal"); 1254349cc55cSDimitry Andric } 1255349cc55cSDimitry Andric HasLiteral = true; 1256349cc55cSDimitry Andric Literal = Val; 1257349cc55cSDimitry Andric return MCOperand::createImm(Literal); 1258349cc55cSDimitry Andric } 1259349cc55cSDimitry Andric 12605f757f3fSDimitry Andric MCOperand AMDGPUDisassembler::decodeLiteralConstant(bool ExtendFP64) const { 12610b57cec5SDimitry Andric // For now all literal constants are supposed to be unsigned integer 12620b57cec5SDimitry Andric // ToDo: deal with signed/unsigned 64-bit integer constants 12630b57cec5SDimitry Andric // ToDo: deal with float/double constants 12640b57cec5SDimitry Andric if (!HasLiteral) { 12650b57cec5SDimitry Andric if (Bytes.size() < 4) { 12660b57cec5SDimitry Andric return errOperand(0, "cannot read literal, inst bytes left " + 12670b57cec5SDimitry Andric Twine(Bytes.size())); 12680b57cec5SDimitry Andric } 12690b57cec5SDimitry Andric HasLiteral = true; 12705f757f3fSDimitry Andric Literal = Literal64 = eatBytes<uint32_t>(Bytes); 12715f757f3fSDimitry Andric if (ExtendFP64) 12725f757f3fSDimitry Andric Literal64 <<= 32; 12730b57cec5SDimitry Andric } 12745f757f3fSDimitry Andric return MCOperand::createImm(ExtendFP64 ? Literal64 : Literal); 12750b57cec5SDimitry Andric } 12760b57cec5SDimitry Andric 12770b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeIntImmed(unsigned Imm) { 12780b57cec5SDimitry Andric using namespace AMDGPU::EncValues; 12790b57cec5SDimitry Andric 12800b57cec5SDimitry Andric assert(Imm >= INLINE_INTEGER_C_MIN && Imm <= INLINE_INTEGER_C_MAX); 12810b57cec5SDimitry Andric return MCOperand::createImm((Imm <= INLINE_INTEGER_C_POSITIVE_MAX) ? 12820b57cec5SDimitry Andric (static_cast<int64_t>(Imm) - INLINE_INTEGER_C_MIN) : 12830b57cec5SDimitry Andric (INLINE_INTEGER_C_POSITIVE_MAX - static_cast<int64_t>(Imm))); 12840b57cec5SDimitry Andric // Cast prevents negative overflow. 12850b57cec5SDimitry Andric } 12860b57cec5SDimitry Andric 12870b57cec5SDimitry Andric static int64_t getInlineImmVal32(unsigned Imm) { 12880b57cec5SDimitry Andric switch (Imm) { 12890b57cec5SDimitry Andric case 240: 129006c3fb27SDimitry Andric return llvm::bit_cast<uint32_t>(0.5f); 12910b57cec5SDimitry Andric case 241: 129206c3fb27SDimitry Andric return llvm::bit_cast<uint32_t>(-0.5f); 12930b57cec5SDimitry Andric case 242: 129406c3fb27SDimitry Andric return llvm::bit_cast<uint32_t>(1.0f); 12950b57cec5SDimitry Andric case 243: 129606c3fb27SDimitry Andric return llvm::bit_cast<uint32_t>(-1.0f); 12970b57cec5SDimitry Andric case 244: 129806c3fb27SDimitry Andric return llvm::bit_cast<uint32_t>(2.0f); 12990b57cec5SDimitry Andric case 245: 130006c3fb27SDimitry Andric return llvm::bit_cast<uint32_t>(-2.0f); 13010b57cec5SDimitry Andric case 246: 130206c3fb27SDimitry Andric return llvm::bit_cast<uint32_t>(4.0f); 13030b57cec5SDimitry Andric case 247: 130406c3fb27SDimitry Andric return llvm::bit_cast<uint32_t>(-4.0f); 13050b57cec5SDimitry Andric case 248: // 1 / (2 * PI) 13060b57cec5SDimitry Andric return 0x3e22f983; 13070b57cec5SDimitry Andric default: 13080b57cec5SDimitry Andric llvm_unreachable("invalid fp inline imm"); 13090b57cec5SDimitry Andric } 13100b57cec5SDimitry Andric } 13110b57cec5SDimitry Andric 13120b57cec5SDimitry Andric static int64_t getInlineImmVal64(unsigned Imm) { 13130b57cec5SDimitry Andric switch (Imm) { 13140b57cec5SDimitry Andric case 240: 131506c3fb27SDimitry Andric return llvm::bit_cast<uint64_t>(0.5); 13160b57cec5SDimitry Andric case 241: 131706c3fb27SDimitry Andric return llvm::bit_cast<uint64_t>(-0.5); 13180b57cec5SDimitry Andric case 242: 131906c3fb27SDimitry Andric return llvm::bit_cast<uint64_t>(1.0); 13200b57cec5SDimitry Andric case 243: 132106c3fb27SDimitry Andric return llvm::bit_cast<uint64_t>(-1.0); 13220b57cec5SDimitry Andric case 244: 132306c3fb27SDimitry Andric return llvm::bit_cast<uint64_t>(2.0); 13240b57cec5SDimitry Andric case 245: 132506c3fb27SDimitry Andric return llvm::bit_cast<uint64_t>(-2.0); 13260b57cec5SDimitry Andric case 246: 132706c3fb27SDimitry Andric return llvm::bit_cast<uint64_t>(4.0); 13280b57cec5SDimitry Andric case 247: 132906c3fb27SDimitry Andric return llvm::bit_cast<uint64_t>(-4.0); 13300b57cec5SDimitry Andric case 248: // 1 / (2 * PI) 13310b57cec5SDimitry Andric return 0x3fc45f306dc9c882; 13320b57cec5SDimitry Andric default: 13330b57cec5SDimitry Andric llvm_unreachable("invalid fp inline imm"); 13340b57cec5SDimitry Andric } 13350b57cec5SDimitry Andric } 13360b57cec5SDimitry Andric 1337*0fca6ea1SDimitry Andric static int64_t getInlineImmValF16(unsigned Imm) { 13380b57cec5SDimitry Andric switch (Imm) { 13390b57cec5SDimitry Andric case 240: 13400b57cec5SDimitry Andric return 0x3800; 13410b57cec5SDimitry Andric case 241: 13420b57cec5SDimitry Andric return 0xB800; 13430b57cec5SDimitry Andric case 242: 13440b57cec5SDimitry Andric return 0x3C00; 13450b57cec5SDimitry Andric case 243: 13460b57cec5SDimitry Andric return 0xBC00; 13470b57cec5SDimitry Andric case 244: 13480b57cec5SDimitry Andric return 0x4000; 13490b57cec5SDimitry Andric case 245: 13500b57cec5SDimitry Andric return 0xC000; 13510b57cec5SDimitry Andric case 246: 13520b57cec5SDimitry Andric return 0x4400; 13530b57cec5SDimitry Andric case 247: 13540b57cec5SDimitry Andric return 0xC400; 13550b57cec5SDimitry Andric case 248: // 1 / (2 * PI) 13560b57cec5SDimitry Andric return 0x3118; 13570b57cec5SDimitry Andric default: 13580b57cec5SDimitry Andric llvm_unreachable("invalid fp inline imm"); 13590b57cec5SDimitry Andric } 13600b57cec5SDimitry Andric } 13610b57cec5SDimitry Andric 1362*0fca6ea1SDimitry Andric static int64_t getInlineImmValBF16(unsigned Imm) { 1363*0fca6ea1SDimitry Andric switch (Imm) { 1364*0fca6ea1SDimitry Andric case 240: 1365*0fca6ea1SDimitry Andric return 0x3F00; 1366*0fca6ea1SDimitry Andric case 241: 1367*0fca6ea1SDimitry Andric return 0xBF00; 1368*0fca6ea1SDimitry Andric case 242: 1369*0fca6ea1SDimitry Andric return 0x3F80; 1370*0fca6ea1SDimitry Andric case 243: 1371*0fca6ea1SDimitry Andric return 0xBF80; 1372*0fca6ea1SDimitry Andric case 244: 1373*0fca6ea1SDimitry Andric return 0x4000; 1374*0fca6ea1SDimitry Andric case 245: 1375*0fca6ea1SDimitry Andric return 0xC000; 1376*0fca6ea1SDimitry Andric case 246: 1377*0fca6ea1SDimitry Andric return 0x4080; 1378*0fca6ea1SDimitry Andric case 247: 1379*0fca6ea1SDimitry Andric return 0xC080; 1380*0fca6ea1SDimitry Andric case 248: // 1 / (2 * PI) 1381*0fca6ea1SDimitry Andric return 0x3E22; 1382*0fca6ea1SDimitry Andric default: 1383*0fca6ea1SDimitry Andric llvm_unreachable("invalid fp inline imm"); 1384*0fca6ea1SDimitry Andric } 1385*0fca6ea1SDimitry Andric } 1386*0fca6ea1SDimitry Andric 1387*0fca6ea1SDimitry Andric static int64_t getInlineImmVal16(unsigned Imm, AMDGPU::OperandSemantics Sema) { 1388*0fca6ea1SDimitry Andric return (Sema == AMDGPU::OperandSemantics::BF16) ? getInlineImmValBF16(Imm) 1389*0fca6ea1SDimitry Andric : getInlineImmValF16(Imm); 1390*0fca6ea1SDimitry Andric } 1391*0fca6ea1SDimitry Andric 1392*0fca6ea1SDimitry Andric MCOperand AMDGPUDisassembler::decodeFPImmed(unsigned ImmWidth, unsigned Imm, 1393*0fca6ea1SDimitry Andric AMDGPU::OperandSemantics Sema) { 1394*0fca6ea1SDimitry Andric assert(Imm >= AMDGPU::EncValues::INLINE_FLOATING_C_MIN && 1395*0fca6ea1SDimitry Andric Imm <= AMDGPU::EncValues::INLINE_FLOATING_C_MAX); 13960b57cec5SDimitry Andric 13970b57cec5SDimitry Andric // ToDo: case 248: 1/(2*PI) - is allowed only on VI 139806c3fb27SDimitry Andric // ImmWidth 0 is a default case where operand should not allow immediates. 139906c3fb27SDimitry Andric // Imm value is still decoded into 32 bit immediate operand, inst printer will 140006c3fb27SDimitry Andric // use it to print verbose error message. 140106c3fb27SDimitry Andric switch (ImmWidth) { 140206c3fb27SDimitry Andric case 0: 140306c3fb27SDimitry Andric case 32: 14040b57cec5SDimitry Andric return MCOperand::createImm(getInlineImmVal32(Imm)); 140506c3fb27SDimitry Andric case 64: 14060b57cec5SDimitry Andric return MCOperand::createImm(getInlineImmVal64(Imm)); 140706c3fb27SDimitry Andric case 16: 1408*0fca6ea1SDimitry Andric return MCOperand::createImm(getInlineImmVal16(Imm, Sema)); 14090b57cec5SDimitry Andric default: 14100b57cec5SDimitry Andric llvm_unreachable("implement me"); 14110b57cec5SDimitry Andric } 14120b57cec5SDimitry Andric } 14130b57cec5SDimitry Andric 14140b57cec5SDimitry Andric unsigned AMDGPUDisassembler::getVgprClassId(const OpWidthTy Width) const { 14150b57cec5SDimitry Andric using namespace AMDGPU; 14160b57cec5SDimitry Andric 14170b57cec5SDimitry Andric assert(OPW_FIRST_ <= Width && Width < OPW_LAST_); 14180b57cec5SDimitry Andric switch (Width) { 14190b57cec5SDimitry Andric default: // fall 14200b57cec5SDimitry Andric case OPW32: 14210b57cec5SDimitry Andric case OPW16: 14220b57cec5SDimitry Andric case OPWV216: 14230b57cec5SDimitry Andric return VGPR_32RegClassID; 1424fe6060f1SDimitry Andric case OPW64: 1425fe6060f1SDimitry Andric case OPWV232: return VReg_64RegClassID; 1426fe6060f1SDimitry Andric case OPW96: return VReg_96RegClassID; 14270b57cec5SDimitry Andric case OPW128: return VReg_128RegClassID; 1428fe6060f1SDimitry Andric case OPW160: return VReg_160RegClassID; 1429fe6060f1SDimitry Andric case OPW256: return VReg_256RegClassID; 1430bdd1243dSDimitry Andric case OPW288: return VReg_288RegClassID; 1431bdd1243dSDimitry Andric case OPW320: return VReg_320RegClassID; 1432bdd1243dSDimitry Andric case OPW352: return VReg_352RegClassID; 1433bdd1243dSDimitry Andric case OPW384: return VReg_384RegClassID; 1434fe6060f1SDimitry Andric case OPW512: return VReg_512RegClassID; 1435fe6060f1SDimitry Andric case OPW1024: return VReg_1024RegClassID; 14360b57cec5SDimitry Andric } 14370b57cec5SDimitry Andric } 14380b57cec5SDimitry Andric 14390b57cec5SDimitry Andric unsigned AMDGPUDisassembler::getAgprClassId(const OpWidthTy Width) const { 14400b57cec5SDimitry Andric using namespace AMDGPU; 14410b57cec5SDimitry Andric 14420b57cec5SDimitry Andric assert(OPW_FIRST_ <= Width && Width < OPW_LAST_); 14430b57cec5SDimitry Andric switch (Width) { 14440b57cec5SDimitry Andric default: // fall 14450b57cec5SDimitry Andric case OPW32: 14460b57cec5SDimitry Andric case OPW16: 14470b57cec5SDimitry Andric case OPWV216: 14480b57cec5SDimitry Andric return AGPR_32RegClassID; 1449fe6060f1SDimitry Andric case OPW64: 1450fe6060f1SDimitry Andric case OPWV232: return AReg_64RegClassID; 1451fe6060f1SDimitry Andric case OPW96: return AReg_96RegClassID; 14520b57cec5SDimitry Andric case OPW128: return AReg_128RegClassID; 1453fe6060f1SDimitry Andric case OPW160: return AReg_160RegClassID; 14545ffd83dbSDimitry Andric case OPW256: return AReg_256RegClassID; 1455bdd1243dSDimitry Andric case OPW288: return AReg_288RegClassID; 1456bdd1243dSDimitry Andric case OPW320: return AReg_320RegClassID; 1457bdd1243dSDimitry Andric case OPW352: return AReg_352RegClassID; 1458bdd1243dSDimitry Andric case OPW384: return AReg_384RegClassID; 14590b57cec5SDimitry Andric case OPW512: return AReg_512RegClassID; 14600b57cec5SDimitry Andric case OPW1024: return AReg_1024RegClassID; 14610b57cec5SDimitry Andric } 14620b57cec5SDimitry Andric } 14630b57cec5SDimitry Andric 14640b57cec5SDimitry Andric 14650b57cec5SDimitry Andric unsigned AMDGPUDisassembler::getSgprClassId(const OpWidthTy Width) const { 14660b57cec5SDimitry Andric using namespace AMDGPU; 14670b57cec5SDimitry Andric 14680b57cec5SDimitry Andric assert(OPW_FIRST_ <= Width && Width < OPW_LAST_); 14690b57cec5SDimitry Andric switch (Width) { 14700b57cec5SDimitry Andric default: // fall 14710b57cec5SDimitry Andric case OPW32: 14720b57cec5SDimitry Andric case OPW16: 14730b57cec5SDimitry Andric case OPWV216: 14740b57cec5SDimitry Andric return SGPR_32RegClassID; 1475fe6060f1SDimitry Andric case OPW64: 1476fe6060f1SDimitry Andric case OPWV232: return SGPR_64RegClassID; 1477fe6060f1SDimitry Andric case OPW96: return SGPR_96RegClassID; 14780b57cec5SDimitry Andric case OPW128: return SGPR_128RegClassID; 1479fe6060f1SDimitry Andric case OPW160: return SGPR_160RegClassID; 14800b57cec5SDimitry Andric case OPW256: return SGPR_256RegClassID; 1481bdd1243dSDimitry Andric case OPW288: return SGPR_288RegClassID; 1482bdd1243dSDimitry Andric case OPW320: return SGPR_320RegClassID; 1483bdd1243dSDimitry Andric case OPW352: return SGPR_352RegClassID; 1484bdd1243dSDimitry Andric case OPW384: return SGPR_384RegClassID; 14850b57cec5SDimitry Andric case OPW512: return SGPR_512RegClassID; 14860b57cec5SDimitry Andric } 14870b57cec5SDimitry Andric } 14880b57cec5SDimitry Andric 14890b57cec5SDimitry Andric unsigned AMDGPUDisassembler::getTtmpClassId(const OpWidthTy Width) const { 14900b57cec5SDimitry Andric using namespace AMDGPU; 14910b57cec5SDimitry Andric 14920b57cec5SDimitry Andric assert(OPW_FIRST_ <= Width && Width < OPW_LAST_); 14930b57cec5SDimitry Andric switch (Width) { 14940b57cec5SDimitry Andric default: // fall 14950b57cec5SDimitry Andric case OPW32: 14960b57cec5SDimitry Andric case OPW16: 14970b57cec5SDimitry Andric case OPWV216: 14980b57cec5SDimitry Andric return TTMP_32RegClassID; 1499fe6060f1SDimitry Andric case OPW64: 1500fe6060f1SDimitry Andric case OPWV232: return TTMP_64RegClassID; 15010b57cec5SDimitry Andric case OPW128: return TTMP_128RegClassID; 15020b57cec5SDimitry Andric case OPW256: return TTMP_256RegClassID; 1503bdd1243dSDimitry Andric case OPW288: return TTMP_288RegClassID; 1504bdd1243dSDimitry Andric case OPW320: return TTMP_320RegClassID; 1505bdd1243dSDimitry Andric case OPW352: return TTMP_352RegClassID; 1506bdd1243dSDimitry Andric case OPW384: return TTMP_384RegClassID; 15070b57cec5SDimitry Andric case OPW512: return TTMP_512RegClassID; 15080b57cec5SDimitry Andric } 15090b57cec5SDimitry Andric } 15100b57cec5SDimitry Andric 15110b57cec5SDimitry Andric int AMDGPUDisassembler::getTTmpIdx(unsigned Val) const { 15120b57cec5SDimitry Andric using namespace AMDGPU::EncValues; 15130b57cec5SDimitry Andric 1514e8d8bef9SDimitry Andric unsigned TTmpMin = isGFX9Plus() ? TTMP_GFX9PLUS_MIN : TTMP_VI_MIN; 1515e8d8bef9SDimitry Andric unsigned TTmpMax = isGFX9Plus() ? TTMP_GFX9PLUS_MAX : TTMP_VI_MAX; 15160b57cec5SDimitry Andric 15170b57cec5SDimitry Andric return (TTmpMin <= Val && Val <= TTmpMax)? Val - TTmpMin : -1; 15180b57cec5SDimitry Andric } 15190b57cec5SDimitry Andric 1520349cc55cSDimitry Andric MCOperand AMDGPUDisassembler::decodeSrcOp(const OpWidthTy Width, unsigned Val, 152106c3fb27SDimitry Andric bool MandatoryLiteral, 1522*0fca6ea1SDimitry Andric unsigned ImmWidth, 1523*0fca6ea1SDimitry Andric AMDGPU::OperandSemantics Sema) const { 15240b57cec5SDimitry Andric using namespace AMDGPU::EncValues; 15250b57cec5SDimitry Andric 15260b57cec5SDimitry Andric assert(Val < 1024); // enum10 15270b57cec5SDimitry Andric 15280b57cec5SDimitry Andric bool IsAGPR = Val & 512; 15290b57cec5SDimitry Andric Val &= 511; 15300b57cec5SDimitry Andric 15310b57cec5SDimitry Andric if (VGPR_MIN <= Val && Val <= VGPR_MAX) { 15320b57cec5SDimitry Andric return createRegOperand(IsAGPR ? getAgprClassId(Width) 15330b57cec5SDimitry Andric : getVgprClassId(Width), Val - VGPR_MIN); 15340b57cec5SDimitry Andric } 15355f757f3fSDimitry Andric return decodeNonVGPRSrcOp(Width, Val & 0xFF, MandatoryLiteral, ImmWidth, 1536*0fca6ea1SDimitry Andric Sema); 15375f757f3fSDimitry Andric } 15385f757f3fSDimitry Andric 1539*0fca6ea1SDimitry Andric MCOperand 1540*0fca6ea1SDimitry Andric AMDGPUDisassembler::decodeNonVGPRSrcOp(const OpWidthTy Width, unsigned Val, 1541*0fca6ea1SDimitry Andric bool MandatoryLiteral, unsigned ImmWidth, 1542*0fca6ea1SDimitry Andric AMDGPU::OperandSemantics Sema) const { 15435f757f3fSDimitry Andric // Cases when Val{8} is 1 (vgpr, agpr or true 16 vgpr) should have been 15445f757f3fSDimitry Andric // decoded earlier. 15455f757f3fSDimitry Andric assert(Val < (1 << 8) && "9-bit Src encoding when Val{8} is 0"); 15465f757f3fSDimitry Andric using namespace AMDGPU::EncValues; 15475f757f3fSDimitry Andric 15480b57cec5SDimitry Andric if (Val <= SGPR_MAX) { 1549e8d8bef9SDimitry Andric // "SGPR_MIN <= Val" is always true and causes compilation warning. 1550bdd1243dSDimitry Andric static_assert(SGPR_MIN == 0); 15510b57cec5SDimitry Andric return createSRegOperand(getSgprClassId(Width), Val - SGPR_MIN); 15520b57cec5SDimitry Andric } 15530b57cec5SDimitry Andric 15540b57cec5SDimitry Andric int TTmpIdx = getTTmpIdx(Val); 15550b57cec5SDimitry Andric if (TTmpIdx >= 0) { 15560b57cec5SDimitry Andric return createSRegOperand(getTtmpClassId(Width), TTmpIdx); 15570b57cec5SDimitry Andric } 15580b57cec5SDimitry Andric 15590b57cec5SDimitry Andric if (INLINE_INTEGER_C_MIN <= Val && Val <= INLINE_INTEGER_C_MAX) 15600b57cec5SDimitry Andric return decodeIntImmed(Val); 15610b57cec5SDimitry Andric 15620b57cec5SDimitry Andric if (INLINE_FLOATING_C_MIN <= Val && Val <= INLINE_FLOATING_C_MAX) 1563*0fca6ea1SDimitry Andric return decodeFPImmed(ImmWidth, Val, Sema); 15640b57cec5SDimitry Andric 1565349cc55cSDimitry Andric if (Val == LITERAL_CONST) { 1566349cc55cSDimitry Andric if (MandatoryLiteral) 1567349cc55cSDimitry Andric // Keep a sentinel value for deferred setting 1568349cc55cSDimitry Andric return MCOperand::createImm(LITERAL_CONST); 1569*0fca6ea1SDimitry Andric return decodeLiteralConstant(Sema == AMDGPU::OperandSemantics::FP64); 1570349cc55cSDimitry Andric } 15710b57cec5SDimitry Andric 15720b57cec5SDimitry Andric switch (Width) { 15730b57cec5SDimitry Andric case OPW32: 15740b57cec5SDimitry Andric case OPW16: 15750b57cec5SDimitry Andric case OPWV216: 15760b57cec5SDimitry Andric return decodeSpecialReg32(Val); 15770b57cec5SDimitry Andric case OPW64: 1578fe6060f1SDimitry Andric case OPWV232: 15790b57cec5SDimitry Andric return decodeSpecialReg64(Val); 15800b57cec5SDimitry Andric default: 15810b57cec5SDimitry Andric llvm_unreachable("unexpected immediate type"); 15820b57cec5SDimitry Andric } 15830b57cec5SDimitry Andric } 15840b57cec5SDimitry Andric 158581ad6265SDimitry Andric // Bit 0 of DstY isn't stored in the instruction, because it's always the 158681ad6265SDimitry Andric // opposite of bit 0 of DstX. 158781ad6265SDimitry Andric MCOperand AMDGPUDisassembler::decodeVOPDDstYOp(MCInst &Inst, 158881ad6265SDimitry Andric unsigned Val) const { 158981ad6265SDimitry Andric int VDstXInd = 159081ad6265SDimitry Andric AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::vdstX); 159181ad6265SDimitry Andric assert(VDstXInd != -1); 159281ad6265SDimitry Andric assert(Inst.getOperand(VDstXInd).isReg()); 159381ad6265SDimitry Andric unsigned XDstReg = MRI.getEncodingValue(Inst.getOperand(VDstXInd).getReg()); 159481ad6265SDimitry Andric Val |= ~XDstReg & 1; 159581ad6265SDimitry Andric auto Width = llvm::AMDGPUDisassembler::OPW32; 159681ad6265SDimitry Andric return createRegOperand(getVgprClassId(Width), Val); 159781ad6265SDimitry Andric } 159881ad6265SDimitry Andric 15990b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeSpecialReg32(unsigned Val) const { 16000b57cec5SDimitry Andric using namespace AMDGPU; 16010b57cec5SDimitry Andric 16020b57cec5SDimitry Andric switch (Val) { 1603bdd1243dSDimitry Andric // clang-format off 16040b57cec5SDimitry Andric case 102: return createRegOperand(FLAT_SCR_LO); 16050b57cec5SDimitry Andric case 103: return createRegOperand(FLAT_SCR_HI); 16060b57cec5SDimitry Andric case 104: return createRegOperand(XNACK_MASK_LO); 16070b57cec5SDimitry Andric case 105: return createRegOperand(XNACK_MASK_HI); 16080b57cec5SDimitry Andric case 106: return createRegOperand(VCC_LO); 16090b57cec5SDimitry Andric case 107: return createRegOperand(VCC_HI); 16100b57cec5SDimitry Andric case 108: return createRegOperand(TBA_LO); 16110b57cec5SDimitry Andric case 109: return createRegOperand(TBA_HI); 16120b57cec5SDimitry Andric case 110: return createRegOperand(TMA_LO); 16130b57cec5SDimitry Andric case 111: return createRegOperand(TMA_HI); 161481ad6265SDimitry Andric case 124: 161581ad6265SDimitry Andric return isGFX11Plus() ? createRegOperand(SGPR_NULL) : createRegOperand(M0); 161681ad6265SDimitry Andric case 125: 161781ad6265SDimitry Andric return isGFX11Plus() ? createRegOperand(M0) : createRegOperand(SGPR_NULL); 16180b57cec5SDimitry Andric case 126: return createRegOperand(EXEC_LO); 16190b57cec5SDimitry Andric case 127: return createRegOperand(EXEC_HI); 1620bdd1243dSDimitry Andric case 235: return createRegOperand(SRC_SHARED_BASE_LO); 1621bdd1243dSDimitry Andric case 236: return createRegOperand(SRC_SHARED_LIMIT_LO); 1622bdd1243dSDimitry Andric case 237: return createRegOperand(SRC_PRIVATE_BASE_LO); 1623bdd1243dSDimitry Andric case 238: return createRegOperand(SRC_PRIVATE_LIMIT_LO); 16240b57cec5SDimitry Andric case 239: return createRegOperand(SRC_POPS_EXITING_WAVE_ID); 16250b57cec5SDimitry Andric case 251: return createRegOperand(SRC_VCCZ); 16260b57cec5SDimitry Andric case 252: return createRegOperand(SRC_EXECZ); 16270b57cec5SDimitry Andric case 253: return createRegOperand(SRC_SCC); 16280b57cec5SDimitry Andric case 254: return createRegOperand(LDS_DIRECT); 16290b57cec5SDimitry Andric default: break; 1630bdd1243dSDimitry Andric // clang-format on 16310b57cec5SDimitry Andric } 16320b57cec5SDimitry Andric return errOperand(Val, "unknown operand encoding " + Twine(Val)); 16330b57cec5SDimitry Andric } 16340b57cec5SDimitry Andric 16350b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeSpecialReg64(unsigned Val) const { 16360b57cec5SDimitry Andric using namespace AMDGPU; 16370b57cec5SDimitry Andric 16380b57cec5SDimitry Andric switch (Val) { 16390b57cec5SDimitry Andric case 102: return createRegOperand(FLAT_SCR); 16400b57cec5SDimitry Andric case 104: return createRegOperand(XNACK_MASK); 16410b57cec5SDimitry Andric case 106: return createRegOperand(VCC); 16420b57cec5SDimitry Andric case 108: return createRegOperand(TBA); 16430b57cec5SDimitry Andric case 110: return createRegOperand(TMA); 164481ad6265SDimitry Andric case 124: 164581ad6265SDimitry Andric if (isGFX11Plus()) 164681ad6265SDimitry Andric return createRegOperand(SGPR_NULL); 164781ad6265SDimitry Andric break; 164881ad6265SDimitry Andric case 125: 164981ad6265SDimitry Andric if (!isGFX11Plus()) 165081ad6265SDimitry Andric return createRegOperand(SGPR_NULL); 165181ad6265SDimitry Andric break; 16520b57cec5SDimitry Andric case 126: return createRegOperand(EXEC); 16530b57cec5SDimitry Andric case 235: return createRegOperand(SRC_SHARED_BASE); 16540b57cec5SDimitry Andric case 236: return createRegOperand(SRC_SHARED_LIMIT); 16550b57cec5SDimitry Andric case 237: return createRegOperand(SRC_PRIVATE_BASE); 16560b57cec5SDimitry Andric case 238: return createRegOperand(SRC_PRIVATE_LIMIT); 16570b57cec5SDimitry Andric case 239: return createRegOperand(SRC_POPS_EXITING_WAVE_ID); 16580b57cec5SDimitry Andric case 251: return createRegOperand(SRC_VCCZ); 16590b57cec5SDimitry Andric case 252: return createRegOperand(SRC_EXECZ); 16600b57cec5SDimitry Andric case 253: return createRegOperand(SRC_SCC); 16610b57cec5SDimitry Andric default: break; 16620b57cec5SDimitry Andric } 16630b57cec5SDimitry Andric return errOperand(Val, "unknown operand encoding " + Twine(Val)); 16640b57cec5SDimitry Andric } 16650b57cec5SDimitry Andric 1666*0fca6ea1SDimitry Andric MCOperand 1667*0fca6ea1SDimitry Andric AMDGPUDisassembler::decodeSDWASrc(const OpWidthTy Width, const unsigned Val, 1668*0fca6ea1SDimitry Andric unsigned ImmWidth, 1669*0fca6ea1SDimitry Andric AMDGPU::OperandSemantics Sema) const { 16700b57cec5SDimitry Andric using namespace AMDGPU::SDWA; 16710b57cec5SDimitry Andric using namespace AMDGPU::EncValues; 16720b57cec5SDimitry Andric 167306c3fb27SDimitry Andric if (STI.hasFeature(AMDGPU::FeatureGFX9) || 167406c3fb27SDimitry Andric STI.hasFeature(AMDGPU::FeatureGFX10)) { 16750b57cec5SDimitry Andric // XXX: cast to int is needed to avoid stupid warning: 16760b57cec5SDimitry Andric // compare with unsigned is always true 16770b57cec5SDimitry Andric if (int(SDWA9EncValues::SRC_VGPR_MIN) <= int(Val) && 16780b57cec5SDimitry Andric Val <= SDWA9EncValues::SRC_VGPR_MAX) { 16790b57cec5SDimitry Andric return createRegOperand(getVgprClassId(Width), 16800b57cec5SDimitry Andric Val - SDWA9EncValues::SRC_VGPR_MIN); 16810b57cec5SDimitry Andric } 16820b57cec5SDimitry Andric if (SDWA9EncValues::SRC_SGPR_MIN <= Val && 1683e8d8bef9SDimitry Andric Val <= (isGFX10Plus() ? SDWA9EncValues::SRC_SGPR_MAX_GFX10 16840b57cec5SDimitry Andric : SDWA9EncValues::SRC_SGPR_MAX_SI)) { 16850b57cec5SDimitry Andric return createSRegOperand(getSgprClassId(Width), 16860b57cec5SDimitry Andric Val - SDWA9EncValues::SRC_SGPR_MIN); 16870b57cec5SDimitry Andric } 16880b57cec5SDimitry Andric if (SDWA9EncValues::SRC_TTMP_MIN <= Val && 16890b57cec5SDimitry Andric Val <= SDWA9EncValues::SRC_TTMP_MAX) { 16900b57cec5SDimitry Andric return createSRegOperand(getTtmpClassId(Width), 16910b57cec5SDimitry Andric Val - SDWA9EncValues::SRC_TTMP_MIN); 16920b57cec5SDimitry Andric } 16930b57cec5SDimitry Andric 16940b57cec5SDimitry Andric const unsigned SVal = Val - SDWA9EncValues::SRC_SGPR_MIN; 16950b57cec5SDimitry Andric 16960b57cec5SDimitry Andric if (INLINE_INTEGER_C_MIN <= SVal && SVal <= INLINE_INTEGER_C_MAX) 16970b57cec5SDimitry Andric return decodeIntImmed(SVal); 16980b57cec5SDimitry Andric 16990b57cec5SDimitry Andric if (INLINE_FLOATING_C_MIN <= SVal && SVal <= INLINE_FLOATING_C_MAX) 1700*0fca6ea1SDimitry Andric return decodeFPImmed(ImmWidth, SVal, Sema); 17010b57cec5SDimitry Andric 17020b57cec5SDimitry Andric return decodeSpecialReg32(SVal); 17030b57cec5SDimitry Andric } 1704*0fca6ea1SDimitry Andric if (STI.hasFeature(AMDGPU::FeatureVolcanicIslands)) 1705*0fca6ea1SDimitry Andric return createRegOperand(getVgprClassId(Width), Val); 17060b57cec5SDimitry Andric llvm_unreachable("unsupported target"); 17070b57cec5SDimitry Andric } 17080b57cec5SDimitry Andric 17090b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeSDWASrc16(unsigned Val) const { 1710*0fca6ea1SDimitry Andric return decodeSDWASrc(OPW16, Val, 16, AMDGPU::OperandSemantics::FP16); 17110b57cec5SDimitry Andric } 17120b57cec5SDimitry Andric 17130b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeSDWASrc32(unsigned Val) const { 1714*0fca6ea1SDimitry Andric return decodeSDWASrc(OPW32, Val, 32, AMDGPU::OperandSemantics::FP32); 17150b57cec5SDimitry Andric } 17160b57cec5SDimitry Andric 17170b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeSDWAVopcDst(unsigned Val) const { 17180b57cec5SDimitry Andric using namespace AMDGPU::SDWA; 17190b57cec5SDimitry Andric 172006c3fb27SDimitry Andric assert((STI.hasFeature(AMDGPU::FeatureGFX9) || 172106c3fb27SDimitry Andric STI.hasFeature(AMDGPU::FeatureGFX10)) && 17220b57cec5SDimitry Andric "SDWAVopcDst should be present only on GFX9+"); 17230b57cec5SDimitry Andric 172406c3fb27SDimitry Andric bool IsWave64 = STI.hasFeature(AMDGPU::FeatureWavefrontSize64); 17250b57cec5SDimitry Andric 17260b57cec5SDimitry Andric if (Val & SDWA9EncValues::VOPC_DST_VCC_MASK) { 17270b57cec5SDimitry Andric Val &= SDWA9EncValues::VOPC_DST_SGPR_MASK; 17280b57cec5SDimitry Andric 17290b57cec5SDimitry Andric int TTmpIdx = getTTmpIdx(Val); 17300b57cec5SDimitry Andric if (TTmpIdx >= 0) { 17318bcb0991SDimitry Andric auto TTmpClsId = getTtmpClassId(IsWave64 ? OPW64 : OPW32); 17328bcb0991SDimitry Andric return createSRegOperand(TTmpClsId, TTmpIdx); 1733*0fca6ea1SDimitry Andric } 1734*0fca6ea1SDimitry Andric if (Val > SGPR_MAX) { 1735*0fca6ea1SDimitry Andric return IsWave64 ? decodeSpecialReg64(Val) : decodeSpecialReg32(Val); 1736*0fca6ea1SDimitry Andric } 17370b57cec5SDimitry Andric return createSRegOperand(getSgprClassId(IsWave64 ? OPW64 : OPW32), Val); 17380b57cec5SDimitry Andric } 17390b57cec5SDimitry Andric return createRegOperand(IsWave64 ? AMDGPU::VCC : AMDGPU::VCC_LO); 17400b57cec5SDimitry Andric } 17410b57cec5SDimitry Andric 17420b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeBoolReg(unsigned Val) const { 174306c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureWavefrontSize64) 174406c3fb27SDimitry Andric ? decodeSrcOp(OPW64, Val) 174506c3fb27SDimitry Andric : decodeSrcOp(OPW32, Val); 17460b57cec5SDimitry Andric } 17470b57cec5SDimitry Andric 17485f757f3fSDimitry Andric MCOperand AMDGPUDisassembler::decodeSplitBarrier(unsigned Val) const { 17495f757f3fSDimitry Andric return decodeSrcOp(OPW32, Val); 17505f757f3fSDimitry Andric } 17515f757f3fSDimitry Andric 1752*0fca6ea1SDimitry Andric MCOperand AMDGPUDisassembler::decodeDpp8FI(unsigned Val) const { 1753*0fca6ea1SDimitry Andric if (Val != AMDGPU::DPP::DPP8_FI_0 && Val != AMDGPU::DPP::DPP8_FI_1) 1754*0fca6ea1SDimitry Andric return MCOperand(); 1755*0fca6ea1SDimitry Andric return MCOperand::createImm(Val); 1756*0fca6ea1SDimitry Andric } 1757*0fca6ea1SDimitry Andric 1758*0fca6ea1SDimitry Andric MCOperand AMDGPUDisassembler::decodeVersionImm(unsigned Imm) const { 1759*0fca6ea1SDimitry Andric using VersionField = AMDGPU::EncodingField<7, 0>; 1760*0fca6ea1SDimitry Andric using W64Bit = AMDGPU::EncodingBit<13>; 1761*0fca6ea1SDimitry Andric using W32Bit = AMDGPU::EncodingBit<14>; 1762*0fca6ea1SDimitry Andric using MDPBit = AMDGPU::EncodingBit<15>; 1763*0fca6ea1SDimitry Andric using Encoding = AMDGPU::EncodingFields<VersionField, W64Bit, W32Bit, MDPBit>; 1764*0fca6ea1SDimitry Andric 1765*0fca6ea1SDimitry Andric auto [Version, W64, W32, MDP] = Encoding::decode(Imm); 1766*0fca6ea1SDimitry Andric 1767*0fca6ea1SDimitry Andric // Decode into a plain immediate if any unused bits are raised. 1768*0fca6ea1SDimitry Andric if (Encoding::encode(Version, W64, W32, MDP) != Imm) 1769*0fca6ea1SDimitry Andric return MCOperand::createImm(Imm); 1770*0fca6ea1SDimitry Andric 1771*0fca6ea1SDimitry Andric const auto &Versions = AMDGPU::UCVersion::getGFXVersions(); 1772*0fca6ea1SDimitry Andric auto I = find_if(Versions, 1773*0fca6ea1SDimitry Andric [Version = Version](const AMDGPU::UCVersion::GFXVersion &V) { 1774*0fca6ea1SDimitry Andric return V.Code == Version; 1775*0fca6ea1SDimitry Andric }); 1776*0fca6ea1SDimitry Andric MCContext &Ctx = getContext(); 1777*0fca6ea1SDimitry Andric const MCExpr *E; 1778*0fca6ea1SDimitry Andric if (I == Versions.end()) 1779*0fca6ea1SDimitry Andric E = MCConstantExpr::create(Version, Ctx); 1780*0fca6ea1SDimitry Andric else 1781*0fca6ea1SDimitry Andric E = MCSymbolRefExpr::create(Ctx.getOrCreateSymbol(I->Symbol), Ctx); 1782*0fca6ea1SDimitry Andric 1783*0fca6ea1SDimitry Andric if (W64) 1784*0fca6ea1SDimitry Andric E = MCBinaryExpr::createOr(E, UCVersionW64Expr, Ctx); 1785*0fca6ea1SDimitry Andric if (W32) 1786*0fca6ea1SDimitry Andric E = MCBinaryExpr::createOr(E, UCVersionW32Expr, Ctx); 1787*0fca6ea1SDimitry Andric if (MDP) 1788*0fca6ea1SDimitry Andric E = MCBinaryExpr::createOr(E, UCVersionMDPExpr, Ctx); 1789*0fca6ea1SDimitry Andric 1790*0fca6ea1SDimitry Andric return MCOperand::createExpr(E); 1791*0fca6ea1SDimitry Andric } 1792*0fca6ea1SDimitry Andric 17930b57cec5SDimitry Andric bool AMDGPUDisassembler::isVI() const { 179406c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureVolcanicIslands); 17950b57cec5SDimitry Andric } 17960b57cec5SDimitry Andric 1797e8d8bef9SDimitry Andric bool AMDGPUDisassembler::isGFX9() const { return AMDGPU::isGFX9(STI); } 1798e8d8bef9SDimitry Andric 1799fe6060f1SDimitry Andric bool AMDGPUDisassembler::isGFX90A() const { 180006c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureGFX90AInsts); 1801fe6060f1SDimitry Andric } 1802fe6060f1SDimitry Andric 1803e8d8bef9SDimitry Andric bool AMDGPUDisassembler::isGFX9Plus() const { return AMDGPU::isGFX9Plus(STI); } 1804e8d8bef9SDimitry Andric 1805e8d8bef9SDimitry Andric bool AMDGPUDisassembler::isGFX10() const { return AMDGPU::isGFX10(STI); } 1806e8d8bef9SDimitry Andric 1807e8d8bef9SDimitry Andric bool AMDGPUDisassembler::isGFX10Plus() const { 1808e8d8bef9SDimitry Andric return AMDGPU::isGFX10Plus(STI); 18090b57cec5SDimitry Andric } 18100b57cec5SDimitry Andric 181181ad6265SDimitry Andric bool AMDGPUDisassembler::isGFX11() const { 181206c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureGFX11); 181381ad6265SDimitry Andric } 181481ad6265SDimitry Andric 181581ad6265SDimitry Andric bool AMDGPUDisassembler::isGFX11Plus() const { 181681ad6265SDimitry Andric return AMDGPU::isGFX11Plus(STI); 181781ad6265SDimitry Andric } 181881ad6265SDimitry Andric 1819*0fca6ea1SDimitry Andric bool AMDGPUDisassembler::isGFX12() const { 1820*0fca6ea1SDimitry Andric return STI.hasFeature(AMDGPU::FeatureGFX12); 1821*0fca6ea1SDimitry Andric } 1822*0fca6ea1SDimitry Andric 18235f757f3fSDimitry Andric bool AMDGPUDisassembler::isGFX12Plus() const { 18245f757f3fSDimitry Andric return AMDGPU::isGFX12Plus(STI); 18255f757f3fSDimitry Andric } 182681ad6265SDimitry Andric 1827fe6060f1SDimitry Andric bool AMDGPUDisassembler::hasArchitectedFlatScratch() const { 182806c3fb27SDimitry Andric return STI.hasFeature(AMDGPU::FeatureArchitectedFlatScratch); 1829fe6060f1SDimitry Andric } 1830fe6060f1SDimitry Andric 18315f757f3fSDimitry Andric bool AMDGPUDisassembler::hasKernargPreload() const { 18325f757f3fSDimitry Andric return AMDGPU::hasKernargPreload(STI); 18335f757f3fSDimitry Andric } 18345f757f3fSDimitry Andric 1835e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 1836e8d8bef9SDimitry Andric // AMDGPU specific symbol handling 1837e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 1838*0fca6ea1SDimitry Andric 1839*0fca6ea1SDimitry Andric /// Print a string describing the reserved bit range specified by Mask with 1840*0fca6ea1SDimitry Andric /// offset BaseBytes for use in error comments. Mask is a single continuous 1841*0fca6ea1SDimitry Andric /// range of 1s surrounded by zeros. The format here is meant to align with the 1842*0fca6ea1SDimitry Andric /// tables that describe these bits in llvm.org/docs/AMDGPUUsage.html. 1843*0fca6ea1SDimitry Andric static SmallString<32> getBitRangeFromMask(uint32_t Mask, unsigned BaseBytes) { 1844*0fca6ea1SDimitry Andric SmallString<32> Result; 1845*0fca6ea1SDimitry Andric raw_svector_ostream S(Result); 1846*0fca6ea1SDimitry Andric 1847*0fca6ea1SDimitry Andric int TrailingZeros = llvm::countr_zero(Mask); 1848*0fca6ea1SDimitry Andric int PopCount = llvm::popcount(Mask); 1849*0fca6ea1SDimitry Andric 1850*0fca6ea1SDimitry Andric if (PopCount == 1) { 1851*0fca6ea1SDimitry Andric S << "bit (" << (TrailingZeros + BaseBytes * CHAR_BIT) << ')'; 1852*0fca6ea1SDimitry Andric } else { 1853*0fca6ea1SDimitry Andric S << "bits in range (" 1854*0fca6ea1SDimitry Andric << (TrailingZeros + PopCount - 1 + BaseBytes * CHAR_BIT) << ':' 1855*0fca6ea1SDimitry Andric << (TrailingZeros + BaseBytes * CHAR_BIT) << ')'; 1856*0fca6ea1SDimitry Andric } 1857*0fca6ea1SDimitry Andric 1858*0fca6ea1SDimitry Andric return Result; 1859*0fca6ea1SDimitry Andric } 1860*0fca6ea1SDimitry Andric 186106c3fb27SDimitry Andric #define GET_FIELD(MASK) (AMDHSA_BITS_GET(FourByteBuffer, MASK)) 1862e8d8bef9SDimitry Andric #define PRINT_DIRECTIVE(DIRECTIVE, MASK) \ 1863e8d8bef9SDimitry Andric do { \ 186406c3fb27SDimitry Andric KdStream << Indent << DIRECTIVE " " << GET_FIELD(MASK) << '\n'; \ 186506c3fb27SDimitry Andric } while (0) 186606c3fb27SDimitry Andric #define PRINT_PSEUDO_DIRECTIVE_COMMENT(DIRECTIVE, MASK) \ 186706c3fb27SDimitry Andric do { \ 186806c3fb27SDimitry Andric KdStream << Indent << MAI.getCommentString() << ' ' << DIRECTIVE " " \ 186906c3fb27SDimitry Andric << GET_FIELD(MASK) << '\n'; \ 1870e8d8bef9SDimitry Andric } while (0) 1871e8d8bef9SDimitry Andric 1872*0fca6ea1SDimitry Andric #define CHECK_RESERVED_BITS_IMPL(MASK, DESC, MSG) \ 1873*0fca6ea1SDimitry Andric do { \ 1874*0fca6ea1SDimitry Andric if (FourByteBuffer & (MASK)) { \ 1875*0fca6ea1SDimitry Andric return createStringError(std::errc::invalid_argument, \ 1876*0fca6ea1SDimitry Andric "kernel descriptor " DESC \ 1877*0fca6ea1SDimitry Andric " reserved %s set" MSG, \ 1878*0fca6ea1SDimitry Andric getBitRangeFromMask((MASK), 0).c_str()); \ 1879*0fca6ea1SDimitry Andric } \ 1880*0fca6ea1SDimitry Andric } while (0) 1881*0fca6ea1SDimitry Andric 1882*0fca6ea1SDimitry Andric #define CHECK_RESERVED_BITS(MASK) CHECK_RESERVED_BITS_IMPL(MASK, #MASK, "") 1883*0fca6ea1SDimitry Andric #define CHECK_RESERVED_BITS_MSG(MASK, MSG) \ 1884*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS_IMPL(MASK, #MASK, ", " MSG) 1885*0fca6ea1SDimitry Andric #define CHECK_RESERVED_BITS_DESC(MASK, DESC) \ 1886*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS_IMPL(MASK, DESC, "") 1887*0fca6ea1SDimitry Andric #define CHECK_RESERVED_BITS_DESC_MSG(MASK, DESC, MSG) \ 1888*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS_IMPL(MASK, DESC, ", " MSG) 1889*0fca6ea1SDimitry Andric 1890e8d8bef9SDimitry Andric // NOLINTNEXTLINE(readability-identifier-naming) 1891*0fca6ea1SDimitry Andric Expected<bool> AMDGPUDisassembler::decodeCOMPUTE_PGM_RSRC1( 1892e8d8bef9SDimitry Andric uint32_t FourByteBuffer, raw_string_ostream &KdStream) const { 1893e8d8bef9SDimitry Andric using namespace amdhsa; 1894e8d8bef9SDimitry Andric StringRef Indent = "\t"; 1895e8d8bef9SDimitry Andric 1896e8d8bef9SDimitry Andric // We cannot accurately backward compute #VGPRs used from 1897e8d8bef9SDimitry Andric // GRANULATED_WORKITEM_VGPR_COUNT. But we are concerned with getting the same 1898e8d8bef9SDimitry Andric // value of GRANULATED_WORKITEM_VGPR_COUNT in the reassembled binary. So we 1899e8d8bef9SDimitry Andric // simply calculate the inverse of what the assembler does. 1900e8d8bef9SDimitry Andric 1901e8d8bef9SDimitry Andric uint32_t GranulatedWorkitemVGPRCount = 190206c3fb27SDimitry Andric GET_FIELD(COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT); 1903e8d8bef9SDimitry Andric 190406c3fb27SDimitry Andric uint32_t NextFreeVGPR = 190506c3fb27SDimitry Andric (GranulatedWorkitemVGPRCount + 1) * 190606c3fb27SDimitry Andric AMDGPU::IsaInfo::getVGPREncodingGranule(&STI, EnableWavefrontSize32); 1907e8d8bef9SDimitry Andric 1908e8d8bef9SDimitry Andric KdStream << Indent << ".amdhsa_next_free_vgpr " << NextFreeVGPR << '\n'; 1909e8d8bef9SDimitry Andric 1910e8d8bef9SDimitry Andric // We cannot backward compute values used to calculate 1911e8d8bef9SDimitry Andric // GRANULATED_WAVEFRONT_SGPR_COUNT. Hence the original values for following 1912e8d8bef9SDimitry Andric // directives can't be computed: 1913e8d8bef9SDimitry Andric // .amdhsa_reserve_vcc 1914e8d8bef9SDimitry Andric // .amdhsa_reserve_flat_scratch 1915e8d8bef9SDimitry Andric // .amdhsa_reserve_xnack_mask 1916e8d8bef9SDimitry Andric // They take their respective default values if not specified in the assembly. 1917e8d8bef9SDimitry Andric // 1918e8d8bef9SDimitry Andric // GRANULATED_WAVEFRONT_SGPR_COUNT 1919e8d8bef9SDimitry Andric // = f(NEXT_FREE_SGPR + VCC + FLAT_SCRATCH + XNACK_MASK) 1920e8d8bef9SDimitry Andric // 1921e8d8bef9SDimitry Andric // We compute the inverse as though all directives apart from NEXT_FREE_SGPR 1922e8d8bef9SDimitry Andric // are set to 0. So while disassembling we consider that: 1923e8d8bef9SDimitry Andric // 1924e8d8bef9SDimitry Andric // GRANULATED_WAVEFRONT_SGPR_COUNT 1925e8d8bef9SDimitry Andric // = f(NEXT_FREE_SGPR + 0 + 0 + 0) 1926e8d8bef9SDimitry Andric // 1927e8d8bef9SDimitry Andric // The disassembler cannot recover the original values of those 3 directives. 1928e8d8bef9SDimitry Andric 1929e8d8bef9SDimitry Andric uint32_t GranulatedWavefrontSGPRCount = 193006c3fb27SDimitry Andric GET_FIELD(COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT); 1931e8d8bef9SDimitry Andric 1932*0fca6ea1SDimitry Andric if (isGFX10Plus()) 1933*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS_MSG(COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT, 1934*0fca6ea1SDimitry Andric "must be zero on gfx10+"); 1935e8d8bef9SDimitry Andric 1936e8d8bef9SDimitry Andric uint32_t NextFreeSGPR = (GranulatedWavefrontSGPRCount + 1) * 1937e8d8bef9SDimitry Andric AMDGPU::IsaInfo::getSGPREncodingGranule(&STI); 1938e8d8bef9SDimitry Andric 1939e8d8bef9SDimitry Andric KdStream << Indent << ".amdhsa_reserve_vcc " << 0 << '\n'; 1940fe6060f1SDimitry Andric if (!hasArchitectedFlatScratch()) 1941e8d8bef9SDimitry Andric KdStream << Indent << ".amdhsa_reserve_flat_scratch " << 0 << '\n'; 1942e8d8bef9SDimitry Andric KdStream << Indent << ".amdhsa_reserve_xnack_mask " << 0 << '\n'; 1943e8d8bef9SDimitry Andric KdStream << Indent << ".amdhsa_next_free_sgpr " << NextFreeSGPR << "\n"; 1944e8d8bef9SDimitry Andric 1945*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_PRIORITY); 1946e8d8bef9SDimitry Andric 1947e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_float_round_mode_32", 1948e8d8bef9SDimitry Andric COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32); 1949e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_float_round_mode_16_64", 1950e8d8bef9SDimitry Andric COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64); 1951e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_float_denorm_mode_32", 1952e8d8bef9SDimitry Andric COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32); 1953e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_float_denorm_mode_16_64", 1954e8d8bef9SDimitry Andric COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64); 1955e8d8bef9SDimitry Andric 1956*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_PRIV); 1957e8d8bef9SDimitry Andric 19585f757f3fSDimitry Andric if (!isGFX12Plus()) 19595f757f3fSDimitry Andric PRINT_DIRECTIVE(".amdhsa_dx10_clamp", 19605f757f3fSDimitry Andric COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP); 1961e8d8bef9SDimitry Andric 1962*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_DEBUG_MODE); 1963e8d8bef9SDimitry Andric 19645f757f3fSDimitry Andric if (!isGFX12Plus()) 19655f757f3fSDimitry Andric PRINT_DIRECTIVE(".amdhsa_ieee_mode", 19665f757f3fSDimitry Andric COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE); 1967e8d8bef9SDimitry Andric 1968*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_BULKY); 1969*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_CDBG_USER); 1970e8d8bef9SDimitry Andric 19715f757f3fSDimitry Andric if (isGFX9Plus()) 19725f757f3fSDimitry Andric PRINT_DIRECTIVE(".amdhsa_fp16_overflow", COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL); 1973e8d8bef9SDimitry Andric 19745f757f3fSDimitry Andric if (!isGFX9Plus()) 1975*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC1_GFX6_GFX8_RESERVED0, 1976*0fca6ea1SDimitry Andric "COMPUTE_PGM_RSRC1", "must be zero pre-gfx9"); 1977*0fca6ea1SDimitry Andric 1978*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS_DESC(COMPUTE_PGM_RSRC1_RESERVED1, "COMPUTE_PGM_RSRC1"); 1979*0fca6ea1SDimitry Andric 19805f757f3fSDimitry Andric if (!isGFX10Plus()) 1981*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC1_GFX6_GFX9_RESERVED2, 1982*0fca6ea1SDimitry Andric "COMPUTE_PGM_RSRC1", "must be zero pre-gfx10"); 1983e8d8bef9SDimitry Andric 1984e8d8bef9SDimitry Andric if (isGFX10Plus()) { 1985e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_workgroup_processor_mode", 19865f757f3fSDimitry Andric COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE); 19875f757f3fSDimitry Andric PRINT_DIRECTIVE(".amdhsa_memory_ordered", COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED); 19885f757f3fSDimitry Andric PRINT_DIRECTIVE(".amdhsa_forward_progress", COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS); 1989e8d8bef9SDimitry Andric } 19905f757f3fSDimitry Andric 19915f757f3fSDimitry Andric if (isGFX12Plus()) 19925f757f3fSDimitry Andric PRINT_DIRECTIVE(".amdhsa_round_robin_scheduling", 19935f757f3fSDimitry Andric COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN); 19945f757f3fSDimitry Andric 1995*0fca6ea1SDimitry Andric return true; 1996e8d8bef9SDimitry Andric } 1997e8d8bef9SDimitry Andric 1998e8d8bef9SDimitry Andric // NOLINTNEXTLINE(readability-identifier-naming) 1999*0fca6ea1SDimitry Andric Expected<bool> AMDGPUDisassembler::decodeCOMPUTE_PGM_RSRC2( 2000e8d8bef9SDimitry Andric uint32_t FourByteBuffer, raw_string_ostream &KdStream) const { 2001e8d8bef9SDimitry Andric using namespace amdhsa; 2002e8d8bef9SDimitry Andric StringRef Indent = "\t"; 2003fe6060f1SDimitry Andric if (hasArchitectedFlatScratch()) 2004fe6060f1SDimitry Andric PRINT_DIRECTIVE(".amdhsa_enable_private_segment", 2005fe6060f1SDimitry Andric COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT); 2006fe6060f1SDimitry Andric else 2007fe6060f1SDimitry Andric PRINT_DIRECTIVE(".amdhsa_system_sgpr_private_segment_wavefront_offset", 2008e8d8bef9SDimitry Andric COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT); 2009e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_id_x", 2010e8d8bef9SDimitry Andric COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X); 2011e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_id_y", 2012e8d8bef9SDimitry Andric COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y); 2013e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_id_z", 2014e8d8bef9SDimitry Andric COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z); 2015e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_info", 2016e8d8bef9SDimitry Andric COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO); 2017e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_system_vgpr_workitem_id", 2018e8d8bef9SDimitry Andric COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID); 2019e8d8bef9SDimitry Andric 2020*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_ADDRESS_WATCH); 2021*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_MEMORY); 2022*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC2_GRANULATED_LDS_SIZE); 2023e8d8bef9SDimitry Andric 2024e8d8bef9SDimitry Andric PRINT_DIRECTIVE( 2025e8d8bef9SDimitry Andric ".amdhsa_exception_fp_ieee_invalid_op", 2026e8d8bef9SDimitry Andric COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION); 2027e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_exception_fp_denorm_src", 2028e8d8bef9SDimitry Andric COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE); 2029e8d8bef9SDimitry Andric PRINT_DIRECTIVE( 2030e8d8bef9SDimitry Andric ".amdhsa_exception_fp_ieee_div_zero", 2031e8d8bef9SDimitry Andric COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO); 2032e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_exception_fp_ieee_overflow", 2033e8d8bef9SDimitry Andric COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW); 2034e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_exception_fp_ieee_underflow", 2035e8d8bef9SDimitry Andric COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW); 2036e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_exception_fp_ieee_inexact", 2037e8d8bef9SDimitry Andric COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT); 2038e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_exception_int_div_zero", 2039e8d8bef9SDimitry Andric COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO); 2040e8d8bef9SDimitry Andric 2041*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS_DESC(COMPUTE_PGM_RSRC2_RESERVED0, "COMPUTE_PGM_RSRC2"); 2042e8d8bef9SDimitry Andric 2043*0fca6ea1SDimitry Andric return true; 2044e8d8bef9SDimitry Andric } 2045e8d8bef9SDimitry Andric 204606c3fb27SDimitry Andric // NOLINTNEXTLINE(readability-identifier-naming) 2047*0fca6ea1SDimitry Andric Expected<bool> AMDGPUDisassembler::decodeCOMPUTE_PGM_RSRC3( 204806c3fb27SDimitry Andric uint32_t FourByteBuffer, raw_string_ostream &KdStream) const { 204906c3fb27SDimitry Andric using namespace amdhsa; 205006c3fb27SDimitry Andric StringRef Indent = "\t"; 205106c3fb27SDimitry Andric if (isGFX90A()) { 205206c3fb27SDimitry Andric KdStream << Indent << ".amdhsa_accum_offset " 205306c3fb27SDimitry Andric << (GET_FIELD(COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET) + 1) * 4 205406c3fb27SDimitry Andric << '\n'; 2055*0fca6ea1SDimitry Andric 205606c3fb27SDimitry Andric PRINT_DIRECTIVE(".amdhsa_tg_split", COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT); 2057*0fca6ea1SDimitry Andric 2058*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX90A_RESERVED0, 2059*0fca6ea1SDimitry Andric "COMPUTE_PGM_RSRC3", "must be zero on gfx90a"); 2060*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX90A_RESERVED1, 2061*0fca6ea1SDimitry Andric "COMPUTE_PGM_RSRC3", "must be zero on gfx90a"); 206206c3fb27SDimitry Andric } else if (isGFX10Plus()) { 2063647cbc5dSDimitry Andric // Bits [0-3]. 2064647cbc5dSDimitry Andric if (!isGFX12Plus()) { 206506c3fb27SDimitry Andric if (!EnableWavefrontSize32 || !*EnableWavefrontSize32) { 206606c3fb27SDimitry Andric PRINT_DIRECTIVE(".amdhsa_shared_vgpr_count", 2067647cbc5dSDimitry Andric COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT); 206806c3fb27SDimitry Andric } else { 206906c3fb27SDimitry Andric PRINT_PSEUDO_DIRECTIVE_COMMENT( 2070647cbc5dSDimitry Andric "SHARED_VGPR_COUNT", 2071647cbc5dSDimitry Andric COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT); 207206c3fb27SDimitry Andric } 20735f757f3fSDimitry Andric } else { 2074*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX12_PLUS_RESERVED0, 2075*0fca6ea1SDimitry Andric "COMPUTE_PGM_RSRC3", 2076*0fca6ea1SDimitry Andric "must be zero on gfx12+"); 20775f757f3fSDimitry Andric } 20785f757f3fSDimitry Andric 2079647cbc5dSDimitry Andric // Bits [4-11]. 2080647cbc5dSDimitry Andric if (isGFX11()) { 2081647cbc5dSDimitry Andric PRINT_PSEUDO_DIRECTIVE_COMMENT("INST_PREF_SIZE", 2082647cbc5dSDimitry Andric COMPUTE_PGM_RSRC3_GFX11_INST_PREF_SIZE); 2083647cbc5dSDimitry Andric PRINT_PSEUDO_DIRECTIVE_COMMENT("TRAP_ON_START", 2084647cbc5dSDimitry Andric COMPUTE_PGM_RSRC3_GFX11_TRAP_ON_START); 2085647cbc5dSDimitry Andric PRINT_PSEUDO_DIRECTIVE_COMMENT("TRAP_ON_END", 2086647cbc5dSDimitry Andric COMPUTE_PGM_RSRC3_GFX11_TRAP_ON_END); 2087647cbc5dSDimitry Andric } else if (isGFX12Plus()) { 2088647cbc5dSDimitry Andric PRINT_PSEUDO_DIRECTIVE_COMMENT( 2089647cbc5dSDimitry Andric "INST_PREF_SIZE", COMPUTE_PGM_RSRC3_GFX12_PLUS_INST_PREF_SIZE); 2090647cbc5dSDimitry Andric } else { 2091*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_RESERVED1, 2092*0fca6ea1SDimitry Andric "COMPUTE_PGM_RSRC3", 2093*0fca6ea1SDimitry Andric "must be zero on gfx10"); 2094647cbc5dSDimitry Andric } 2095647cbc5dSDimitry Andric 2096647cbc5dSDimitry Andric // Bits [12]. 2097*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_PLUS_RESERVED2, 2098*0fca6ea1SDimitry Andric "COMPUTE_PGM_RSRC3", "must be zero on gfx10+"); 20995f757f3fSDimitry Andric 2100647cbc5dSDimitry Andric // Bits [13]. 2101647cbc5dSDimitry Andric if (isGFX12Plus()) { 2102647cbc5dSDimitry Andric PRINT_PSEUDO_DIRECTIVE_COMMENT("GLG_EN", 2103647cbc5dSDimitry Andric COMPUTE_PGM_RSRC3_GFX12_PLUS_GLG_EN); 2104647cbc5dSDimitry Andric } else { 2105*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_GFX11_RESERVED3, 2106*0fca6ea1SDimitry Andric "COMPUTE_PGM_RSRC3", 2107*0fca6ea1SDimitry Andric "must be zero on gfx10 or gfx11"); 2108647cbc5dSDimitry Andric } 2109647cbc5dSDimitry Andric 2110647cbc5dSDimitry Andric // Bits [14-30]. 2111*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_PLUS_RESERVED4, 2112*0fca6ea1SDimitry Andric "COMPUTE_PGM_RSRC3", "must be zero on gfx10+"); 2113647cbc5dSDimitry Andric 2114647cbc5dSDimitry Andric // Bits [31]. 21155f757f3fSDimitry Andric if (isGFX11Plus()) { 211606c3fb27SDimitry Andric PRINT_PSEUDO_DIRECTIVE_COMMENT("IMAGE_OP", 2117647cbc5dSDimitry Andric COMPUTE_PGM_RSRC3_GFX11_PLUS_IMAGE_OP); 21185f757f3fSDimitry Andric } else { 2119*0fca6ea1SDimitry Andric CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_RESERVED5, 2120*0fca6ea1SDimitry Andric "COMPUTE_PGM_RSRC3", 2121*0fca6ea1SDimitry Andric "must be zero on gfx10"); 21225f757f3fSDimitry Andric } 212306c3fb27SDimitry Andric } else if (FourByteBuffer) { 2124*0fca6ea1SDimitry Andric return createStringError( 2125*0fca6ea1SDimitry Andric std::errc::invalid_argument, 2126*0fca6ea1SDimitry Andric "kernel descriptor COMPUTE_PGM_RSRC3 must be all zero before gfx9"); 212706c3fb27SDimitry Andric } 2128*0fca6ea1SDimitry Andric return true; 212906c3fb27SDimitry Andric } 213006c3fb27SDimitry Andric #undef PRINT_PSEUDO_DIRECTIVE_COMMENT 2131e8d8bef9SDimitry Andric #undef PRINT_DIRECTIVE 213206c3fb27SDimitry Andric #undef GET_FIELD 2133*0fca6ea1SDimitry Andric #undef CHECK_RESERVED_BITS_IMPL 2134*0fca6ea1SDimitry Andric #undef CHECK_RESERVED_BITS 2135*0fca6ea1SDimitry Andric #undef CHECK_RESERVED_BITS_MSG 2136*0fca6ea1SDimitry Andric #undef CHECK_RESERVED_BITS_DESC 2137*0fca6ea1SDimitry Andric #undef CHECK_RESERVED_BITS_DESC_MSG 2138e8d8bef9SDimitry Andric 2139*0fca6ea1SDimitry Andric /// Create an error object to return from onSymbolStart for reserved kernel 2140*0fca6ea1SDimitry Andric /// descriptor bits being set. 2141*0fca6ea1SDimitry Andric static Error createReservedKDBitsError(uint32_t Mask, unsigned BaseBytes, 2142*0fca6ea1SDimitry Andric const char *Msg = "") { 2143*0fca6ea1SDimitry Andric return createStringError( 2144*0fca6ea1SDimitry Andric std::errc::invalid_argument, "kernel descriptor reserved %s set%s%s", 2145*0fca6ea1SDimitry Andric getBitRangeFromMask(Mask, BaseBytes).c_str(), *Msg ? ", " : "", Msg); 2146*0fca6ea1SDimitry Andric } 2147*0fca6ea1SDimitry Andric 2148*0fca6ea1SDimitry Andric /// Create an error object to return from onSymbolStart for reserved kernel 2149*0fca6ea1SDimitry Andric /// descriptor bytes being set. 2150*0fca6ea1SDimitry Andric static Error createReservedKDBytesError(unsigned BaseInBytes, 2151*0fca6ea1SDimitry Andric unsigned WidthInBytes) { 2152*0fca6ea1SDimitry Andric // Create an error comment in the same format as the "Kernel Descriptor" 2153*0fca6ea1SDimitry Andric // table here: https://llvm.org/docs/AMDGPUUsage.html#kernel-descriptor . 2154*0fca6ea1SDimitry Andric return createStringError( 2155*0fca6ea1SDimitry Andric std::errc::invalid_argument, 2156*0fca6ea1SDimitry Andric "kernel descriptor reserved bits in range (%u:%u) set", 2157*0fca6ea1SDimitry Andric (BaseInBytes + WidthInBytes) * CHAR_BIT - 1, BaseInBytes * CHAR_BIT); 2158*0fca6ea1SDimitry Andric } 2159*0fca6ea1SDimitry Andric 2160*0fca6ea1SDimitry Andric Expected<bool> AMDGPUDisassembler::decodeKernelDescriptorDirective( 2161e8d8bef9SDimitry Andric DataExtractor::Cursor &Cursor, ArrayRef<uint8_t> Bytes, 2162e8d8bef9SDimitry Andric raw_string_ostream &KdStream) const { 2163e8d8bef9SDimitry Andric #define PRINT_DIRECTIVE(DIRECTIVE, MASK) \ 2164e8d8bef9SDimitry Andric do { \ 2165e8d8bef9SDimitry Andric KdStream << Indent << DIRECTIVE " " \ 2166e8d8bef9SDimitry Andric << ((TwoByteBuffer & MASK) >> (MASK##_SHIFT)) << '\n'; \ 2167e8d8bef9SDimitry Andric } while (0) 2168e8d8bef9SDimitry Andric 2169e8d8bef9SDimitry Andric uint16_t TwoByteBuffer = 0; 2170e8d8bef9SDimitry Andric uint32_t FourByteBuffer = 0; 2171e8d8bef9SDimitry Andric 2172e8d8bef9SDimitry Andric StringRef ReservedBytes; 2173e8d8bef9SDimitry Andric StringRef Indent = "\t"; 2174e8d8bef9SDimitry Andric 2175e8d8bef9SDimitry Andric assert(Bytes.size() == 64); 2176e8d8bef9SDimitry Andric DataExtractor DE(Bytes, /*IsLittleEndian=*/true, /*AddressSize=*/8); 2177e8d8bef9SDimitry Andric 2178e8d8bef9SDimitry Andric switch (Cursor.tell()) { 2179e8d8bef9SDimitry Andric case amdhsa::GROUP_SEGMENT_FIXED_SIZE_OFFSET: 2180e8d8bef9SDimitry Andric FourByteBuffer = DE.getU32(Cursor); 2181e8d8bef9SDimitry Andric KdStream << Indent << ".amdhsa_group_segment_fixed_size " << FourByteBuffer 2182e8d8bef9SDimitry Andric << '\n'; 2183*0fca6ea1SDimitry Andric return true; 2184e8d8bef9SDimitry Andric 2185e8d8bef9SDimitry Andric case amdhsa::PRIVATE_SEGMENT_FIXED_SIZE_OFFSET: 2186e8d8bef9SDimitry Andric FourByteBuffer = DE.getU32(Cursor); 2187e8d8bef9SDimitry Andric KdStream << Indent << ".amdhsa_private_segment_fixed_size " 2188e8d8bef9SDimitry Andric << FourByteBuffer << '\n'; 2189*0fca6ea1SDimitry Andric return true; 2190e8d8bef9SDimitry Andric 2191fe6060f1SDimitry Andric case amdhsa::KERNARG_SIZE_OFFSET: 2192fe6060f1SDimitry Andric FourByteBuffer = DE.getU32(Cursor); 2193fe6060f1SDimitry Andric KdStream << Indent << ".amdhsa_kernarg_size " 2194fe6060f1SDimitry Andric << FourByteBuffer << '\n'; 2195*0fca6ea1SDimitry Andric return true; 2196fe6060f1SDimitry Andric 2197e8d8bef9SDimitry Andric case amdhsa::RESERVED0_OFFSET: 2198fe6060f1SDimitry Andric // 4 reserved bytes, must be 0. 2199fe6060f1SDimitry Andric ReservedBytes = DE.getBytes(Cursor, 4); 2200fe6060f1SDimitry Andric for (int I = 0; I < 4; ++I) { 2201*0fca6ea1SDimitry Andric if (ReservedBytes[I] != 0) 2202*0fca6ea1SDimitry Andric return createReservedKDBytesError(amdhsa::RESERVED0_OFFSET, 4); 2203e8d8bef9SDimitry Andric } 2204*0fca6ea1SDimitry Andric return true; 2205e8d8bef9SDimitry Andric 2206e8d8bef9SDimitry Andric case amdhsa::KERNEL_CODE_ENTRY_BYTE_OFFSET_OFFSET: 2207e8d8bef9SDimitry Andric // KERNEL_CODE_ENTRY_BYTE_OFFSET 2208e8d8bef9SDimitry Andric // So far no directive controls this for Code Object V3, so simply skip for 2209e8d8bef9SDimitry Andric // disassembly. 2210e8d8bef9SDimitry Andric DE.skip(Cursor, 8); 2211*0fca6ea1SDimitry Andric return true; 2212e8d8bef9SDimitry Andric 2213e8d8bef9SDimitry Andric case amdhsa::RESERVED1_OFFSET: 2214e8d8bef9SDimitry Andric // 20 reserved bytes, must be 0. 2215e8d8bef9SDimitry Andric ReservedBytes = DE.getBytes(Cursor, 20); 2216e8d8bef9SDimitry Andric for (int I = 0; I < 20; ++I) { 2217*0fca6ea1SDimitry Andric if (ReservedBytes[I] != 0) 2218*0fca6ea1SDimitry Andric return createReservedKDBytesError(amdhsa::RESERVED1_OFFSET, 20); 2219e8d8bef9SDimitry Andric } 2220*0fca6ea1SDimitry Andric return true; 2221e8d8bef9SDimitry Andric 2222e8d8bef9SDimitry Andric case amdhsa::COMPUTE_PGM_RSRC3_OFFSET: 2223e8d8bef9SDimitry Andric FourByteBuffer = DE.getU32(Cursor); 222406c3fb27SDimitry Andric return decodeCOMPUTE_PGM_RSRC3(FourByteBuffer, KdStream); 2225e8d8bef9SDimitry Andric 2226e8d8bef9SDimitry Andric case amdhsa::COMPUTE_PGM_RSRC1_OFFSET: 2227e8d8bef9SDimitry Andric FourByteBuffer = DE.getU32(Cursor); 222806c3fb27SDimitry Andric return decodeCOMPUTE_PGM_RSRC1(FourByteBuffer, KdStream); 2229e8d8bef9SDimitry Andric 2230e8d8bef9SDimitry Andric case amdhsa::COMPUTE_PGM_RSRC2_OFFSET: 2231e8d8bef9SDimitry Andric FourByteBuffer = DE.getU32(Cursor); 223206c3fb27SDimitry Andric return decodeCOMPUTE_PGM_RSRC2(FourByteBuffer, KdStream); 2233e8d8bef9SDimitry Andric 2234e8d8bef9SDimitry Andric case amdhsa::KERNEL_CODE_PROPERTIES_OFFSET: 2235e8d8bef9SDimitry Andric using namespace amdhsa; 2236e8d8bef9SDimitry Andric TwoByteBuffer = DE.getU16(Cursor); 2237e8d8bef9SDimitry Andric 2238fe6060f1SDimitry Andric if (!hasArchitectedFlatScratch()) 2239e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_user_sgpr_private_segment_buffer", 2240e8d8bef9SDimitry Andric KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER); 2241e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_user_sgpr_dispatch_ptr", 2242e8d8bef9SDimitry Andric KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR); 2243e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_user_sgpr_queue_ptr", 2244e8d8bef9SDimitry Andric KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR); 2245e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_user_sgpr_kernarg_segment_ptr", 2246e8d8bef9SDimitry Andric KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR); 2247e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_user_sgpr_dispatch_id", 2248e8d8bef9SDimitry Andric KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID); 2249fe6060f1SDimitry Andric if (!hasArchitectedFlatScratch()) 2250e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_user_sgpr_flat_scratch_init", 2251e8d8bef9SDimitry Andric KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT); 2252e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_user_sgpr_private_segment_size", 2253e8d8bef9SDimitry Andric KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE); 2254e8d8bef9SDimitry Andric 2255e8d8bef9SDimitry Andric if (TwoByteBuffer & KERNEL_CODE_PROPERTY_RESERVED0) 2256*0fca6ea1SDimitry Andric return createReservedKDBitsError(KERNEL_CODE_PROPERTY_RESERVED0, 2257*0fca6ea1SDimitry Andric amdhsa::KERNEL_CODE_PROPERTIES_OFFSET); 2258e8d8bef9SDimitry Andric 2259e8d8bef9SDimitry Andric // Reserved for GFX9 2260e8d8bef9SDimitry Andric if (isGFX9() && 2261e8d8bef9SDimitry Andric (TwoByteBuffer & KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32)) { 2262*0fca6ea1SDimitry Andric return createReservedKDBitsError( 2263*0fca6ea1SDimitry Andric KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32, 2264*0fca6ea1SDimitry Andric amdhsa::KERNEL_CODE_PROPERTIES_OFFSET, "must be zero on gfx9"); 2265*0fca6ea1SDimitry Andric } 2266*0fca6ea1SDimitry Andric if (isGFX10Plus()) { 2267e8d8bef9SDimitry Andric PRINT_DIRECTIVE(".amdhsa_wavefront_size32", 2268e8d8bef9SDimitry Andric KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32); 2269e8d8bef9SDimitry Andric } 2270e8d8bef9SDimitry Andric 2271*0fca6ea1SDimitry Andric if (CodeObjectVersion >= AMDGPU::AMDHSA_COV5) 2272fcaf7f86SDimitry Andric PRINT_DIRECTIVE(".amdhsa_uses_dynamic_stack", 2273fcaf7f86SDimitry Andric KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK); 2274fcaf7f86SDimitry Andric 2275*0fca6ea1SDimitry Andric if (TwoByteBuffer & KERNEL_CODE_PROPERTY_RESERVED1) { 2276*0fca6ea1SDimitry Andric return createReservedKDBitsError(KERNEL_CODE_PROPERTY_RESERVED1, 2277*0fca6ea1SDimitry Andric amdhsa::KERNEL_CODE_PROPERTIES_OFFSET); 2278*0fca6ea1SDimitry Andric } 2279e8d8bef9SDimitry Andric 2280*0fca6ea1SDimitry Andric return true; 2281e8d8bef9SDimitry Andric 22825f757f3fSDimitry Andric case amdhsa::KERNARG_PRELOAD_OFFSET: 22835f757f3fSDimitry Andric using namespace amdhsa; 22845f757f3fSDimitry Andric TwoByteBuffer = DE.getU16(Cursor); 22855f757f3fSDimitry Andric if (TwoByteBuffer & KERNARG_PRELOAD_SPEC_LENGTH) { 22865f757f3fSDimitry Andric PRINT_DIRECTIVE(".amdhsa_user_sgpr_kernarg_preload_length", 22875f757f3fSDimitry Andric KERNARG_PRELOAD_SPEC_LENGTH); 22885f757f3fSDimitry Andric } 22895f757f3fSDimitry Andric 22905f757f3fSDimitry Andric if (TwoByteBuffer & KERNARG_PRELOAD_SPEC_OFFSET) { 22915f757f3fSDimitry Andric PRINT_DIRECTIVE(".amdhsa_user_sgpr_kernarg_preload_offset", 22925f757f3fSDimitry Andric KERNARG_PRELOAD_SPEC_OFFSET); 22935f757f3fSDimitry Andric } 2294*0fca6ea1SDimitry Andric return true; 22955f757f3fSDimitry Andric 22965f757f3fSDimitry Andric case amdhsa::RESERVED3_OFFSET: 22975f757f3fSDimitry Andric // 4 bytes from here are reserved, must be 0. 22985f757f3fSDimitry Andric ReservedBytes = DE.getBytes(Cursor, 4); 22995f757f3fSDimitry Andric for (int I = 0; I < 4; ++I) { 2300e8d8bef9SDimitry Andric if (ReservedBytes[I] != 0) 2301*0fca6ea1SDimitry Andric return createReservedKDBytesError(amdhsa::RESERVED3_OFFSET, 4); 2302e8d8bef9SDimitry Andric } 2303*0fca6ea1SDimitry Andric return true; 2304e8d8bef9SDimitry Andric 2305e8d8bef9SDimitry Andric default: 2306e8d8bef9SDimitry Andric llvm_unreachable("Unhandled index. Case statements cover everything."); 2307*0fca6ea1SDimitry Andric return true; 2308e8d8bef9SDimitry Andric } 2309e8d8bef9SDimitry Andric #undef PRINT_DIRECTIVE 2310e8d8bef9SDimitry Andric } 2311e8d8bef9SDimitry Andric 2312*0fca6ea1SDimitry Andric Expected<bool> AMDGPUDisassembler::decodeKernelDescriptor( 2313e8d8bef9SDimitry Andric StringRef KdName, ArrayRef<uint8_t> Bytes, uint64_t KdAddress) const { 2314*0fca6ea1SDimitry Andric 2315e8d8bef9SDimitry Andric // CP microcode requires the kernel descriptor to be 64 aligned. 2316e8d8bef9SDimitry Andric if (Bytes.size() != 64 || KdAddress % 64 != 0) 2317*0fca6ea1SDimitry Andric return createStringError(std::errc::invalid_argument, 2318*0fca6ea1SDimitry Andric "kernel descriptor must be 64-byte aligned"); 2319e8d8bef9SDimitry Andric 232006c3fb27SDimitry Andric // FIXME: We can't actually decode "in order" as is done below, as e.g. GFX10 232106c3fb27SDimitry Andric // requires us to know the setting of .amdhsa_wavefront_size32 in order to 232206c3fb27SDimitry Andric // accurately produce .amdhsa_next_free_vgpr, and they appear in the wrong 232306c3fb27SDimitry Andric // order. Workaround this by first looking up .amdhsa_wavefront_size32 here 232406c3fb27SDimitry Andric // when required. 232506c3fb27SDimitry Andric if (isGFX10Plus()) { 232606c3fb27SDimitry Andric uint16_t KernelCodeProperties = 232706c3fb27SDimitry Andric support::endian::read16(&Bytes[amdhsa::KERNEL_CODE_PROPERTIES_OFFSET], 23285f757f3fSDimitry Andric llvm::endianness::little); 232906c3fb27SDimitry Andric EnableWavefrontSize32 = 233006c3fb27SDimitry Andric AMDHSA_BITS_GET(KernelCodeProperties, 233106c3fb27SDimitry Andric amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32); 233206c3fb27SDimitry Andric } 233306c3fb27SDimitry Andric 2334e8d8bef9SDimitry Andric std::string Kd; 2335e8d8bef9SDimitry Andric raw_string_ostream KdStream(Kd); 2336e8d8bef9SDimitry Andric KdStream << ".amdhsa_kernel " << KdName << '\n'; 2337e8d8bef9SDimitry Andric 2338e8d8bef9SDimitry Andric DataExtractor::Cursor C(0); 2339e8d8bef9SDimitry Andric while (C && C.tell() < Bytes.size()) { 2340*0fca6ea1SDimitry Andric Expected<bool> Res = decodeKernelDescriptorDirective(C, Bytes, KdStream); 2341e8d8bef9SDimitry Andric 2342e8d8bef9SDimitry Andric cantFail(C.takeError()); 2343e8d8bef9SDimitry Andric 2344*0fca6ea1SDimitry Andric if (!Res) 2345*0fca6ea1SDimitry Andric return Res; 2346e8d8bef9SDimitry Andric } 2347e8d8bef9SDimitry Andric KdStream << ".end_amdhsa_kernel\n"; 2348e8d8bef9SDimitry Andric outs() << KdStream.str(); 2349*0fca6ea1SDimitry Andric return true; 2350e8d8bef9SDimitry Andric } 2351e8d8bef9SDimitry Andric 2352*0fca6ea1SDimitry Andric Expected<bool> AMDGPUDisassembler::onSymbolStart(SymbolInfoTy &Symbol, 2353*0fca6ea1SDimitry Andric uint64_t &Size, 2354*0fca6ea1SDimitry Andric ArrayRef<uint8_t> Bytes, 2355*0fca6ea1SDimitry Andric uint64_t Address) const { 2356e8d8bef9SDimitry Andric // Right now only kernel descriptor needs to be handled. 2357e8d8bef9SDimitry Andric // We ignore all other symbols for target specific handling. 2358e8d8bef9SDimitry Andric // TODO: 2359e8d8bef9SDimitry Andric // Fix the spurious symbol issue for AMDGPU kernels. Exists for both Code 2360e8d8bef9SDimitry Andric // Object V2 and V3 when symbols are marked protected. 2361e8d8bef9SDimitry Andric 2362e8d8bef9SDimitry Andric // amd_kernel_code_t for Code Object V2. 2363e8d8bef9SDimitry Andric if (Symbol.Type == ELF::STT_AMDGPU_HSA_KERNEL) { 2364e8d8bef9SDimitry Andric Size = 256; 2365*0fca6ea1SDimitry Andric return createStringError(std::errc::invalid_argument, 2366*0fca6ea1SDimitry Andric "code object v2 is not supported"); 2367e8d8bef9SDimitry Andric } 2368e8d8bef9SDimitry Andric 2369e8d8bef9SDimitry Andric // Code Object V3 kernel descriptors. 2370e8d8bef9SDimitry Andric StringRef Name = Symbol.Name; 23715f757f3fSDimitry Andric if (Symbol.Type == ELF::STT_OBJECT && Name.ends_with(StringRef(".kd"))) { 2372e8d8bef9SDimitry Andric Size = 64; // Size = 64 regardless of success or failure. 2373e8d8bef9SDimitry Andric return decodeKernelDescriptor(Name.drop_back(3), Bytes, Address); 2374e8d8bef9SDimitry Andric } 2375*0fca6ea1SDimitry Andric 2376*0fca6ea1SDimitry Andric return false; 2377*0fca6ea1SDimitry Andric } 2378*0fca6ea1SDimitry Andric 2379*0fca6ea1SDimitry Andric const MCExpr *AMDGPUDisassembler::createConstantSymbolExpr(StringRef Id, 2380*0fca6ea1SDimitry Andric int64_t Val) { 2381*0fca6ea1SDimitry Andric MCContext &Ctx = getContext(); 2382*0fca6ea1SDimitry Andric MCSymbol *Sym = Ctx.getOrCreateSymbol(Id); 2383*0fca6ea1SDimitry Andric // Note: only set value to Val on a new symbol in case an dissassembler 2384*0fca6ea1SDimitry Andric // has already been initialized in this context. 2385*0fca6ea1SDimitry Andric if (!Sym->isVariable()) { 2386*0fca6ea1SDimitry Andric Sym->setVariableValue(MCConstantExpr::create(Val, Ctx)); 2387*0fca6ea1SDimitry Andric } else { 2388*0fca6ea1SDimitry Andric int64_t Res = ~Val; 2389*0fca6ea1SDimitry Andric bool Valid = Sym->getVariableValue()->evaluateAsAbsolute(Res); 2390*0fca6ea1SDimitry Andric if (!Valid || Res != Val) 2391*0fca6ea1SDimitry Andric Ctx.reportWarning(SMLoc(), "unsupported redefinition of " + Id); 2392*0fca6ea1SDimitry Andric } 2393*0fca6ea1SDimitry Andric return MCSymbolRefExpr::create(Sym, Ctx); 23940b57cec5SDimitry Andric } 23950b57cec5SDimitry Andric 23960b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 23970b57cec5SDimitry Andric // AMDGPUSymbolizer 23980b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 23990b57cec5SDimitry Andric 24000b57cec5SDimitry Andric // Try to find symbol name for specified label 240181ad6265SDimitry Andric bool AMDGPUSymbolizer::tryAddingSymbolicOperand( 240281ad6265SDimitry Andric MCInst &Inst, raw_ostream & /*cStream*/, int64_t Value, 240381ad6265SDimitry Andric uint64_t /*Address*/, bool IsBranch, uint64_t /*Offset*/, 240481ad6265SDimitry Andric uint64_t /*OpSize*/, uint64_t /*InstSize*/) { 24050b57cec5SDimitry Andric 24060b57cec5SDimitry Andric if (!IsBranch) { 24070b57cec5SDimitry Andric return false; 24080b57cec5SDimitry Andric } 24090b57cec5SDimitry Andric 24100b57cec5SDimitry Andric auto *Symbols = static_cast<SectionSymbolsTy *>(DisInfo); 24110b57cec5SDimitry Andric if (!Symbols) 24120b57cec5SDimitry Andric return false; 24130b57cec5SDimitry Andric 2414e8d8bef9SDimitry Andric auto Result = llvm::find_if(*Symbols, [Value](const SymbolInfoTy &Val) { 2415e8d8bef9SDimitry Andric return Val.Addr == static_cast<uint64_t>(Value) && 2416e8d8bef9SDimitry Andric Val.Type == ELF::STT_NOTYPE; 24170b57cec5SDimitry Andric }); 24180b57cec5SDimitry Andric if (Result != Symbols->end()) { 24195ffd83dbSDimitry Andric auto *Sym = Ctx.getOrCreateSymbol(Result->Name); 24200b57cec5SDimitry Andric const auto *Add = MCSymbolRefExpr::create(Sym, Ctx); 24210b57cec5SDimitry Andric Inst.addOperand(MCOperand::createExpr(Add)); 24220b57cec5SDimitry Andric return true; 24230b57cec5SDimitry Andric } 2424fe6060f1SDimitry Andric // Add to list of referenced addresses, so caller can synthesize a label. 2425fe6060f1SDimitry Andric ReferencedAddresses.push_back(static_cast<uint64_t>(Value)); 24260b57cec5SDimitry Andric return false; 24270b57cec5SDimitry Andric } 24280b57cec5SDimitry Andric 24290b57cec5SDimitry Andric void AMDGPUSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream, 24300b57cec5SDimitry Andric int64_t Value, 24310b57cec5SDimitry Andric uint64_t Address) { 24320b57cec5SDimitry Andric llvm_unreachable("unimplemented"); 24330b57cec5SDimitry Andric } 24340b57cec5SDimitry Andric 24350b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 24360b57cec5SDimitry Andric // Initialization 24370b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 24380b57cec5SDimitry Andric 24390b57cec5SDimitry Andric static MCSymbolizer *createAMDGPUSymbolizer(const Triple &/*TT*/, 24400b57cec5SDimitry Andric LLVMOpInfoCallback /*GetOpInfo*/, 24410b57cec5SDimitry Andric LLVMSymbolLookupCallback /*SymbolLookUp*/, 24420b57cec5SDimitry Andric void *DisInfo, 24430b57cec5SDimitry Andric MCContext *Ctx, 24440b57cec5SDimitry Andric std::unique_ptr<MCRelocationInfo> &&RelInfo) { 24450b57cec5SDimitry Andric return new AMDGPUSymbolizer(*Ctx, std::move(RelInfo), DisInfo); 24460b57cec5SDimitry Andric } 24470b57cec5SDimitry Andric 24480b57cec5SDimitry Andric static MCDisassembler *createAMDGPUDisassembler(const Target &T, 24490b57cec5SDimitry Andric const MCSubtargetInfo &STI, 24500b57cec5SDimitry Andric MCContext &Ctx) { 24510b57cec5SDimitry Andric return new AMDGPUDisassembler(STI, Ctx, T.createMCInstrInfo()); 24520b57cec5SDimitry Andric } 24530b57cec5SDimitry Andric 2454480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAMDGPUDisassembler() { 24550b57cec5SDimitry Andric TargetRegistry::RegisterMCDisassembler(getTheGCNTarget(), 24560b57cec5SDimitry Andric createAMDGPUDisassembler); 24570b57cec5SDimitry Andric TargetRegistry::RegisterMCSymbolizer(getTheGCNTarget(), 24580b57cec5SDimitry Andric createAMDGPUSymbolizer); 24590b57cec5SDimitry Andric } 2460