mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-23 14:25:37 +00:00
CPU/CodeCache: Don't choke on indirect branches in delay slot
Fixes emulator crash/memory usage explosion in Shadow Master.
This commit is contained in:
parent
d7c3a0137f
commit
5164840c25
|
@ -527,6 +527,11 @@ bool CompileBlock(CodeBlock* block)
|
||||||
Log_WarningPrintf("Conditional branch delay slot at %08X, skipping block", cbi.pc);
|
Log_WarningPrintf("Conditional branch delay slot at %08X, skipping block", cbi.pc);
|
||||||
return false;
|
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
|
// change the pc for the second branch's delay slot, it comes from the first branch
|
||||||
const CodeBlockInstruction& prev_cbi = block->instructions.back();
|
const CodeBlockInstruction& prev_cbi = block->instructions.back();
|
||||||
|
|
|
@ -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)
|
u32 GetBranchInstructionTarget(const Instruction& instruction, u32 instruction_pc)
|
||||||
{
|
{
|
||||||
switch (instruction.op)
|
switch (instruction.op)
|
||||||
|
@ -96,6 +114,7 @@ u32 GetBranchInstructionTarget(const Instruction& instruction, u32 instruction_p
|
||||||
return instruction_pc + 4 + (instruction.i.imm_sext32() << 2);
|
return instruction_pc + 4 + (instruction.i.imm_sext32() << 2);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
Panic("Trying to get branch target of indirect or invalid branch");
|
||||||
return instruction_pc;
|
return instruction_pc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,6 +213,7 @@ union Instruction
|
||||||
// Instruction helpers.
|
// Instruction helpers.
|
||||||
bool IsBranchInstruction(const Instruction& instruction);
|
bool IsBranchInstruction(const Instruction& instruction);
|
||||||
bool IsUnconditionalBranchInstruction(const Instruction& instruction);
|
bool IsUnconditionalBranchInstruction(const Instruction& instruction);
|
||||||
|
bool IsDirectBranchInstruction(const Instruction& instruction);
|
||||||
u32 GetBranchInstructionTarget(const Instruction& instruction, u32 instruction_pc);
|
u32 GetBranchInstructionTarget(const Instruction& instruction, u32 instruction_pc);
|
||||||
bool IsMemoryLoadInstruction(const Instruction& instruction);
|
bool IsMemoryLoadInstruction(const Instruction& instruction);
|
||||||
bool IsMemoryStoreInstruction(const Instruction& instruction);
|
bool IsMemoryStoreInstruction(const Instruction& instruction);
|
||||||
|
|
Loading…
Reference in a new issue