2008-10-27 03:17:22 +00:00
|
|
|
#include <assert.h>
|
2015-02-10 01:42:50 -05:00
|
|
|
#include "make_unique.h"
|
2008-11-07 23:50:47 +00:00
|
|
|
#include "Iop_Spu2.h"
|
2025-03-11 12:48:26 -04:00
|
|
|
#include "Log.h"
|
2008-12-24 01:39:03 +00:00
|
|
|
#include "placeholder_def.h"
|
2008-10-21 22:33:11 +00:00
|
|
|
|
2008-11-07 23:50:47 +00:00
|
|
|
#define LOG_NAME ("iop_spu2")
|
2008-10-21 22:33:11 +00:00
|
|
|
|
2008-11-06 23:48:40 +00:00
|
|
|
using namespace Iop;
|
|
|
|
using namespace Iop::Spu2;
|
2008-10-21 22:33:11 +00:00
|
|
|
|
2008-11-06 23:48:40 +00:00
|
|
|
CSpu2::CSpu2(CSpuBase& spuBase0, CSpuBase& spuBase1)
|
2008-10-21 22:33:11 +00:00
|
|
|
{
|
2008-10-24 22:14:40 +00:00
|
|
|
for(unsigned int i = 0; i < CORE_NUM; i++)
|
|
|
|
{
|
2008-11-06 23:48:40 +00:00
|
|
|
CSpuBase& base(i == 0 ? spuBase0 : spuBase1);
|
2015-02-08 17:18:41 -05:00
|
|
|
m_core[i] = std::make_unique<CCore>(i, base);
|
2008-10-24 22:14:40 +00:00
|
|
|
}
|
2008-10-23 22:17:44 +00:00
|
|
|
|
2012-03-11 20:16:15 +00:00
|
|
|
m_readDispatchInfo.global = std::bind(&CSpu2::ReadRegisterImpl, this, std::placeholders::_1, std::placeholders::_2);
|
|
|
|
m_writeDispatchInfo.global = std::bind(&CSpu2::WriteRegisterImpl, this, std::placeholders::_1, std::placeholders::_2);
|
2008-10-23 22:17:44 +00:00
|
|
|
for(unsigned int i = 0; i < CORE_NUM; i++)
|
|
|
|
{
|
2015-02-08 17:18:41 -05:00
|
|
|
m_readDispatchInfo.core[i] = std::bind(&CCore::ReadRegister, m_core[i].get(), std::placeholders::_1, std::placeholders::_2);
|
|
|
|
m_writeDispatchInfo.core[i] = std::bind(&CCore::WriteRegister, m_core[i].get(), std::placeholders::_1, std::placeholders::_2);
|
2008-10-23 22:17:44 +00:00
|
|
|
}
|
2008-10-21 22:33:11 +00:00
|
|
|
}
|
|
|
|
|
2008-11-03 00:38:24 +00:00
|
|
|
void CSpu2::Reset()
|
|
|
|
{
|
|
|
|
for(unsigned int i = 0; i < CORE_NUM; i++)
|
|
|
|
{
|
|
|
|
m_core[i]->Reset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-27 03:17:22 +00:00
|
|
|
CCore* CSpu2::GetCore(unsigned int coreId)
|
|
|
|
{
|
2012-03-11 20:16:15 +00:00
|
|
|
assert(coreId < CORE_NUM);
|
2015-02-08 17:18:41 -05:00
|
|
|
if(coreId >= CORE_NUM) return nullptr;
|
|
|
|
return m_core[coreId].get();
|
2008-10-27 03:17:22 +00:00
|
|
|
}
|
|
|
|
|
2008-10-21 22:33:11 +00:00
|
|
|
uint32 CSpu2::ReadRegister(uint32 address)
|
2008-10-23 22:17:44 +00:00
|
|
|
{
|
|
|
|
return ProcessRegisterAccess(m_readDispatchInfo, address, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CSpu2::WriteRegister(uint32 address, uint32 value)
|
|
|
|
{
|
|
|
|
return ProcessRegisterAccess(m_writeDispatchInfo, address, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CSpu2::ProcessRegisterAccess(const REGISTER_DISPATCH_INFO& dispatchInfo, uint32 address, uint32 value)
|
2008-10-21 22:33:11 +00:00
|
|
|
{
|
2012-03-11 20:16:15 +00:00
|
|
|
uint32 tmpAddress = address - REGS_BEGIN;
|
|
|
|
if(tmpAddress < 0x760)
|
|
|
|
{
|
2008-10-23 22:17:44 +00:00
|
|
|
unsigned int coreId = (tmpAddress & 0x400) ? 1 : 0;
|
|
|
|
address &= ~0x400;
|
|
|
|
return dispatchInfo.core[coreId](address, value);
|
2012-03-11 20:16:15 +00:00
|
|
|
}
|
2008-12-09 18:04:58 +00:00
|
|
|
else if(tmpAddress < 0x7B0)
|
|
|
|
{
|
|
|
|
unsigned int coreId = (tmpAddress - 0x760) / 40;
|
|
|
|
address -= coreId * 40;
|
|
|
|
return dispatchInfo.core[coreId](address, value);
|
|
|
|
}
|
2008-10-23 22:17:44 +00:00
|
|
|
return dispatchInfo.global(address, value);
|
2008-10-21 22:33:11 +00:00
|
|
|
}
|
|
|
|
|
2008-10-23 22:17:44 +00:00
|
|
|
uint32 CSpu2::ReadRegisterImpl(uint32 address, uint32 value)
|
2008-10-21 22:33:11 +00:00
|
|
|
{
|
2015-02-08 17:18:41 -05:00
|
|
|
uint32 result = 0;
|
|
|
|
switch(address)
|
|
|
|
{
|
|
|
|
case C_IRQINFO:
|
|
|
|
for(unsigned int i = 0; i < CORE_NUM; i++)
|
|
|
|
{
|
2015-10-17 00:12:42 -04:00
|
|
|
auto& core = m_core[i];
|
|
|
|
if(core->GetSpuBase().GetIrqPending())
|
2015-02-08 17:18:41 -05:00
|
|
|
{
|
|
|
|
result |= (1 << (i + 2));
|
2015-10-17 00:12:42 -04:00
|
|
|
core->GetSpuBase().ClearIrqPending();
|
2015-02-08 17:18:41 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2008-10-23 22:17:44 +00:00
|
|
|
LogRead(address);
|
2015-02-08 17:18:41 -05:00
|
|
|
return result;
|
2008-10-23 22:17:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CSpu2::WriteRegisterImpl(uint32 address, uint32 value)
|
|
|
|
{
|
|
|
|
LogWrite(address, value);
|
2008-10-21 22:33:11 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSpu2::LogRead(uint32 address)
|
|
|
|
{
|
|
|
|
switch(address)
|
|
|
|
{
|
2015-02-08 17:18:41 -05:00
|
|
|
case C_IRQINFO:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, " = C_IRQINFO\r\n");
|
|
|
|
break;
|
2008-10-21 22:33:11 +00:00
|
|
|
default:
|
2021-01-21 09:26:31 -05:00
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "Read an unknown register 0x%08X.\r\n", address);
|
2008-10-21 22:33:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSpu2::LogWrite(uint32 address, uint32 value)
|
|
|
|
{
|
|
|
|
switch(address)
|
|
|
|
{
|
|
|
|
default:
|
2021-01-21 09:26:31 -05:00
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "Wrote 0x%08X to unknown register 0x%08X.\r\n", value, address);
|
2008-10-21 22:33:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|