From 20f12cc80eefe842a7b74434dce4feedb2c7ebae Mon Sep 17 00:00:00 2001 From: asimplestray <304690168+asimplestray@users.noreply.github.com> Date: Fri, 2 Oct 2026 16:04:44 +0000 Subject: [PATCH] feat(shader): implement legacy float multiply-add ops --- core/libs/prx/libSceAgcDriver/CMakeLists.txt | 8 ++++++ core/libs/tests/VectorMadLegacy.cpp | 26 +++++++++++++++++++ .../include/RdnaDecoder/RdnaOpcode.hpp | 2 ++ .../recompiler/RdnaDecoder/src/RdnaOpcode.cpp | 2 ++ .../RdnaDecoder/src/RdnaVectorOpDecoder.cpp | 2 ++ .../Translation/src/VectorInstructions.cpp | 2 ++ 6 files changed, 42 insertions(+) create mode 100644 core/libs/tests/VectorMadLegacy.cpp diff --git a/core/libs/prx/libSceAgcDriver/CMakeLists.txt b/core/libs/prx/libSceAgcDriver/CMakeLists.txt index cd4a431dc..2c03bc875 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 a1e040990..b662b74e1 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 fcf4df05b..dca037ccf 100644 --- a/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp +++ b/core/shader/recompiler/RdnaDecoder/src/RdnaOpcode.cpp @@ -151,6 +151,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 5b664ec8b..8a2f9c490 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 9b6710ea9..9bb1b6155 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: