From bf5f53e1d13df5febc934baf410985f0656c7ddb Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 6 Mar 2021 01:33:12 +1000 Subject: [PATCH] CPU/CodeCache: Don't choke on indirect -> direct branch in delay slot --- src/core/cpu_code_cache.cpp | 9 ++++----- src/core/cpu_code_cache.h | 1 + 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/cpu_code_cache.cpp b/src/core/cpu_code_cache.cpp index c25d3d969..944700aa6 100644 --- a/src/core/cpu_code_cache.cpp +++ b/src/core/cpu_code_cache.cpp @@ -494,7 +494,6 @@ bool CompileBlock(CodeBlock* block) { u32 pc = block->GetPC(); bool is_branch_delay_slot = false; - bool is_unconditional_branch_delay_slot = false; bool is_load_delay_slot = false; #if 0 @@ -519,6 +518,7 @@ bool CompileBlock(CodeBlock* block) cbi.is_branch_delay_slot = is_branch_delay_slot; cbi.is_load_delay_slot = is_load_delay_slot; cbi.is_branch_instruction = IsBranchInstruction(cbi.instruction); + cbi.is_direct_branch_instruction = IsDirectBranchInstruction(cbi.instruction); cbi.is_unconditional_branch_instruction = IsUnconditionalBranchInstruction(cbi.instruction); cbi.is_load_instruction = IsMemoryLoadInstruction(cbi.instruction); cbi.is_store_instruction = IsMemoryStoreInstruction(cbi.instruction); @@ -543,9 +543,10 @@ bool CompileBlock(CodeBlock* block) if (is_branch_delay_slot && cbi.is_branch_instruction) { - if (!is_unconditional_branch_delay_slot) + const CodeBlockInstruction& prev_cbi = block->instructions.back(); + if (!prev_cbi.is_unconditional_branch_instruction || !prev_cbi.is_direct_branch_instruction) { - Log_WarningPrintf("Conditional branch delay slot at %08X, skipping block", cbi.pc); + Log_WarningPrintf("Conditional or indirect branch delay slot at %08X, skipping block", cbi.pc); return false; } if (!IsDirectBranchInstruction(cbi.instruction)) @@ -555,7 +556,6 @@ bool CompileBlock(CodeBlock* block) } // change the pc for the second branch's delay slot, it comes from the first branch - const CodeBlockInstruction& prev_cbi = block->instructions.back(); pc = GetBranchInstructionTarget(prev_cbi.instruction, prev_cbi.pc); Log_DevPrintf("Double branch at %08X, using delay slot from %08X -> %08X", cbi.pc, prev_cbi.pc, pc); } @@ -570,7 +570,6 @@ bool CompileBlock(CodeBlock* block) // if this is a branch, we grab the next instruction (delay slot), and then exit is_branch_delay_slot = cbi.is_branch_instruction; - is_unconditional_branch_delay_slot = cbi.is_unconditional_branch_instruction; // same for load delay is_load_delay_slot = cbi.has_load_delay; diff --git a/src/core/cpu_code_cache.h b/src/core/cpu_code_cache.h index a984a0224..e609039f6 100644 --- a/src/core/cpu_code_cache.h +++ b/src/core/cpu_code_cache.h @@ -52,6 +52,7 @@ struct CodeBlockInstruction u32 pc; bool is_branch_instruction : 1; + bool is_direct_branch_instruction : 1; bool is_unconditional_branch_instruction : 1; bool is_branch_delay_slot : 1; bool is_load_instruction : 1;