Core: Create a handler for RSP registers that is accessible to the core and the RSP

This commit is contained in:
zilmar 2023-09-28 07:03:01 +09:30
parent 03e13455f9
commit f817becf9c
11 changed files with 423 additions and 423 deletions

View File

@ -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;
}

View File

@ -4,6 +4,7 @@
#include <Project64-core\Logging.h>
#include <Project64-core\Settings\DebugSettings.h>
#include <Project64-core\Settings\GameSettings.h>
#include <Project64-rsp-core/cpu/RSPRegisterHandler.h>
#include <stdint.h>
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;

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -295,6 +295,9 @@
<Project>{3326e128-33af-422c-bb7c-67cc6b915610}</Project>
</ProjectReference>
<ProjectReference Include="..\Common\Common.vcxproj" />
<ProjectReference Include="..\Project64-rsp-core\Project64-rsp-core.vcxproj">
<Project>{7598f6b8-9da6-4897-b26f-f6865f824bf4}</Project>
</ProjectReference>
<ProjectReference Include="..\UpdateVersion\UpdateVersion.vcxproj">
<Project>{1968162c-0793-491d-91a1-81645a24d399}</Project>
</ProjectReference>

View File

@ -49,6 +49,7 @@
<ClCompile Include="cpu\RspLog.cpp" />
<ClCompile Include="cpu\RspMemory.cpp" />
<ClCompile Include="cpu\RSPRegister.cpp" />
<ClCompile Include="cpu\RSPRegisterHandler.cpp" />
<ClCompile Include="cpu\RspTypes.cpp" />
<ClCompile Include="Recompiler\Mmx.cpp" />
<ClCompile Include="Recompiler\RspProfiling.cpp" />
@ -72,6 +73,7 @@
<ClInclude Include="cpu\RspLog.h" />
<ClInclude Include="cpu\RspMemory.h" />
<ClInclude Include="cpu\RSPOpcode.h" />
<ClInclude Include="cpu\RSPRegisterHandler.h" />
<ClInclude Include="cpu\RSPRegisters.h" />
<ClInclude Include="cpu\RspTypes.h" />
<ClInclude Include="Recompiler\RspProfiling.h" />

View File

@ -96,6 +96,9 @@
<ClCompile Include="cpu\RspClamp.cpp">
<Filter>Source Files\cpu</Filter>
</ClCompile>
<ClCompile Include="cpu\RSPRegisterHandler.cpp">
<Filter>Source Files\cpu</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="cpu\RSPInstruction.h">
@ -155,5 +158,8 @@
<ClInclude Include="cpu\RspClamp.h">
<Filter>Header Files\cpu</Filter>
</ClInclude>
<ClInclude Include="cpu\RSPRegisterHandler.h">
<Filter>Header Files\cpu</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -8,7 +8,7 @@
#include <map>
#include <vector>
class CProfiling
class CRspProfiling
{
typedef std::map<uint32_t, __int64> 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;
}

View File

@ -0,0 +1,324 @@
#include "RSPRegisterHandler.h"
#include "RSPRegisters.h"
#include <Project64-plugin-spec/Rsp.h>
#include <Settings/Settings.h>
#include <string.h>
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();
}
}

View File

@ -0,0 +1,49 @@
#pragma once
#include <stdint.h>
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;
};