2008-11-25 02:00:42 +00:00
|
|
|
#include "Iop_SubSystem.h"
|
2008-12-24 01:39:03 +00:00
|
|
|
#include "../MemoryStateFile.h"
|
2008-11-25 02:00:42 +00:00
|
|
|
#include "../Ps2Const.h"
|
|
|
|
#include "../Log.h"
|
2008-12-24 01:39:03 +00:00
|
|
|
#include "placeholder_def.h"
|
2008-11-25 02:00:42 +00:00
|
|
|
|
|
|
|
using namespace Iop;
|
|
|
|
using namespace std::tr1;
|
|
|
|
using namespace PS2;
|
|
|
|
|
|
|
|
#define LOG_NAME ("iop_subsystem")
|
|
|
|
|
2008-12-24 01:39:03 +00:00
|
|
|
#define STATE_CPU ("iop_cpu")
|
|
|
|
#define STATE_RAM ("iop_ram")
|
|
|
|
#define STATE_SCRATCH ("iop_scratch")
|
|
|
|
|
2011-06-06 00:18:33 +00:00
|
|
|
CSubSystem::CSubSystem()
|
|
|
|
: m_cpu(MEMORYMAP_ENDIAN_LSBF, 0, 0x1FFFFFFF)
|
|
|
|
, m_executor(m_cpu)
|
|
|
|
, m_ram(new uint8[IOP_RAM_SIZE])
|
|
|
|
, m_scratchPad(new uint8[IOP_SCRATCH_SIZE])
|
|
|
|
, m_spuRam(new uint8[SPU_RAM_SIZE])
|
|
|
|
, m_dmac(m_ram, m_intc)
|
|
|
|
, m_counters(IOP_CLOCK_FREQ, m_intc)
|
|
|
|
, m_spuCore0(m_spuRam, SPU_RAM_SIZE)
|
|
|
|
, m_spuCore1(m_spuRam, SPU_RAM_SIZE)
|
|
|
|
, m_spu(m_spuCore0)
|
|
|
|
, m_spu2(m_spuCore0, m_spuCore1)
|
|
|
|
, m_cpuArch(MIPS_REGSIZE_32)
|
|
|
|
, m_copScu(MIPS_REGSIZE_32)
|
2008-11-25 02:00:42 +00:00
|
|
|
{
|
|
|
|
//Read memory map
|
2008-12-08 03:43:30 +00:00
|
|
|
m_cpu.m_pMemoryMap->InsertReadMap((0 * IOP_RAM_SIZE), (0 * IOP_RAM_SIZE) + IOP_RAM_SIZE - 1, m_ram, 0x01);
|
|
|
|
m_cpu.m_pMemoryMap->InsertReadMap((1 * IOP_RAM_SIZE), (1 * IOP_RAM_SIZE) + IOP_RAM_SIZE - 1, m_ram, 0x02);
|
|
|
|
m_cpu.m_pMemoryMap->InsertReadMap((2 * IOP_RAM_SIZE), (2 * IOP_RAM_SIZE) + IOP_RAM_SIZE - 1, m_ram, 0x03);
|
|
|
|
m_cpu.m_pMemoryMap->InsertReadMap((3 * IOP_RAM_SIZE), (3 * IOP_RAM_SIZE) + IOP_RAM_SIZE - 1, m_ram, 0x04);
|
|
|
|
m_cpu.m_pMemoryMap->InsertReadMap(0x1F800000, 0x1F8003FF, m_scratchPad, 0x05);
|
2008-12-24 01:39:03 +00:00
|
|
|
m_cpu.m_pMemoryMap->InsertReadMap(HW_REG_BEGIN, HW_REG_END, bind(&CSubSystem::ReadIoRegister, this, PLACEHOLDER_1), 0x06);
|
2008-11-25 02:00:42 +00:00
|
|
|
|
|
|
|
//Write memory map
|
2008-12-08 03:43:30 +00:00
|
|
|
m_cpu.m_pMemoryMap->InsertWriteMap((0 * IOP_RAM_SIZE), (0 * IOP_RAM_SIZE) + IOP_RAM_SIZE - 1, m_ram, 0x01);
|
|
|
|
m_cpu.m_pMemoryMap->InsertWriteMap((1 * IOP_RAM_SIZE), (1 * IOP_RAM_SIZE) + IOP_RAM_SIZE - 1, m_ram, 0x02);
|
|
|
|
m_cpu.m_pMemoryMap->InsertWriteMap((2 * IOP_RAM_SIZE), (2 * IOP_RAM_SIZE) + IOP_RAM_SIZE - 1, m_ram, 0x03);
|
|
|
|
m_cpu.m_pMemoryMap->InsertWriteMap((3 * IOP_RAM_SIZE), (3 * IOP_RAM_SIZE) + IOP_RAM_SIZE - 1, m_ram, 0x04);
|
|
|
|
m_cpu.m_pMemoryMap->InsertWriteMap(0x1F800000, 0x1F8003FF, m_scratchPad, 0x05);
|
2008-12-24 01:39:03 +00:00
|
|
|
m_cpu.m_pMemoryMap->InsertWriteMap(HW_REG_BEGIN, HW_REG_END, bind(&CSubSystem::WriteIoRegister, this, PLACEHOLDER_1, PLACEHOLDER_2), 0x06);
|
2008-11-25 02:00:42 +00:00
|
|
|
|
|
|
|
//Instruction memory map
|
|
|
|
m_cpu.m_pMemoryMap->InsertInstructionMap((0 * IOP_RAM_SIZE), (0 * IOP_RAM_SIZE) + IOP_RAM_SIZE - 1, m_ram, 0x01);
|
|
|
|
m_cpu.m_pMemoryMap->InsertInstructionMap((1 * IOP_RAM_SIZE), (1 * IOP_RAM_SIZE) + IOP_RAM_SIZE - 1, m_ram, 0x02);
|
|
|
|
m_cpu.m_pMemoryMap->InsertInstructionMap((2 * IOP_RAM_SIZE), (2 * IOP_RAM_SIZE) + IOP_RAM_SIZE - 1, m_ram, 0x03);
|
|
|
|
m_cpu.m_pMemoryMap->InsertInstructionMap((3 * IOP_RAM_SIZE), (3 * IOP_RAM_SIZE) + IOP_RAM_SIZE - 1, m_ram, 0x04);
|
|
|
|
|
2009-03-30 04:57:52 +00:00
|
|
|
m_cpu.m_pArch = &m_cpuArch;
|
2011-06-06 00:18:33 +00:00
|
|
|
m_cpu.m_pCOP[0] = &m_copScu;
|
2008-11-25 02:00:42 +00:00
|
|
|
m_cpu.m_pAddrTranslator = &CMIPS::TranslateAddress64;
|
|
|
|
|
2008-12-24 01:39:03 +00:00
|
|
|
m_dmac.SetReceiveFunction(4, bind(&CSpuBase::ReceiveDma, &m_spuCore0, PLACEHOLDER_1, PLACEHOLDER_2, PLACEHOLDER_3));
|
|
|
|
m_dmac.SetReceiveFunction(8, bind(&CSpuBase::ReceiveDma, &m_spuCore1, PLACEHOLDER_1, PLACEHOLDER_2, PLACEHOLDER_3));
|
2008-11-25 02:00:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CSubSystem::~CSubSystem()
|
|
|
|
{
|
2009-12-08 03:47:34 +00:00
|
|
|
delete [] m_ram;
|
|
|
|
delete [] m_scratchPad;
|
|
|
|
delete [] m_spuRam;
|
2008-11-25 02:00:42 +00:00
|
|
|
}
|
|
|
|
|
2009-03-30 04:57:52 +00:00
|
|
|
void CSubSystem::SetBios(const BiosPtr& bios)
|
2008-11-25 02:00:42 +00:00
|
|
|
{
|
|
|
|
m_bios = bios;
|
|
|
|
}
|
|
|
|
|
2011-05-05 04:28:11 +00:00
|
|
|
void CSubSystem::NotifyVBlankStart()
|
|
|
|
{
|
|
|
|
m_bios->NotifyVBlankStart();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSubSystem::NotifyVBlankEnd()
|
|
|
|
{
|
|
|
|
m_bios->NotifyVBlankEnd();
|
|
|
|
}
|
|
|
|
|
2009-07-31 02:51:31 +00:00
|
|
|
void CSubSystem::SaveState(Framework::CZipArchiveWriter& archive)
|
2008-12-24 01:39:03 +00:00
|
|
|
{
|
|
|
|
archive.InsertFile(new CMemoryStateFile(STATE_CPU, &m_cpu.m_State, sizeof(MIPSSTATE)));
|
|
|
|
archive.InsertFile(new CMemoryStateFile(STATE_RAM, m_ram, IOP_RAM_SIZE));
|
|
|
|
archive.InsertFile(new CMemoryStateFile(STATE_SCRATCH, m_scratchPad, IOP_SCRATCH_SIZE));
|
2009-01-26 02:53:10 +00:00
|
|
|
m_bios->SaveState(archive);
|
2008-12-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
2009-07-31 02:51:31 +00:00
|
|
|
void CSubSystem::LoadState(Framework::CZipArchiveReader& archive)
|
2008-12-24 01:39:03 +00:00
|
|
|
{
|
|
|
|
archive.BeginReadFile(STATE_CPU )->Read(&m_cpu.m_State, sizeof(MIPSSTATE));
|
|
|
|
archive.BeginReadFile(STATE_RAM )->Read(m_ram, IOP_RAM_SIZE);
|
|
|
|
archive.BeginReadFile(STATE_SCRATCH )->Read(m_scratchPad, IOP_SCRATCH_SIZE);
|
2009-01-26 02:53:10 +00:00
|
|
|
m_bios->LoadState(archive);
|
2008-12-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
2008-11-25 02:00:42 +00:00
|
|
|
void CSubSystem::Reset()
|
|
|
|
{
|
|
|
|
memset(m_ram, 0, IOP_RAM_SIZE);
|
|
|
|
memset(m_scratchPad, 0, IOP_SCRATCH_SIZE);
|
|
|
|
memset(m_spuRam, 0, SPU_RAM_SIZE);
|
2010-11-17 03:59:29 +00:00
|
|
|
m_executor.Reset();
|
2008-11-25 02:00:42 +00:00
|
|
|
m_cpu.Reset();
|
|
|
|
m_spuCore0.Reset();
|
|
|
|
m_spuCore1.Reset();
|
|
|
|
m_spu.Reset();
|
|
|
|
m_spu2.Reset();
|
|
|
|
m_counters.Reset();
|
|
|
|
m_dmac.Reset();
|
|
|
|
m_intc.Reset();
|
2009-03-30 04:57:52 +00:00
|
|
|
m_bios.reset();
|
2008-11-28 02:56:27 +00:00
|
|
|
|
|
|
|
m_cpu.m_Comments.RemoveTags();
|
|
|
|
m_cpu.m_Functions.RemoveTags();
|
2008-11-25 02:00:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CSubSystem::ReadIoRegister(uint32 address)
|
|
|
|
{
|
|
|
|
if(address == 0x1F801814)
|
|
|
|
{
|
|
|
|
return 0x14802000;
|
|
|
|
}
|
|
|
|
else if(address >= CSpu::SPU_BEGIN && address <= CSpu::SPU_END)
|
|
|
|
{
|
|
|
|
return m_spu.ReadRegister(address);
|
|
|
|
}
|
|
|
|
else if(address >= CDmac::DMAC_ZONE1_START && address <= CDmac::DMAC_ZONE1_END)
|
|
|
|
{
|
|
|
|
return m_dmac.ReadRegister(address);
|
|
|
|
}
|
|
|
|
else if(address >= CDmac::DMAC_ZONE2_START && address <= CDmac::DMAC_ZONE2_END)
|
|
|
|
{
|
|
|
|
return m_dmac.ReadRegister(address);
|
|
|
|
}
|
|
|
|
else if(address >= CIntc::ADDR_BEGIN && address <= CIntc::ADDR_END)
|
|
|
|
{
|
|
|
|
return m_intc.ReadRegister(address);
|
|
|
|
}
|
|
|
|
else if(address >= CRootCounters::ADDR_BEGIN && address <= CRootCounters::ADDR_END)
|
|
|
|
{
|
|
|
|
return m_counters.ReadRegister(address);
|
|
|
|
}
|
|
|
|
else if(address >= CSpu2::REGS_BEGIN && address <= CSpu2::REGS_END)
|
|
|
|
{
|
|
|
|
return m_spu2.ReadRegister(address);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Reading an unknown hardware register (0x%0.8X).\r\n", address);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CSubSystem::WriteIoRegister(uint32 address, uint32 value)
|
|
|
|
{
|
|
|
|
if(address >= CDmac::DMAC_ZONE1_START && address <= CDmac::DMAC_ZONE1_END)
|
|
|
|
{
|
|
|
|
m_dmac.WriteRegister(address, value);
|
|
|
|
}
|
|
|
|
else if(address >= CSpu::SPU_BEGIN && address <= CSpu::SPU_END)
|
|
|
|
{
|
|
|
|
m_spu.WriteRegister(address, static_cast<uint16>(value));
|
|
|
|
}
|
|
|
|
else if(address >= CDmac::DMAC_ZONE2_START && address <= CDmac::DMAC_ZONE2_END)
|
|
|
|
{
|
|
|
|
m_dmac.WriteRegister(address, value);
|
|
|
|
}
|
|
|
|
else if(address >= CIntc::ADDR_BEGIN && address <= CIntc::ADDR_END)
|
|
|
|
{
|
|
|
|
m_intc.WriteRegister(address, value);
|
|
|
|
}
|
|
|
|
else if(address >= CRootCounters::ADDR_BEGIN && address <= CRootCounters::ADDR_END)
|
|
|
|
{
|
|
|
|
m_counters.WriteRegister(address, value);
|
|
|
|
}
|
|
|
|
else if(address >= CSpu2::REGS_BEGIN && address <= CSpu2::REGS_END)
|
|
|
|
{
|
|
|
|
return m_spu2.WriteRegister(address, value);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Writing to an unknown hardware register (0x%0.8X, 0x%0.8X).\r\n", address, value);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int CSubSystem::ExecuteCpu(bool singleStep)
|
|
|
|
{
|
|
|
|
int ticks = 0;
|
|
|
|
if(!m_cpu.m_State.nHasException)
|
|
|
|
{
|
|
|
|
if(m_intc.HasPendingInterrupt())
|
|
|
|
{
|
|
|
|
m_bios->HandleInterrupt();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!m_cpu.m_State.nHasException)
|
|
|
|
{
|
2010-03-30 04:19:45 +00:00
|
|
|
bool isIdle = false;
|
2008-11-25 02:00:42 +00:00
|
|
|
int quota = singleStep ? 1 : 500;
|
2010-03-30 04:19:45 +00:00
|
|
|
|
2008-11-25 02:00:42 +00:00
|
|
|
{
|
2009-01-26 02:53:10 +00:00
|
|
|
if(m_bios->IsIdle())
|
2008-11-25 02:00:42 +00:00
|
|
|
{
|
2010-03-30 04:19:45 +00:00
|
|
|
isIdle = true;
|
2008-11-25 02:00:42 +00:00
|
|
|
ticks += (quota * 2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-11-17 03:59:29 +00:00
|
|
|
BasicBlockPtr nextBlock = m_executor.FindBlockAt(m_cpu.m_State.nPC);
|
|
|
|
if(nextBlock && nextBlock->GetSelfLoopCount() > 5000)
|
2008-11-25 02:00:42 +00:00
|
|
|
{
|
|
|
|
//Go a little bit faster if we're "stuck"
|
2010-03-30 04:19:45 +00:00
|
|
|
isIdle = true;
|
2008-11-25 02:00:42 +00:00
|
|
|
ticks += (quota * 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-03-30 04:19:45 +00:00
|
|
|
|
2010-08-11 03:47:19 +00:00
|
|
|
if(isIdle && !singleStep)
|
2010-03-30 04:19:45 +00:00
|
|
|
{
|
|
|
|
quota /= 50;
|
|
|
|
}
|
|
|
|
|
|
|
|
ticks += (quota - m_executor.Execute(quota));
|
|
|
|
assert(ticks >= 0);
|
|
|
|
|
2008-11-25 02:00:42 +00:00
|
|
|
if(ticks > 0)
|
|
|
|
{
|
|
|
|
m_counters.Update(ticks);
|
|
|
|
m_bios->CountTicks(ticks);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(m_cpu.m_State.nHasException)
|
|
|
|
{
|
|
|
|
m_bios->HandleException();
|
|
|
|
}
|
|
|
|
return ticks;
|
|
|
|
}
|