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)); }