From b8a514a483b70f758f47b0ee78609c8175ca5e28 Mon Sep 17 00:00:00 2001 From: zilmar Date: Thu, 6 Feb 2025 16:09:31 +1030 Subject: [PATCH] core: Create instruction region to update after a block --- .../N64System/Interpreter/InterpreterOps.cpp | 78 +++++++++++++------ .../N64System/Interpreter/InterpreterOps.h | 4 + Source/Project64-core/N64System/Profiling.cpp | 5 +- 3 files changed, 64 insertions(+), 23 deletions(-) diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp index 2fbe53e09..fe1264298 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp @@ -45,7 +45,10 @@ R4300iOp::R4300iOp(CN64System & System, bool Force32bit) : m_FPR_S_L(System.m_Reg.m_FPR_S_L), m_FPR_D(System.m_Reg.m_FPR_D), m_FPCR(System.m_Reg.m_FPCR), - m_LLBit(System.m_Reg.m_LLBit) + m_LLBit(System.m_Reg.m_LLBit), + m_InstructionRegion(0), + m_InstructionMemory(nullptr), + m_InstructionPtr(nullptr) { m_Opcode.Value = 0; BuildInterpreter(Force32bit); @@ -91,29 +94,10 @@ void R4300iOp::ExecuteOps(uint32_t Cycles) int32_t & NextTimer = *g_NextTimer; bool CheckTimer = false; + UpdateInstructionMemory(); while (!Done && Cycles > 0) { - if ((uint64_t)((int32_t)m_PROGRAM_COUNTER) != m_PROGRAM_COUNTER) - { - uint32_t PAddr; - bool MemoryUnused; - if (!m_TLB.VAddrToPAddr(m_PROGRAM_COUNTER, PAddr, MemoryUnused)) - { - m_Reg.TriggerAddressException(m_PROGRAM_COUNTER, MemoryUnused ? EXC_RADE : EXC_RMISS); - m_PROGRAM_COUNTER = JumpToLocation; - PipelineStage = PIPELINE_STAGE_NORMAL; - continue; - } - m_MMU.LW_PhysicalAddress(PAddr, m_Opcode.Value); - } - else if (!m_MMU.MemoryValue32((uint32_t)m_PROGRAM_COUNTER, m_Opcode.Value)) - { - m_Reg.TriggerAddressException((int32_t)m_PROGRAM_COUNTER, EXC_RMISS); - m_PROGRAM_COUNTER = JumpToLocation; - PipelineStage = PIPELINE_STAGE_NORMAL; - continue; - } - + m_Opcode.Value = *m_InstructionPtr; if (HaveDebugger()) { if (HaveExecutionBP() && g_Debugger->ExecutionBP((uint32_t)m_PROGRAM_COUNTER)) @@ -159,6 +143,8 @@ void R4300iOp::ExecuteOps(uint32_t Cycles) } m_PROGRAM_COUNTER += 4; + m_InstructionPtr++; + switch (PipelineStage) { case PIPELINE_STAGE_NORMAL: @@ -191,11 +177,13 @@ void R4300iOp::ExecuteOps(uint32_t Cycles) SystemEvents.ExecuteEvents(); } } + UpdateInstructionMemory(); break; case PIPELINE_STAGE_JUMP_DELAY_SLOT: PipelineStage = PIPELINE_STAGE_JUMP; m_PROGRAM_COUNTER = JumpToLocation; JumpToLocation = JumpDelayLocation; + UpdateInstructionMemory(); break; case PIPELINE_STAGE_PERMLOOP_DELAY_DONE: m_PROGRAM_COUNTER = JumpToLocation; @@ -206,10 +194,16 @@ void R4300iOp::ExecuteOps(uint32_t Cycles) { SystemEvents.ExecuteEvents(); } + UpdateInstructionMemory(); break; default: g_Notify->BreakPoint(__FILE__, __LINE__); } + + if ((((uint32_t)m_PROGRAM_COUNTER) & 0xFFFUL) == 0) + { + UpdateInstructionMemory(); + } } g_SystemTimer->UpdateTimers(); } @@ -3962,3 +3956,43 @@ bool R4300iOp::SetFPUException(void) } return Res; } + +void R4300iOp::UpdateInstructionMemory() +{ + if (m_InstructionRegion != (m_PROGRAM_COUNTER & ~0xFFFLL)) + { + m_InstructionRegion = m_PROGRAM_COUNTER & ~0xFFFLL; + if ((uint64_t)((int32_t)m_PROGRAM_COUNTER) != m_PROGRAM_COUNTER) + { + uint32_t PAddr; + bool MemoryUnused; + if (!m_TLB.VAddrToPAddr(m_InstructionRegion, PAddr, MemoryUnused)) + { + m_Reg.TriggerAddressException(m_PROGRAM_COUNTER, MemoryUnused ? EXC_RADE : EXC_RMISS); + m_PROGRAM_COUNTER = m_System.m_JumpToLocation; + m_System.m_PipelineStage = PIPELINE_STAGE_NORMAL; + UpdateInstructionMemory(); + return; + } + if (PAddr >= m_MMU.RdramSize()) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + return; + } + m_InstructionMemory = &m_MMU.Rdram()[PAddr]; + } + else + { + m_InstructionMemory = m_MMU.MemoryPtr((uint32_t)m_InstructionRegion, 4, true); + if (m_InstructionMemory == nullptr) + { + m_Reg.TriggerAddressException((int32_t)m_PROGRAM_COUNTER, EXC_RMISS); + m_PROGRAM_COUNTER = m_System.m_JumpToLocation; + m_System.m_PipelineStage = PIPELINE_STAGE_NORMAL; + UpdateInstructionMemory(); + return; + } + } + } + m_InstructionPtr = (uint32_t *)(((uint8_t *)m_InstructionMemory) + (m_PROGRAM_COUNTER & 0xFFFLL)); +} diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.h b/Source/Project64-core/N64System/Interpreter/InterpreterOps.h index b4d108132..567fc206b 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.h +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.h @@ -302,6 +302,9 @@ private: double ** m_FPR_D; uint32_t * m_FPCR; uint32_t & m_LLBit; + uint64_t m_InstructionRegion; + uint8_t * m_InstructionMemory; + uint32_t * m_InstructionPtr; Func Jump_Opcode[64]; Func Jump_Special[64]; @@ -328,6 +331,7 @@ private: bool CheckFPUInvalidException(void); bool InitFpuOperation(FPRoundingMode RoundingModel); bool SetFPUException(void); + void UpdateInstructionMemory(); static const uint32_t SWL_MASK[4], SWR_MASK[4], LWL_MASK[4], LWR_MASK[4]; static const int32_t SWL_SHIFT[4], SWR_SHIFT[4], LWL_SHIFT[4], LWR_SHIFT[4]; diff --git a/Source/Project64-core/N64System/Profiling.cpp b/Source/Project64-core/N64System/Profiling.cpp index 26bc023c7..fdf716353 100644 --- a/Source/Project64-core/N64System/Profiling.cpp +++ b/Source/Project64-core/N64System/Profiling.cpp @@ -64,7 +64,10 @@ void CProfiling::ShowCPU_Usage() { PROFILE_TIMERS PreviousType = StopTimer(); uint64_t TotalTime = m_Timers[Timer_R4300] + m_Timers[Timer_RSP_Dlist] + m_Timers[Timer_RSP_Alist] + m_Timers[Timer_Idel]; - + if (TotalTime == 0) + { + return; + } if (m_CurrentDisplayCount > 0) { m_CurrentDisplayCount -= 1;