#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_SHADERDECODER_H_ #define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_SHADERDECODER_H_ #include "common/common.h" #include "common/stringUtils.h" #include #include #include namespace Libs::Graphics::ShaderRecompiler::Decoder { enum class Family { Unknown, SOP1, SOP2, SOPK, SOPC, SOPP, VOP1, VOP2, VOP3, VOP3P, VOPC, VINTRP, SMEM, MUBUF, MTBUF, FLAT, DS, MIMG, EXP }; enum class Opcode { Unknown, Unsupported, SMovB32, SMovB64, SMovkI32, SAbsI32, SBrevB32, SBcnt1I32B32, SBcnt1I32B64, SFf1I32B32, SFf1I32B64, SFlbitI32B64, SBitreplicateB64B32, SGetpcB64, SSetpcB64, SAndSaveexecB32, SAndn1SaveexecB32, SAndSaveexecB64, SOrn2SaveexecB64, SAndn1SaveexecB64, SNotB32, SNotB64, SWqmB64, SAddU32, SAddcU32, SSubbU32, SSubU32, SAddI32, SSubI32, SBitcmp0B32, SBitcmp1B32, SBitset0B32, SBitset1B32, SMinI32, SMaxI32, SMinU32, SMaxU32, SAndB32, SAndB64, SAndn2B32, SAndn2B64, SOrB32, SOrB64, SOrn2B32, SOrn2B64, SXorB32, SXorB64, SNandB32, SNandB64, SNorB32, SNorB64, SXnorB32, SXnorB64, SLshlB32, SLshlB64, SLshl1AddU32, SLshl2AddU32, SLshl3AddU32, SLshl4AddU32, SLshrB32, SLshrB64, SAshrI32, SMulI32, SMulHiU32, SMulkI32, SBfeU32, SBfeI32, SBfeU64, SBfmB32, SBfmB64, SCselectB32, SCselectB64, SPackLlB32B16, SPackLhB32B16, SPackHhB32B16, SCmpEqI32, SCmpLgI32, SCmpGtI32, SCmpGeI32, SCmpLtI32, SCmpLeI32, SCmpEqU32, SCmpLgU32, SCmpGtU32, SCmpGeU32, SCmpLtU32, SCmpLeU32, SCmpEqU64, SCmpLgU64, VNop, VMovB32, VMovreldB32, VMovrelsB32, VReadfirstlaneB32, VReadlaneB32, VWritelaneB32, VPermlane16B32, VPermlanex16B32, VCubeidF32, VCubescF32, VCubetcF32, VCubemaF32, VCndmaskB32, VDot2cF32F16, VCvtF32I32, VCvtF32U32, VCvtU32F32, VCvtI32F32, VCvtF16F32, VCvtF32F16, VCvtF16U16, VCvtU16F16, VCvtF16I16, VCvtI16F16, VCvtRpiI32F32, VCvtFlrI32F32, VCvtOffF32I4, VCvtF32Ubyte0, VCvtF32Ubyte1, VCvtF32Ubyte2, VCvtF32Ubyte3, VRcpF32, VRcpIflagF32, VFractF32, VTruncF32, VCeilF32, VRndneF32, VFloorF32, VExpF32, VLogF32, VRsqF32, VSqrtF32, VRcpF16, VSqrtF16, VRsqF16, VLogF16, VExpF16, VFloorF16, VCeilF16, VTruncF16, VRndneF16, VSinF32, VCosF32, VNotB32, VBfrevB32, VFfbhU32, VFfblB32, VAddF32, VSubF32, VSubrevF32, VMulF32, VMacF32, VMadmkF32, VMadakF32, VMinF32, VMaxF32, VAddF16, VSubF16, VSubrevF16, VMulF16, VFmacF16, VFmamkF16, VFmaakF16, VMinI32, VMaxI32, VMulI32I24, VMulU32U24, VMulLoU32, VMulHiU32, VMulLoI32, VMulHiI32, VCvtPkrtzF16F32, VCvtPkU8F32, VMadF32, VMadI32I24, VMadU32U24, VMadU64U32, VFmaF32, VFmaF16, VPackB32F16, VBfeU32, VBfeI32, VBfiB32, VAlignbitB32, VAlignbyteB32, VMin3F32, VMin3I32, VMin3U32, VMin3F16, VMax3F32, VMax3I32, VMax3U32, VMax3F16, VMed3F32, VMed3I32, VMed3U32, VMed3F16, VSadU32, VAdd3U32, VLshlAddU32, VAddLshlU32, VXadU32, VLshlOrB32, VAndOrB32, VOr3B32, VXor3B32, VAddI32, VSubI32, VSubrevI32, VBfmB32, VLdexpF32, VCvtPknormI16F32, VCvtPknormU16F32, VCvtPkU16U32, VCvtPkI16I32, VPkMadI16, VPkMulLoU16, VPkAddI16, VPkSubI16, VPkLshlrevB16, VPkLshrrevB16, VPkAshrrevI16, VPkMaxI16, VPkMinI16, VPkMadU16, VPkAddF16, VPkMulF16, VPkMinF16, VPkMaxF16, VPkFmaF16, VPkFmacF16, VPkAddU16, VPkSubU16, VPkMaxU16, VPkMinU16, VMadMixloF16, VMadMixhiF16, VAddNcU32, VAddcU32, VSubrevCoCiU32, VSubNcU32, VSubrevNcU32, VAddNcU16, VSubNcU16, VMaxU16, VMaxI16, VMinU16, VMinI16, VAddNcI16, VSubNcI16, VAndB32, VOrB32, VXorB32, VXnorB32, VLshlB32, VLshlrevB32, VLshrB32, VLshrrevB32, VAshrI32, VAshrrevI32, VLshlrevB16, VLshrrevB16, VAshrrevI16, VBcntU32B32, VMbcntLoU32B32, VMbcntHiU32B32, VMinU32, VMaxU32, VMaxF16, VMinF16, VCmpFF32, VCmpLtF32, VCmpEqF32, VCmpLeF32, VCmpGtF32, VCmpLgF32, VCmpGeF32, VCmpOF32, VCmpUF32, VCmpNgeF32, VCmpNlgF32, VCmpNgtF32, VCmpNleF32, VCmpNeqF32, VCmpNltF32, VCmpTruF32, VCmpxLtF32, VCmpxEqF32, VCmpxLeF32, VCmpxGtF32, VCmpxLgF32, VCmpxGeF32, VCmpxNgeF32, VCmpxNlgF32, VCmpxNgtF32, VCmpxNleF32, VCmpxNeqF32, VCmpxNltF32, VCmpFI32, VCmpLtI32, VCmpEqI32, VCmpLeI32, VCmpGtI32, VCmpNeI32, VCmpGeI32, VCmpTI32, VCmpClassF32, VCmpLtI16, VCmpEqI16, VCmpLeI16, VCmpGtI16, VCmpNeI16, VCmpGeI16, VCmpLtF16, VCmpEqF16, VCmpLeF16, VCmpGtF16, VCmpLgF16, VCmpGeF16, VCmpNeqF16, VCmpxLtF16, VCmpxEqF16, VCmpxLeF16, VCmpxGtF16, VCmpxGeF16, VCmpxNeqF16, VCmpxNltF16, VCmpxLtI32, VCmpxEqI32, VCmpxLeI32, VCmpxGtI32, VCmpxNeI32, VCmpxGeI32, VCmpLtU16, VCmpEqU16, VCmpLeU16, VCmpGtU16, VCmpNeU16, VCmpGeU16, VCmpFU32, VCmpLtU32, VCmpEqU32, VCmpLeU32, VCmpGtU32, VCmpNeU32, VCmpGeU32, VCmpTU32, VCmpEqI64, VCmpGtU64, VCmpNeU64, VCmpxLtU32, VCmpxEqU32, VCmpxLeU32, VCmpxGtU32, VCmpxNeU32, VCmpxGeU32, SLoadDword, SLoadDwordx2, SLoadDwordx4, SLoadDwordx8, SLoadDwordx16, SBufferLoadDword, SBufferLoadDwordx2, SBufferLoadDwordx4, SBufferLoadDwordx8, SBufferLoadDwordx16, BufferLoadFormatX, BufferLoadFormatXy, BufferLoadFormatXyz, BufferLoadFormatXyzw, BufferStoreFormatX, BufferStoreFormatXy, BufferStoreFormatXyz, BufferStoreFormatXyzw, BufferLoadUbyte, BufferLoadSbyte, BufferLoadUshort, BufferLoadSshort, BufferLoadDword, BufferLoadDwordx2, BufferLoadDwordx3, BufferLoadDwordx4, BufferStoreByte, BufferStoreShort, BufferStoreDword, BufferStoreDwordx2, BufferStoreDwordx3, BufferStoreDwordx4, TBufferLoadFormatX, TBufferLoadFormatXy, TBufferLoadFormatXyz, TBufferLoadFormatXyzw, TBufferStoreFormatX, TBufferStoreFormatXy, TBufferStoreFormatXyz, TBufferStoreFormatXyzw, BufferAtomicSwap, BufferAtomicAdd, BufferAtomicSub, BufferAtomicSMin, BufferAtomicUMin, BufferAtomicSMax, BufferAtomicUMax, BufferAtomicAnd, BufferAtomicOr, BufferAtomicXor, BufferAtomicFMin, BufferAtomicFMax, FlatLoadUbyte, FlatLoadSbyte, FlatLoadUshort, FlatLoadSshort, FlatLoadDword, FlatLoadDwordx2, FlatLoadDwordx3, FlatLoadDwordx4, FlatStoreByte, FlatStoreShort, FlatStoreDword, FlatStoreDwordx2, FlatStoreDwordx3, FlatStoreDwordx4, DsAddU32, DsAddRtnU32, DsSubU32, DsSubRtnU32, DsMinI32, DsMinRtnI32, DsMaxI32, DsMaxRtnI32, DsMinU32, DsMinRtnU32, DsMaxU32, DsMaxRtnU32, DsAndB32, DsAndRtnB32, DsOrB32, DsOrRtnB32, DsXorB32, DsXorRtnB32, DsWrxchgRtnB32, DsMinF32, DsMaxF32, DsSwizzleB32, DsConsume, DsAppend, DsReadSbyte, DsReadUbyte, DsReadSshort, DsReadUshort, DsRead2B32, DsReadB32, DsReadB64, DsRead2B64, DsRead2St64B64, DsReadB96, DsReadB128, DsWriteByte, DsWriteShort, DsWrite2B32, DsWrite2St64B32, DsWrite2B64, DsWrite2St64B64, DsWriteB32, DsWriteB64, DsWriteB96, DsWriteB128, DsWriteAddtidB32, DsReadAddtidB32, ImageGetResinfo, ImageGetLod, ImageLoad, ImageLoadMip, ImageStore, ImageStoreMip, ImageAtomicAdd, ImageAtomicUMin, ImageAtomicUMax, ImageAtomicAnd, ImageAtomicOr, ImageAtomicXor, ImageSample, ImageGather4Lz, ImageGather4C, ImageGather4CLz, ImageGather4LzO, ImageGather4CO, ImageGather4CLzO, ImageGather4H, VInterpP1F32, VInterpP2F32, VInterpMovF32, SNop, SWaitcnt, SBarrier, SBranch, SCbranchScc0, SCbranchScc1, SCbranchVccz, SCbranchVccnz, SCbranchExecz, SCbranchExecnz, SSendmsg, SSetregB32, SSleep, STrap, STtraceData, SInstPrefetch, SEndpgm, Exp }; enum class OperandKind { Unknown, LiteralConstant, IntegerInlineConstant, FloatInlineConstant, Sgpr, VccLo, VccHi, VccZ, ExecLo, ExecHi, ExecZ, Scc, M0, PopsExitingWaveId, Null, Vgpr, }; enum ImageSampleFlag : uint32_t { ImageSampleFlagLod = 1u << 0u, ImageSampleFlagBias = 1u << 1u, ImageSampleFlagDerivative = 1u << 2u, ImageSampleFlagCompare = 1u << 3u, ImageSampleFlagOffset = 1u << 4u, ImageSampleFlagLevelZero = 1u << 5u, ImageSampleFlagLodClamp = 1u << 6u, ImageSampleFlagA16 = 1u << 7u, ImageSampleFlagCd = 1u << 8u, ImageSampleFlagGatherHorizontal = 1u << 9u, }; enum class ImageDimension : uint32_t { Unknown, Dim1D, Dim1DArray, Dim2D, Dim3D, Dim2DArray, Dim2DMsaa, Dim2DMsaaArray, }; constexpr uint32_t MaxInstructionRawWords = 5u; constexpr uint32_t MaxImageNsaAddressComponents = 12u; struct Operand { OperandKind kind = OperandKind::Unknown; uint32_t value = 0; int32_t signed_val = 0; float float_val = 0.0f; uint32_t reg = 0; uint32_t sdwa_sel = 6; // Native 16-bit destinations use the same selector fields internally but preserve the // untouched half. Real SDWA encodings overwrite this with their decoded DST_U value. uint32_t sdwa_dst_unused = 2; uint32_t omod = 0; uint32_t dpp_ctrl = 0; uint32_t dpp_row_mask = 0xf; uint32_t dpp_bank_mask = 0xf; bool sdwa_sext = false; bool dpp_fetch_inactive = false; bool dpp_bound_ctrl = false; bool op_sel = false; bool op_sel_hi = false; bool negate = false; bool negate_hi = false; bool absolute = false; bool clamp = false; bool dpp = false; }; struct Instruction { uint32_t pc = 0; uint32_t word = 0; uint32_t word_count = 1; uint32_t raw[MaxInstructionRawWords] = {}; uint32_t raw_count = 1; Family family = Family::Unknown; uint32_t opcode_id = 0; Opcode opcode = Opcode::Unknown; Operand dst; Operand dst2; Operand src0; Operand src1; Operand src2; Operand src3; uint32_t src_count = 0; uint32_t offset = 0; uint32_t secondary_offset = 0; uint32_t dmask = 0; uint32_t data_dwords = 1; uint32_t data_bits = 32; uint32_t data_format = 0; uint32_t number_format = 0; uint32_t image_sample_flags = 0; ImageDimension image_dimension = ImageDimension::Unknown; uint32_t image_address_components = 0; uint32_t image_nsa_dwords = 0; uint32_t image_nsa_addr[MaxImageNsaAddressComponents] = {}; uint32_t memory_segment = 0; bool data_signed = false; bool typed = false; bool formatted = false; bool gds = false; bool glc = false; bool slc = false; bool idxen = false; bool offen = false; int32_t branch_offset = 0; uint32_t branch_target = 0; struct { uint32_t target = 0; uint32_t en = 0; bool done = false; bool compr = false; bool vm = false; } exp; std::string_view unsupported_reason; }; struct Program { std::span code; std::vector instructions; }; // Code spans are trusted to contain complete instructions, valid branch targets, and 32-bit PCs. Family GetInstructionFamily(uint32_t word); // The output object must be freshly initialized. bool DecodeInstruction(std::span code, uint32_t word_index, Instruction& inst, std::string* error); bool DecodeProgram(std::span code, Program& program, std::string* error); bool DecodeScalarSource(uint32_t code, uint32_t pc, Operand& operand, std::string* error); bool DecodeScalarDestination(uint32_t code, uint32_t pc, Operand& operand, std::string* error); void DecodeVectorGpr(uint32_t reg, Operand& operand); void ReadLiteralOperands(std::span code, uint32_t word_index, Instruction& inst); void SetRawWords(Instruction& inst, std::span code, uint32_t word_index, uint32_t word_count); void SetUnsupported(Instruction& inst, Family family, uint32_t opcode_id, const char* reason); std::string FamilyToString(Family family); std::string OpcodeToString(Opcode opcode); std::string OperandToString(const Operand& operand); const char* ImageDimensionToString(ImageDimension dimension); std::string InstructionToString(const Instruction& inst); std::string ProgramToString(const Program& program); } // namespace Libs::Graphics::ShaderRecompiler::Decoder #endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_SHADERDECODER_H_ */