diff --git a/src/core/cpu_code_cache.cpp b/src/core/cpu_code_cache.cpp index b0235be9c..3c196d365 100644 --- a/src/core/cpu_code_cache.cpp +++ b/src/core/cpu_code_cache.cpp @@ -527,6 +527,11 @@ bool CompileBlock(CodeBlock* block) Log_WarningPrintf("Conditional branch delay slot at %08X, skipping block", cbi.pc); return false; } + if (!IsDirectBranchInstruction(cbi.instruction)) + { + Log_WarningPrintf("Indirect branch in 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(); diff --git a/src/core/cpu_types.cpp b/src/core/cpu_types.cpp index 7250e6c52..1d4436686 100644 --- a/src/core/cpu_types.cpp +++ b/src/core/cpu_types.cpp @@ -80,6 +80,24 @@ bool IsUnconditionalBranchInstruction(const Instruction& instruction) } } +bool IsDirectBranchInstruction(const Instruction& instruction) +{ + switch (instruction.op) + { + case InstructionOp::j: + case InstructionOp::jal: + case InstructionOp::b: + case InstructionOp::beq: + case InstructionOp::bgtz: + case InstructionOp::blez: + case InstructionOp::bne: + return true; + + default: + return false; + } +} + u32 GetBranchInstructionTarget(const Instruction& instruction, u32 instruction_pc) { switch (instruction.op) @@ -96,6 +114,7 @@ u32 GetBranchInstructionTarget(const Instruction& instruction, u32 instruction_p return instruction_pc + 4 + (instruction.i.imm_sext32() << 2); default: + Panic("Trying to get branch target of indirect or invalid branch"); return instruction_pc; } } diff --git a/src/core/cpu_types.h b/src/core/cpu_types.h index a7955aaf0..874bb6f91 100644 --- a/src/core/cpu_types.h +++ b/src/core/cpu_types.h @@ -213,6 +213,7 @@ union Instruction // Instruction helpers. bool IsBranchInstruction(const Instruction& instruction); bool IsUnconditionalBranchInstruction(const Instruction& instruction); +bool IsDirectBranchInstruction(const Instruction& instruction); u32 GetBranchInstructionTarget(const Instruction& instruction, u32 instruction_pc); bool IsMemoryLoadInstruction(const Instruction& instruction); bool IsMemoryStoreInstruction(const Instruction& instruction);