CPU/CodeCache: Fetch second delay slot from first branch for double branches

This commit is contained in:
Connor McLaughlin
2020-11-18 20:34:25 +10:00
parent 3890a539ee
commit 042bdd9c0c
5 changed files with 81 additions and 3 deletions

View File

@ -460,6 +460,7 @@ 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
@ -479,6 +480,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_unconditional_branch_instruction = IsUnconditionalBranchInstruction(cbi.instruction);
cbi.is_load_instruction = IsMemoryLoadInstruction(cbi.instruction);
cbi.is_store_instruction = IsMemoryStoreInstruction(cbi.instruction);
cbi.has_load_delay = InstructionHasLoadDelay(cbi.instruction);
@ -498,9 +500,24 @@ bool CompileBlock(CodeBlock* block)
block->contains_loadstore_instructions |= cbi.is_load_instruction;
block->contains_loadstore_instructions |= cbi.is_store_instruction;
pc += sizeof(cbi.instruction.bits);
if (is_branch_delay_slot && cbi.is_branch_instruction)
{
if (!is_unconditional_branch_delay_slot)
{
Log_WarningPrintf("Conditional branch delay slot at %08X, skipping block", cbi.pc);
return false;
}
// 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);
}
// instruction is decoded now
block->instructions.push_back(cbi);
pc += sizeof(cbi.instruction.bits);
// if we're in a branch delay slot, the block is now done
// except if this is a branch in a branch delay slot, then we grab the one after that, and so on...
@ -509,6 +526,7 @@ 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;