KytyPS5/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h

898 lines
18 KiB
C++

#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_SHADERDECODER_H_
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_SHADERDECODER_H_
#include "common/common.h"
#include <magic_enum.hpp>
#include <span>
#include <string_view>
#include <vector>
namespace Libs::Graphics::ShaderRecompiler::Decoder {
// PS5 flat stack addresses use these SH_MEM_BASES aperture tags in VA[63:32].
constexpr uint32_t PrivateApertureHigh = 0x70000000u;
constexpr uint32_t SharedApertureHigh = 0x80000000u;
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,
S_MOV_B32,
S_MOV_B64,
S_CMOV_B64,
S_MOVK_I32,
S_ABS_I32,
S_SEXT_I32_I8,
S_SEXT_I32_I16,
S_ABSDIFF_I32,
S_BREV_B32,
S_BREV_B64,
S_BCNT0_I32_B32,
S_BCNT0_I32_B64,
S_BCNT1_I32_B32,
S_BCNT1_I32_B64,
S_FF0_I32_B32,
S_FF0_I32_B64,
S_FF1_I32_B32,
S_FF1_I32_B64,
S_FLBIT_I32_B32,
S_FLBIT_I32_B64,
S_BITREPLICATE_B64_B32,
S_QUADMASK_B64,
S_GETPC_B64,
S_SETPC_B64,
S_SWAPPC_B64,
S_SUBVECTOR_LOOP_BEGIN,
S_SUBVECTOR_LOOP_END,
S_AND_SAVEEXEC_B32,
S_ORN2_SAVEEXEC_B32,
S_ANDN1_SAVEEXEC_B32,
S_AND_SAVEEXEC_B64,
S_ORN2_SAVEEXEC_B64,
S_ANDN1_SAVEEXEC_B64,
S_NOT_B32,
S_NOT_B64,
S_WQM_B32,
S_WQM_B64,
S_ADD_U32,
S_ADDC_U32,
S_SUBB_U32,
S_SUB_U32,
S_ADD_I32,
S_SUB_I32,
S_BITCMP0_B32,
S_BITCMP1_B32,
S_BITCMP0_B64,
S_BITCMP1_B64,
S_BITSET0_B32,
S_BITSET1_B32,
S_BITSET0_B64,
S_BITSET1_B64,
S_MIN_I32,
S_MAX_I32,
S_MIN_U32,
S_MAX_U32,
S_AND_B32,
S_AND_B64,
S_ANDN2_B32,
S_ANDN2_B64,
S_OR_B32,
S_OR_B64,
S_ORN2_B32,
S_ORN2_B64,
S_XOR_B32,
S_XOR_B64,
S_NAND_B32,
S_NAND_B64,
S_NOR_B32,
S_NOR_B64,
S_XNOR_B32,
S_XNOR_B64,
S_LSHL_B32,
S_LSHL_B64,
S_LSHL1_ADD_U32,
S_LSHL2_ADD_U32,
S_LSHL3_ADD_U32,
S_LSHL4_ADD_U32,
S_LSHR_B32,
S_LSHR_B64,
S_ASHR_I32,
S_ASHR_I64,
S_MUL_I32,
S_MUL_HI_U32,
S_MUL_HI_I32,
S_MULK_I32,
S_BFE_U32,
S_BFE_I32,
S_BFE_U64,
S_BFM_B32,
S_BFM_B64,
S_CSELECT_B32,
S_CSELECT_B64,
S_SETPRIO,
S_PACK_LL_B32_B16,
S_PACK_LH_B32_B16,
S_PACK_HH_B32_B16,
S_CMP_EQ_I32,
S_CMP_LG_I32,
S_CMP_GT_I32,
S_CMP_GE_I32,
S_CMP_LT_I32,
S_CMP_LE_I32,
S_CMP_EQ_U32,
S_CMP_LG_U32,
S_CMP_GT_U32,
S_CMP_GE_U32,
S_CMP_LT_U32,
S_CMP_LE_U32,
S_CMP_EQ_U64,
S_CMP_LG_U64,
V_NOP,
V_MOV_B32,
V_MOVRELD_B32,
V_MOVRELS_B32,
V_READFIRSTLANE_B32,
V_READLANE_B32,
V_WRITELANE_B32,
V_PERMLANE16_B32,
V_PERMLANEX16_B32,
V_CUBEID_F32,
V_CUBESC_F32,
V_CUBETC_F32,
V_CUBEMA_F32,
V_CNDMASK_B32,
V_DOT2C_F32_F16,
V_CVT_F64_I32,
V_CVT_F32_F64,
V_CVT_F64_F32,
V_CVT_F64_U32,
V_CVT_F32_I32,
V_CVT_F32_U32,
V_CVT_U32_F32,
V_CVT_I32_F32,
V_CVT_F16_F32,
V_CVT_F32_F16,
V_CVT_F16_U16,
V_CVT_U16_F16,
V_CVT_F16_I16,
V_CVT_I16_F16,
V_CVT_RPI_I32_F32,
V_CVT_FLR_I32_F32,
V_FREXP_EXP_I32_F32,
V_FREXP_MANT_F32,
V_CVT_OFF_F32_I4,
V_CVT_F32_UBYTE0,
V_CVT_F32_UBYTE1,
V_CVT_F32_UBYTE2,
V_CVT_F32_UBYTE3,
V_RCP_F64,
V_RCP_F32,
V_RCP_IFLAG_F32,
V_FRACT_F32,
V_FRACT_F64,
V_TRUNC_F32,
V_TRUNC_F64,
V_CEIL_F32,
V_CEIL_F64,
V_RNDNE_F32,
V_FLOOR_F32,
V_FLOOR_F64,
V_EXP_F32,
V_LOG_F32,
V_RSQ_F32,
V_SQRT_F32,
V_RCP_F16,
V_SQRT_F16,
V_RSQ_F16,
V_LOG_F16,
V_EXP_F16,
V_FLOOR_F16,
V_CEIL_F16,
V_TRUNC_F16,
V_RNDNE_F16,
V_FRACT_F16,
V_SIN_F16,
V_COS_F16,
V_SIN_F32,
V_COS_F32,
V_NOT_B32,
V_BFREV_B32,
V_FFBH_U32,
V_FFBL_B32,
V_FFBH_I32,
V_ADD_F32,
V_SUB_F32,
V_SUBREV_F32,
V_MUL_F32,
V_MAC_F32,
V_MADMK_F32,
V_MADAK_F32,
V_FMAC_F32,
V_FMAMK_F32,
V_FMAAK_F32,
V_MIN_F32,
V_MAX_F32,
V_ADD_F16,
V_SUB_F16,
V_SUBREV_F16,
V_MUL_F16,
V_FMAC_F16,
V_FMAMK_F16,
V_FMAAK_F16,
V_MIN_I32,
V_MAX_I32,
V_MUL_I32_I24,
V_MUL_U32_U24,
V_MUL_LO_U32,
V_MUL_HI_U32,
V_MUL_LO_I32,
V_MUL_HI_I32,
V_CVT_PKRTZ_F16_F32,
V_CVT_PK_U8_F32,
V_MAD_F32,
V_MAD_I16,
V_MAD_I32_I24,
V_MAD_U32_U24,
V_MAD_U64_U32,
V_FMA_F64,
V_ADD_F64,
V_MUL_F64,
V_MIN_F64,
V_MAX_F64,
V_FMA_F32,
V_FMA_F16,
V_PACK_B32_F16,
V_BFE_U32,
V_BFE_I32,
V_BFI_B32,
V_ALIGNBIT_B32,
V_ALIGNBYTE_B32,
V_MIN3_F32,
V_MIN3_I32,
V_MIN3_U32,
V_MIN3_F16,
V_MIN3_U16,
V_MAX3_F32,
V_MAX3_I32,
V_MAX3_U32,
V_MAX3_F16,
V_MED3_F32,
V_MED3_I32,
V_MED3_U32,
V_MED3_F16,
V_MED3_I16,
V_SAD_U32,
V_ADD3_U32,
V_LSHL_ADD_U32,
V_ADD_LSHL_U32,
V_XAD_U32,
V_LSHL_OR_B32,
V_AND_OR_B32,
V_OR3_B32,
V_XOR3_B32,
V_ADD_I32,
V_SUB_I32,
V_SUBREV_I32,
V_BFM_B32,
V_LDEXP_F32,
V_CVT_PKNORM_I16_F32,
V_CVT_PKNORM_U16_F32,
V_CVT_PK_U16_U32,
V_CVT_PK_I16_I32,
V_PK_MAD_I16,
V_PK_MUL_LO_U16,
V_PK_ADD_I16,
V_PK_SUB_I16,
V_PK_LSHLREV_B16,
V_PK_LSHRREV_B16,
V_PK_ASHRREV_I16,
V_PK_MAX_I16,
V_PK_MIN_I16,
V_PK_MAD_U16,
V_PK_ADD_F16,
V_PK_MUL_F16,
V_PK_MIN_F16,
V_PK_MAX_F16,
V_PK_FMA_F16,
V_PK_FMAC_F16,
V_PK_ADD_U16,
V_PK_SUB_U16,
V_PK_MAX_U16,
V_PK_MIN_U16,
V_MAD_MIXLO_F16,
V_MAD_MIXHI_F16,
V_ADD_NC_U32,
V_ADDC_U32,
V_SUB_CO_CI_U32,
V_SUBREV_CO_CI_U32,
V_SUB_NC_U32,
V_SUBREV_NC_U32,
V_ADD_NC_U16,
V_SUB_NC_U16,
V_MUL_LO_U16,
V_MAX_U16,
V_MAX_I16,
V_MIN_U16,
V_MIN_I16,
V_ADD_NC_I16,
V_SUB_NC_I16,
V_AND_B32,
V_OR_B32,
V_XOR_B32,
V_XNOR_B32,
V_LSHL_B32,
V_LSHLREV_B32,
V_LSHR_B32,
V_LSHRREV_B32,
V_ASHR_I32,
V_ASHRREV_I32,
V_LSHLREV_B64,
V_LSHRREV_B64,
V_LSHLREV_B16,
V_LSHRREV_B16,
V_ASHRREV_I16,
V_BCNT_U32_B32,
V_MBCNT_LO_U32_B32,
V_MBCNT_HI_U32_B32,
V_MIN_U32,
V_MAX_U32,
V_MAX_F16,
V_MIN_F16,
V_CMP_F_F32,
V_CMP_LT_F32,
V_CMP_EQ_F32,
V_CMP_LE_F32,
V_CMP_GT_F32,
V_CMP_LG_F32,
V_CMP_GE_F32,
V_CMP_O_F32,
V_CMP_U_F32,
V_CMP_NGE_F32,
V_CMP_NLG_F32,
V_CMP_NGT_F32,
V_CMP_NLE_F32,
V_CMP_NEQ_F32,
V_CMP_NLT_F32,
V_CMP_TRU_F32,
V_CMP_F_F64,
V_CMP_LT_F64,
V_CMP_EQ_F64,
V_CMP_LE_F64,
V_CMP_GT_F64,
V_CMP_LG_F64,
V_CMP_GE_F64,
V_CMP_O_F64,
V_CMP_U_F64,
V_CMP_NGE_F64,
V_CMP_NLG_F64,
V_CMP_NGT_F64,
V_CMP_NLE_F64,
V_CMP_NEQ_F64,
V_CMP_NLT_F64,
V_CMP_TRU_F64,
V_CMPX_F_F64,
V_CMPX_LT_F64,
V_CMPX_EQ_F64,
V_CMPX_LE_F64,
V_CMPX_GT_F64,
V_CMPX_LG_F64,
V_CMPX_GE_F64,
V_CMPX_O_F64,
V_CMPX_U_F64,
V_CMPX_NGE_F64,
V_CMPX_NLG_F64,
V_CMPX_NGT_F64,
V_CMPX_NLE_F64,
V_CMPX_NEQ_F64,
V_CMPX_NLT_F64,
V_CMPX_TRU_F64,
V_CMPX_LT_F32,
V_CMPX_EQ_F32,
V_CMPX_LE_F32,
V_CMPX_GT_F32,
V_CMPX_LG_F32,
V_CMPX_GE_F32,
V_CMPX_O_F32,
V_CMPX_U_F32,
V_CMPX_NGE_F32,
V_CMPX_NLG_F32,
V_CMPX_NGT_F32,
V_CMPX_NLE_F32,
V_CMPX_NEQ_F32,
V_CMPX_NLT_F32,
V_CMP_F_I32,
V_CMP_LT_I32,
V_CMP_EQ_I32,
V_CMP_LE_I32,
V_CMP_GT_I32,
V_CMP_NE_I32,
V_CMP_GE_I32,
V_CMP_T_I32,
V_CMP_CLASS_F32,
V_CMPX_CLASS_F32,
V_CMP_CLASS_F16,
V_CMPX_CLASS_F16,
V_CMP_LT_I16,
V_CMP_EQ_I16,
V_CMP_LE_I16,
V_CMP_GT_I16,
V_CMP_NE_I16,
V_CMP_GE_I16,
V_CMPX_LT_I16,
V_CMPX_EQ_I16,
V_CMPX_LE_I16,
V_CMPX_GT_I16,
V_CMPX_NE_I16,
V_CMPX_GE_I16,
V_CMP_LT_F16,
V_CMP_EQ_F16,
V_CMP_LE_F16,
V_CMP_GT_F16,
V_CMP_LG_F16,
V_CMP_GE_F16,
V_CMP_NGE_F16,
V_CMP_NGT_F16,
V_CMP_NEQ_F16,
V_CMP_NLT_F16,
V_CMPX_LT_F16,
V_CMPX_EQ_F16,
V_CMPX_LE_F16,
V_CMPX_GT_F16,
V_CMPX_GE_F16,
V_CMPX_NGT_F16,
V_CMPX_NLE_F16,
V_CMPX_NEQ_F16,
V_CMPX_NLT_F16,
V_CMPX_LT_I32,
V_CMPX_EQ_I32,
V_CMPX_LE_I32,
V_CMPX_GT_I32,
V_CMPX_NE_I32,
V_CMPX_GE_I32,
V_CMP_LT_U16,
V_CMP_EQ_U16,
V_CMP_LE_U16,
V_CMP_GT_U16,
V_CMPX_LT_U16,
V_CMPX_EQ_U16,
V_CMPX_GT_U16,
V_CMPX_NE_U16,
V_CMP_NE_U16,
V_CMP_GE_U16,
V_CMP_F_U32,
V_CMP_LT_U32,
V_CMP_EQ_U32,
V_CMP_LE_U32,
V_CMP_GT_U32,
V_CMP_NE_U32,
V_CMP_GE_U32,
V_CMP_T_U32,
// Keep V_CMP_F_I64 to V_CMPX_T_U64 contiguous: VectorAluOps.cpp tests this range.
V_CMP_F_I64,
V_CMP_LT_I64,
V_CMP_EQ_I64,
V_CMP_LE_I64,
V_CMP_GT_I64,
V_CMP_NE_I64,
V_CMP_GE_I64,
V_CMP_T_I64,
V_CMP_F_U64,
V_CMP_LT_U64,
V_CMP_EQ_U64,
V_CMP_LE_U64,
V_CMP_GT_U64,
V_CMP_NE_U64,
V_CMP_GE_U64,
V_CMP_T_U64,
V_CMPX_F_I64,
V_CMPX_LT_I64,
V_CMPX_EQ_I64,
V_CMPX_LE_I64,
V_CMPX_GT_I64,
V_CMPX_NE_I64,
V_CMPX_GE_I64,
V_CMPX_T_I64,
V_CMPX_F_U64,
V_CMPX_LT_U64,
V_CMPX_EQ_U64,
V_CMPX_LE_U64,
V_CMPX_GT_U64,
V_CMPX_NE_U64,
V_CMPX_GE_U64,
V_CMPX_T_U64,
V_CMPX_LT_U32,
V_CMPX_EQ_U32,
V_CMPX_LE_U32,
V_CMPX_GT_U32,
V_CMPX_NE_U32,
V_CMPX_GE_U32,
S_LOAD_DWORD,
S_LOAD_DWORDX2,
S_LOAD_DWORDX4,
S_LOAD_DWORDX8,
S_LOAD_DWORDX16,
S_BUFFER_LOAD_DWORD,
S_BUFFER_LOAD_DWORDX2,
S_BUFFER_LOAD_DWORDX4,
S_BUFFER_LOAD_DWORDX8,
S_BUFFER_LOAD_DWORDX16,
S_MEMREALTIME,
BUFFER_LOAD_FORMAT_X,
BUFFER_LOAD_FORMAT_XY,
BUFFER_LOAD_FORMAT_XYZ,
BUFFER_LOAD_FORMAT_XYZW,
BUFFER_LOAD_FORMAT_D16_X,
BUFFER_STORE_FORMAT_X,
BUFFER_STORE_FORMAT_XY,
BUFFER_STORE_FORMAT_XYZ,
BUFFER_STORE_FORMAT_XYZW,
BUFFER_STORE_FORMAT_D16_X,
BUFFER_LOAD_UBYTE,
BUFFER_LOAD_SBYTE,
BUFFER_LOAD_USHORT,
BUFFER_LOAD_SSHORT,
BUFFER_LOAD_SHORT_D16,
BUFFER_LOAD_SHORT_D16_HI,
BUFFER_LOAD_DWORD,
BUFFER_LOAD_DWORDX2,
BUFFER_LOAD_DWORDX3,
BUFFER_LOAD_DWORDX4,
BUFFER_STORE_BYTE,
BUFFER_STORE_SHORT,
BUFFER_STORE_DWORD,
BUFFER_STORE_DWORDX2,
BUFFER_STORE_DWORDX3,
BUFFER_STORE_DWORDX4,
TBUFFER_LOAD_FORMAT_X,
TBUFFER_LOAD_FORMAT_XY,
TBUFFER_LOAD_FORMAT_XYZ,
TBUFFER_LOAD_FORMAT_XYZW,
TBUFFER_STORE_FORMAT_X,
TBUFFER_STORE_FORMAT_XY,
TBUFFER_STORE_FORMAT_XYZ,
TBUFFER_STORE_FORMAT_XYZW,
BUFFER_ATOMIC_SWAP,
BUFFER_ATOMIC_CMPSWAP,
BUFFER_ATOMIC_SWAP_X2,
BUFFER_ATOMIC_ADD,
BUFFER_ATOMIC_SUB,
BUFFER_ATOMIC_SMIN,
BUFFER_ATOMIC_UMIN,
BUFFER_ATOMIC_SMAX,
BUFFER_ATOMIC_UMAX,
BUFFER_ATOMIC_AND,
BUFFER_ATOMIC_AND_X2,
BUFFER_ATOMIC_OR,
BUFFER_ATOMIC_OR_X2,
BUFFER_ATOMIC_XOR,
BUFFER_ATOMIC_FMIN,
BUFFER_ATOMIC_FMAX,
FLAT_LOAD_UBYTE,
FLAT_LOAD_SBYTE,
FLAT_LOAD_USHORT,
FLAT_LOAD_SSHORT,
FLAT_LOAD_SHORT_D16,
FLAT_LOAD_DWORD,
FLAT_LOAD_DWORDX2,
FLAT_LOAD_DWORDX3,
FLAT_LOAD_DWORDX4,
FLAT_STORE_BYTE,
FLAT_STORE_SHORT,
FLAT_STORE_DWORD,
FLAT_STORE_DWORDX2,
FLAT_STORE_DWORDX3,
FLAT_STORE_DWORDX4,
DS_ADD_U32,
DS_ADD_U64,
DS_ADD_RTN_U32,
DS_SUB_U32,
DS_SUB_RTN_U32,
DS_INC_U32,
DS_INC_RTN_U32,
DS_DEC_U32,
DS_DEC_RTN_U32,
DS_MIN_I32,
DS_MIN_RTN_I32,
DS_MAX_I32,
DS_MAX_RTN_I32,
DS_MIN_U32,
DS_MIN_RTN_U32,
DS_MAX_U32,
DS_MAX_RTN_U32,
DS_MAX_RTN_U64,
DS_CMPST_RTN_B64,
DS_AND_B32,
DS_AND_RTN_B32,
DS_OR_B32,
DS_OR_B64,
DS_OR_RTN_B32,
DS_XOR_B32,
DS_XOR_RTN_B32,
DS_MSKOR_B32,
DS_WRXCHG_RTN_B32,
DS_MIN_F32,
DS_MAX_F32,
DS_SWIZZLE_B32,
DS_PERMUTE_B32,
DS_BPERMUTE_B32,
DS_CONSUME,
DS_APPEND,
DS_ORDERED_COUNT,
DS_READ_I8,
DS_READ_U8,
DS_READ_I16,
DS_READ_U16,
DS_READ_U16_D16,
DS_READ_U16_D16_HI,
DS_READ2_B32,
DS_READ2ST64_B32,
DS_READ_B32,
DS_READ_B64,
DS_READ2_B64,
DS_READ2ST64_B64,
DS_READ_B96,
DS_READ_B128,
DS_WRITE_B8,
DS_WRITE_B16,
DS_WRITE_B8_D16_HI,
DS_WRITE_B16_D16_HI,
DS_WRITE2_B32,
DS_WRITE2ST64_B32,
DS_WRITE2_B64,
DS_WRITE2ST64_B64,
DS_WRITE_B32,
DS_WRITE_B64,
DS_WRITE_B96,
DS_WRITE_B128,
DS_WRITE_ADDTID_B32,
DS_READ_ADDTID_B32,
IMAGE_BVH_INTERSECT_RAY,
IMAGE_GET_RESINFO,
IMAGE_GET_LOD,
IMAGE_LOAD,
IMAGE_LOAD_MIP,
IMAGE_STORE,
IMAGE_STORE_MIP,
IMAGE_ATOMIC_SWAP,
IMAGE_ATOMIC_CMPSWAP,
IMAGE_ATOMIC_ADD,
IMAGE_ATOMIC_SMIN,
IMAGE_ATOMIC_UMIN,
IMAGE_ATOMIC_SMAX,
IMAGE_ATOMIC_UMAX,
IMAGE_ATOMIC_AND,
IMAGE_ATOMIC_OR,
IMAGE_ATOMIC_XOR,
IMAGE_ATOMIC_FMIN,
IMAGE_ATOMIC_FMAX,
IMAGE_SAMPLE,
IMAGE_GATHER4_L,
IMAGE_GATHER4_LZ,
IMAGE_GATHER4_C,
IMAGE_GATHER4_C_LZ,
IMAGE_GATHER4_LZ_O,
IMAGE_GATHER4_C_O,
IMAGE_GATHER4_C_LZ_O,
IMAGE_GATHER4H,
V_INTERP_P1_F32,
V_INTERP_P2_F32,
V_INTERP_MOV_F32,
S_NOP,
S_WAITCNT,
S_WAITCNT_VSCNT,
S_WAITCNT_DEPCTR,
S_BARRIER,
S_BRANCH,
S_CBRANCH_SCC0,
S_CBRANCH_SCC1,
S_CBRANCH_VCCZ,
S_CBRANCH_VCCNZ,
S_CBRANCH_EXECZ,
S_CBRANCH_EXECNZ,
S_CBRANCH_CDBGSYS,
S_CBRANCH_CDBGUSER,
S_CBRANCH_CDBGSYS_OR_USER,
S_CBRANCH_CDBGSYS_AND_USER,
S_SENDMSG,
S_GETREG_B32,
S_SETREG_B32,
S_SLEEP,
S_TRAP,
S_TTRACEDATA,
S_INST_PREFETCH,
S_ENDPGM,
EXP,
COUNT
};
enum class OperandKind {
Unknown,
LiteralConstant,
IntegerInlineConstant,
FloatInlineConstant,
Sgpr,
VccLo,
VccHi,
VccZ,
ExecLo,
ExecHi,
ExecZ,
Scc,
M0,
PopsExitingWaveId,
SharedBase,
PrivateBase,
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,
ImageSampleFlagAdjust = 1u << 10u,
ImageSampleFlagUnnormalized = 1u << 11u,
};
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;
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 explicit_sdwa_dst = false;
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;
bool dpp8 = false;
};
struct Instruction {
uint32_t pc = 0;
uint32_t word_count = 1;
uint32_t raw[MaxInstructionRawWords] = {};
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_components = 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 dlc = false;
bool slc = false;
bool idxen = false;
bool offen = false;
bool image_r128 = false;
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<const uint32_t> code;
std::vector<Instruction> instructions;
bool has_swap_pc = false;
};
// 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.
void DecodeInstruction(std::span<const uint32_t> code, uint32_t word_index, Instruction& inst);
Program DecodeFrontProgram(std::span<const uint32_t> front);
void DecodeProgram(std::span<const uint32_t> code, Program& program);
bool IsConditionalBranch(Opcode opcode);
bool IsDirectBranch(Opcode opcode);
void DecodeScalarSource(uint32_t code, uint32_t pc, Operand& operand);
void DecodeScalarDestination(uint32_t code, uint32_t pc, Operand& operand);
void DecodeVectorGpr(uint32_t reg, Operand& operand);
void ReadLiteralOperands(std::span<const uint32_t> code, uint32_t word_index, Instruction& inst);
void SetRawWords(Instruction& inst, std::span<const uint32_t> code, uint32_t word_index,
uint32_t word_count);
void SetUnsupported(Instruction& inst, Family family, uint32_t opcode_id, const char* reason);
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
template <>
struct magic_enum::customize::enum_range<Libs::Graphics::ShaderRecompiler::Decoder::Opcode> {
static constexpr int min =
static_cast<int>(Libs::Graphics::ShaderRecompiler::Decoder::Opcode::UNKNOWN);
static constexpr int max =
static_cast<int>(Libs::Graphics::ShaderRecompiler::Decoder::Opcode::COUNT) - 1;
};
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_SHADER_RECOMPILER_SHADERDECODER_H_ */