diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterCPU.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterCPU.cpp index 7b8180d7a..c264d99d2 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterCPU.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterCPU.cpp @@ -134,6 +134,8 @@ void CInterpreterCPU::ExecuteCPU() if ((PROGRAM_COUNTER & 0x3) != 0) { GenerateAddressErrorException((int32_t)JumpToLocation, true); + PROGRAM_COUNTER = JumpToLocation; + PipelineStage = PIPELINE_STAGE_NORMAL; } else if (CheckTimer) { diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp index 534b8306e..39f946161 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp @@ -3045,9 +3045,7 @@ bool R4300iOp::MemoryBreakpoint() void R4300iOp::GenerateAddressErrorException(uint64_t VAddr, bool FromRead) { - g_Reg->DoAddressError(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP, VAddr, FromRead); - g_System->m_PipelineStage = PIPELINE_STAGE_JUMP; - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER); + g_Reg->DoAddressError(VAddr, FromRead); } void R4300iOp::GenerateTLBReadException(uint64_t VAddr, const char * function) diff --git a/Source/Project64-core/N64System/Mips/Register.cpp b/Source/Project64-core/N64System/Mips/Register.cpp index eafc003ba..ad84a1f09 100644 --- a/Source/Project64-core/N64System/Mips/Register.cpp +++ b/Source/Project64-core/N64System/Mips/Register.cpp @@ -528,7 +528,7 @@ void CRegisters::CheckInterrupts() } } -void CRegisters::DoAddressError(bool DelaySlot, uint64_t BadVaddr, bool FromRead) +void CRegisters::DoAddressError(uint64_t BadVaddr, bool FromRead) { if (BreakOnAddressError()) { @@ -549,7 +549,7 @@ void CRegisters::DoAddressError(bool DelaySlot, uint64_t BadVaddr, bool FromRead XCONTEXT_REGISTER.BadVPN2 = BadVaddr >> 13; XCONTEXT_REGISTER.R = BadVaddr >> 61; - if (DelaySlot) + if (m_System->m_PipelineStage == PIPELINE_STAGE_JUMP) { CAUSE_REGISTER.BranchDelay = 1; EPC_REGISTER = (int32_t)(m_PROGRAM_COUNTER - 4); @@ -560,7 +560,8 @@ void CRegisters::DoAddressError(bool DelaySlot, uint64_t BadVaddr, bool FromRead EPC_REGISTER = (int32_t)m_PROGRAM_COUNTER; } STATUS_REGISTER.ExceptionLevel = 1; - m_PROGRAM_COUNTER = 0x80000180; + m_System->m_JumpToLocation = 0x80000180; + m_System->m_PipelineStage = PIPELINE_STAGE_JUMP; } void CRegisters::FixFpuLocations() diff --git a/Source/Project64-core/N64System/Mips/Register.h b/Source/Project64-core/N64System/Mips/Register.h index 2fc6230e2..1c93a945c 100644 --- a/Source/Project64-core/N64System/Mips/Register.h +++ b/Source/Project64-core/N64System/Mips/Register.h @@ -450,7 +450,7 @@ public: CRegisters(CN64System * System, CSystemEvents * SystemEvents); void CheckInterrupts(); - void DoAddressError(bool DelaySlot, uint64_t BadVaddr, bool FromRead); + void DoAddressError(uint64_t BadVaddr, bool FromRead); bool DoIntrException(); void DoTLBReadMiss(bool DelaySlot, uint64_t BadVaddr); void DoTLBWriteMiss(bool DelaySlot, uint64_t BadVaddr); diff --git a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp index e637bf49e..ff3dca46d 100644 --- a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp @@ -9659,7 +9659,7 @@ void CX86RecompilerOps::CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo ExitCodeBlock(); break; case ExitReason_DoSysCall: - m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL); + m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", InDelaySlot ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL); m_Assembler.push(0); m_Assembler.PushImm32("EXC_SYSCALL", EXC_SYSCALL); m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::TriggerException), "CRegisters::TriggerException", 12); @@ -9669,7 +9669,7 @@ void CX86RecompilerOps::CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo ExitCodeBlock(); break; case ExitReason_Break: - m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL); + m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", InDelaySlot ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL); m_Assembler.push(0); m_Assembler.PushImm32("EXC_BREAK", EXC_BREAK); m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::TriggerException), "CRegisters::TriggerException", 12); @@ -9679,7 +9679,7 @@ void CX86RecompilerOps::CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo ExitCodeBlock(); break; case ExitReason_COP1Unuseable: - m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL); + m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", InDelaySlot ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL); m_Assembler.push(1); m_Assembler.PushImm32("EXC_CPU", EXC_CPU); m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::TriggerException), "CRegisters::TriggerException", 12); @@ -9707,7 +9707,7 @@ void CX86RecompilerOps::CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo ExitCodeBlock(); break; case ExitReason_ExceptionOverflow: - m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL); + m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", InDelaySlot ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL); m_Assembler.push(0); m_Assembler.PushImm32("EXC_OV", EXC_OV); m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::TriggerException), "CRegisters::TriggerException", 12); @@ -9717,28 +9717,34 @@ void CX86RecompilerOps::CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo ExitCodeBlock(); break; case ExitReason_AddressErrorExceptionRead32: + m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", InDelaySlot ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL); m_Assembler.push(1); m_Assembler.MoveVariableToX86reg(asmjit::x86::edx, &m_TempValue32, "TempValue32"); m_Assembler.mov(asmjit::x86::eax, asmjit::x86::edx); m_Assembler.sar(asmjit::x86::eax, 31); m_Assembler.push(asmjit::x86::eax); m_Assembler.push(asmjit::x86::edx); - m_Assembler.PushImm32(InDelaySlot ? "true" : "false", InDelaySlot); m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::DoAddressError), "CRegisters::DoAddressError", 12); + m_Assembler.MoveVariableToX86reg(asmjit::x86::edx, &g_System->m_JumpToLocation, "System->m_JumpToLocation"); + m_Assembler.MoveX86regToVariable(&g_Reg->m_PROGRAM_COUNTER, "PROGRAM_COUNTER", asmjit::x86::edx); + m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", PIPELINE_STAGE_NORMAL); ExitCodeBlock(); break; case ExitReason_AddressErrorExceptionRead64: + m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", InDelaySlot ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL); m_Assembler.push(1); m_Assembler.MoveVariableToX86reg(asmjit::x86::edx, &m_TempValue64, "TempValue64"); m_Assembler.MoveVariableToX86reg(asmjit::x86::eax, &m_TempValue64 + 4, "TempValue64+4"); m_Assembler.push(asmjit::x86::eax); m_Assembler.push(asmjit::x86::edx); - m_Assembler.PushImm32(InDelaySlot ? "true" : "false", InDelaySlot); m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::DoAddressError), "CRegisters::DoAddressError", 12); + m_Assembler.MoveVariableToX86reg(asmjit::x86::edx, &g_System->m_JumpToLocation, "System->m_JumpToLocation"); + m_Assembler.MoveX86regToVariable(&g_Reg->m_PROGRAM_COUNTER, "PROGRAM_COUNTER", asmjit::x86::edx); + m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "g_System->m_PipelineStage", PIPELINE_STAGE_NORMAL); ExitCodeBlock(); break; case ExitReason_IllegalInstruction: - m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", m_PipelineStage == PIPELINE_STAGE_JUMP || m_PipelineStage == PIPELINE_STAGE_DELAY_SLOT ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL); + m_Assembler.MoveConstToVariable(&g_System->m_PipelineStage, "System->m_PipelineStage", InDelaySlot ? PIPELINE_STAGE_JUMP : PIPELINE_STAGE_NORMAL); m_Assembler.push(0); m_Assembler.PushImm32("EXC_II", EXC_II); m_Assembler.CallThis((uint32_t)g_Reg, AddressOf(&CRegisters::TriggerException), "CRegisters::TriggerException", 12);