diff --git a/core/libs/prx/libSceAgcDriver/CMakeLists.txt b/core/libs/prx/libSceAgcDriver/CMakeLists.txt index 1d8e5eacf..5fb7a0538 100644 --- a/core/libs/prx/libSceAgcDriver/CMakeLists.txt +++ b/core/libs/prx/libSceAgcDriver/CMakeLists.txt @@ -344,6 +344,18 @@ add_test_executable(agc_vop1_control_decode_tests EXCLUDE_FROM_ALL tests/Vop1Con target_link_libraries(agc_vop1_control_decode_tests PRIVATE shader_recompiler_agc_driver libc) set_target_properties(agc_vop1_control_decode_tests PROPERTIES CXX_EXTENSIONS OFF) configure_windows_unwind(agc_vop1_control_decode_tests) +add_test_executable(agc_vop2_encoding_decode_tests EXCLUDE_FROM_ALL tests/Vop2EncodingDecode.cpp) +target_link_libraries(agc_vop2_encoding_decode_tests PRIVATE shader_recompiler_agc_driver libc) +set_target_properties(agc_vop2_encoding_decode_tests PROPERTIES CXX_EXTENSIONS OFF) +configure_windows_unwind(agc_vop2_encoding_decode_tests) +if(BUILD_TESTING) + set_target_properties(agc_vop2_encoding_decode_tests PROPERTIES EXCLUDE_FROM_ALL OFF) + add_test(NAME agc_vop2_encoding_decode COMMAND agc_vop2_encoding_decode_tests) + if(WIN32) + set_tests_properties(agc_vop2_encoding_decode PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() +endif() add_test_executable(agc_dcc_key_sharing_tests EXCLUDE_FROM_ALL tests/DccKeySharing.cpp) target_include_directories(agc_dcc_key_sharing_tests PRIVATE ${LIBS_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/core/shader/recompiler ${CMAKE_SOURCE_DIR}/3rdparty/Vulkan-Headers/include) diff --git a/core/libs/prx/libSceAgcDriver/tests/Vop2EncodingDecode.cpp b/core/libs/prx/libSceAgcDriver/tests/Vop2EncodingDecode.cpp new file mode 100644 index 000000000..83f4a3c52 --- /dev/null +++ b/core/libs/prx/libSceAgcDriver/tests/Vop2EncodingDecode.cpp @@ -0,0 +1,82 @@ +#include "RdnaDecoder/RdnaInstructionDecoder.hpp" +#include +#include +#include +#include + +using namespace ShaderRecompiler; + +namespace { + +struct Accepted { + std::vector words; + RdnaOpcode op; + const char* name; +}; + +struct Refused { + std::vector words; + const char* reason; + const char* name; +}; + +} + +int main() { + const std::vector accepted{ + {{0x2c040300u}, RdnaOpcode::VLshrrevB32, "v_lshrrev_b32"}, + {{0x6e040300u, 0x00003c00u}, RdnaOpcode::VFmamkF16, "v_fmamk_f16"}, + {{0x78040300u}, RdnaOpcode::VPkFmacF16, "v_pk_fmac_f16"}, + {{0xd5160002u, 0x00020300u}, RdnaOpcode::VLshrrevB32, "VOP3 v_lshrrev_b32"}, + {{0xd7640002u, 0x00020300u}, RdnaOpcode::VBcntU32B32, "VOP3 v_bcnt_u32_b32"}, + {{0xd7650002u, 0x00020300u}, RdnaOpcode::VMbcntLoU32B32, "VOP3 v_mbcnt_lo_u32_b32"}, + {{0xd7660002u, 0x00020300u}, RdnaOpcode::VMbcntHiU32B32, "VOP3 v_mbcnt_hi_u32_b32"}, + }; + const std::vector refused{ + {{0x2a040300u}, "VOP2 opcode is not implemented", "VOP2 opcode 0x15"}, + {{0x2e040300u}, "VOP2 opcode is not implemented", "VOP2 opcode 0x17"}, + {{0x32040300u}, "VOP2 opcode is not implemented", "VOP2 opcode 0x19"}, + {{0x44040300u}, "VOP2 opcode is not implemented", "VOP2 opcode 0x22"}, + {{0x46040300u}, "VOP2 opcode is not implemented", "VOP2 opcode 0x23"}, + {{0x48040300u}, "VOP2 opcode is not implemented", "VOP2 opcode 0x24"}, + {{0xd5150002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x115"}, + {{0xd5170002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x117"}, + {{0xd5190002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x119"}, + {{0xd5220002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x122"}, + {{0xd5230002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x123"}, + {{0xd5240002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x124"}, + {{0xd5370002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x137"}, + {{0xd5380002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x138"}, + {{0xd53c0002u, 0x00020300u}, "VOP3 opcode is not implemented", "VOP3 opcode 0x13c"}, + }; + int failures = 0; + for (const auto& test : accepted) { + auto code = test.words; + code.push_back(0xbf810000u); + try { + const auto decoded = RdnaInstructionDecoder{}.Decode(code); + if (decoded.instructions.empty() || decoded.instructions[0].op != test.op || decoded.instructions[0].wordCount != test.words.size()) { + std::fprintf(stderr, "%s decodes to the wrong opcode or length\n", test.name); + ++failures; + } + } catch (const std::exception& error) { + std::fprintf(stderr, "%s was refused: %s\n", test.name, error.what()); + ++failures; + } + } + for (const auto& test : refused) { + auto code = test.words; + code.push_back(0xbf810000u); + std::string refusal; + try { + static_cast(RdnaInstructionDecoder{}.Decode(code)); + } catch (const std::exception& error) { + refusal = error.what(); + } + if (refusal.find(test.reason) == std::string::npos) { + std::fprintf(stderr, "%s was not refused\n", test.name); + ++failures; + } + } + return failures == 0 ? 0 : 1; +} diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/BufferAtomicCsub.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/BufferAtomicCsub.cpp index 5a2a267f4..0b150b2da 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/BufferAtomicCsub.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/BufferAtomicCsub.cpp @@ -28,12 +28,12 @@ constexpr std::uint32_t SharedExhausted = 1000u; alignas(256) std::array Input{}; alignas(256) std::array Output{}; -alignas(256) constexpr std::array Code{ +alignas(256) constexpr std::array Code{ 0x34020084, 0x34040085, 0xe0301000, 0x80000401, 0xe0301004, 0x80000501, 0xe0301008, 0x80000601, - 0xbf8c3f70, 0x7e140280, 0x461414c1, 0x481414c1, 0x7e0e0304, 0xe0d05000, 0x80010702, 0x7e100304, - 0xbefe03ff, 0x55555555, 0xe0d05004, 0x80010802, 0xbefe03c1, 0x7e120305, 0xe0d04800, 0x80010900, - 0x7e160306, 0xe0d04804, 0x80010b00, 0xbf8c3f70, 0xe0701008, 0x80010702, 0xe070100c, 0x80010802, - 0xe0701010, 0x80010a02, 0xbf810000, + 0xbf8c3f70, 0x7e140280, 0xd765000a, 0x000214c1, 0xd766000a, 0x000214c1, 0x7e0e0304, 0xe0d05000, + 0x80010702, 0x7e100304, 0xbefe03ff, 0x55555555, 0xe0d05004, 0x80010802, 0xbefe03c1, 0x7e120305, + 0xe0d04800, 0x80010900, 0x7e160306, 0xe0d04804, 0x80010b00, 0xbf8c3f70, 0xe0701008, 0x80010702, + 0xe070100c, 0x80010802, 0xe0701010, 0x80010a02, 0xbf810000, }; alignas(256) constexpr std::array NoReturnCode{ diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalLoadAddtid.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalLoadAddtid.cpp index e7875353c..34ccd295e 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/GlobalLoadAddtid.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/GlobalLoadAddtid.cpp @@ -28,12 +28,13 @@ constexpr std::uint32_t MaskedExecLo = 0x55555555u; alignas(256) std::array Table{}; alignas(256) std::array Output{}; -alignas(256) constexpr std::array AddtidCode{ +alignas(256) constexpr std::array AddtidCode{ 0x34020085, 0x34040082, 0xbe880300, 0x8709ff01, 0x0000ffff, 0x800aff08, 0x00000200, 0x820b8009, - 0x7e080280, 0x460808c1, 0x480808c1, 0x7e0a02ff, 0xabcdabcd, 0x7e0c02ff, 0xabcdabcd, 0x7e0e02ff, - 0xabcdabcd, 0xe0301000, 0x80000802, 0xdc588040, 0x05080000, 0xdc588fe4, 0x060a0000, 0xbefe03ff, - 0x55555555, 0xdc588000, 0x07080000, 0xbefe03c1, 0xe0701000, 0x80010401, 0xe0701004, 0x80010501, - 0xe0701008, 0x80010601, 0xe070100c, 0x80010701, 0xe0701010, 0x80010801, 0xbf810000, + 0x7e080280, 0xd7650004, 0x000208c1, 0xd7660004, 0x000208c1, 0x7e0a02ff, 0xabcdabcd, 0x7e0c02ff, + 0xabcdabcd, 0x7e0e02ff, 0xabcdabcd, 0xe0301000, 0x80000802, 0xdc588040, 0x05080000, 0xdc588fe4, + 0x060a0000, 0xbefe03ff, 0x55555555, 0xdc588000, 0x07080000, 0xbefe03c1, 0xe0701000, 0x80010401, + 0xe0701004, 0x80010501, 0xe0701008, 0x80010601, 0xe070100c, 0x80010701, 0xe0701010, 0x80010801, + 0xbf810000, }; struct Workgroup { diff --git a/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaOpcode.hpp b/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaOpcode.hpp index bdffac7f0..0b83c3ae6 100644 --- a/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaOpcode.hpp +++ b/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaOpcode.hpp @@ -70,9 +70,6 @@ enum class RdnaOpcode : std::uint16_t { VAndB32, VOrB32, VXorB32, - VLshlB32, - VLshrB32, - VAshrI32, VCmpEqF32, VCmpLtF32, VCmpGtF32, diff --git a/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp b/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp index 79affa1cd..374315cb1 100644 --- a/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp +++ b/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp @@ -183,9 +183,6 @@ bool IsVectorAluOpcode(RdnaOpcode opcode) { case RdnaOpcode::VAndB32: case RdnaOpcode::VOrB32: case RdnaOpcode::VXorB32: - case RdnaOpcode::VLshlB32: - case RdnaOpcode::VLshrB32: - case RdnaOpcode::VAshrI32: case RdnaOpcode::VCmpEqF32: case RdnaOpcode::VCmpLtF32: case RdnaOpcode::VCmpGtF32: diff --git a/core/shader/recompiler/RdnaDecoder/src/RdnaVectorOpDecoder.cpp b/core/shader/recompiler/RdnaDecoder/src/RdnaVectorOpDecoder.cpp index 326343f03..185071115 100644 --- a/core/shader/recompiler/RdnaDecoder/src/RdnaVectorOpDecoder.cpp +++ b/core/shader/recompiler/RdnaDecoder/src/RdnaVectorOpDecoder.cpp @@ -58,11 +58,8 @@ constexpr Vop2OpcodeInfo vop2Opcodes[] = { {0x12u, RdnaOpcode::VMaxI32, Vop2SdwaProfile::Integer}, {0x13u, RdnaOpcode::VMinU32, Vop2SdwaProfile::Integer}, {0x14u, RdnaOpcode::VMaxU32, Vop2SdwaProfile::Integer}, - {0x15u, RdnaOpcode::VLshrB32}, {0x16u, RdnaOpcode::VLshrrevB32, Vop2SdwaProfile::Integer}, - {0x17u, RdnaOpcode::VAshrI32}, {0x18u, RdnaOpcode::VAshrrevI32, Vop2SdwaProfile::Integer}, - {0x19u, RdnaOpcode::VLshlB32}, {0x1au, RdnaOpcode::VLshlrevB32, Vop2SdwaProfile::Integer}, {0x1bu, RdnaOpcode::VAndB32, Vop2SdwaProfile::Integer}, {0x1cu, RdnaOpcode::VOrB32, Vop2SdwaProfile::Integer}, @@ -71,9 +68,6 @@ constexpr Vop2OpcodeInfo vop2Opcodes[] = { {0x1fu, RdnaOpcode::VMacF32}, {0x20u, RdnaOpcode::VMadmkF32}, {0x21u, RdnaOpcode::VMadakF32}, - {0x22u, RdnaOpcode::VBcntU32B32}, - {0x23u, RdnaOpcode::VMbcntLoU32B32}, - {0x24u, RdnaOpcode::VMbcntHiU32B32}, {0x25u, RdnaOpcode::VAddNcU32, Vop2SdwaProfile::Integer}, {0x28u, RdnaOpcode::VAddcU32, Vop2SdwaProfile::Integer}, {0x29u, RdnaOpcode::VSubCoCiU32, Vop2SdwaProfile::Integer}, @@ -630,11 +624,11 @@ RdnaOpcode lookupVectorOpcode(const TEntry (&table)[Size], std::uint32_t encodin } bool isVop2LiteralMadOpcode(std::uint32_t opcode) { - return opcode == 0x20u || opcode == 0x21u || opcode == 0x2cu || opcode == 0x2du; + return opcode == 0x20u || opcode == 0x21u || opcode == 0x2cu || opcode == 0x2du || opcode == 0x37u || opcode == 0x38u; } bool isUnsupportedVop3EncodedVop2Alias(std::uint32_t opcode) { - return isVop2LiteralMadOpcode(opcode) || opcode == 0x02u || opcode == 0x0du; + return isVop2LiteralMadOpcode(opcode) || opcode == 0x02u || opcode == 0x0du || opcode == 0x3cu; } bool isVop3EncodedVopc(std::uint32_t opcode) { diff --git a/core/shader/recompiler/Translation/src/VectorInstructions.cpp b/core/shader/recompiler/Translation/src/VectorInstructions.cpp index 9b5fd4580..7fa68d0e3 100644 --- a/core/shader/recompiler/Translation/src/VectorInstructions.cpp +++ b/core/shader/recompiler/Translation/src/VectorInstructions.cpp @@ -1113,16 +1113,10 @@ bool TranslationContext::emitVector(const RdnaInstruction& inst) { return simpleInteger(inst, IrOpcode::BitReverse32, IrType::U32, false, false, false); case RdnaOpcode::VFfblB32: return simpleInteger(inst, IrOpcode::FindILsb32, IrType::U32, false, false, false); - case RdnaOpcode::VLshlB32: - return simpleInteger(inst, IrOpcode::ShiftLeftLogical32, IrType::U32, false, true, false); case RdnaOpcode::VLshlrevB32: return simpleInteger(inst, IrOpcode::ShiftLeftLogical32, IrType::U32, true, true, false); - case RdnaOpcode::VLshrB32: - return simpleInteger(inst, IrOpcode::ShiftRightLogical32, IrType::U32, false, true, false); case RdnaOpcode::VLshrrevB32: return simpleInteger(inst, IrOpcode::ShiftRightLogical32, IrType::U32, true, true, false); - case RdnaOpcode::VAshrI32: - return simpleInteger(inst, IrOpcode::ShiftRightArithmetic32, IrType::U32, false, true, false); case RdnaOpcode::VAshrrevI32: return simpleInteger(inst, IrOpcode::ShiftRightArithmetic32, IrType::U32, true, true, false); case RdnaOpcode::VLshlrevB64: