Improved RAW SPU

Fixed sc binder_func_10
This commit is contained in:
DH 2013-11-23 20:50:54 +02:00
parent 8463694d4f
commit da9c778a4c
7 changed files with 125 additions and 40 deletions

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "Emu/Memory/MemoryBlock.h" #include "Emu/Memory/MemoryBlock.h"
#include "Emu/Cell/PPCDecoder.h" #include "Emu/CPU/CPUDecoder.h"
enum CPUThreadType enum CPUThreadType
{ {

View file

@ -163,16 +163,16 @@ struct DMAC
if(proxy_pos) if(proxy_pos)
{ {
DMAC_Proxy p = proxy[0]; DMAC_Proxy p = proxy[0];
memcpy(proxy, proxy + 1, proxy_pos--); memcpy(proxy, proxy + 1, --proxy_pos * sizeof(DMAC_Proxy));
switch(p.cmd) switch(p.cmd)
{ {
case MFC_PUT_CMD: case MFC_PUT_CMD:
memcpy(Memory + ls_offset + p.lsa, Memory + p.ea, p.size); memcpy(Memory + p.ea, Memory + ls_offset + p.lsa, p.size);
break; break;
case MFC_GET_CMD: case MFC_GET_CMD:
memcpy(Memory + p.ea, Memory + ls_offset + p.lsa, p.size); memcpy(Memory + ls_offset + p.lsa, Memory + p.ea, p.size);
break; break;
default: default:

View file

@ -11,7 +11,14 @@ RawSPUThread::RawSPUThread(u32 index, CPUThreadType type)
RawSPUThread::~RawSPUThread() RawSPUThread::~RawSPUThread()
{ {
MemoryBlock::Delete(); for(int i=0; i<Memory.MemoryBlocks.GetCount(); ++i)
{
if(&Memory.MemoryBlocks[i] == this)
{
Memory.MemoryBlocks.RemoveFAt(i);
return;
}
}
} }
bool RawSPUThread::Read8(const u64 addr, u8* value) bool RawSPUThread::Read8(const u64 addr, u8* value)
@ -59,9 +66,13 @@ bool RawSPUThread::Read32(const u64 addr, u32* value)
case Prxy_QueryType_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryType)", m_index); *value = Prxy.QueryType.GetValue(); break; case Prxy_QueryType_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryType)", m_index); *value = Prxy.QueryType.GetValue(); break;
case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryMask)", m_index); *value = Prxy.QueryMask.GetValue(); break; case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryMask)", m_index); *value = Prxy.QueryMask.GetValue(); break;
case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_TagStatus)", m_index); *value = Prxy.TagStatus.GetValue(); break; case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_TagStatus)", m_index); *value = Prxy.TagStatus.GetValue(); break;
case SPU_Out_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Out_MBox)", m_index); *value = SPU.Out_MBox.GetValue(); break; case SPU_Out_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Out_MBox)", m_index); while(!SPU.Out_MBox.Pop(*value) && !Emu.IsStopped()) Sleep(1); break;
case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_In_MBox)", m_index); *value = SPU.In_MBox.GetValue(); break; case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_In_MBox)", m_index); *value = SPU.In_MBox.GetValue(); break;
case SPU_MBox_Status_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_MBox_Status)", m_index); *value = SPU.MBox_Status.GetValue(); break; case SPU_MBox_Status_offs: //ConLog.Warning("RawSPUThread[%d]: Read32(SPU_MBox_Status)", m_index);
SPU.MBox_Status.SetValue(SPU.Out_MBox.GetCount() ? SPU.MBox_Status.GetValue() | 1 : SPU.MBox_Status.GetValue() & ~1);
SPU.MBox_Status.SetValue((SPU.MBox_Status.GetValue() & ~0xff00) | (SPU.In_MBox.GetCount() << 8));
*value = SPU.MBox_Status.GetValue();
break;
case SPU_RunCntl_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RunCntl)", m_index); *value = SPU.RunCntl.GetValue(); break; case SPU_RunCntl_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RunCntl)", m_index); *value = SPU.RunCntl.GetValue(); break;
case SPU_Status_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Status)", m_index); *value = SPU.Status.GetValue(); break; case SPU_Status_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Status)", m_index); *value = SPU.Status.GetValue(); break;
case SPU_NPC_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_NPC)", m_index); *value = SPU.NPC.GetValue(); break; case SPU_NPC_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_NPC)", m_index); *value = SPU.NPC.GetValue(); break;
@ -201,7 +212,7 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value)
break; break;
case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_QueryMask, 0x%x)", m_index, value); Prxy.QueryMask.SetValue(value); break; case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_QueryMask, 0x%x)", m_index, value); Prxy.QueryMask.SetValue(value); break;
case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_TagStatus, 0x%x)", m_index, value); Prxy.TagStatus.SetValue(value); break; case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_TagStatus, 0x%x)", m_index, value); Prxy.TagStatus.SetValue(value); break;
case SPU_Out_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_Out_MBox, 0x%x)", m_index, value); SPU.Out_MBox.SetValue(value); break; case SPU_Out_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_Out_MBox, 0x%x)", m_index, value); while(!SPU.Out_MBox.Push(value) && !Emu.IsStopped()) Sleep(1); break;
case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_In_MBox, 0x%x)", m_index, value); SPU.In_MBox.SetValue(value); break; case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_In_MBox, 0x%x)", m_index, value); SPU.In_MBox.SetValue(value); break;
case SPU_MBox_Status_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_MBox_Status, 0x%x)", m_index, value); SPU.MBox_Status.SetValue(value); break; case SPU_MBox_Status_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_MBox_Status, 0x%x)", m_index, value); SPU.MBox_Status.SetValue(value); break;
case SPU_RunCntl_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RunCntl, 0x%x)", m_index, value); SPU.RunCntl.SetValue(value); break; case SPU_RunCntl_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RunCntl, 0x%x)", m_index, value); SPU.RunCntl.SetValue(value); break;
@ -247,7 +258,7 @@ bool RawSPUThread::Write128(const u64 addr, const u128 value)
void RawSPUThread::InitRegs() void RawSPUThread::InitRegs()
{ {
m_offset = GetStartAddr() + RAW_SPU_LS_OFFSET; dmac.ls_offset = m_offset = GetStartAddr() + RAW_SPU_LS_OFFSET;
SPUThread::InitRegs(); SPUThread::InitRegs();
} }
@ -289,6 +300,8 @@ void RawSPUThread::Task()
continue; continue;
} }
dmac.DoCmd();
if(SPU.RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE) if(SPU.RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE)
{ {
if(!is_last_paused) if(!is_last_paused)
@ -311,6 +324,7 @@ void RawSPUThread::Task()
SPU.Status.SetValue(SPU_STATUS_RUNNING); SPU.Status.SetValue(SPU_STATUS_RUNNING);
} }
Step();
NextPc(m_dec->DecodeMemory(PC + m_offset)); NextPc(m_dec->DecodeMemory(PC + m_offset));
for(uint i=0; i<bp.GetCount(); ++i) for(uint i=0; i<bp.GetCount(); ++i)

View file

@ -30,6 +30,11 @@ private:
CPU.SetExitStatus(code & 0xfff); CPU.SetExitStatus(code & 0xfff);
CPU.Stop(); CPU.Stop();
} }
else
{
ConLog.Warning("STOP: 0x%x", code);
Emu.Pause();
}
} }
void LNOP() void LNOP()
{ {
@ -272,23 +277,23 @@ private:
} }
void BIZ(u32 rt, u32 ra) void BIZ(u32 rt, u32 ra)
{ {
if(CPU.GPR[rt]._u32[0] == 0) if(CPU.GPR[rt]._u32[3] == 0)
CPU.SetBranch(CPU.GPR[ra]._u32[0] & 0xfffffffc); CPU.SetBranch(CPU.GPR[ra]._u32[3] & 0xfffffffc);
} }
void BINZ(u32 rt, u32 ra) void BINZ(u32 rt, u32 ra)
{ {
if(CPU.GPR[rt]._u32[0] != 0) if(CPU.GPR[rt]._u32[3] != 0)
CPU.SetBranch(CPU.GPR[ra]._u32[0] & 0xfffffffc); CPU.SetBranch(CPU.GPR[ra]._u32[3] & 0xfffffffc);
} }
void BIHZ(u32 rt, u32 ra) void BIHZ(u32 rt, u32 ra)
{ {
if(CPU.GPR[rt]._u16[0] == 0) if(CPU.GPR[rt]._u16[7] == 0)
CPU.SetBranch(CPU.GPR[ra]._u32[0] & 0xfffffffc); CPU.SetBranch(CPU.GPR[ra]._u32[3] & 0xfffffffc);
} }
void BIHNZ(u32 rt, u32 ra) void BIHNZ(u32 rt, u32 ra)
{ {
if(CPU.GPR[rt]._u16[0] != 0) if(CPU.GPR[rt]._u16[7] != 0)
CPU.SetBranch(CPU.GPR[ra]._u32[0] & 0xfffffffc); CPU.SetBranch(CPU.GPR[ra]._u32[3] & 0xfffffffc);
} }
void STOPD(u32 rc, u32 ra, u32 rb) void STOPD(u32 rc, u32 ra, u32 rb)
{ {
@ -296,7 +301,15 @@ private:
} }
void STQX(u32 rt, u32 ra, u32 rb) void STQX(u32 rt, u32 ra, u32 rb)
{ {
CPU.WriteLS128(CPU.GPR[ra]._u32[0] + CPU.GPR[rb]._u32[0], CPU.GPR[rt]._u128); u32 lsa = CPU.GPR[ra]._u32[3] + CPU.GPR[rb]._u32[3];
if(!CPU.IsGoodLSA(lsa))
{
ConLog.Error("STQX: bad lsa (0x%x)", lsa);
Emu.Pause();
return;
}
CPU.WriteLS128(lsa, CPU.GPR[rt]._u128);
} }
void BI(u32 ra) void BI(u32 ra)
{ {
@ -368,7 +381,15 @@ private:
} }
void LQX(u32 rt, u32 ra, u32 rb) void LQX(u32 rt, u32 ra, u32 rb)
{ {
CPU.GPR[rt]._u128 = CPU.ReadLS128(CPU.GPR[ra]._u32[0] + CPU.GPR[rb]._u32[0]); u32 lsa = CPU.GPR[ra]._u32[3] + CPU.GPR[rb]._u32[3];
if(!CPU.IsGoodLSA(lsa))
{
ConLog.Error("LQX: bad lsa (0x%x)", lsa);
Emu.Pause();
return;
}
CPU.GPR[rt]._u128 = CPU.ReadLS128(lsa);
} }
void ROTQBYBI(u32 rt, u32 ra, u32 rb) void ROTQBYBI(u32 rt, u32 ra, u32 rb)
{ {
@ -957,7 +978,15 @@ private:
} }
void STQA(u32 rt, s32 i16) void STQA(u32 rt, s32 i16)
{ {
CPU.WriteLS128(i16 << 2, CPU.GPR[rt]._u128); u32 lsa = i16 << 2;
if(!CPU.IsGoodLSA(lsa))
{
ConLog.Error("STQA: bad lsa (0x%x)", lsa);
Emu.Pause();
return;
}
CPU.WriteLS128(lsa, CPU.GPR[rt]._u128);
} }
void BRNZ(u32 rt, s32 i16) void BRNZ(u32 rt, s32 i16)
{ {
@ -974,7 +1003,15 @@ private:
} }
void STQR(u32 rt, s32 i16) void STQR(u32 rt, s32 i16)
{ {
CPU.WriteLS128(branchTarget(CPU.PC, i16), CPU.GPR[rt]._u128); u32 lsa = branchTarget(CPU.PC, i16);
if(!CPU.IsGoodLSA(lsa))
{
ConLog.Error("STQR: bad lsa (0x%x)", lsa);
Emu.Pause();
return;
}
CPU.WriteLS128(lsa, CPU.GPR[rt]._u128);
} }
void BRA(s32 i16) void BRA(s32 i16)
{ {
@ -982,7 +1019,15 @@ private:
} }
void LQA(u32 rt, s32 i16) void LQA(u32 rt, s32 i16)
{ {
CPU.GPR[rt]._u128 = CPU.ReadLS128(i16 << 2); u32 lsa = i16 << 2;
if(!CPU.IsGoodLSA(lsa))
{
ConLog.Error("LQA: bad lsa (0x%x)", lsa);
Emu.Pause();
return;
}
CPU.GPR[rt]._u128 = CPU.ReadLS128(lsa);
} }
void BRASL(u32 rt, s32 i16) void BRASL(u32 rt, s32 i16)
{ {
@ -1018,7 +1063,15 @@ private:
} }
void LQR(u32 rt, s32 i16) void LQR(u32 rt, s32 i16)
{ {
CPU.GPR[rt]._u128 = CPU.ReadLS128(branchTarget(CPU.PC, i16)); u32 lsa = branchTarget(CPU.PC, i16);
if(!CPU.IsGoodLSA(lsa))
{
ConLog.Error("LQR: bad lsa (0x%x)", lsa);
Emu.Pause();
return;
}
CPU.GPR[rt]._u128 = CPU.ReadLS128(lsa);
} }
void IL(u32 rt, s32 i16) void IL(u32 rt, s32 i16)
{ {
@ -1103,11 +1156,26 @@ private:
} }
void STQD(u32 rt, s32 i10, u32 ra) void STQD(u32 rt, s32 i10, u32 ra)
{ {
CPU.WriteLS128(CPU.GPR[ra]._u32[3] + i10, CPU.GPR[rt]._u128); u32 lsa = CPU.GPR[ra]._u32[3] + i10;
if(!CPU.IsGoodLSA(lsa))
{
ConLog.Error("STQD: bad lsa (0x%x)", lsa);
Emu.Pause();
return;
}
CPU.WriteLS128(lsa, CPU.GPR[rt]._u128);
} }
void LQD(u32 rt, s32 i10, u32 ra) void LQD(u32 rt, s32 i10, u32 ra)
{ {
CPU.GPR[rt]._u128 = CPU.ReadLS128(CPU.GPR[ra]._u32[3] + i10); u32 lsa = CPU.GPR[ra]._u32[3] + i10;
if(!CPU.IsGoodLSA(lsa))
{
ConLog.Error("LQD: bad lsa (0x%x)", lsa);
Emu.Pause();
return;
}
CPU.GPR[rt]._u128 = CPU.ReadLS128(lsa);
} }
void XORI(u32 rt, u32 ra, s32 i10) void XORI(u32 rt, u32 ra, s32 i10)
{ {
@ -1203,7 +1271,6 @@ private:
void HBRA(s32 ro, s32 i16) void HBRA(s32 ro, s32 i16)
{ {
UNIMPLEMENTED(); UNIMPLEMENTED();
UNIMPLEMENTED();
} }
void HBRR(s32 ro, s32 i16) void HBRR(s32 ro, s32 i16)
{ {
@ -1228,7 +1295,7 @@ private:
} }
void SHUFB(u32 rt, u32 ra, u32 rb, u32 rc) void SHUFB(u32 rt, u32 ra, u32 rb, u32 rc)
{ {
ConLog.Warning("SHUFB"); //ConLog.Warning("SHUFB");
} }
void MPYA(u32 rc, u32 ra, u32 rb, u32 rt) void MPYA(u32 rc, u32 ra, u32 rb, u32 rt)
{ {

View file

@ -37,7 +37,7 @@ void SPUThread::DoReset()
void SPUThread::InitRegs() void SPUThread::InitRegs()
{ {
//GPR[1]._u64[0] = stack_point; GPR[1]._u32[3] = 0x40000 - 120;
GPR[3]._u64[1] = m_args[0]; GPR[3]._u64[1] = m_args[0];
GPR[4]._u64[1] = m_args[1]; GPR[4]._u64[1] = m_args[1];
GPR[5]._u64[1] = m_args[2]; GPR[5]._u64[1] = m_args[2];
@ -56,7 +56,7 @@ void SPUThread::InitRegs()
u64 SPUThread::GetFreeStackSize() const u64 SPUThread::GetFreeStackSize() const
{ {
return (GetStackAddr() + GetStackSize()) - GPR[1]._u64[0]; return (GetStackAddr() + GetStackSize()) - GPR[1]._u64[3];
} }
void SPUThread::DoRun() void SPUThread::DoRun()
@ -72,6 +72,9 @@ void SPUThread::DoRun()
m_dec = new SPUDecoder(*new SPUInterpreter(*this)); m_dec = new SPUDecoder(*new SPUInterpreter(*this));
break; break;
} }
Pause();
//Emu.Pause();
} }
void SPUThread::DoResume() void SPUThread::DoResume()
@ -85,5 +88,5 @@ void SPUThread::DoPause()
void SPUThread::DoStop() void SPUThread::DoStop()
{ {
delete m_dec; delete m_dec;
m_dec = 0; m_dec = nullptr;
} }

View file

@ -359,7 +359,7 @@ public:
return SPU.Out_MBox.GetFreeCount(); return SPU.Out_MBox.GetFreeCount();
case SPU_RdInMbox: case SPU_RdInMbox:
return SPU.In_MBox.GetFreeCount(); return SPU.In_MBox.GetCount();
case SPU_WrOutIntrMbox: case SPU_WrOutIntrMbox:
return 0;//return SPU.OutIntr_Mbox.GetFreeCount(); return 0;//return SPU.OutIntr_Mbox.GetFreeCount();
@ -380,19 +380,20 @@ public:
{ {
case SPU_WrOutIntrMbox: case SPU_WrOutIntrMbox:
ConLog.Warning("SPU_WrOutIntrMbox = 0x%x", v); ConLog.Warning("SPU_WrOutIntrMbox = 0x%x", v);
if(!SPU.OutIntr_Mbox.Push(v))
while(!SPU.OutIntr_Mbox.Push(v) && !Emu.IsStopped())
{ {
ConLog.Warning("Not enought free rooms."); Sleep(1);
} }
break; break;
case SPU_WrOutMbox: case SPU_WrOutMbox:
ConLog.Warning("SPU_WrOutMbox = 0x%x", v); ConLog.Warning("SPU_WrOutMbox = 0x%x", v);
if(!SPU.Out_MBox.Push(v))
while(!SPU.Out_MBox.Push(v) && !Emu.IsStopped())
{ {
ConLog.Warning("Not enought free rooms."); Sleep(1);
} }
SPU.Status.SetValue((SPU.Status.GetValue() & ~0xff) | 1);
break; break;
default: default:
@ -410,7 +411,7 @@ public:
{ {
case SPU_RdInMbox: case SPU_RdInMbox:
if(!SPU.In_MBox.Pop(v)) v = 0; if(!SPU.In_MBox.Pop(v)) v = 0;
SPU.Status.SetValue((SPU.Status.GetValue() & ~0xff00) | (SPU.In_MBox.GetCount() << 8)); ConLog.Warning("%s: SPU_RdInMbox(0x%x).", __FUNCTION__, v);
break; break;
default: default:
@ -419,7 +420,7 @@ public:
} }
} }
bool IsGoodLSA(const u32 lsa) const { return Memory.IsGoodAddr(lsa + m_offset); } bool IsGoodLSA(const u32 lsa) const { return Memory.IsGoodAddr(lsa + m_offset) && lsa < 0x40000; }
virtual u8 ReadLS8 (const u32 lsa) const { return Memory.Read8 (lsa + (m_offset & 0x3fffc)); } virtual u8 ReadLS8 (const u32 lsa) const { return Memory.Read8 (lsa + (m_offset & 0x3fffc)); }
virtual u16 ReadLS16 (const u32 lsa) const { return Memory.Read16 (lsa + m_offset); } virtual u16 ReadLS16 (const u32 lsa) const { return Memory.Read16 (lsa + m_offset); }
virtual u32 ReadLS32 (const u32 lsa) const { return Memory.Read32 (lsa + m_offset); } virtual u32 ReadLS32 (const u32 lsa) const { return Memory.Read32 (lsa + m_offset); }
@ -478,7 +479,7 @@ public:
} }
public: public:
virtual void InitRegs(); virtual void InitRegs();
virtual u64 GetFreeStackSize() const; virtual u64 GetFreeStackSize() const;
protected: protected:

View file

@ -255,7 +255,7 @@ class binder_func_10<void, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : public fun
public: public:
binder_func_10(func_t call) : func_caller(), m_call(call) {} binder_func_10(func_t call) : func_caller(), m_call(call) {}
virtual void operator()() { declCPU(); m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7), ARG(8), ARG(9), ARG(10), ARG(11)); } virtual void operator()() { declCPU(); m_call(ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7), ARG(8), ARG(9), ARG(10)); }
}; };
template<typename TR, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11> template<typename TR, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11>