From 5688573b3de12ca5bc49a038d92319d7bea54726 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 8 Dec 2025 02:44:20 +0300 Subject: [PATCH] rsx/fp: Fix pre-branch epilogue emit --- rpcs3/Emu/RSX/Program/Assembler/FPToCFG.cpp | 2 + .../RSX/Program/FragmentProgramDecompiler.cpp | 53 ++++++++++--------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/rpcs3/Emu/RSX/Program/Assembler/FPToCFG.cpp b/rpcs3/Emu/RSX/Program/Assembler/FPToCFG.cpp index 577252fd83..1f1e5b3678 100644 --- a/rpcs3/Emu/RSX/Program/Assembler/FPToCFG.cpp +++ b/rpcs3/Emu/RSX/Program/Assembler/FPToCFG.cpp @@ -139,6 +139,7 @@ namespace rsx::assembler default: // Missing an edge type? rsx_log.error("CFG: Unexpected block exit. Report to developers."); + break; } } else if (bb->pred.empty()) @@ -221,6 +222,7 @@ namespace rsx::assembler ir_inst.length += 4; pc++; } + break; } pc++; diff --git a/rpcs3/Emu/RSX/Program/FragmentProgramDecompiler.cpp b/rpcs3/Emu/RSX/Program/FragmentProgramDecompiler.cpp index 589e677b25..94b92ce98e 100644 --- a/rpcs3/Emu/RSX/Program/FragmentProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Program/FragmentProgramDecompiler.cpp @@ -1276,7 +1276,7 @@ std::string FragmentProgramDecompiler::Decompile() // The RSX CFG is missing the output block. We inject a fake tail block that ingests the ROP outputs. BasicBlock* rop_block = nullptr; BasicBlock* tail_block = &graph.blocks.back(); - if (tail_block->instructions.size() == 0) + if (tail_block->instructions.empty()) { // Merge block. Use this directly rop_block = tail_block; @@ -1326,6 +1326,20 @@ std::string FragmentProgramDecompiler::Decompile() block_data[block] = { level, loop }; }; + auto emit_block = [&](const std::vector& instructions) + { + for (auto& inst : instructions) + { + m_instruction = &inst; + dst.HEX = inst.bytecode[0]; + src0.HEX = inst.bytecode[1]; + src1.HEX = inst.bytecode[2]; + src2.HEX = inst.bytecode[3]; + + ensure(handle_tex_srb(inst.opcode) || handle_sct_scb(inst.opcode), "Unsupported operation"); + } + }; + for (const auto &block : graph.blocks) { auto found = block_data.find(&block); @@ -1376,21 +1390,22 @@ std::string FragmentProgramDecompiler::Decompile() if (!block.prologue.empty()) { AddCode("// Prologue"); - - for (auto& inst : block.prologue) - { - m_instruction = &inst; - dst.HEX = inst.bytecode[0]; - src0.HEX = inst.bytecode[1]; - src1.HEX = inst.bytecode[2]; - src2.HEX = inst.bytecode[3]; - - ensure(handle_tex_srb(inst.opcode) || handle_sct_scb(inst.opcode), "Unsupported operation"); - } + emit_block(block.prologue); } + const bool early_epilogue = + !block.epilogue.empty() && + !block.succ.empty() && + (block.succ.front().type == EdgeType::IF || block.succ.front().type == EdgeType::LOOP); + for (const auto& inst : block.instructions) { + if (early_epilogue && &inst == &block.instructions.back()) + { + AddCode("// Epilogue"); + emit_block(block.epilogue); + } + m_instruction = &inst; dst.HEX = inst.bytecode[0]; @@ -1459,20 +1474,10 @@ std::string FragmentProgramDecompiler::Decompile() if (dst.end) break; } - if (!block.epilogue.empty()) + if (!early_epilogue && !block.epilogue.empty()) { AddCode("// Epilogue"); - - for (auto& inst : block.epilogue) - { - m_instruction = &inst; - dst.HEX = inst.bytecode[0]; - src0.HEX = inst.bytecode[1]; - src1.HEX = inst.bytecode[2]; - src2.HEX = inst.bytecode[3]; - - ensure(handle_tex_srb(inst.opcode) || handle_sct_scb(inst.opcode), "Unsupported operation"); - } + emit_block(block.epilogue); } for (auto& succ : block.succ)