From d54e54b66ddc4675d2eed9cad6bac408fc333ef0 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Thu, 19 Mar 2026 01:35:05 +0300 Subject: [PATCH] rsx/cfg: Handle IF-ELSE aliasing statement as inverted condition - If there is no IF block but ELSE block exists, treat the branch as being inverted and the ELSE block as the main IF body - Rare but seen in some games --- rpcs3/Emu/RSX/Program/Assembler/FPOpcodes.cpp | 8 ++++++++ rpcs3/Emu/RSX/Program/Assembler/FPOpcodes.h | 3 +++ rpcs3/Emu/RSX/Program/Assembler/FPToCFG.cpp | 10 +++++++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/rpcs3/Emu/RSX/Program/Assembler/FPOpcodes.cpp b/rpcs3/Emu/RSX/Program/Assembler/FPOpcodes.cpp index c195b4a75b..d00a104e8f 100644 --- a/rpcs3/Emu/RSX/Program/Assembler/FPOpcodes.cpp +++ b/rpcs3/Emu/RSX/Program/Assembler/FPOpcodes.cpp @@ -459,4 +459,12 @@ namespace rsx::assembler::FP return result; } + + // Invert execution mask on an instruction + void invert_conditional_execution_mask(Instruction* instruction) + { + // We want to invert src0.exec_if_gt|lt|eq which should be at bit offset 18-20 + constexpr u32 inv_mask = (0b111 << 18u); + instruction->bytecode[1] = instruction->bytecode[1] ^ inv_mask; + } } diff --git a/rpcs3/Emu/RSX/Program/Assembler/FPOpcodes.h b/rpcs3/Emu/RSX/Program/Assembler/FPOpcodes.h index a29b22c842..636ac06082 100644 --- a/rpcs3/Emu/RSX/Program/Assembler/FPOpcodes.h +++ b/rpcs3/Emu/RSX/Program/Assembler/FPOpcodes.h @@ -131,5 +131,8 @@ namespace rsx::assembler // Compile a register file annotated blob to register references std::vector compile_register_file(const std::array& file); + + // Invert execution mask on an instruction + void invert_conditional_execution_mask(Instruction* instruction); } } diff --git a/rpcs3/Emu/RSX/Program/Assembler/FPToCFG.cpp b/rpcs3/Emu/RSX/Program/Assembler/FPToCFG.cpp index 99e7c56f6e..954954b377 100644 --- a/rpcs3/Emu/RSX/Program/Assembler/FPToCFG.cpp +++ b/rpcs3/Emu/RSX/Program/Assembler/FPToCFG.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "CFG.h" +#include "FPOpcodes.h" #include "Emu/RSX/Common/simple_array.hpp" #include "Emu/RSX/Program/RSXFragmentProgram.h" @@ -211,7 +212,14 @@ namespace rsx::assembler auto parent = bb; bb = safe_insert_block(parent, pc + 1u, EdgeType::IF); - if (end_addr != else_addr) + + if (else_addr == pc + 1u) + { + // Empty IF block. We co-opt the ELSE block as the IF and invert the condition. + auto& inst = parent->instructions.back(); + FP::invert_conditional_execution_mask(&inst); + } + else if (end_addr != else_addr) { else_blocks.push_back(safe_insert_block(parent, else_addr, EdgeType::ELSE)); }