From f817becf9c93277bb2abdd6d2d1c785f911e0937 Mon Sep 17 00:00:00 2001 From: zilmar Date: Thu, 28 Sep 2023 07:03:01 +0930 Subject: [PATCH] Core: Create a handler for RSP registers that is accessible to the core and the RSP --- .../MemoryHandler/SPRegistersHandler.cpp | 300 +--------------- .../MemoryHandler/SPRegistersHandler.h | 16 +- .../N64System/Mips/MemoryVirtualMem.cpp | 113 ------ .../N64System/Mips/MemoryVirtualMem.h | 5 +- .../Recompiler/x86/x86RecompilerOps.cpp | 20 +- Source/Project64-core/Project64-core.vcxproj | 3 + .../Project64-rsp-core.vcxproj | 2 + .../Project64-rsp-core.vcxproj.filters | 6 + .../Recompiler/RspProfiling.cpp | 8 +- .../cpu/RSPRegisterHandler.cpp | 324 ++++++++++++++++++ .../cpu/RSPRegisterHandler.h | 49 +++ 11 files changed, 423 insertions(+), 423 deletions(-) create mode 100644 Source/Project64-rsp-core/cpu/RSPRegisterHandler.cpp create mode 100644 Source/Project64-rsp-core/cpu/RSPRegisterHandler.h diff --git a/Source/Project64-core/N64System/MemoryHandler/SPRegistersHandler.cpp b/Source/Project64-core/N64System/MemoryHandler/SPRegistersHandler.cpp index 9e088b291..d9e43c117 100644 --- a/Source/Project64-core/N64System/MemoryHandler/SPRegistersHandler.cpp +++ b/Source/Project64-core/N64System/MemoryHandler/SPRegistersHandler.cpp @@ -21,11 +21,8 @@ SPRegistersReg::SPRegistersReg(uint32_t * SignalProcessorInterface) : } SPRegistersHandler::SPRegistersHandler(CN64System & System, CMipsMemoryVM & MMU, CRegisters & Reg) : - SPRegistersReg(Reg.m_SigProcessor_Interface), + RSPRegisterHandler(Reg.m_SigProcessor_Interface, MMU.Rdram(), MMU.RdramSize(), m_IMEM, m_DMEM), MIPSInterfaceReg(Reg.m_Mips_Interface), - m_SPMemAddrRegRead(0), - m_SPDramAddrRegRead(0), - m_ExecutedDMARead(false), m_System(System), m_MMU(MMU), m_Reg(Reg), @@ -33,7 +30,6 @@ SPRegistersHandler::SPRegistersHandler(CN64System & System, CMipsMemoryVM & MMU, m_PC(Reg.m_PROGRAM_COUNTER) { System.RegisterCallBack(CN64SystemCB_Reset, this, (CN64System::CallBackFunction)stSystemReset); - System.RegisterCallBack(CN64SystemCB_LoadedGameState, this, (CN64System::CallBackFunction)stLoadedGameState); } bool SPRegistersHandler::Read32(uint32_t Address, uint32_t & Value) @@ -53,8 +49,8 @@ bool SPRegistersHandler::Read32(uint32_t Address, uint32_t & Value) switch (Address & 0x1FFFFFFF) { - case 0x04040000: Value = m_ExecutedDMARead ? m_SPMemAddrRegRead : SP_MEM_ADDR_REG; break; - case 0x04040004: Value = m_ExecutedDMARead ? m_SPDramAddrRegRead : SP_DRAM_ADDR_REG; break; + case 0x04040000: Value = SP_MEM_ADDR_REG; break; + case 0x04040004: Value = SP_DRAM_ADDR_REG; break; case 0x04040008: Value = SP_RD_LEN_REG; break; case 0x0404000C: Value = SP_WR_LEN_REG; break; case 0x04040010: Value = SP_STATUS_REG; break; @@ -134,122 +130,12 @@ bool SPRegistersHandler::Write32(uint32_t Address, uint32_t Value, uint32_t Mask switch (Address & 0x1FFFFFFF) { - case 0x04040000: SP_MEM_ADDR_REG = (SP_MEM_ADDR_REG & ~Mask) | (MaskedValue); break; - case 0x04040004: SP_DRAM_ADDR_REG = (SP_DRAM_ADDR_REG & ~Mask) | (MaskedValue); break; - case 0x04040008: - SP_RD_LEN_REG = MaskedValue; - SP_DMA_READ(); - break; - case 0x0404000C: - SP_WR_LEN_REG = (SP_WR_LEN_REG & ~Mask) | (MaskedValue); - SP_DMA_WRITE(); - break; + case 0x04040000: WriteReg(RSPRegister_MEM_ADDR, (SP_MEM_ADDR_REG & ~Mask) | (MaskedValue)); break; + case 0x04040004: WriteReg(RSPRegister_DRAM_ADDR, (SP_DRAM_ADDR_REG & ~Mask) | (MaskedValue)); break; + case 0x04040008: WriteReg(RSPRegister_RD_LEN, MaskedValue); break; + case 0x0404000C: WriteReg(RSPRegister_WR_LEN, MaskedValue); break; case 0x04040010: - if ((MaskedValue & SP_CLR_HALT) != 0) - { - SP_STATUS_REG &= ~SP_STATUS_HALT; - } - if ((MaskedValue & SP_SET_HALT) != 0) - { - SP_STATUS_REG |= SP_STATUS_HALT; - } - if ((MaskedValue & SP_CLR_BROKE) != 0) - { - SP_STATUS_REG &= ~SP_STATUS_BROKE; - } - if ((MaskedValue & SP_CLR_INTR) != 0) - { - MI_INTR_REG &= ~MI_INTR_SP; - m_RspIntrReg &= ~MI_INTR_SP; - m_Reg.CheckInterrupts(); - } - if ((MaskedValue & SP_SET_INTR) != 0) - { - if (BreakOnUnhandledMemory()) - { - g_Notify->BreakPoint(__FILE__, __LINE__); - } - } - if ((MaskedValue & SP_CLR_SSTEP) != 0) - { - SP_STATUS_REG &= ~SP_STATUS_SSTEP; - } - if ((MaskedValue & SP_SET_SSTEP) != 0) - { - SP_STATUS_REG |= SP_STATUS_SSTEP; - } - if ((MaskedValue & SP_CLR_INTR_BREAK) != 0) - { - SP_STATUS_REG &= ~SP_STATUS_INTR_BREAK; - } - if ((MaskedValue & SP_SET_INTR_BREAK) != 0) - { - SP_STATUS_REG |= SP_STATUS_INTR_BREAK; - } - if ((MaskedValue & SP_CLR_SIG0) != 0) - { - SP_STATUS_REG &= ~SP_STATUS_SIG0; - } - if ((MaskedValue & SP_SET_SIG0) != 0) - { - SP_STATUS_REG |= SP_STATUS_SIG0; - } - if ((MaskedValue & SP_CLR_SIG1) != 0) - { - SP_STATUS_REG &= ~SP_STATUS_SIG1; - } - if ((MaskedValue & SP_SET_SIG1) != 0) - { - SP_STATUS_REG |= SP_STATUS_SIG1; - } - if ((MaskedValue & SP_CLR_SIG2) != 0) - { - SP_STATUS_REG &= ~SP_STATUS_SIG2; - } - if ((MaskedValue & SP_SET_SIG2) != 0) - { - SP_STATUS_REG |= SP_STATUS_SIG2; - } - if ((MaskedValue & SP_CLR_SIG3) != 0) - { - SP_STATUS_REG &= ~SP_STATUS_SIG3; - } - if ((MaskedValue & SP_SET_SIG3) != 0) - { - SP_STATUS_REG |= SP_STATUS_SIG3; - } - if ((MaskedValue & SP_CLR_SIG4) != 0) - { - SP_STATUS_REG &= ~SP_STATUS_SIG4; - } - if ((MaskedValue & SP_SET_SIG4) != 0) - { - SP_STATUS_REG |= SP_STATUS_SIG4; - } - if ((MaskedValue & SP_CLR_SIG5) != 0) - { - SP_STATUS_REG &= ~SP_STATUS_SIG5; - } - if ((MaskedValue & SP_SET_SIG5) != 0) - { - SP_STATUS_REG |= SP_STATUS_SIG5; - } - if ((MaskedValue & SP_CLR_SIG6) != 0) - { - SP_STATUS_REG &= ~SP_STATUS_SIG6; - } - if ((MaskedValue & SP_SET_SIG6) != 0) - { - SP_STATUS_REG |= SP_STATUS_SIG6; - } - if ((MaskedValue & SP_CLR_SIG7) != 0) - { - SP_STATUS_REG &= ~SP_STATUS_SIG7; - } - if ((MaskedValue & SP_SET_SIG7) != 0) - { - SP_STATUS_REG |= SP_STATUS_SIG7; - } + WriteReg(RSPRegister_STATUS, MaskedValue); if ((MaskedValue & SP_SET_SIG0) != 0 && RspAudioSignal()) { MI_INTR_REG |= MI_INTR_SP; @@ -268,164 +154,22 @@ bool SPRegistersHandler::Write32(uint32_t Address, uint32_t Value, uint32_t Mask return true; } -void SPRegistersHandler::SP_DMA_READ() +void SPRegistersHandler::ClearSPInterrupt(void) { - uint8_t * Dest = ((SP_MEM_ADDR_REG & 0x1000) != 0 ? m_IMEM : m_DMEM); - uint8_t * Source = m_MMU.Rdram(); - uint32_t ReadPos = SP_DRAM_ADDR_REG & 0x00FFFFF8; - int32_t Length = ((SP_RD_LEN_REG & 0xFFF) | 7) + 1; - int32_t Count = ((SP_RD_LEN_REG >> 12) & 0xFF) + 1; - int32_t Skip = (SP_RD_LEN_REG >> 20) & 0xF8; - int32_t Pos = (SP_MEM_ADDR_REG & 0x0FF8); - - for (int32_t i = 0; i < Count; i++) - { - int32_t CopyLength = Length; - if ((Pos + Length) > 0x1000) - { - CopyLength = 0x1000 - Pos; - if (CopyLength <= 0) - { - break; - } - } - - uint32_t NullLen = 0; - if ((ReadPos + Length) > m_MMU.RdramSize()) - { - if ((m_MMU.RdramSize() - ReadPos) < (uint32_t)CopyLength) - { - CopyLength = (int32_t)m_MMU.RdramSize() - (int32_t)ReadPos; - } - else - { - NullLen = CopyLength; - } - } - - if (NullLen != 0) - { - memset(&Dest[Pos], 0, NullLen); - } - else - { - memcpy(&Dest[Pos], &Source[ReadPos], CopyLength); - } - if (CopyLength != Length) - { - ReadPos = (ReadPos + CopyLength) & 0x00FFFFFF; - CopyLength = Length - CopyLength; - Pos = 0; - if ((CopyLength + ReadPos) > m_MMU.RdramSize()) - { - int32_t CopyAmount = m_MMU.RdramSize() - ReadPos; - if (CopyAmount < 0) - { - CopyAmount = 0; - } - NullLen = CopyLength - CopyAmount; - - if (CopyAmount > 0) - { - memcpy(&Dest[Pos], &Source[ReadPos], CopyLength); - } - if (NullLen > 0) - { - memset(&Dest[Pos], 0, NullLen); - } - } - else - { - memcpy(&Dest[Pos], &Source[ReadPos], CopyLength); - } - } - ReadPos += CopyLength + Skip; - Pos += CopyLength; - } - - if (Count > 1) - { - ReadPos -= Skip; - } - - SP_DMA_BUSY_REG = 0; - SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY; - - m_ExecutedDMARead = true; - m_SPMemAddrRegRead = Pos | (SP_MEM_ADDR_REG & 0x1000); - m_SPDramAddrRegRead = ReadPos; - SP_RD_LEN_REG = (SP_RD_LEN_REG & 0xFF800000) | 0x00000FF8; - SP_WR_LEN_REG = (SP_RD_LEN_REG & 0xFF800000) | 0x00000FF8; + MI_INTR_REG &= ~MI_INTR_SP; + m_RspIntrReg &= ~MI_INTR_SP; + m_Reg.CheckInterrupts(); } -void SPRegistersHandler::SP_DMA_WRITE() +void SPRegistersHandler::SetSPInterrupt(void) { - uint8_t * Source = ((SP_MEM_ADDR_REG & 0x1000) != 0 ? m_IMEM : m_DMEM); - uint8_t * Dest = m_MMU.Rdram(); - uint32_t WritePos = SP_DRAM_ADDR_REG & 0x00FFFFF8; - int32_t Length = ((SP_WR_LEN_REG & 0xFFF) | 7) + 1; - int32_t Count = ((SP_WR_LEN_REG >> 12) & 0xFF) + 1; - int32_t Skip = (SP_WR_LEN_REG >> 20) & 0xF8; - int32_t Pos = (SP_MEM_ADDR_REG & 0x0FF8); + MI_INTR_REG |= MI_INTR_SP; + m_RspIntrReg |= MI_INTR_SP; + m_Reg.CheckInterrupts(); +} - for (int32_t i = 0; i < Count; i++) - { - int32_t CopyLength = Length; - if (Pos + Length > 0x1000) - { - CopyLength = 0x1000 - Pos; - if (CopyLength <= 0) - { - break; - } - } - - if (WritePos < m_MMU.RdramSize()) - { - int32_t CopyAmount = (int32_t)m_MMU.RdramSize() - (int32_t)WritePos; - if (CopyLength < CopyAmount) - { - CopyAmount = CopyLength; - } - if (CopyAmount > 0) - { - memcpy(&Dest[WritePos], &Source[Pos], CopyAmount); - } - } - - if (CopyLength != Length) - { - WritePos = (WritePos + CopyLength) & 0x00FFFFFF; - CopyLength = Length - CopyLength; - Pos = 0; - - int32_t CopyAmount = (int32_t)m_MMU.RdramSize() - (int32_t)WritePos; - if (CopyLength < CopyAmount) - { - CopyAmount = CopyLength; - } - if (CopyAmount > 0) - { - memcpy(&Dest[WritePos], &Source[Pos], CopyAmount); - } - } - WritePos += CopyLength + Skip; - Pos += CopyLength; - } - - if (Count > 1) - { - WritePos -= Skip; - } - - SP_DMA_BUSY_REG = 0; - SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY; - - m_ExecutedDMARead = true; - m_SPMemAddrRegRead = Pos | (SP_MEM_ADDR_REG & 0x1000); - m_SPDramAddrRegRead = WritePos; - SP_RD_LEN_REG = (SP_WR_LEN_REG & 0xFF800000) | 0x00000FF8; - SP_WR_LEN_REG = (SP_WR_LEN_REG & 0xFF800000) | 0x00000FF8; +void SPRegistersHandler::SetHalt(void) +{ } void SPRegistersHandler::SystemReset(void) @@ -435,10 +179,4 @@ void SPRegistersHandler::SystemReset(void) memset(m_IMEM, 0, sizeof(m_IMEM)); memset(m_DMEM, 0, sizeof(m_DMEM)); -} - -void SPRegistersHandler::LoadedGameState(void) -{ - m_SPMemAddrRegRead = 0; - m_ExecutedDMARead = false; } \ No newline at end of file diff --git a/Source/Project64-core/N64System/MemoryHandler/SPRegistersHandler.h b/Source/Project64-core/N64System/MemoryHandler/SPRegistersHandler.h index e86cec453..50b23b120 100644 --- a/Source/Project64-core/N64System/MemoryHandler/SPRegistersHandler.h +++ b/Source/Project64-core/N64System/MemoryHandler/SPRegistersHandler.h @@ -4,6 +4,7 @@ #include #include #include +#include #include class SPRegistersReg @@ -35,7 +36,7 @@ class CN64System; class SPRegistersHandler : public MemoryHandler, - public SPRegistersReg, + private RSPRegisterHandler, private CGameSettings, private MIPSInterfaceReg, private CDebugSettings, @@ -65,21 +66,14 @@ private: { _this->SystemReset(); } - static void stLoadedGameState(SPRegistersHandler * _this) - { - _this->LoadedGameState(); - } - void SP_DMA_READ(); - void SP_DMA_WRITE(); + void ClearSPInterrupt(void); + void SetSPInterrupt(void); + void SetHalt(void); void SystemReset(void); - void LoadedGameState(void); uint8_t m_IMEM[0x1000]; uint8_t m_DMEM[0x1000]; - uint32_t m_SPMemAddrRegRead; - uint32_t m_SPDramAddrRegRead; - bool m_ExecutedDMARead; CN64System & m_System; CMipsMemoryVM & m_MMU; CRegisters & m_Reg; diff --git a/Source/Project64-core/N64System/Mips/MemoryVirtualMem.cpp b/Source/Project64-core/N64System/Mips/MemoryVirtualMem.cpp index 8d46d4651..9f5651430 100755 --- a/Source/Project64-core/N64System/Mips/MemoryVirtualMem.cpp +++ b/Source/Project64-core/N64System/Mips/MemoryVirtualMem.cpp @@ -1077,119 +1077,6 @@ void CMipsMemoryVM::RdramChanged(CMipsMemoryVM * _this) _this->m_AllocatedRdramSize = (uint32_t)new_size; } -void CMipsMemoryVM::ChangeSpStatus() -{ - if ((RegModValue & SP_CLR_HALT) != 0) - { - g_Reg->SP_STATUS_REG &= ~SP_STATUS_HALT; - } - if ((RegModValue & SP_SET_HALT) != 0) - { - g_Reg->SP_STATUS_REG |= SP_STATUS_HALT; - } - if ((RegModValue & SP_CLR_BROKE) != 0) - { - g_Reg->SP_STATUS_REG &= ~SP_STATUS_BROKE; - } - if ((RegModValue & SP_CLR_INTR) != 0) - { - g_Reg->MI_INTR_REG &= ~MI_INTR_SP; - g_Reg->m_RspIntrReg &= ~MI_INTR_SP; - g_Reg->CheckInterrupts(); - } - if ((RegModValue & SP_SET_INTR) != 0 && HaveDebugger()) - { - g_Notify->DisplayError("SP_SET_INTR"); - } - if ((RegModValue & SP_CLR_SSTEP) != 0) - { - g_Reg->SP_STATUS_REG &= ~SP_STATUS_SSTEP; - } - if ((RegModValue & SP_SET_SSTEP) != 0) - { - g_Reg->SP_STATUS_REG |= SP_STATUS_SSTEP; - } - if ((RegModValue & SP_CLR_INTR_BREAK) != 0) - { - g_Reg->SP_STATUS_REG &= ~SP_STATUS_INTR_BREAK; - } - if ((RegModValue & SP_SET_INTR_BREAK) != 0) - { - g_Reg->SP_STATUS_REG |= SP_STATUS_INTR_BREAK; - } - if ((RegModValue & SP_CLR_SIG0) != 0) - { - g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG0; - } - if ((RegModValue & SP_SET_SIG0) != 0) - { - g_Reg->SP_STATUS_REG |= SP_STATUS_SIG0; - } - if ((RegModValue & SP_CLR_SIG1) != 0) - { - g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG1; - } - if ((RegModValue & SP_SET_SIG1) != 0) - { - g_Reg->SP_STATUS_REG |= SP_STATUS_SIG1; - } - if ((RegModValue & SP_CLR_SIG2) != 0) - { - g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG2; - } - if ((RegModValue & SP_SET_SIG2) != 0) - { - g_Reg->SP_STATUS_REG |= SP_STATUS_SIG2; - } - if ((RegModValue & SP_CLR_SIG3) != 0) - { - g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG3; - } - if ((RegModValue & SP_SET_SIG3) != 0) - { - g_Reg->SP_STATUS_REG |= SP_STATUS_SIG3; - } - if ((RegModValue & SP_CLR_SIG4) != 0) - { - g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG4; - } - if ((RegModValue & SP_SET_SIG4) != 0) - { - g_Reg->SP_STATUS_REG |= SP_STATUS_SIG4; - } - if ((RegModValue & SP_CLR_SIG5) != 0) - { - g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG5; - } - if ((RegModValue & SP_SET_SIG5) != 0) - { - g_Reg->SP_STATUS_REG |= SP_STATUS_SIG5; - } - if ((RegModValue & SP_CLR_SIG6) != 0) - { - g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG6; - } - if ((RegModValue & SP_SET_SIG6) != 0) - { - g_Reg->SP_STATUS_REG |= SP_STATUS_SIG6; - } - if ((RegModValue & SP_CLR_SIG7) != 0) - { - g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG7; - } - if ((RegModValue & SP_SET_SIG7) != 0) - { - g_Reg->SP_STATUS_REG |= SP_STATUS_SIG7; - } - - if ((RegModValue & SP_SET_SIG0) != 0 && g_System->RspAudioSignal()) - { - g_Reg->MI_INTR_REG |= MI_INTR_SP; - g_Reg->CheckInterrupts(); - } - g_Plugins->RSP()->RunRSP(); -} - void CMipsMemoryVM::ChangeMiIntrMask() { if ((RegModValue & MI_INTR_MASK_CLR_SP) != 0) diff --git a/Source/Project64-core/N64System/Mips/MemoryVirtualMem.h b/Source/Project64-core/N64System/Mips/MemoryVirtualMem.h index 1ed332a1b..ffa2e2b03 100644 --- a/Source/Project64-core/N64System/Mips/MemoryVirtualMem.h +++ b/Source/Project64-core/N64System/Mips/MemoryVirtualMem.h @@ -61,11 +61,11 @@ public: bool Initialize(bool SyncSystem); void Reset(bool EraseMemory); - uint8_t * Rdram() const + uint8_t *& Rdram() { return m_RDRAM; } - uint32_t RdramSize() const + const uint32_t & RdramSize() const { return m_AllocatedRdramSize; } @@ -161,7 +161,6 @@ private: #endif static void RdramChanged(CMipsMemoryVM * _this); - static void ChangeSpStatus(); static void ChangeMiIntrMask(); bool LB_NonMemory(uint32_t VAddr, uint8_t & Value); diff --git a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp index 32f7f12e6..d28c02217 100644 --- a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp @@ -10599,8 +10599,8 @@ void CX86RecompilerOps::SW_Const(uint32_t Value, uint32_t VAddr) { switch (PAddr) { - case 0x04040000: m_Assembler.MoveConstToVariable(&g_Reg->SP_MEM_ADDR_REG, "SP_MEM_ADDR_REG", Value); break; - case 0x04040004: m_Assembler.MoveConstToVariable(&g_Reg->SP_DRAM_ADDR_REG, "SP_DRAM_ADDR_REG", Value); break; + case 0x04040000: + case 0x04040004: case 0x04040008: case 0x0404000C: m_RegWorkingSet.BeforeCallDirect(); @@ -11026,10 +11026,15 @@ void CX86RecompilerOps::SW_Register(const asmjit::x86::Gp & Reg, uint32_t VAddr) case 0x04000000: switch (PAddr) { - case 0x04040000: m_Assembler.MoveX86regToVariable(&g_Reg->SP_MEM_ADDR_REG, "SP_MEM_ADDR_REG", Reg); break; - case 0x04040004: m_Assembler.MoveX86regToVariable(&g_Reg->SP_DRAM_ADDR_REG, "SP_DRAM_ADDR_REG", Reg); break; + case 0x04040000: + case 0x04040004: case 0x04040008: case 0x0404000C: + case 0x04040010: + if (PAddr == 0x04040010) + { + UpdateCounters(m_RegWorkingSet, false, true, false); + } m_RegWorkingSet.BeforeCallDirect(); m_Assembler.push(0xFFFFFFFF); m_Assembler.push(Reg); @@ -11037,13 +11042,6 @@ void CX86RecompilerOps::SW_Register(const asmjit::x86::Gp & Reg, uint32_t VAddr) m_Assembler.CallThis((uint32_t)(MemoryHandler *)&g_MMU->m_SPRegistersHandler, (uint32_t)((long **)(MemoryHandler *)&g_MMU->m_SPRegistersHandler)[0][1], "SPRegistersHandler::Write32", 16); m_RegWorkingSet.AfterCallDirect(); break; - case 0x04040010: - UpdateCounters(m_RegWorkingSet, false, true, false); - m_Assembler.MoveX86regToVariable(&CMipsMemoryVM::RegModValue, "CMipsMemoryVM::RegModValue", Reg); - m_RegWorkingSet.BeforeCallDirect(); - m_Assembler.CallFunc((uint32_t)CMipsMemoryVM::ChangeSpStatus, "CMipsMemoryVM::ChangeSpStatus"); - m_RegWorkingSet.AfterCallDirect(); - break; case 0x0404001C: m_Assembler.MoveConstToVariable(&g_Reg->SP_SEMAPHORE_REG, "SP_SEMAPHORE_REG", 0); break; case 0x04080000: m_Assembler.MoveX86regToVariable(&g_Reg->SP_PC_REG, "SP_PC_REG", Reg); diff --git a/Source/Project64-core/Project64-core.vcxproj b/Source/Project64-core/Project64-core.vcxproj index 4487f3bd7..01df7ecf1 100644 --- a/Source/Project64-core/Project64-core.vcxproj +++ b/Source/Project64-core/Project64-core.vcxproj @@ -295,6 +295,9 @@ {3326e128-33af-422c-bb7c-67cc6b915610} + + {7598f6b8-9da6-4897-b26f-f6865f824bf4} + {1968162c-0793-491d-91a1-81645a24d399} diff --git a/Source/Project64-rsp-core/Project64-rsp-core.vcxproj b/Source/Project64-rsp-core/Project64-rsp-core.vcxproj index dad4c70a4..9676ddf31 100644 --- a/Source/Project64-rsp-core/Project64-rsp-core.vcxproj +++ b/Source/Project64-rsp-core/Project64-rsp-core.vcxproj @@ -49,6 +49,7 @@ + @@ -72,6 +73,7 @@ + diff --git a/Source/Project64-rsp-core/Project64-rsp-core.vcxproj.filters b/Source/Project64-rsp-core/Project64-rsp-core.vcxproj.filters index 7851056c2..3564c5bc3 100644 --- a/Source/Project64-rsp-core/Project64-rsp-core.vcxproj.filters +++ b/Source/Project64-rsp-core/Project64-rsp-core.vcxproj.filters @@ -96,6 +96,9 @@ Source Files\cpu + + Source Files\cpu + @@ -155,5 +158,8 @@ Header Files\cpu + + Header Files\cpu + \ No newline at end of file diff --git a/Source/Project64-rsp-core/Recompiler/RspProfiling.cpp b/Source/Project64-rsp-core/Recompiler/RspProfiling.cpp index c747eb569..89c4b4fe9 100644 --- a/Source/Project64-rsp-core/Recompiler/RspProfiling.cpp +++ b/Source/Project64-rsp-core/Recompiler/RspProfiling.cpp @@ -8,7 +8,7 @@ #include #include -class CProfiling +class CRspProfiling { typedef std::map PROFILE_ENRTIES; typedef PROFILE_ENRTIES::iterator PROFILE_ENRTY; @@ -24,7 +24,7 @@ class CProfiling PROFILE_ENRTIES m_Entries; public: - CProfiling() + CRspProfiling() { m_CurrentTimerAddr = Timer_None; } @@ -168,9 +168,9 @@ public: } }; -CProfiling & GetProfiler(void) +CRspProfiling & GetProfiler(void) { - static CProfiling Profile; + static CRspProfiling Profile; return Profile; } diff --git a/Source/Project64-rsp-core/cpu/RSPRegisterHandler.cpp b/Source/Project64-rsp-core/cpu/RSPRegisterHandler.cpp new file mode 100644 index 000000000..0808adf1c --- /dev/null +++ b/Source/Project64-rsp-core/cpu/RSPRegisterHandler.cpp @@ -0,0 +1,324 @@ +#include "RSPRegisterHandler.h" +#include "RSPRegisters.h" +#include +#include +#include + +RSPRegisterHandler::RSPRegisterHandler(uint32_t * SignalProcessorInterface, uint8_t *& Rdram, const uint32_t & RdramSize, uint8_t * IMEM, uint8_t * DMEM) : + SP_MEM_ADDR_REG(SignalProcessorInterface[0]), + SP_DRAM_ADDR_REG(SignalProcessorInterface[1]), + SP_RD_LEN_REG(SignalProcessorInterface[2]), + SP_WR_LEN_REG(SignalProcessorInterface[3]), + SP_STATUS_REG(SignalProcessorInterface[4]), + SP_DMA_FULL_REG(SignalProcessorInterface[5]), + SP_DMA_BUSY_REG(SignalProcessorInterface[6]), + SP_SEMAPHORE_REG(SignalProcessorInterface[7]), + SP_PC_REG(SignalProcessorInterface[8]), + m_Rdram(Rdram), + m_RdramSize(RdramSize), + m_IMEM(IMEM), + m_DMEM(DMEM), + m_PendingSPMemAddr(0), + m_PendingSPDramAddr(0), + m_ExecutedDMARead(false) +{ +} + +void RSPRegisterHandler::SP_DMA_READ() +{ + SP_STATUS_REG |= SP_STATUS_DMA_BUSY; + + uint8_t * Dest = ((m_PendingSPMemAddr & 0x1000) != 0 ? m_IMEM : m_DMEM); + uint8_t * Source = m_Rdram; + uint32_t ReadPos = m_PendingSPDramAddr & 0x00FFFFF8; + int32_t Length = ((SP_RD_LEN_REG & 0xFFF) | 7) + 1; + int32_t Count = ((SP_RD_LEN_REG >> 12) & 0xFF) + 1; + int32_t Skip = (SP_RD_LEN_REG >> 20) & 0xF8; + int32_t Pos = (m_PendingSPMemAddr & 0x0FF8); + + for (int32_t i = 0; i < Count; i++) + { + int32_t CopyLength = Length; + if ((Pos + Length) > 0x1000) + { + CopyLength = 0x1000 - Pos; + if (CopyLength <= 0) + { + break; + } + } + + uint32_t NullLen = 0; + if ((ReadPos + Length) > m_RdramSize) + { + if ((m_RdramSize - ReadPos) < (uint32_t)CopyLength) + { + CopyLength = (int32_t)m_RdramSize - (int32_t)ReadPos; + } + else + { + NullLen = CopyLength; + } + } + + if (NullLen != 0) + { + memset(&Dest[Pos], 0, NullLen); + } + else + { + memcpy(&Dest[Pos], &Source[ReadPos], CopyLength); + } + if (CopyLength != Length) + { + ReadPos = (ReadPos + CopyLength) & 0x00FFFFFF; + CopyLength = Length - CopyLength; + Pos = 0; + if ((CopyLength + ReadPos) > m_RdramSize) + { + int32_t CopyAmount = m_RdramSize - ReadPos; + if (CopyAmount < 0) + { + CopyAmount = 0; + } + NullLen = CopyLength - CopyAmount; + + if (CopyAmount > 0) + { + memcpy(&Dest[Pos], &Source[ReadPos], CopyLength); + } + if (NullLen > 0) + { + memset(&Dest[Pos], 0, NullLen); + } + } + else + { + memcpy(&Dest[Pos], &Source[ReadPos], CopyLength); + } + } + ReadPos += CopyLength + Skip; + Pos += CopyLength; + } + + if (Count > 1) + { + ReadPos -= Skip; + } + + SP_DMA_BUSY_REG = 0; + SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY; + + m_ExecutedDMARead = true; + SP_MEM_ADDR_REG = (Pos & 0xFFF) | (m_PendingSPMemAddr & 0x1000); + SP_DRAM_ADDR_REG = ReadPos; + SP_RD_LEN_REG = (SP_RD_LEN_REG & 0xFF800000) | 0x00000FF8; + SP_WR_LEN_REG = (SP_RD_LEN_REG & 0xFF800000) | 0x00000FF8; +} + +void RSPRegisterHandler::SP_DMA_WRITE() +{ + SP_STATUS_REG |= SP_STATUS_DMA_BUSY; + + uint8_t * Source = ((m_PendingSPMemAddr & 0x1000) != 0 ? m_IMEM : m_DMEM); + uint8_t * Dest = m_Rdram; + uint32_t WritePos = m_PendingSPDramAddr & 0x00FFFFF8; + int32_t Length = ((SP_WR_LEN_REG & 0xFFF) | 7) + 1; + int32_t Count = ((SP_WR_LEN_REG >> 12) & 0xFF) + 1; + int32_t Skip = (SP_WR_LEN_REG >> 20) & 0xF8; + int32_t Pos = (m_PendingSPMemAddr & 0x0FF8); + + for (int32_t i = 0; i < Count; i++) + { + int32_t CopyLength = Length; + if (Pos + Length > 0x1000) + { + CopyLength = 0x1000 - Pos; + if (CopyLength <= 0) + { + break; + } + } + + if (WritePos < m_RdramSize) + { + int32_t CopyAmount = (int32_t)m_RdramSize - (int32_t)WritePos; + if (CopyLength < CopyAmount) + { + CopyAmount = CopyLength; + } + if (CopyAmount > 0) + { + memcpy(&Dest[WritePos], &Source[Pos], CopyAmount); + } + } + + if (CopyLength != Length) + { + WritePos = (WritePos + CopyLength) & 0x00FFFFFF; + CopyLength = Length - CopyLength; + Pos = 0; + + int32_t CopyAmount = (int32_t)m_RdramSize - (int32_t)WritePos; + if (CopyLength < CopyAmount) + { + CopyAmount = CopyLength; + } + if (CopyAmount > 0) + { + memcpy(&Dest[WritePos], &Source[Pos], CopyAmount); + } + } + WritePos += CopyLength + Skip; + Pos += CopyLength; + } + + if (Count > 1) + { + WritePos -= Skip; + } + + SP_DMA_BUSY_REG = 0; + SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY; + + m_ExecutedDMARead = true; + SP_MEM_ADDR_REG = (Pos & 0xFFF) | (m_PendingSPMemAddr & 0x1000); + SP_DRAM_ADDR_REG = WritePos; + SP_RD_LEN_REG = (SP_WR_LEN_REG & 0xFF800000) | 0x00000FF8; + SP_WR_LEN_REG = (SP_WR_LEN_REG & 0xFF800000) | 0x00000FF8; +} + +uint32_t RSPRegisterHandler::ReadReg(RSPRegister Reg) +{ + switch (Reg) + { + case RSPRegister_MEM_ADDR: return SP_MEM_ADDR_REG; + case RSPRegister_DRAM_ADDR: return SP_DRAM_ADDR_REG; + case RSPRegister_RD_LEN: return SP_RD_LEN_REG; + case RSPRegister_WR_LEN: return SP_WR_LEN_REG; + case RSPRegister_STATUS: return SP_STATUS_REG; + } + return 0; +} + +void RSPRegisterHandler::WriteReg(RSPRegister Reg, uint32_t Value) +{ + switch (Reg) + { + case RSPRegister_MEM_ADDR: m_PendingSPMemAddr = Value; break; + case RSPRegister_DRAM_ADDR: m_PendingSPDramAddr = Value; break; + case RSPRegister_RD_LEN: + SP_RD_LEN_REG = Value; + SP_DMA_READ(); + break; + case RSPRegister_WR_LEN: + SP_WR_LEN_REG = Value; + SP_DMA_WRITE(); + break; + case RSPRegister_STATUS: + if ((Value & SP_CLR_HALT) != 0 && (Value & SP_SET_HALT) == 0) + { + SP_STATUS_REG &= ~SP_STATUS_HALT; + } + if ((Value & SP_SET_HALT) != 0 && (Value & SP_CLR_HALT) == 0 && (SP_STATUS_REG & SP_STATUS_HALT) == 0) + { + SP_STATUS_REG |= SP_STATUS_HALT; + SetHalt(); + } + if ((Value & SP_CLR_BROKE) != 0) + { + SP_STATUS_REG &= ~SP_STATUS_BROKE; + } + if ((Value & SP_CLR_INTR) != 0 && (Value & SP_SET_INTR) == 0) + { + ClearSPInterrupt(); + } + if ((Value & SP_SET_INTR) != 0 && (Value & SP_CLR_INTR) == 0) + { + SetSPInterrupt(); + } + if ((Value & SP_CLR_SSTEP) != 0 && (Value & SP_SET_SSTEP) == 0) + { + SP_STATUS_REG &= ~SP_STATUS_SSTEP; + } + if ((Value & SP_SET_SSTEP) != 0 && (Value & SP_CLR_SSTEP) == 0) + { + SP_STATUS_REG |= SP_STATUS_SSTEP; + } + if ((Value & SP_CLR_INTR_BREAK) != 0 && (Value & SP_SET_INTR_BREAK) == 0) + { + SP_STATUS_REG &= ~SP_STATUS_INTR_BREAK; + } + if ((Value & SP_SET_INTR_BREAK) != 0 && (Value & SP_CLR_INTR_BREAK) == 0) + { + SP_STATUS_REG |= SP_STATUS_INTR_BREAK; + } + if ((Value & SP_CLR_SIG0) != 0 && (Value & SP_SET_SIG0) == 0) + { + SP_STATUS_REG &= ~SP_STATUS_SIG0; + } + if ((Value & SP_SET_SIG0) != 0 && (Value & SP_CLR_SIG0) == 0) + { + SP_STATUS_REG |= SP_STATUS_SIG0; + } + if ((Value & SP_CLR_SIG1) != 0 && (Value & SP_SET_SIG1) == 0) + { + SP_STATUS_REG &= ~SP_STATUS_SIG1; + } + if ((Value & SP_SET_SIG1) != 0 && (Value & SP_CLR_SIG1) == 0) + { + SP_STATUS_REG |= SP_STATUS_SIG1; + } + if ((Value & SP_CLR_SIG2) != 0 && (Value & SP_SET_SIG2) == 0) + { + SP_STATUS_REG &= ~SP_STATUS_SIG2; + } + if ((Value & SP_SET_SIG2) != 0 && (Value & SP_CLR_SIG2) == 0) + { + SP_STATUS_REG |= SP_STATUS_SIG2; + } + if ((Value & SP_CLR_SIG3) != 0 && (Value & SP_SET_SIG3) == 0) + { + SP_STATUS_REG &= ~SP_STATUS_SIG3; + } + if ((Value & SP_SET_SIG3) != 0 && (Value & SP_CLR_SIG3) == 0) + { + SP_STATUS_REG |= SP_STATUS_SIG3; + } + if ((Value & SP_CLR_SIG4) != 0 && (Value & SP_SET_SIG4) == 0) + { + SP_STATUS_REG &= ~SP_STATUS_SIG4; + } + if ((Value & SP_SET_SIG4) != 0 && (Value & SP_CLR_SIG4) == 0) + { + SP_STATUS_REG |= SP_STATUS_SIG4; + } + if ((Value & SP_CLR_SIG5) != 0 && (Value & SP_SET_SIG5) == 0) + { + SP_STATUS_REG &= ~SP_STATUS_SIG5; + } + if ((Value & SP_SET_SIG5) != 0 && (Value & SP_CLR_SIG5) == 0) + { + SP_STATUS_REG |= SP_STATUS_SIG5; + } + if ((Value & SP_CLR_SIG6) != 0 && (Value & SP_SET_SIG6) == 0) + { + SP_STATUS_REG &= ~SP_STATUS_SIG6; + } + if ((Value & SP_SET_SIG6) != 0 && (Value & SP_CLR_SIG6) == 0) + { + SP_STATUS_REG |= SP_STATUS_SIG6; + } + if ((Value & SP_CLR_SIG7) != 0 && (Value & SP_SET_SIG7) == 0) + { + SP_STATUS_REG &= ~SP_STATUS_SIG7; + } + if ((Value & SP_SET_SIG7) != 0 && (Value & SP_CLR_SIG7) == 0) + { + SP_STATUS_REG |= SP_STATUS_SIG7; + } + break; + default: + __debugbreak(); + } +} \ No newline at end of file diff --git a/Source/Project64-rsp-core/cpu/RSPRegisterHandler.h b/Source/Project64-rsp-core/cpu/RSPRegisterHandler.h new file mode 100644 index 000000000..ac85b22c8 --- /dev/null +++ b/Source/Project64-rsp-core/cpu/RSPRegisterHandler.h @@ -0,0 +1,49 @@ +#pragma once +#include + +enum RSPRegister +{ + RSPRegister_MEM_ADDR, + RSPRegister_DRAM_ADDR, + RSPRegister_RD_LEN, + RSPRegister_WR_LEN, + RSPRegister_STATUS, + RSPRegister_SEMAPHORE, + RSPRegister_PC, +}; + +struct _RSP_INFO; + +class RSPRegisterHandler +{ +public: + RSPRegisterHandler(uint32_t * SignalProcessorInterface, uint8_t *& Rdram, const uint32_t & RdramSize, uint8_t * IMEM, uint8_t * DMEM); + + void SP_DMA_READ(void); + void SP_DMA_WRITE(void); + + uint32_t ReadReg(RSPRegister Reg); + void WriteReg(RSPRegister Reg, uint32_t Value); + +protected: + virtual void ClearSPInterrupt(void) = 0; + virtual void SetSPInterrupt(void) = 0; + virtual void SetHalt(void) = 0; + + uint32_t & SP_MEM_ADDR_REG; + uint32_t & SP_DRAM_ADDR_REG; + uint32_t & SP_RD_LEN_REG; + uint32_t & SP_WR_LEN_REG; + uint32_t & SP_STATUS_REG; + uint32_t & SP_DMA_FULL_REG; + uint32_t & SP_DMA_BUSY_REG; + uint32_t & SP_SEMAPHORE_REG; + uint32_t & SP_PC_REG; + uint8_t *& m_Rdram; + const uint32_t & m_RdramSize; + uint8_t * m_IMEM; + uint8_t * m_DMEM; + uint32_t m_PendingSPMemAddr; + uint32_t m_PendingSPDramAddr; + bool m_ExecutedDMARead; +};