diff --git a/core/libs/prx/libSceAgcDriver/CMakeLists.txt b/core/libs/prx/libSceAgcDriver/CMakeLists.txt index 21b44c72a..52cd05e97 100644 --- a/core/libs/prx/libSceAgcDriver/CMakeLists.txt +++ b/core/libs/prx/libSceAgcDriver/CMakeLists.txt @@ -609,6 +609,14 @@ if(BUILD_TESTING) set_tests_properties(vector_min_max_med16 PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() + add_test_executable(vector_mad_legacy_tests ${LIBS_INCLUDE_DIR}/tests/VectorMadLegacy.cpp) + target_link_libraries(vector_mad_legacy_tests PRIVATE shader_recompiler_agc_driver libc) + configure_windows_unwind(vector_mad_legacy_tests) + add_test(NAME vector_mad_legacy COMMAND vector_mad_legacy_tests) + if(WIN32) + set_tests_properties(vector_mad_legacy PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() add_test_executable(scalar_saveexec_tests ${LIBS_INCLUDE_DIR}/tests/ScalarSaveexec.cpp) target_link_libraries(scalar_saveexec_tests PRIVATE shader_recompiler_agc_driver libc) configure_windows_unwind(scalar_saveexec_tests) diff --git a/core/libs/tests/VectorMadLegacy.cpp b/core/libs/tests/VectorMadLegacy.cpp new file mode 100644 index 000000000..cf2677161 --- /dev/null +++ b/core/libs/tests/VectorMadLegacy.cpp @@ -0,0 +1,26 @@ +#include "Translation/TranslationContext.hpp" +#include "RdnaDecoder/RdnaVectorOpDecoder.hpp" +#include +#include + +using namespace ShaderRecompiler; +static void Require(bool value) { if (!value) throw std::runtime_error("vector legacy mad regression"); } +static void Check(std::uint32_t encoding, RdnaOpcode opcode, IrOpcode expected) { + const std::array code{(encoding << 16u) | 1u, 1u | (2u << 9u) | (3u << 18u)}; + const RdnaInstruction instruction = DecodeRdnaVop3(0u, code, 0u); + Require(instruction.op == opcode); + Require(instruction.family == RdnaInstructionFamily::VOP3); + Require(IsVectorAluOpcode(instruction.op)); + IrProgram program; + auto& block = program.CreateBlock(); + program.SetEntryBlock(block); + TranslationContext context(program, block, 256); + context.TranslateInstruction(instruction); + bool found = false; + for (auto* value : block.Instructions()) found = found || value->Opcode() == expected; + Require(found); +} +int main() { + Check(0x140u, RdnaOpcode::VMadLegacyF32, IrOpcode::FPFma32); + Check(0x150u, RdnaOpcode::VMullitF32, IrOpcode::FPMul32); +} diff --git a/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaOpcode.hpp b/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaOpcode.hpp index fe7bbb1ec..318f7a3a7 100644 --- a/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaOpcode.hpp +++ b/core/shader/recompiler/RdnaDecoder/include/RdnaDecoder/RdnaOpcode.hpp @@ -50,6 +50,8 @@ enum class RdnaOpcode : std::uint16_t { VSubF32, VMulF32, VMadF32, + VMadLegacyF32, + VMullitF32, VFmaF32, VAddI32, VSubI32, diff --git a/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp b/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp index f2aa8c443..d8829f978 100644 --- a/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp +++ b/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp @@ -156,6 +156,8 @@ bool IsVectorAluOpcode(RdnaOpcode opcode) { case RdnaOpcode::VSubF32: case RdnaOpcode::VMulF32: case RdnaOpcode::VMadF32: + case RdnaOpcode::VMadLegacyF32: + case RdnaOpcode::VMullitF32: case RdnaOpcode::VFmaF32: case RdnaOpcode::VAddI32: case RdnaOpcode::VSubI32: diff --git a/core/shader/recompiler/RdnaDecoder/src/RdnaVectorOpDecoder.cpp b/core/shader/recompiler/RdnaDecoder/src/RdnaVectorOpDecoder.cpp index 9ec27141e..393595a51 100644 --- a/core/shader/recompiler/RdnaDecoder/src/RdnaVectorOpDecoder.cpp +++ b/core/shader/recompiler/RdnaDecoder/src/RdnaVectorOpDecoder.cpp @@ -372,6 +372,7 @@ constexpr VopcOpcodeInfo vopcOpcodes[] = { }; constexpr VectorOpcodeInfo vop3Opcodes[] = { + {0x140u, RdnaOpcode::VMadLegacyF32}, {0x141u, RdnaOpcode::VMadF32}, {0x142u, RdnaOpcode::VMadI32I24}, {0x143u, RdnaOpcode::VMadU32U24}, @@ -385,6 +386,7 @@ constexpr VectorOpcodeInfo vop3Opcodes[] = { {0x149u, RdnaOpcode::VBfeI32}, {0x14au, RdnaOpcode::VBfiB32}, {0x14eu, RdnaOpcode::VAlignbitB32}, + {0x150u, RdnaOpcode::VMullitF32}, {0x151u, RdnaOpcode::VMin3F32}, {0x152u, RdnaOpcode::VMin3I32}, {0x153u, RdnaOpcode::VMin3U32}, diff --git a/core/shader/recompiler/Translation/src/VectorInstructions.cpp b/core/shader/recompiler/Translation/src/VectorInstructions.cpp index b77d91e09..d371a1111 100644 --- a/core/shader/recompiler/Translation/src/VectorInstructions.cpp +++ b/core/shader/recompiler/Translation/src/VectorInstructions.cpp @@ -724,6 +724,7 @@ bool TranslationContext::emitVector(const RdnaInstruction& inst) { case RdnaOpcode::VSubrevF32: return floatBinary(inst, IrOpcode::FPSub32, true); case RdnaOpcode::VMulF32: + case RdnaOpcode::VMullitF32: return floatBinary(inst, IrOpcode::FPMul32, false); case RdnaOpcode::VMinF32: return floatBinary(inst, IrOpcode::FPMin32, false); @@ -736,6 +737,7 @@ bool TranslationContext::emitVector(const RdnaInstruction& inst) { case RdnaOpcode::VMadmkF32: case RdnaOpcode::VMadakF32: case RdnaOpcode::VMadF32: + case RdnaOpcode::VMadLegacyF32: case RdnaOpcode::VFmaF32: return floatTernary(inst, IrOpcode::FPFma32, false, true); case RdnaOpcode::VMin3F32: