git-svn-id: http://svn.purei.org/purei/trunk@391 b36208d7-6611-0410-8bec-b1987f11c4a2

This commit is contained in:
jpd002 2008-10-27 03:17:22 +00:00
parent 7038810345
commit 1d1298fef1
11 changed files with 445 additions and 13 deletions

View File

@ -202,6 +202,10 @@
RelativePath=".\Source\AppDef.h"
>
</File>
<File
RelativePath=".\Source\BasicUnions.h"
>
</File>
<File
RelativePath=".\Source\CounterRegView.cpp"
>
@ -297,6 +301,14 @@
RelativePath=".\Source\ps2\Iop_Dmac.h"
>
</File>
<File
RelativePath=".\Source\ps2\Iop_DmacChannel.cpp"
>
</File>
<File
RelativePath=".\Source\ps2\Iop_DmacChannel.h"
>
</File>
<File
RelativePath=".\Source\ps2\PsfDevice.cpp"
>
@ -321,6 +333,14 @@
RelativePath=".\Source\ps2\Spu2.h"
>
</File>
<File
RelativePath=".\Source\ps2\Spu2_Channel.cpp"
>
</File>
<File
RelativePath=".\Source\ps2\Spu2_Channel.h"
>
</File>
<File
RelativePath=".\Source\ps2\Spu2_Core.cpp"
>

View File

@ -1,13 +1,185 @@
#include <assert.h>
#include "Iop_Dmac.h"
#include "Log.h"
#define LOG_NAME ("iop_dmac")
using namespace Iop;
using namespace Iop::Dmac;
CDmac::CDmac()
CDmac::CDmac(uint8* ram) :
m_ram(ram),
m_channelSpu(CH4_BASE, 4, *this)
{
memset(m_channel, 0, sizeof(m_channel));
m_channel[4] = &m_channelSpu;
Reset();
}
CDmac::~CDmac()
{
}
void CDmac::Reset()
{
m_DPCR = 0;
m_DICR = 0;
for(unsigned int i = 0; i < MAX_CHANNEL; i++)
{
CChannel* channel(m_channel[i]);
if(!channel) continue;
channel->Reset();
}
}
void CDmac::SetReceiveFunction(unsigned int channelId, const CChannel::ReceiveFunctionType& handler)
{
assert(channelId < MAX_CHANNEL);
if(channelId >= MAX_CHANNEL) return;
CChannel* channel(m_channel[channelId]);
if(channel)
{
channel->SetReceiveFunction(handler);
}
}
CChannel* CDmac::GetChannelFromAddress(uint32 address)
{
unsigned int channelId = (address - DMAC_ZONE1_START) / 0x10;
assert(channelId < MAX_CHANNEL);
if(channelId >= MAX_CHANNEL) return NULL;
return m_channel[channelId];
}
void CDmac::AssertLine(unsigned int line)
{
m_DICR |= 1 << (line + 24);
//m_intc.AssertLine(CIntc::LINE_DMAC);
}
uint8* CDmac::GetRam()
{
return m_ram;
}
uint32 CDmac::ReadRegister(uint32 address)
{
#ifdef _DEBUG
LogRead(address);
#endif
switch(address)
{
case DPCR:
return m_DPCR;
break;
case DICR:
return m_DICR;
break;
default:
{
CChannel* channel(GetChannelFromAddress(address));
if(channel)
{
return channel->ReadRegister(address);
}
}
}
return 0;
}
uint32 CDmac::WriteRegister(uint32 address, uint32 value)
{
#ifdef _DEBUG
LogWrite(address, value);
#endif
switch(address)
{
case DPCR:
m_DPCR = value;
break;
case DICR:
m_DICR &= 0xFF000000;
m_DICR |= value;
m_DICR &= ~(value & 0xFF000000);
break;
default:
{
CChannel* channel(GetChannelFromAddress(address));
if(channel)
{
channel->WriteRegister(address, value);
}
}
break;
}
return 0;
}
void CDmac::LogRead(uint32 address)
{
switch(address)
{
case DPCR:
CLog::GetInstance().Print(LOG_NAME, "= DPCR.\r\n");
break;
case DICR:
CLog::GetInstance().Print(LOG_NAME, "= DICR.\r\n");
break;
default:
{
unsigned int channelId = (address - DMAC_ZONE1_START) / 0x10;
unsigned int registerId = address & 0xF;
switch(registerId)
{
case CChannel::REG_CHCR:
CLog::GetInstance().Print(LOG_NAME, "ch%0.2d: = CHCR.\r\n", channelId);
break;
default:
CLog::GetInstance().Print(LOG_NAME, "Read an unknown register 0x%0.8X.\r\n",
address);
break;
}
}
break;
}
}
void CDmac::LogWrite(uint32 address, uint32 value)
{
switch(address)
{
case DPCR:
CLog::GetInstance().Print(LOG_NAME, "DPCR = 0x%0.8X.\r\n", value);
break;
case DICR:
CLog::GetInstance().Print(LOG_NAME, "DICR = 0x%0.8X.\r\n", value);
break;
default:
{
unsigned int channelId = (address - DMAC_ZONE1_START) / 0x10;
unsigned int registerId = address & 0xF;
switch(registerId)
{
case CChannel::REG_MADR:
CLog::GetInstance().Print(LOG_NAME, "ch%0.2d: MADR = 0x%0.8X.\r\n", channelId, value);
break;
case CChannel::REG_BCR:
CLog::GetInstance().Print(LOG_NAME, "ch%0.2d: BCR = 0x%0.8X.\r\n", channelId, value);
break;
case CChannel::REG_BCR + 2:
CLog::GetInstance().Print(LOG_NAME, "ch%0.2d: BCR.ba = 0x%0.8X.\r\n", channelId, value);
break;
case CChannel::REG_CHCR:
CLog::GetInstance().Print(LOG_NAME, "ch%0.2d: CHCR = 0x%0.8X.\r\n", channelId, value);
break;
default:
CLog::GetInstance().Print(LOG_NAME, "Wrote 0x%0.8X to unknown register 0x%0.8X.\r\n",
value, address);
break;
}
}
break;
}
}

View File

@ -1,13 +1,29 @@
#ifndef _IOP_DMAC_H_
#define _IOP_DMAC_H_
#include "Types.h"
#include "Iop_DmacChannel.h"
namespace Iop
{
class CDmac
{
public:
CDmac();
virtual ~CDmac();
enum
{
MAX_CHANNEL = 7,
};
enum
{
CH0_BASE = 0x1F801080,
CH1_BASE = 0x1F801090,
CH2_BASE = 0x1F8010A0,
CH3_BASE = 0x1F8010B0,
CH4_BASE = 0x1F8010C0,
CH5_BASE = 0x1F8010D0,
CH6_BASE = 0x1F8010E0
};
enum DMAC_ZONE1
{
@ -15,8 +31,34 @@ namespace Iop
DMAC_ZONE1_END = 0x1F8010FF,
};
private:
CDmac(uint8*);
virtual ~CDmac();
void Reset();
void SetReceiveFunction(unsigned int, const Dmac::CChannel::ReceiveFunctionType&);
uint32 ReadRegister(uint32);
uint32 WriteRegister(uint32, uint32);
void AssertLine(unsigned int);
uint8* GetRam();
enum
{
DPCR = 0x1F8010F0,
DICR = 0x1F8010F4
};
private:
Dmac::CChannel* GetChannelFromAddress(uint32);
void LogRead(uint32);
void LogWrite(uint32, uint32);
Dmac::CChannel m_channelSpu;
Dmac::CChannel* m_channel[MAX_CHANNEL];
uint32 m_DPCR;
uint32 m_DICR;
uint8* m_ram;
};
}

View File

@ -0,0 +1,91 @@
#include <assert.h>
#include "Iop_DmacChannel.h"
#include "Iop_Dmac.h"
using namespace Iop;
using namespace Iop::Dmac;
CChannel::CChannel(uint32 baseAddress, unsigned int number, CDmac& dmac) :
m_dmac(dmac),
m_number(number),
m_baseAddress(baseAddress)
{
Reset();
}
CChannel::~CChannel()
{
}
void CChannel::Reset()
{
m_CHCR <<= 0;
m_BCR <<= 0;
m_MADR = 0;
}
void CChannel::SetReceiveFunction(const ReceiveFunctionType& receiveFunction)
{
m_receiveFunction = receiveFunction;
}
void CChannel::ResumeDma()
{
if(m_CHCR.tr == 0) return;
assert(m_CHCR.co == 1 && m_CHCR.dr == 1);
assert(m_receiveFunction);
uint32 address = m_MADR & 0x1FFFFFFF;
uint32 blocksTransfered = m_receiveFunction(m_dmac.GetRam() + address, m_BCR.bs * 4, m_BCR.ba);
assert(blocksTransfered <= m_BCR.ba);
m_BCR.ba -= blocksTransfered;
if(m_BCR.ba == 0)
{
//Trigger interrupt
m_CHCR.tr = 0;
m_dmac.AssertLine(m_number);
}
}
uint32 CChannel::ReadRegister(uint32 address)
{
switch(address - m_baseAddress)
{
case REG_MADR:
return m_MADR;
break;
case REG_BCR:
return m_BCR;
break;
case REG_CHCR:
return m_CHCR;
break;
}
return 0;
}
void CChannel::WriteRegister(uint32 address, uint32 value)
{
assert(m_CHCR.tr == 0);
switch(address - m_baseAddress)
{
case REG_MADR:
m_MADR = value;
break;
case REG_BCR:
m_BCR <<= value;
break;
case REG_BCR + 2:
//Not really cool...
m_BCR.ba = static_cast<uint16>(value);
break;
case REG_CHCR:
m_CHCR <<= value;
if(m_CHCR.tr)
{
ResumeDma();
}
break;
}
}

View File

@ -0,0 +1,67 @@
#ifndef _IOP_DMACCHANNEL_H_
#define _IOP_DMACCHANNEL_H_
#include "convertible.h"
#include "Types.h"
#include <boost/static_assert.hpp>
#include <functional>
namespace Iop
{
class CDmac;
namespace Dmac
{
class CChannel
{
public:
typedef std::tr1::function<uint32 (uint8*, uint32, uint32)> ReceiveFunctionType;
enum
{
REG_MADR = 0x00,
REG_BCR = 0x04,
REG_CHCR = 0x08
};
struct BCR : public convertible<uint32>
{
unsigned int bs : 16;
unsigned int ba : 16;
};
BOOST_STATIC_ASSERT(sizeof(BCR) == sizeof(uint32));
struct CHCR : public convertible<uint32>
{
unsigned int dr : 1;
unsigned int unused0 : 8;
unsigned int co : 1;
unsigned int li : 1;
unsigned int unused1 : 13;
unsigned int tr : 1;
unsigned int unused2 : 7;
};
BOOST_STATIC_ASSERT(sizeof(CHCR) == sizeof(uint32));
CChannel(uint32, unsigned int, CDmac&);
virtual ~CChannel();
void Reset();
void SetReceiveFunction(const ReceiveFunctionType&);
void ResumeDma();
uint32 ReadRegister(uint32);
void WriteRegister(uint32, uint32);
private:
ReceiveFunctionType m_receiveFunction;
unsigned int m_number;
uint32 m_baseAddress;
uint32 m_MADR;
BCR m_BCR;
CHCR m_CHCR;
CDmac& m_dmac;
};
}
}
#endif

View File

@ -7,12 +7,14 @@ using namespace std;
using namespace std::tr1;
using namespace std::tr1::placeholders;
using namespace boost;
using namespace Iop;
#define PSF_DEVICENAME "psf"
CPsfVm::CPsfVm() :
m_ram(new uint8[IOPRAMSIZE]),
m_cpu(MEMORYMAP_ENDIAN_LSBF, 0x00000000, IOPRAMSIZE),
m_dmac(m_ram),
m_executor(m_cpu),
m_status(PAUSED),
m_singleStep(false),
@ -23,12 +25,14 @@ m_thread(bind(&CPsfVm::ThreadProc, this))
//IOP context setup
{
//Read map
m_cpu.m_pMemoryMap->InsertReadMap(0x00000000, IOPRAMSIZE - 1, m_ram, 0x00);
m_cpu.m_pMemoryMap->InsertReadMap(CSpu2::REGS_BEGIN, CSpu2::REGS_END, bind(&CSpu2::ReadRegister, &m_spu, _1), 0x01);
m_cpu.m_pMemoryMap->InsertReadMap(0x00000000, IOPRAMSIZE - 1, m_ram, 0x00);
m_cpu.m_pMemoryMap->InsertReadMap(CDmac::DMAC_ZONE1_START, CDmac::DMAC_ZONE1_END, bind(&CDmac::ReadRegister, &m_dmac, _1), 0x01);
m_cpu.m_pMemoryMap->InsertReadMap(CSpu2::REGS_BEGIN, CSpu2::REGS_END, bind(&CSpu2::ReadRegister, &m_spu, _1), 0x02);
//Write map
m_cpu.m_pMemoryMap->InsertWriteMap(0x00000000, IOPRAMSIZE - 1, m_ram, 0x00);
m_cpu.m_pMemoryMap->InsertWriteMap(CSpu2::REGS_BEGIN, CSpu2::REGS_END, bind(&CSpu2::WriteRegister, &m_spu, _1, _2), 0x01);
m_cpu.m_pMemoryMap->InsertWriteMap(0x00000000, IOPRAMSIZE - 1, m_ram, 0x00);
m_cpu.m_pMemoryMap->InsertWriteMap(CDmac::DMAC_ZONE1_START, CDmac::DMAC_ZONE1_END, bind(&CDmac::WriteRegister, &m_dmac, _1, _2), 0x01);
m_cpu.m_pMemoryMap->InsertWriteMap(CSpu2::REGS_BEGIN, CSpu2::REGS_END, bind(&CSpu2::WriteRegister, &m_spu, _1, _2), 0x02);
//Instruction map
m_cpu.m_pMemoryMap->InsertInstructionMap(0x00000000, IOPRAMSIZE - 1, m_ram, 0x00);
@ -37,6 +41,8 @@ m_thread(bind(&CPsfVm::ThreadProc, this))
m_cpu.m_pAddrTranslator = &CMIPS::TranslateAddress64;
}
m_dmac.SetReceiveFunction(4, bind(&Spu2::CCore::ReceiveDma, m_spu.GetCore(0), _1, _2, _3));
}
CPsfVm::~CPsfVm()
@ -65,6 +71,7 @@ void CPsfVm::Reset()
{
memset(m_ram, 0, IOPRAMSIZE);
m_bios.Reset();
m_dmac.Reset();
}
CVirtualMachine::STATUS CPsfVm::GetStatus() const

View File

@ -39,11 +39,11 @@ namespace PS2
unsigned int ExecuteCpu(bool);
void ThreadProc();
CSpu2 m_spu;
uint8* m_ram;
CSpu2 m_spu;
Iop::CDmac m_dmac;
Iop::CIntc m_intc;
CMipsExecutor m_executor;
uint8* m_ram;
CMIPS m_cpu;
CIopBios m_bios;
CMailBox m_mailBox;

View File

@ -1,3 +1,4 @@
#include <assert.h>
#include "Spu2.h"
#include "Log.h"
@ -218,6 +219,13 @@ CSpu2::~CSpu2()
}
CCore* CSpu2::GetCore(unsigned int coreId)
{
assert(coreId < CORE_NUM);
if(coreId >= CORE_NUM) return NULL;
return m_core[coreId];
}
uint32 CSpu2::ReadRegister(uint32 address)
{
return ProcessRegisterAccess(m_readDispatchInfo, address, 0);

View File

@ -16,6 +16,8 @@ namespace PS2
uint32 ReadRegister(uint32);
uint32 WriteRegister(uint32, uint32);
Spu2::CCore* GetCore(unsigned int);
enum
{
REGS_BEGIN = 0x1F900000,

View File

@ -1,4 +1,5 @@
#include <boost/lexical_cast.hpp>
#include <assert.h>
#include "Spu2_Core.h"
#include "Log.h"
@ -11,7 +12,8 @@ using namespace Framework;
using namespace boost;
CCore::CCore(unsigned int coreId) :
m_coreId(coreId)
m_coreId(coreId),
m_ram(new uint8[RAMSIZE])
{
m_logName = LOG_NAME_PREFIX + lexical_cast<string>(m_coreId);
@ -26,11 +28,12 @@ m_coreId(coreId)
CCore::~CCore()
{
delete [] m_ram;
}
void CCore::Reset()
{
memset(m_ram, 0, RAMSIZE);
m_transferAddress.w = 0;
}
@ -44,6 +47,11 @@ uint32 CCore::WriteRegister(uint32 address, uint32 value)
return ProcessRegisterAccess(m_writeDispatch, address, value);
}
uint32 CCore::ReceiveDma(uint8* buffer, uint32 blockSize, uint32 blockAmount)
{
return blockAmount;
}
uint32 CCore::ProcessRegisterAccess(const REGISTER_DISPATCH_INFO& dispatchInfo, uint32 address, uint32 value)
{
if(address < S_REG_BASE)
@ -86,6 +94,14 @@ uint32 CCore::WriteRegisterCore(unsigned int channelId, uint32 address, uint32 v
{
switch(address)
{
case A_STD:
{
uint32 address = m_transferAddress.w << 1;
address &= RAMSIZE - 1;
*reinterpret_cast<uint16*>(m_ram + address) = static_cast<uint16>(value);
m_transferAddress.w++;
}
break;
case A_TSA_HI:
m_transferAddress.h1 = static_cast<uint16>(value);
break;

View File

@ -22,6 +22,7 @@ namespace PS2
uint32 ReadRegister(uint32, uint32);
uint32 WriteRegister(uint32, uint32);
uint32 ReceiveDma(uint8*, uint32, uint32);
enum REGISTERS
{
@ -54,6 +55,11 @@ namespace PS2
MAX_CHANNEL = 24,
};
enum
{
RAMSIZE = 0x80000
};
struct REGISTER_DISPATCH_INFO
{
RegisterAccessFunction core;
@ -75,6 +81,7 @@ namespace PS2
REGISTER_DISPATCH_INFO m_readDispatch;
REGISTER_DISPATCH_INFO m_writeDispatch;
uint8* m_ram;
CChannel m_channel[MAX_CHANNEL];
unsigned int m_coreId;
UNION32_16 m_transferAddress;