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
This commit is contained in:
@@ -459,4 +459,12 @@ namespace rsx::assembler::FP
|
|||||||
|
|
||||||
return result;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,5 +131,8 @@ namespace rsx::assembler
|
|||||||
|
|
||||||
// Compile a register file annotated blob to register references
|
// Compile a register file annotated blob to register references
|
||||||
std::vector<RegisterRef> compile_register_file(const std::array<char, 48 * 8>& file);
|
std::vector<RegisterRef> compile_register_file(const std::array<char, 48 * 8>& file);
|
||||||
|
|
||||||
|
// Invert execution mask on an instruction
|
||||||
|
void invert_conditional_execution_mask(Instruction* instruction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "CFG.h"
|
#include "CFG.h"
|
||||||
|
#include "FPOpcodes.h"
|
||||||
|
|
||||||
#include "Emu/RSX/Common/simple_array.hpp"
|
#include "Emu/RSX/Common/simple_array.hpp"
|
||||||
#include "Emu/RSX/Program/RSXFragmentProgram.h"
|
#include "Emu/RSX/Program/RSXFragmentProgram.h"
|
||||||
@@ -211,7 +212,14 @@ namespace rsx::assembler
|
|||||||
|
|
||||||
auto parent = bb;
|
auto parent = bb;
|
||||||
bb = safe_insert_block(parent, pc + 1u, EdgeType::IF);
|
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));
|
else_blocks.push_back(safe_insert_block(parent, else_addr, EdgeType::ELSE));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user