diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterCPU.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterCPU.cpp index 3d8d5ed9d..cb1ff4db0 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterCPU.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterCPU.cpp @@ -65,6 +65,7 @@ void CInterpreterCPU::ExecuteCPU() uint32_t & PROGRAM_COUNTER = *_PROGRAM_COUNTER; R4300iOpcode & Opcode = R4300iOp::m_Opcode; uint32_t & JumpToLocation = g_System->m_JumpToLocation; + uint32_t & JumpDelayLocation = g_System->m_JumpDelayLocation; bool & TestTimer = R4300iOp::m_TestTimer; const int32_t & bDoSomething = g_SystemEvents->DoSomething(); uint32_t CountPerOp = g_System->CountPerOp(); @@ -151,6 +152,11 @@ void CInterpreterCPU::ExecuteCPU() } } break; + case PIPELINE_STAGE_JUMP_DELAY_SLOT: + PipelineStage = PIPELINE_STAGE_JUMP; + PROGRAM_COUNTER = JumpToLocation; + JumpToLocation = JumpDelayLocation; + break; case PIPELINE_STAGE_PERMLOOP_DELAY_DONE: PROGRAM_COUNTER = JumpToLocation; PipelineStage = PIPELINE_STAGE_NORMAL; @@ -179,6 +185,7 @@ void CInterpreterCPU::ExecuteOps(int32_t Cycles) uint32_t & PROGRAM_COUNTER = *_PROGRAM_COUNTER; R4300iOpcode & Opcode = R4300iOp::m_Opcode; PIPELINE_STAGE & PipelineStage = g_System->m_PipelineStage; + uint32_t & JumpDelayLocation = g_System->m_JumpDelayLocation; uint32_t & JumpToLocation = g_System->m_JumpToLocation; bool & TestTimer = R4300iOp::m_TestTimer; const int32_t & DoSomething = g_SystemEvents->DoSomething(); @@ -255,6 +262,11 @@ void CInterpreterCPU::ExecuteOps(int32_t Cycles) } } break; + case PIPELINE_STAGE_JUMP_DELAY_SLOT: + PipelineStage = PIPELINE_STAGE_JUMP; + PROGRAM_COUNTER = JumpToLocation; + JumpToLocation = JumpDelayLocation; + break; case PIPELINE_STAGE_PERMLOOP_DELAY_DONE: PROGRAM_COUNTER = JumpToLocation; PipelineStage = PIPELINE_STAGE_NORMAL; diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp index 1243b68ef..d0096e3d2 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp @@ -707,107 +707,60 @@ R4300iOp::Func * R4300iOp::BuildInterpreter() void R4300iOp::J() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = ((*_PROGRAM_COUNTER) & 0xF0000000) + (m_Opcode.target << 2); - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } + g_System->DelayedJump((*_PROGRAM_COUNTER & 0xF0000000) + (m_Opcode.target << 2)); } void R4300iOp::JAL() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = ((*_PROGRAM_COUNTER) & 0xF0000000) + (m_Opcode.target << 2); - _GPR[31].DW = (int32_t)((*_PROGRAM_COUNTER) + 8); - - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } + g_System->DelayedJump((*_PROGRAM_COUNTER & 0xF0000000) + (m_Opcode.target << 2)); + _GPR[31].DW = (int32_t)(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP_DELAY_SLOT ? g_System->m_JumpToLocation + 4 : *_PROGRAM_COUNTER + 8); } void R4300iOp::BEQ() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; if (_GPR[m_Opcode.rs].DW == _GPR[m_Opcode.rt].DW) { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; + g_System->DelayedJump(*_PROGRAM_COUNTER + 8); } } void R4300iOp::BNE() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; if (_GPR[m_Opcode.rs].DW != _GPR[m_Opcode.rt].DW) { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; + g_System->DelayedJump(*_PROGRAM_COUNTER + 8); } } void R4300iOp::BLEZ() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; if (_GPR[m_Opcode.rs].DW <= 0) { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; + g_System->DelayedJump(*_PROGRAM_COUNTER + 8); } } void R4300iOp::BGTZ() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; if (_GPR[m_Opcode.rs].DW > 0) { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; + g_System->DelayedJump(*_PROGRAM_COUNTER + 8); } } @@ -904,16 +857,7 @@ void R4300iOp::BEQL() { if (_GPR[m_Opcode.rs].DW == _GPR[m_Opcode.rt].DW) { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { @@ -926,16 +870,7 @@ void R4300iOp::BNEL() { if (_GPR[m_Opcode.rs].DW != _GPR[m_Opcode.rt].DW) { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { @@ -948,16 +883,7 @@ void R4300iOp::BLEZL() { if (_GPR[m_Opcode.rs].DW <= 0) { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { @@ -970,16 +896,7 @@ void R4300iOp::BGTZL() { if (_GPR[m_Opcode.rs].DW > 0) { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { @@ -1349,16 +1266,14 @@ void R4300iOp::SPECIAL_SRAV() void R4300iOp::SPECIAL_JR() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = _GPR[m_Opcode.rs].UW[0]; + g_System->DelayedJump(_GPR[m_Opcode.rs].UW[0]); m_TestTimer = true; } void R4300iOp::SPECIAL_JALR() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = _GPR[m_Opcode.rs].UW[0]; - _GPR[m_Opcode.rd].DW = (int32_t)((*_PROGRAM_COUNTER) + 8); + g_System->DelayedJump(_GPR[m_Opcode.rs].UW[0]); + _GPR[m_Opcode.rd].DW = (int32_t)(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP_DELAY_SLOT ? g_System->m_JumpToLocation + 4 : *_PROGRAM_COUNTER + 8); m_TestTimer = true; } @@ -1735,43 +1650,25 @@ void R4300iOp::SPECIAL_DSRA32() void R4300iOp::REGIMM_BLTZ() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; if (_GPR[m_Opcode.rs].DW < 0) { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; + g_System->DelayedJump(*_PROGRAM_COUNTER + 8); } } void R4300iOp::REGIMM_BGEZ() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; if (_GPR[m_Opcode.rs].DW >= 0) { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; + g_System->DelayedJump(*_PROGRAM_COUNTER + 8); } } @@ -1779,16 +1676,7 @@ void R4300iOp::REGIMM_BLTZL() { if (_GPR[m_Opcode.rs].DW < 0) { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { @@ -1801,16 +1689,7 @@ void R4300iOp::REGIMM_BGEZL() { if (_GPR[m_Opcode.rs].DW >= 0) { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { @@ -1821,73 +1700,42 @@ void R4300iOp::REGIMM_BGEZL() void R4300iOp::REGIMM_BLTZAL() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; if (_GPR[m_Opcode.rs].DW < 0) { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; + g_System->DelayedJump(*_PROGRAM_COUNTER + 8); } - _GPR[31].DW = (int32_t)((*_PROGRAM_COUNTER) + 8); + _GPR[31].DW = (int32_t)(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP_DELAY_SLOT ? g_System->m_JumpToLocation + 4 : *_PROGRAM_COUNTER + 8); } void R4300iOp::REGIMM_BGEZAL() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; if (_GPR[m_Opcode.rs].DW >= 0) { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - if (CDebugSettings::HaveDebugger()) - { - if (g_Reg->m_PROGRAM_COUNTER < 0x80000400) - { - // Break out of possible checksum halt - g_Notify->DisplayMessage(5, "Broke out of permanent loop! Invalid checksum?"); - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; - _GPR[31].DW = (int32_t)((*_PROGRAM_COUNTER) + 8); - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - return; - } - } - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; + g_System->DelayedJump(*_PROGRAM_COUNTER + 8); } - _GPR[31].DW = (int32_t)((*_PROGRAM_COUNTER) + 8); + _GPR[31].DW = (int32_t)(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP_DELAY_SLOT ? g_System->m_JumpToLocation + 4 : *_PROGRAM_COUNTER + 8); } void R4300iOp::REGIMM_BGEZALL() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; if (_GPR[m_Opcode.rs].DW >= 0) { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { g_System->m_PipelineStage = PIPELINE_STAGE_JUMP; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; } - _GPR[31].DW = (int32_t)((*_PROGRAM_COUNTER) + 8); + _GPR[31].DW = (int32_t)(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP_DELAY_SLOT ? g_System->m_JumpToLocation + 4 : *_PROGRAM_COUNTER + 8); } void R4300iOp::REGIMM_TEQI() diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp index d9402b5ae..d975ebc1e 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps32.cpp @@ -1,9 +1,9 @@ #include "stdafx.h" -#include "InterpreterOps32.h" #include #include #include +#include #include #include #include @@ -99,7 +99,7 @@ R4300iOp32::Func * R4300iOp32::BuildInterpreter() Jump_Special[10] = R4300iOp::UnknownOpcode; Jump_Special[11] = R4300iOp::UnknownOpcode; Jump_Special[12] = R4300iOp::SPECIAL_SYSCALL; - Jump_Special[13] = R4300iOp::UnknownOpcode; + Jump_Special[13] = R4300iOp::SPECIAL_BREAK; Jump_Special[14] = R4300iOp::UnknownOpcode; Jump_Special[15] = R4300iOp::SPECIAL_SYNC; Jump_Special[16] = R4300iOp::SPECIAL_MFHI; @@ -615,97 +615,56 @@ R4300iOp32::Func * R4300iOp32::BuildInterpreter() void R4300iOp32::JAL() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = ((*_PROGRAM_COUNTER) & 0xF0000000) + (m_Opcode.target << 2); - _GPR[31].UW[0] = (*_PROGRAM_COUNTER) + 8; - - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } + g_System->DelayedJump((*_PROGRAM_COUNTER & 0xF0000000) + (m_Opcode.target << 2)); + g_System->DelayedJump((*_PROGRAM_COUNTER & 0xF0000000) + (m_Opcode.target << 2)); + _GPR[31].DW = (int32_t)(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP_DELAY_SLOT ? g_System->m_JumpToLocation + 4 : *_PROGRAM_COUNTER + 8); } void R4300iOp32::BEQ() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; if (_GPR[m_Opcode.rs].W[0] == _GPR[m_Opcode.rt].W[0]) { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; + g_System->DelayedJump(*_PROGRAM_COUNTER + 8); } } void R4300iOp32::BNE() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; if (_GPR[m_Opcode.rs].W[0] != _GPR[m_Opcode.rt].W[0]) { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; + g_System->DelayedJump(*_PROGRAM_COUNTER + 8); } } void R4300iOp32::BLEZ() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; if (_GPR[m_Opcode.rs].W[0] <= 0) { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; + g_System->DelayedJump(*_PROGRAM_COUNTER + 8); } } void R4300iOp32::BGTZ() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; if (_GPR[m_Opcode.rs].W[0] > 0) { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; + g_System->DelayedJump(*_PROGRAM_COUNTER + 8); } } @@ -802,16 +761,7 @@ void R4300iOp32::BEQL() { if (_GPR[m_Opcode.rs].W[0] == _GPR[m_Opcode.rt].W[0]) { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { @@ -824,16 +774,7 @@ void R4300iOp32::BNEL() { if (_GPR[m_Opcode.rs].W[0] != _GPR[m_Opcode.rt].W[0]) { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { @@ -846,16 +787,7 @@ void R4300iOp32::BLEZL() { if (_GPR[m_Opcode.rs].W[0] <= 0) { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { @@ -868,16 +800,7 @@ void R4300iOp32::BGTZL() { if (_GPR[m_Opcode.rs].W[0] > 0) { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { @@ -1003,9 +926,8 @@ void R4300iOp32::SPECIAL_SRAV() void R4300iOp32::SPECIAL_JALR() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = _GPR[m_Opcode.rs].UW[0]; - _GPR[m_Opcode.rd].W[0] = (int32_t)((*_PROGRAM_COUNTER) + 8); + g_System->DelayedJump(_GPR[m_Opcode.rs].UW[0]); + _GPR[m_Opcode.rd].W[0] = g_System->m_PipelineStage == PIPELINE_STAGE_JUMP_DELAY_SLOT ? g_System->m_JumpToLocation + 4 : *_PROGRAM_COUNTER + 8; m_TestTimer = true; } @@ -1103,43 +1025,25 @@ void R4300iOp32::SPECIAL_TEQ() void R4300iOp32::REGIMM_BLTZ() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; if (_GPR[m_Opcode.rs].W[0] < 0) { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; + g_System->DelayedJump(*_PROGRAM_COUNTER + 8); } } void R4300iOp32::REGIMM_BGEZ() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; if (_GPR[m_Opcode.rs].W[0] >= 0) { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; + g_System->DelayedJump(*_PROGRAM_COUNTER + 8); } } @@ -1147,16 +1051,7 @@ void R4300iOp32::REGIMM_BLTZL() { if (_GPR[m_Opcode.rs].W[0] < 0) { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { @@ -1169,16 +1064,7 @@ void R4300iOp32::REGIMM_BGEZL() { if (_GPR[m_Opcode.rs].W[0] >= 0) { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { @@ -1189,52 +1075,22 @@ void R4300iOp32::REGIMM_BGEZL() void R4300iOp32::REGIMM_BLTZAL() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; if (_GPR[m_Opcode.rs].W[0] < 0) { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; + g_System->DelayedJump(*_PROGRAM_COUNTER + 8); } - _GPR[31].W[0] = (int32_t)((*_PROGRAM_COUNTER) + 8); + _GPR[31].W[0] = g_System->m_PipelineStage == PIPELINE_STAGE_JUMP_DELAY_SLOT ? g_System->m_JumpToLocation + 4 : *_PROGRAM_COUNTER + 8; } void R4300iOp32::REGIMM_BGEZAL() { - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; if (_GPR[m_Opcode.rs].W[0] >= 0) { - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4; - if ((*_PROGRAM_COUNTER) == g_System->m_JumpToLocation) - { - if (CDebugSettings::HaveDebugger()) - { - if (g_Reg->m_PROGRAM_COUNTER < 0x80000400) - { - // Break out of possible checksum halt - g_Notify->DisplayMessage(5, "Broke out of permanent loop! Invalid checksum?"); - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER) + 8; - _GPR[31].DW = (int32_t)((*_PROGRAM_COUNTER) + 8); - g_System->m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; - return; - } - } - R4300iOpcode DelaySlot; - if (g_MMU->MemoryValue32(*_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(*_PROGRAM_COUNTER, m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) - { - g_System->m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; - } - } + g_System->DelayedRelativeJump(((int16_t)m_Opcode.offset << 2) + 4); } else { diff --git a/Source/Project64-core/N64System/N64System.cpp b/Source/Project64-core/N64System/N64System.cpp index 6c877d6be..faf20fd78 100644 --- a/Source/Project64-core/N64System/N64System.cpp +++ b/Source/Project64-core/N64System/N64System.cpp @@ -43,6 +43,7 @@ CN64System::CN64System(CPlugins * Plugins, uint32_t randomizer_seed, bool SavesR m_TestTimer(false), m_PipelineStage(PIPELINE_STAGE_NORMAL), m_JumpToLocation(0), + m_JumpDelayLocation(0), m_TLBLoadAddress(0), m_TLBStoreAddress(0), m_SyncCount(0), @@ -2420,6 +2421,46 @@ void CN64System::NotifyCallback(CN64SystemCB Type) } } +void CN64System::DelayedJump(uint32_t JumpLocation) +{ + if (m_PipelineStage == PIPELINE_STAGE_JUMP) + { + m_PipelineStage = PIPELINE_STAGE_JUMP_DELAY_SLOT; + m_JumpDelayLocation = JumpLocation; + } + else + { + m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; + m_JumpToLocation = JumpLocation; + } + if ((m_Reg.m_PROGRAM_COUNTER) == m_JumpToLocation) + { + m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; + } +} + +void CN64System::DelayedRelativeJump(uint32_t RelativeLocation) +{ + if (m_PipelineStage == PIPELINE_STAGE_JUMP) + { + m_PipelineStage = PIPELINE_STAGE_JUMP_DELAY_SLOT; + m_JumpDelayLocation = m_Reg.m_PROGRAM_COUNTER + RelativeLocation + 4; + } + else + { + m_PipelineStage = PIPELINE_STAGE_DELAY_SLOT; + m_JumpToLocation = m_Reg.m_PROGRAM_COUNTER + RelativeLocation; + } + if (m_Reg.m_PROGRAM_COUNTER == m_JumpToLocation) + { + R4300iOpcode DelaySlot; + if (m_MMU_VM.MemoryValue32(m_Reg.m_PROGRAM_COUNTER + 4, DelaySlot.Value) && !R4300iInstruction(m_Reg.m_PROGRAM_COUNTER, R4300iOp::m_Opcode.Value).DelaySlotEffectsCompare(DelaySlot.Value)) + { + m_PipelineStage = PIPELINE_STAGE_PERMLOOP_DO_DELAY; + } + } +} + void CN64System::RunRSP() { WriteTrace(TraceRSP, TraceDebug, "Start (SP Status %X)", m_Reg.SP_STATUS_REG); diff --git a/Source/Project64-core/N64System/N64System.h b/Source/Project64-core/N64System/N64System.h index 1d703e766..e87213921 100644 --- a/Source/Project64-core/N64System/N64System.h +++ b/Source/Project64-core/N64System/N64System.h @@ -163,6 +163,8 @@ private: void InitRegisters(bool bPostPif, CMipsMemoryVM & MMU); void DisplayRSPListCount(); void NotifyCallback(CN64SystemCB Type); + void DelayedJump(uint32_t JumpLocation); + void DelayedRelativeJump(uint32_t RelativeLocation); // CPU methods void ExecuteRecompiler(); @@ -198,6 +200,7 @@ private: bool m_TestTimer; PIPELINE_STAGE m_PipelineStage; uint32_t m_JumpToLocation; + uint32_t m_JumpDelayLocation; uint32_t m_TLBLoadAddress; uint32_t m_TLBStoreAddress; uint32_t m_SyncCount; diff --git a/Source/Project64-core/N64System/N64Types.h b/Source/Project64-core/N64System/N64Types.h index 5700c7a77..66910baec 100644 --- a/Source/Project64-core/N64System/N64Types.h +++ b/Source/Project64-core/N64System/N64Types.h @@ -146,6 +146,7 @@ enum PIPELINE_STAGE PIPELINE_STAGE_END_DELAY_SLOT, PIPELINE_STAGE_LIKELY_DELAY_SLOT, PIPELINE_STAGE_JUMP, + PIPELINE_STAGE_JUMP_DELAY_SLOT, PIPELINE_STAGE_DELAY_SLOT_DONE, PIPELINE_STAGE_LIKELY_DELAY_SLOT_DONE, PIPELINE_STAGE_END_BLOCK,