CPU: Move alignment check to branch instead of fetch

There is no other way to end up with an unaligned PC.
This commit is contained in:
Connor McLaughlin 2019-10-13 18:35:19 +10:00
parent 7448cbaf9d
commit b4a6c98bbe
1 changed files with 11 additions and 8 deletions

View File

@ -88,6 +88,7 @@ bool Core::DoState(StateWrapper& sw)
void Core::SetPC(u32 new_pc)
{
DebugAssert(Common::IsAlignedPow2(new_pc, 4));
m_regs.npc = new_pc;
FlushPipeline();
}
@ -228,6 +229,14 @@ bool Core::SafeWriteMemoryWord(VirtualMemoryAddress addr, u32 value)
void Core::Branch(u32 target)
{
if (!Common::IsAlignedPow2(target, 4))
{
// The BadVaddr and EPC must be set to the fetching address, not the instruction about to execute.
m_cop0_regs.BadVaddr = target;
RaiseException(Exception::AdEL, target, false, false, 0);
return;
}
m_regs.npc = target;
m_branch_was_taken = true;
}
@ -562,14 +571,8 @@ void Core::Execute()
bool Core::FetchInstruction()
{
if (!Common::IsAlignedPow2(m_regs.npc, 4))
{
// The EPC must be set to the fetching address, not the instruction about to execute.
m_cop0_regs.BadVaddr = m_regs.npc;
RaiseException(Exception::AdEL, m_regs.npc, false, false, 0);
return false;
}
else if (DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::Word>(m_regs.npc, m_next_instruction.bits) < 0)
DebugAssert(Common::IsAlignedPow2(m_regs.npc, 4));
if (DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::Word>(m_regs.npc, m_next_instruction.bits) < 0)
{
// Bus errors don't set BadVaddr.
RaiseException(Exception::IBE, m_regs.npc, false, false, 0);