mirror of https://github.com/RPCS3/rpcs3.git
SPU Improvements
Implemented SNR channels and syscalls, fixed sys_spu_thread_initialize (args' passing, SPU image copying for each thread)
This commit is contained in:
parent
e28ba30561
commit
c9abf559be
|
@ -82,8 +82,8 @@ bool RawSPUThread::Read32(const u64 addr, u32* value)
|
||||||
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;
|
||||||
case SPU_RdSigNotify1_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify1)", m_index); *value = SPU.RdSigNotify1.GetValue(); break;
|
case SPU_RdSigNotify1_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify1)", m_index); *value = SPU.SNR[0].GetValue(); break;
|
||||||
case SPU_RdSigNotify2_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify2)", m_index); *value = SPU.RdSigNotify2.GetValue(); break;
|
case SPU_RdSigNotify2_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify2)", m_index); *value = SPU.SNR[1].GetValue(); break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ConLog.Error("RawSPUThread[%d]: Read32(0x%x)", m_index, offset);
|
ConLog.Error("RawSPUThread[%d]: Read32(0x%x)", m_index, offset);
|
||||||
|
@ -197,8 +197,8 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value)
|
||||||
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;
|
||||||
case SPU_Status_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_Status, 0x%x)", m_index, value); SPU.Status.SetValue(value); break;
|
case SPU_Status_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_Status, 0x%x)", m_index, value); SPU.Status.SetValue(value); break;
|
||||||
case SPU_NPC_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_NPC, 0x%x)", m_index, value); SPU.NPC.SetValue(value); break;
|
case SPU_NPC_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_NPC, 0x%x)", m_index, value); SPU.NPC.SetValue(value); break;
|
||||||
case SPU_RdSigNotify1_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RdSigNotify1, 0x%x)", m_index, value); SPU.RdSigNotify1.SetValue(value); break;
|
case SPU_RdSigNotify1_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RdSigNotify1, 0x%x)", m_index, value); SPU.SNR[0].SetValue(value); break;
|
||||||
case SPU_RdSigNotify2_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RdSigNotify2, 0x%x)", m_index, value); SPU.RdSigNotify2.SetValue(value); break;
|
case SPU_RdSigNotify2_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RdSigNotify2, 0x%x)", m_index, value); SPU.SNR[1].SetValue(value); break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ConLog.Error("RawSPUThread[%d]: Write32(0x%x, 0x%x)", m_index, offset, value);
|
ConLog.Error("RawSPUThread[%d]: Write32(0x%x, 0x%x)", m_index, offset, value);
|
||||||
|
|
|
@ -35,24 +35,24 @@ private:
|
||||||
if(code & 0x2000)
|
if(code & 0x2000)
|
||||||
{
|
{
|
||||||
CPU.SetExitStatus(code & 0xfff);
|
CPU.SetExitStatus(code & 0xfff);
|
||||||
CPU.Stop();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ConLog.Warning("STOP: 0x%x", code);
|
ConLog.Warning("STOP: 0x%x", code);
|
||||||
Emu.Pause();
|
//Emu.Pause();
|
||||||
}
|
}
|
||||||
|
CPU.Stop();
|
||||||
}
|
}
|
||||||
void LNOP()
|
void LNOP()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
void SYNC(u32 Cbit)
|
void SYNC(u32 Cbit)
|
||||||
{
|
{
|
||||||
//UNIMPLEMENTED();
|
_mm_mfence();
|
||||||
}
|
}
|
||||||
void DSYNC()
|
void DSYNC()
|
||||||
{
|
{
|
||||||
//UNIMPLEMENTED();
|
_mm_mfence();
|
||||||
}
|
}
|
||||||
void MFSPR(u32 rt, u32 sa)
|
void MFSPR(u32 rt, u32 sa)
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,6 +43,8 @@ void SPUThread::InitRegs()
|
||||||
GPR[5]._u64[1] = m_args[2];
|
GPR[5]._u64[1] = m_args[2];
|
||||||
GPR[6]._u64[1] = m_args[3];
|
GPR[6]._u64[1] = m_args[3];
|
||||||
|
|
||||||
|
cfg.Reset();
|
||||||
|
|
||||||
dmac.ls_offset = m_offset;
|
dmac.ls_offset = m_offset;
|
||||||
dmac.proxy_pos = 0;
|
dmac.proxy_pos = 0;
|
||||||
dmac.queue_pos = 0;
|
dmac.queue_pos = 0;
|
||||||
|
|
|
@ -249,12 +249,30 @@ union SPU_SPR_hdr
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
union SPU_SNRConfig_hdr
|
||||||
|
{
|
||||||
|
u64 value;
|
||||||
|
|
||||||
|
SPU_SNRConfig_hdr() {}
|
||||||
|
|
||||||
|
wxString ToString() const
|
||||||
|
{
|
||||||
|
return wxString::Format("%01x", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reset()
|
||||||
|
{
|
||||||
|
memset(this, 0, sizeof(*this));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class SPUThread : public PPCThread
|
class SPUThread : public PPCThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SPU_GPR_hdr GPR[128]; //General-Purpose Register
|
SPU_GPR_hdr GPR[128]; //General-Purpose Register
|
||||||
SPU_SPR_hdr SPR[128]; //Special-Purpose Registers
|
SPU_SPR_hdr SPR[128]; //Special-Purpose Registers
|
||||||
FPSCR FPSCR;
|
FPSCR FPSCR;
|
||||||
|
SPU_SNRConfig_hdr cfg; //Signal Notification Registers Configuration (OR-mode enabled: 0x1 for SNR1, 0x2 for SNR2)
|
||||||
|
|
||||||
template<size_t _max_count>
|
template<size_t _max_count>
|
||||||
class Channel
|
class Channel
|
||||||
|
@ -322,6 +340,18 @@ public:
|
||||||
m_lock = 0;
|
m_lock = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__forceinline void PushUncond_OR(u32 value)
|
||||||
|
{
|
||||||
|
while (_InterlockedExchange(&m_lock, 1));
|
||||||
|
_mm_lfence();
|
||||||
|
if(m_index >= max_count)
|
||||||
|
m_value[max_count-1] |= value; //last message is logically ORed
|
||||||
|
else
|
||||||
|
m_value[m_index++] = value;
|
||||||
|
_mm_sfence();
|
||||||
|
m_lock = 0;
|
||||||
|
}
|
||||||
|
|
||||||
__forceinline void PopUncond(u32& res)
|
__forceinline void PopUncond(u32& res)
|
||||||
{
|
{
|
||||||
while (_InterlockedExchange(&m_lock, 1));
|
while (_InterlockedExchange(&m_lock, 1));
|
||||||
|
@ -385,8 +415,7 @@ public:
|
||||||
Channel<1> RunCntl;
|
Channel<1> RunCntl;
|
||||||
Channel<1> Status;
|
Channel<1> Status;
|
||||||
Channel<1> NPC;
|
Channel<1> NPC;
|
||||||
Channel<1> RdSigNotify1;
|
Channel<1> SNR[2];
|
||||||
Channel<1> RdSigNotify2;
|
|
||||||
} SPU;
|
} SPU;
|
||||||
|
|
||||||
u32 LSA;
|
u32 LSA;
|
||||||
|
@ -404,31 +433,29 @@ public:
|
||||||
u32 cmd = MFCArgs.CMDStatus.GetValue();
|
u32 cmd = MFCArgs.CMDStatus.GetValue();
|
||||||
u16 op = cmd & MFC_MASK_CMD;
|
u16 op = cmd & MFC_MASK_CMD;
|
||||||
|
|
||||||
switch(op & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK))
|
|
||||||
{
|
|
||||||
case MFC_PUT_CMD:
|
|
||||||
case MFC_GET_CMD:
|
|
||||||
{
|
|
||||||
u32 lsa = MFCArgs.LSA.GetValue();
|
u32 lsa = MFCArgs.LSA.GetValue();
|
||||||
u64 ea = (u64)MFCArgs.EAL.GetValue() | ((u64)MFCArgs.EAH.GetValue() << 32);
|
u64 ea = (u64)MFCArgs.EAL.GetValue() | ((u64)MFCArgs.EAH.GetValue() << 32);
|
||||||
u32 size_tag = MFCArgs.Size_Tag.GetValue();
|
u32 size_tag = MFCArgs.Size_Tag.GetValue();
|
||||||
u16 tag = (u16)size_tag;
|
u16 tag = (u16)size_tag;
|
||||||
u16 size = size_tag >> 16;
|
u16 size = size_tag >> 16;
|
||||||
|
|
||||||
ConLog.Warning("DMA %s:", op & MFC_PUT_CMD ? "PUT" : "GET");
|
switch(op & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK))
|
||||||
ConLog.Warning("*** lsa = 0x%x", lsa);
|
{
|
||||||
ConLog.Warning("*** ea = 0x%llx", ea);
|
case MFC_PUT_CMD:
|
||||||
ConLog.Warning("*** tag = 0x%x", tag);
|
case MFC_GET_CMD:
|
||||||
ConLog.Warning("*** size = 0x%x", size);
|
{
|
||||||
ConLog.Warning("*** cmd = 0x%x", cmd);
|
ConLog.Warning("DMA %s%s%s: lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x",
|
||||||
ConLog.SkipLn();
|
op & MFC_PUT_CMD ? "PUT" : "GET",
|
||||||
|
op & MFC_BARRIER_MASK ? "B" : "",
|
||||||
|
op & MFC_FENCE_MASK ? "F" : "",
|
||||||
|
lsa, ea, tag, size, cmd);
|
||||||
MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
|
MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ConLog.Error("Unknown MFC cmd. (opcode=0x%x, cmd=0x%x)", op, cmd);
|
ConLog.Error("Unknown MFC cmd. (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)",
|
||||||
|
op, cmd, lsa, ea, tag, size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -446,6 +473,15 @@ public:
|
||||||
case SPU_WrOutIntrMbox:
|
case SPU_WrOutIntrMbox:
|
||||||
return 0;//return SPU.OutIntr_Mbox.GetFreeCount();
|
return 0;//return SPU.OutIntr_Mbox.GetFreeCount();
|
||||||
|
|
||||||
|
case MFC_RdTagStat:
|
||||||
|
return Prxy.TagStatus.GetCount();
|
||||||
|
|
||||||
|
case SPU_RdSigNotify1:
|
||||||
|
return SPU.SNR[0].GetCount();
|
||||||
|
|
||||||
|
case SPU_RdSigNotify2:
|
||||||
|
return SPU.SNR[1].GetCount();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]);
|
ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]);
|
||||||
break;
|
break;
|
||||||
|
@ -458,30 +494,26 @@ public:
|
||||||
{
|
{
|
||||||
const u32 v = r._u32[3];
|
const u32 v = r._u32[3];
|
||||||
|
|
||||||
ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v);
|
|
||||||
|
|
||||||
switch(ch)
|
switch(ch)
|
||||||
{
|
{
|
||||||
case SPU_WrOutIntrMbox:
|
case SPU_WrOutIntrMbox:
|
||||||
while(!SPU.OutIntr_Mbox.Push(v) && !Emu.IsStopped())
|
ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v);
|
||||||
{
|
while (!SPU.OutIntr_Mbox.Push(v) && !Emu.IsStopped()) _mm_pause();
|
||||||
Sleep(1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPU_WrOutMbox:
|
case SPU_WrOutMbox:
|
||||||
while(!SPU.Out_MBox.Push(v) && !Emu.IsStopped())
|
ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v);
|
||||||
{
|
while (!SPU.Out_MBox.Push(v) && !Emu.IsStopped()) _mm_pause();
|
||||||
Sleep(1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MFC_WrTagMask:
|
case MFC_WrTagMask:
|
||||||
|
//ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v);
|
||||||
Prxy.QueryMask.SetValue(v);
|
Prxy.QueryMask.SetValue(v);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MFC_WrTagUpdate:
|
case MFC_WrTagUpdate:
|
||||||
Prxy.TagStatus.SetValue(Prxy.QueryMask.GetValue());
|
//ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v);
|
||||||
|
Prxy.TagStatus.PushUncond(Prxy.QueryMask.GetValue());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MFC_LSA:
|
case MFC_LSA:
|
||||||
|
@ -523,19 +555,30 @@ public:
|
||||||
switch(ch)
|
switch(ch)
|
||||||
{
|
{
|
||||||
case SPU_RdInMbox:
|
case SPU_RdInMbox:
|
||||||
if(!SPU.In_MBox.Pop(v)) v = 0;
|
while (!SPU.In_MBox.Pop(v) && !Emu.IsStopped()) _mm_pause();
|
||||||
|
ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MFC_RdTagStat:
|
case MFC_RdTagStat:
|
||||||
v = Prxy.TagStatus.GetValue();
|
while (dmac.proxy_pos) dmac.DoCmd(); //probably incompatible with MFC lists
|
||||||
|
while (!Prxy.TagStatus.Pop(v) && !Emu.IsStopped()) _mm_pause();
|
||||||
|
//ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SPU_RdSigNotify1:
|
||||||
|
while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) _mm_pause();
|
||||||
|
ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SPU_RdSigNotify2:
|
||||||
|
while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) _mm_pause();
|
||||||
|
//ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]);
|
ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsGoodLSA(const u32 lsa) const { return Memory.IsGoodAddr(lsa + m_offset) && lsa < 0x40000; }
|
bool IsGoodLSA(const u32 lsa) const { return Memory.IsGoodAddr(lsa + m_offset) && lsa < 0x40000; }
|
||||||
|
|
|
@ -97,8 +97,8 @@ static func_caller* sc_table[1024] =
|
||||||
null_func, null_func, null_func, null_func, bind_func(sys_spu_initialize), //169
|
null_func, null_func, null_func, null_func, bind_func(sys_spu_initialize), //169
|
||||||
bind_func(sys_spu_thread_group_create), bind_func(sys_spu_thread_set_argument), bind_func(sys_spu_thread_initialize), bind_func(sys_spu_thread_group_start), null_func, //174
|
bind_func(sys_spu_thread_group_create), bind_func(sys_spu_thread_set_argument), bind_func(sys_spu_thread_initialize), bind_func(sys_spu_thread_group_start), null_func, //174
|
||||||
null_func, null_func, null_func, null_func, null_func, //179
|
null_func, null_func, null_func, null_func, null_func, //179
|
||||||
null_func, bind_func(sys_spu_thread_write_ls), bind_func(sys_spu_thread_read_ls), null_func, null_func, //184
|
null_func, bind_func(sys_spu_thread_write_ls), bind_func(sys_spu_thread_read_ls), null_func, bind_func(sys_spu_thread_write_snr), //184
|
||||||
null_func, null_func, null_func, null_func, null_func, //189
|
null_func, null_func, bind_func(sys_spu_thread_set_spu_cfg), bind_func(sys_spu_thread_get_spu_cfg), null_func, //189
|
||||||
bind_func(sys_spu_thread_write_spu_mb), bind_func(sys_spu_thread_connect_event), null_func, null_func, null_func, //194
|
bind_func(sys_spu_thread_write_spu_mb), bind_func(sys_spu_thread_connect_event), null_func, null_func, null_func, //194
|
||||||
null_func, null_func, null_func, null_func, null_func, //199
|
null_func, null_func, null_func, null_func, null_func, //199
|
||||||
null_func, null_func, null_func, null_func, null_func, //204
|
null_func, null_func, null_func, null_func, null_func, //204
|
||||||
|
|
|
@ -292,6 +292,9 @@ extern int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu);
|
||||||
extern int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type);
|
extern int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type);
|
||||||
extern int sys_spu_thread_read_ls(u32 id, u32 address, mem64_t value, u32 type);
|
extern int sys_spu_thread_read_ls(u32 id, u32 address, mem64_t value, u32 type);
|
||||||
extern int sys_spu_thread_write_spu_mb(u32 id, u32 value);
|
extern int sys_spu_thread_write_spu_mb(u32 id, u32 value);
|
||||||
|
extern int sys_spu_thread_set_spu_cfg(u32 id, u64 value);
|
||||||
|
extern int sys_spu_thread_get_spu_cfg(u32 id, mem64_t value);
|
||||||
|
extern int sys_spu_thread_write_snr(u32 id, u32 number, u32 value);
|
||||||
|
|
||||||
//sys_time
|
//sys_time
|
||||||
extern int sys_time_get_timezone(mem32_t timezone, mem32_t summertime);
|
extern int sys_time_get_timezone(mem32_t timezone, mem32_t summertime);
|
||||||
|
|
|
@ -21,12 +21,14 @@ struct SpuGroupInfo
|
||||||
};
|
};
|
||||||
|
|
||||||
u64 g_spu_offset = 0;
|
u64 g_spu_offset = 0;
|
||||||
|
u64 g_spu_alloc_size = 0;
|
||||||
|
|
||||||
u32 LoadSpuImage(vfsStream& stream)
|
u32 LoadSpuImage(vfsStream& stream)
|
||||||
{
|
{
|
||||||
ELFLoader l(stream);
|
ELFLoader l(stream);
|
||||||
l.LoadInfo();
|
l.LoadInfo();
|
||||||
g_spu_offset = Memory.MainMem.Alloc(0xFFFFED - stream.GetSize());
|
g_spu_alloc_size = 0xFFFFED - stream.GetSize();
|
||||||
|
g_spu_offset = Memory.MainMem.Alloc(g_spu_alloc_size);
|
||||||
l.LoadData(g_spu_offset);
|
l.LoadData(g_spu_offset);
|
||||||
|
|
||||||
return g_spu_offset + l.GetEntry();
|
return g_spu_offset + l.GetEntry();
|
||||||
|
@ -56,6 +58,7 @@ int sys_spu_image_open(mem_ptr_t<sys_spu_image> img, u32 path_addr)
|
||||||
img->entry_point = entry;
|
img->entry_point = entry;
|
||||||
img->segs_addr = 0x0;
|
img->segs_addr = 0x0;
|
||||||
img->nsegs = 0;
|
img->nsegs = 0;
|
||||||
|
img->_img_offs = g_spu_offset;
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
@ -93,37 +96,42 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t<
|
||||||
return CELL_EBUSY;
|
return CELL_EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 entry = img->entry_point;
|
u32 ls_entry = img->entry_point - img->_img_offs;
|
||||||
std::string name = Memory.ReadString(attr->name_addr, attr->name_len).mb_str();
|
std::string name = Memory.ReadString(attr->name_addr, attr->name_len).mb_str();
|
||||||
u64 a1 = arg->arg1;
|
u64 a1 = arg->arg1;
|
||||||
u64 a2 = arg->arg2;
|
u64 a2 = arg->arg2;
|
||||||
u64 a3 = arg->arg3;
|
u64 a3 = arg->arg3;
|
||||||
u64 a4 = arg->arg4;
|
u64 a4 = arg->arg4;
|
||||||
|
|
||||||
|
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_SPU);
|
||||||
|
//copy SPU image:
|
||||||
|
g_spu_alloc_size = 256 * 1024;
|
||||||
|
g_spu_offset = Memory.MainMem.Alloc(g_spu_alloc_size);
|
||||||
|
memcpy(Memory + g_spu_offset, Memory + img->_img_offs, g_spu_alloc_size);
|
||||||
|
//initialize from new place:
|
||||||
|
new_thread.SetOffset(g_spu_offset);
|
||||||
|
new_thread.SetEntry(ls_entry);
|
||||||
|
new_thread.SetName(name);
|
||||||
|
new_thread.SetArg(0, a1);
|
||||||
|
new_thread.SetArg(1, a2);
|
||||||
|
new_thread.SetArg(2, a3);
|
||||||
|
new_thread.SetArg(3, a4);
|
||||||
|
new_thread.Run();
|
||||||
|
|
||||||
|
thread = new_thread.GetId();
|
||||||
|
|
||||||
|
group_info.threads[spu_num] = &new_thread;
|
||||||
|
|
||||||
ConLog.Write("New SPU Thread:");
|
ConLog.Write("New SPU Thread:");
|
||||||
ConLog.Write("entry = 0x%x", entry);
|
ConLog.Write("ls_entry = 0x%x", ls_entry);
|
||||||
ConLog.Write("name = %s", name);
|
ConLog.Write("name = %s", name);
|
||||||
ConLog.Write("a1 = 0x%x", a1);
|
ConLog.Write("a1 = 0x%x", a1);
|
||||||
ConLog.Write("a2 = 0x%x", a2);
|
ConLog.Write("a2 = 0x%x", a2);
|
||||||
ConLog.Write("a3 = 0x%x", a3);
|
ConLog.Write("a3 = 0x%x", a3);
|
||||||
ConLog.Write("a4 = 0x%x", a4);
|
ConLog.Write("a4 = 0x%x", a4);
|
||||||
|
ConLog.Write("ls_offset = 0x%x", ((SPUThread&)new_thread).dmac.ls_offset);
|
||||||
ConLog.SkipLn();
|
ConLog.SkipLn();
|
||||||
|
|
||||||
CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_SPU);
|
|
||||||
new_thread.SetOffset(g_spu_offset);
|
|
||||||
new_thread.SetEntry(entry - g_spu_offset);
|
|
||||||
new_thread.SetName(name);
|
|
||||||
new_thread.Run();
|
|
||||||
new_thread.Pause();
|
|
||||||
new_thread.SetArg(0, a1);
|
|
||||||
new_thread.SetArg(1, a2);
|
|
||||||
new_thread.SetArg(2, a3);
|
|
||||||
new_thread.SetArg(3, a4);
|
|
||||||
|
|
||||||
thread = new_thread.GetId();
|
|
||||||
|
|
||||||
group_info.threads[spu_num] = &new_thread;
|
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +172,7 @@ int sys_spu_thread_group_start(u32 id)
|
||||||
ID& id_data = Emu.GetIdManager().GetIDData(id);
|
ID& id_data = Emu.GetIdManager().GetIDData(id);
|
||||||
SpuGroupInfo& group_info = *(SpuGroupInfo*)id_data.m_data;
|
SpuGroupInfo& group_info = *(SpuGroupInfo*)id_data.m_data;
|
||||||
|
|
||||||
Emu.Pause();
|
//Emu.Pause();
|
||||||
for(int i=0; i<g_spu_group_thr_count; i++)
|
for(int i=0; i<g_spu_group_thr_count; i++)
|
||||||
{
|
{
|
||||||
if(group_info.threads[i])
|
if(group_info.threads[i])
|
||||||
|
@ -335,6 +343,72 @@ int sys_spu_thread_write_spu_mb(u32 id, u32 value)
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//187
|
||||||
|
int sys_spu_thread_set_spu_cfg(u32 id, u64 value)
|
||||||
|
{
|
||||||
|
sc_spu.Warning("sys_spu_thread_set_spu_cfg(id=0x%x, value=0x%x)", id, value);
|
||||||
|
|
||||||
|
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||||
|
|
||||||
|
if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
|
||||||
|
{
|
||||||
|
return CELL_ESRCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value > 3)
|
||||||
|
{
|
||||||
|
return CELL_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*(SPUThread*)thr).cfg.value = value;
|
||||||
|
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//188
|
||||||
|
int sys_spu_thread_get_spu_cfg(u32 id, mem64_t value)
|
||||||
|
{
|
||||||
|
sc_spu.Warning("sys_spu_thread_get_spu_cfg(id=0x%x, value_addr=0x%x)", id, value.GetAddr());
|
||||||
|
|
||||||
|
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||||
|
|
||||||
|
if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
|
||||||
|
{
|
||||||
|
return CELL_ESRCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = (*(SPUThread*)thr).cfg.value;
|
||||||
|
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//184
|
||||||
|
int sys_spu_thread_write_snr(u32 id, u32 number, u32 value)
|
||||||
|
{
|
||||||
|
CPUThread* thr = Emu.GetCPU().GetThread(id);
|
||||||
|
|
||||||
|
if(!thr || (thr->GetType() != CPU_THREAD_SPU && thr->GetType() != CPU_THREAD_RAW_SPU))
|
||||||
|
{
|
||||||
|
return CELL_ESRCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (number > 1)
|
||||||
|
{
|
||||||
|
return CELL_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*(SPUThread*)thr).cfg.value & (1<<number))
|
||||||
|
{ //logical OR
|
||||||
|
(*(SPUThread*)thr).SPU.SNR[number].PushUncond_OR(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ //overwrite
|
||||||
|
(*(SPUThread*)thr).SPU.SNR[number].PushUncond(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 spup_addr)
|
int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 spup_addr)
|
||||||
{
|
{
|
||||||
sc_spu.Warning("sys_spu_thread_group_connect_event_all_threads(id=0x%x, eq=0x%x, req=0x%llx, spup_addr=0x%x)",
|
sc_spu.Warning("sys_spu_thread_group_connect_event_all_threads(id=0x%x, eq=0x%x, req=0x%llx, spup_addr=0x%x)",
|
||||||
|
|
|
@ -29,4 +29,5 @@ struct sys_spu_image
|
||||||
be_t<u32> entry_point;
|
be_t<u32> entry_point;
|
||||||
be_t<u32> segs_addr;
|
be_t<u32> segs_addr;
|
||||||
be_t<int> nsegs;
|
be_t<int> nsegs;
|
||||||
|
u64 _img_offs;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue