Small update

This commit is contained in:
Nekotekina 2014-10-02 14:29:20 +04:00
parent 4a6779469c
commit 752449bbc0
10 changed files with 173 additions and 76 deletions

View file

@ -104,6 +104,16 @@ union u128
return ret; return ret;
} }
static u128 from32r(u32 _3, u32 _2 = 0, u32 _1 = 0, u32 _0 = 0)
{
u128 ret;
ret._u32[0] = _0;
ret._u32[1] = _1;
ret._u32[2] = _2;
ret._u32[3] = _3;
return ret;
}
static u128 fromBit(u32 bit) static u128 fromBit(u32 bit)
{ {
u128 ret = {}; u128 ret = {};

View file

@ -61,5 +61,4 @@ enum
struct DMAC struct DMAC
{ {
u32 ls_offset;
}; };

View file

@ -190,7 +190,7 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value)
void RawSPUThread::InitRegs() void RawSPUThread::InitRegs()
{ {
dmac.ls_offset = m_offset = (u32)GetStartAddr() + RAW_SPU_LS_OFFSET; ls_offset = m_offset = (u32)GetStartAddr() + RAW_SPU_LS_OFFSET;
SPUThread::InitRegs(); SPUThread::InitRegs();
} }

View file

@ -3,7 +3,7 @@
#define UNIMPLEMENTED() UNK(__FUNCTION__) #define UNIMPLEMENTED() UNK(__FUNCTION__)
#define MEM_AND_REG_HASH() \ #define MEM_AND_REG_HASH() \
unsigned char mem_h[20]; sha1(vm::get_ptr<u8>(CPU.dmac.ls_offset), 256*1024, mem_h); \ unsigned char mem_h[20]; sha1(vm::get_ptr<u8>(CPU.ls_offset), 256*1024, mem_h); \
unsigned char reg_h[20]; sha1((const unsigned char*)CPU.GPR, sizeof(CPU.GPR), reg_h); \ unsigned char reg_h[20]; sha1((const unsigned char*)CPU.GPR, sizeof(CPU.GPR), reg_h); \
LOG_NOTICE(Log::SPU, "Mem hash: 0x%llx, reg hash: 0x%llx", *(u64*)mem_h, *(u64*)reg_h); LOG_NOTICE(Log::SPU, "Mem hash: 0x%llx, reg hash: 0x%llx", *(u64*)mem_h, *(u64*)reg_h);

View file

@ -49,7 +49,7 @@ void SPURecompilerCore::Compile(u16 pos)
u64 time0 = 0; u64 time0 = 0;
SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode); SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode);
dis_asm.offset = vm::get_ptr<u8>(CPU.dmac.ls_offset); dis_asm.offset = vm::get_ptr<u8>(CPU.ls_offset);
StringLogger stringLogger; StringLogger stringLogger;
stringLogger.setOption(kLoggerOptionBinaryForm, true); stringLogger.setOption(kLoggerOptionBinaryForm, true);
@ -103,7 +103,7 @@ void SPURecompilerCore::Compile(u16 pos)
while (true) while (true)
{ {
const u32 opcode = vm::read32(CPU.dmac.ls_offset + pos * 4); const u32 opcode = vm::read32(CPU.ls_offset + pos * 4);
m_enc->do_finalize = false; m_enc->do_finalize = false;
if (opcode) if (opcode)
{ {
@ -182,8 +182,8 @@ void SPURecompilerCore::Compile(u16 pos)
u8 SPURecompilerCore::DecodeMemory(const u32 address) u8 SPURecompilerCore::DecodeMemory(const u32 address)
{ {
assert(CPU.dmac.ls_offset == address - CPU.PC); assert(CPU.ls_offset == address - CPU.PC);
const u32 m_offset = CPU.dmac.ls_offset; const u32 m_offset = CPU.ls_offset;
const u16 pos = (u16)(CPU.PC >> 2); const u16 pos = (u16)(CPU.PC >> 2);
//ConLog.Write("DecodeMemory: pos=%d", pos); //ConLog.Write("DecodeMemory: pos=%d", pos);

View file

@ -80,7 +80,7 @@ void SPUThread::InitRegs()
cfg.Reset(); cfg.Reset();
dmac.ls_offset = m_offset; ls_offset = m_offset;
SPU.Status.SetValue(SPU_STATUS_STOPPED); SPU.Status.SetValue(SPU_STATUS_STOPPED);
@ -148,19 +148,27 @@ void SPUThread::DoClose()
void SPUThread::FastCall(u32 ls_addr) void SPUThread::FastCall(u32 ls_addr)
{ {
// doesn't touch thread status (instead of PPUThread::FastCall2); // can't be called from another thread (because it doesn't make sense)
// can't be called from another thread (because it doesn't make sense); WriteLS32(0x0, 2);
// FastStop-like routine is not defined (TODO);
auto old_PC = PC; auto old_PC = PC;
auto old_stack = GPR[1]; // only saved and restored (may be wrong) auto old_LR = GPR[0]._u32[3];
auto old_stack = GPR[1]._u32[3]; // only saved and restored (may be wrong)
m_status = Running;
PC = ls_addr; PC = ls_addr;
GPR[0]._u32[3] = 0x0;
CPUThread::Task(); CPUThread::Task();
PC = old_PC; PC = old_PC;
GPR[1] = old_stack; GPR[0]._u32[3] = old_LR;
GPR[1]._u32[3] = old_stack;
}
void SPUThread::FastStop()
{
m_status = Stopped;
} }
void SPUThread::WriteSNR(bool number, u32 value) void SPUThread::WriteSNR(bool number, u32 value)
@ -206,11 +214,11 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
if ((addr <= 0x3ffff) && (addr + size <= 0x40000)) if ((addr <= 0x3ffff) && (addr + size <= 0x40000))
{ {
// LS access // LS access
ea = spu->dmac.ls_offset + addr; ea = spu->ls_offset + addr;
} }
else if ((cmd & MFC_PUT_CMD) && size == 4 && (addr == SYS_SPU_THREAD_SNR1 || addr == SYS_SPU_THREAD_SNR2)) else if ((cmd & MFC_PUT_CMD) && size == 4 && (addr == SYS_SPU_THREAD_SNR1 || addr == SYS_SPU_THREAD_SNR2))
{ {
spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, vm::read32(dmac.ls_offset + lsa)); spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, vm::read32(ls_offset + lsa));
return; return;
} }
else else
@ -256,13 +264,13 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
{ {
case MFC_PUT_CMD: case MFC_PUT_CMD:
{ {
memcpy(vm::get_ptr<void>(ea), vm::get_ptr<void>(dmac.ls_offset + lsa), size); memcpy(vm::get_ptr<void>(ea), vm::get_ptr<void>(ls_offset + lsa), size);
return; return;
} }
case MFC_GET_CMD: case MFC_GET_CMD:
{ {
memcpy(vm::get_ptr<void>(dmac.ls_offset + lsa), vm::get_ptr<void>(ea), size); memcpy(vm::get_ptr<void>(ls_offset + lsa), vm::get_ptr<void>(ea), size);
return; return;
} }
@ -294,7 +302,7 @@ void SPUThread::ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFC
for (u32 i = 0; i < list_size; i++) for (u32 i = 0; i < list_size; i++)
{ {
auto rec = vm::ptr<list_element>::make(dmac.ls_offset + list_addr + i * 8); auto rec = vm::ptr<list_element>::make(ls_offset + list_addr + i * 8);
u32 size = rec->ts; u32 size = rec->ts;
if (!(rec->s.ToBE() & se16(0x8000)) && size < 16 && size != 1 && size != 2 && size != 4 && size != 8) if (!(rec->s.ToBE() & se16(0x8000)) && size < 16 && size != 1 && size != 2 && size != 4 && size != 8)
@ -405,7 +413,7 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
for (u32 i = 0; i < 16; i++) for (u32 i = 0; i < 16; i++)
{ {
R_DATA[i] = vm::get_ptr<u64>(R_ADDR)[i]; R_DATA[i] = vm::get_ptr<u64>(R_ADDR)[i];
vm::get_ptr<u64>(dmac.ls_offset + lsa)[i] = R_DATA[i]; vm::get_ptr<u64>(ls_offset + lsa)[i] = R_DATA[i];
} }
MFCArgs.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS); MFCArgs.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS);
} }
@ -419,7 +427,7 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
u64 buf[16]; u64 buf[16];
for (u32 i = 0; i < 16; i++) for (u32 i = 0; i < 16; i++)
{ {
buf[i] = vm::get_ptr<u64>(dmac.ls_offset + lsa)[i]; buf[i] = vm::get_ptr<u64>(ls_offset + lsa)[i];
if (buf[i] != R_DATA[i]) if (buf[i] != R_DATA[i])
{ {
changed++; changed++;
@ -464,8 +472,8 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
for (s32 i = (s32)PC; i < (s32)PC + 4 * 7; i += 4) for (s32 i = (s32)PC; i < (s32)PC + 4 * 7; i += 4)
{ {
dis_asm.dump_pc = i; dis_asm.dump_pc = i;
dis_asm.offset = vm::get_ptr<u8>(dmac.ls_offset); dis_asm.offset = vm::get_ptr<u8>(ls_offset);
const u32 opcode = vm::read32(i + dmac.ls_offset); const u32 opcode = vm::read32(i + ls_offset);
(*SPU_instr::rrr_list)(&dis_asm, opcode); (*SPU_instr::rrr_list)(&dis_asm, opcode);
if (i >= 0 && i < 0x40000) if (i >= 0 && i < 0x40000)
{ {
@ -526,18 +534,20 @@ bool SPUThread::CheckEvents()
u32 SPUThread::GetChannelCount(u32 ch) u32 SPUThread::GetChannelCount(u32 ch)
{ {
u32 res = 0xdeafbeef;
switch (ch) switch (ch)
{ {
case SPU_WrOutMbox: return SPU.Out_MBox.GetFreeCount(); case SPU_WrOutMbox: res = SPU.Out_MBox.GetFreeCount(); break;
case SPU_WrOutIntrMbox: return SPU.Out_IntrMBox.GetFreeCount(); case SPU_WrOutIntrMbox: res = SPU.Out_IntrMBox.GetFreeCount(); break;
case SPU_RdInMbox: return SPU.In_MBox.GetCount(); case SPU_RdInMbox: res = SPU.In_MBox.GetCount(); break;
case MFC_RdTagStat: return MFC1.TagStatus.GetCount(); case MFC_RdTagStat: res = MFC1.TagStatus.GetCount(); break;
case MFC_RdListStallStat: return StallStat.GetCount(); case MFC_RdListStallStat: res = StallStat.GetCount(); break;
case MFC_WrTagUpdate: return MFC1.TagStatus.GetCount(); // hack case MFC_WrTagUpdate: res = MFC1.TagStatus.GetCount(); break;// hack
case SPU_RdSigNotify1: return SPU.SNR[0].GetCount(); case SPU_RdSigNotify1: res = SPU.SNR[0].GetCount(); break;
case SPU_RdSigNotify2: return SPU.SNR[1].GetCount(); case SPU_RdSigNotify2: res = SPU.SNR[1].GetCount(); break;
case MFC_RdAtomicStat: return MFC1.AtomicStat.GetCount(); case MFC_RdAtomicStat: res = MFC1.AtomicStat.GetCount(); break;
case SPU_RdEventStat: return CheckEvents() ? 1 : 0; case SPU_RdEventStat: res = CheckEvents() ? 1 : 0; break;
default: default:
{ {
@ -546,12 +556,17 @@ u32 SPUThread::GetChannelCount(u32 ch)
return 0; return 0;
} }
} }
//LOG_NOTICE(Log::SPU, "%s(%s) -> 0x%x", __FUNCTION__, spu_ch_name[ch], res);
return res;
} }
void SPUThread::WriteChannel(u32 ch, const u128& r) void SPUThread::WriteChannel(u32 ch, const u128& r)
{ {
const u32 v = r._u32[3]; const u32 v = r._u32[3];
//LOG_NOTICE(Log::SPU, "%s(%s): v=0x%x", __FUNCTION__, spu_ch_name[ch], v);
switch (ch) switch (ch)
{ {
case SPU_WrOutIntrMbox: case SPU_WrOutIntrMbox:
@ -908,13 +923,27 @@ void SPUThread::ReadChannel(u128& r, u32 ch)
case SPU_RdSigNotify1: case SPU_RdSigNotify1:
{ {
while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); if (cfg.value & 1)
{
while (!SPU.SNR[0].Pop_XCHG(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
else
{
while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
break; break;
} }
case SPU_RdSigNotify2: case SPU_RdSigNotify2:
{ {
while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); if (cfg.value & 2)
{
while (!SPU.SNR[1].Pop_XCHG(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
else
{
while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
break; break;
} }
@ -964,6 +993,8 @@ void SPUThread::ReadChannel(u128& r, u32 ch)
} }
if (Emu.IsStopped()) LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]); if (Emu.IsStopped()) LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]);
//LOG_NOTICE(Log::SPU, "%s(%s) -> 0x%x", __FUNCTION__, spu_ch_name[ch], v);
} }
void SPUThread::StopAndSignal(u32 code) void SPUThread::StopAndSignal(u32 code)
@ -973,6 +1004,18 @@ void SPUThread::StopAndSignal(u32 code)
switch (code) switch (code)
{ {
case 0x001:
{
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
break;
}
case 0x002:
{
FastStop();
break;
}
case 0x110: case 0x110:
{ {
/* ===== sys_spu_thread_receive_event ===== */ /* ===== sys_spu_thread_receive_event ===== */

View file

@ -420,7 +420,7 @@ public:
struct { u32 EAH, EAL; }; struct { u32 EAH, EAL; };
}; };
DMAC dmac; u32 ls_offset;
void ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size); void ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size);
@ -510,6 +510,7 @@ public:
virtual void InitRegs(); virtual void InitRegs();
virtual void Task(); virtual void Task();
void FastCall(u32 ls_addr); void FastCall(u32 ls_addr);
void FastStop();
protected: protected:
virtual void DoReset(); virtual void DoReset();

View file

@ -102,14 +102,16 @@ s64 spursInit(
{ {
spurs->m.xC0[i] = -1; spurs->m.xC0[i] = -1;
} }
// default or system workload:
#ifdef PRX_DEBUG #ifdef PRX_DEBUG
spurs->m.unk7 = vm::read32(libsre_rtoc - 0x7EA4); // write 64-bit pointer to unknown data spurs->m.wklSysG.pm.set(be_t<u64>::make(vm::read32(libsre_rtoc - 0x7EA4)));
#else #else
spurs->m.unk7 = 0x7ull << 48 | 0x7; // wrong 64-bit address spurs->m.wklSysG.pm.set(be_t<u64>::make(0x100)); // wrong 64-bit address
#endif #endif
spurs->m.unk8 = 0ull; spurs->m.wklSysG.data = 0;
spurs->m.unk9 = 0x2200; spurs->m.wklSysG.size = 0x2200;
spurs->m.unk10 = -1; spurs->m.wklSysG.copy.write_relaxed(0xff);
u32 sem; u32 sem;
for (u32 i = 0; i < 0x10; i++) for (u32 i = 0; i < 0x10; i++)
{ {
@ -161,13 +163,58 @@ s64 spursInit(
name += "CellSpursKernel0"; name += "CellSpursKernel0";
for (s32 num = 0; num < nSpus; num++, name[name.size() - 1]++) for (s32 num = 0; num < nSpus; num++, name[name.size() - 1]++)
{ {
spurs->m.spus[num] = spu_thread_initialize(tg, num, spurs->m.spuImg, name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, 0, 0, 0, 0, [spurs, num, isSecond](SPUThread& CPU) spurs->m.spus[num] = spu_thread_initialize(tg, num, spurs->m.spuImg, name, SYS_SPU_THREAD_OPTION_DEC_SYNC_TB_ENABLE, 0, 0, 0, 0, [spurs, num, isSecond](SPUThread& SPU)
{ {
#ifdef PRX_DEBUG #ifdef PRX_DEBUG_XXX
CPU.GPR[3]._u32[3] = num; SPU.GPR[3]._u32[3] = num;
CPU.GPR[4]._u64[1] = spurs.addr(); SPU.GPR[4]._u64[1] = spurs.addr();
return CPU.FastCall(CPU.PC); return SPU.FastCall(SPU.PC);
#endif #endif
SPU.WriteLS128(0x1c0, u128::from32r(0, spurs.addr(), num, 0x1f));
u32 wid = 0x20;
while (true)
{
if (Emu.IsStopped())
{
cellSpurs->Warning("Spurs Kernel aborted");
return;
}
// get current workload info:
auto& wkl = wid <= 15 ? spurs->m.wklG1[wid] : (wid <= 31 && isSecond ? spurs->m.wklG2[wid & 0xf] : spurs->m.wklSysG);
if (SPU.ReadLS64(0x1d0) != wkl.pm.addr())
{
// load executable code:
memcpy(vm::get_ptr<void>(SPU.ls_offset + 0xa00), wkl.pm.get_ptr(), wkl.size);
SPU.WriteLS64(0x1d0, wkl.pm.addr());
SPU.WriteLS32(0x1d8, wkl.priority.ToLE() >> 24 & 0xff); // ???
}
if (!isSecond) SPU.WriteLS16(0x1e8, 0);
// run workload:
SPU.GPR[1]._u32[3] = 0x3FFB0;
SPU.GPR[3]._u32[3] = 0x100;
SPU.GPR[4]._u64[1] = wkl.data;
SPU.GPR[5]._u32[3] = 0;
SPU.FastCall(0xa00);
// check status:
auto status = SPU.SPU.Status.GetValue();
if (status == SPU_STATUS_STOPPED_BY_STOP)
{
return;
}
else
{
assert(status == SPU_STATUS_RUNNING);
}
// get workload id:
}
})->GetId(); })->GetId();
} }
@ -240,7 +287,7 @@ s64 spursInit(
for (u32 i = 0; i < 16; i++) for (u32 i = 0; i < 16; i++)
{ {
if (spurs->m.wklStat1[i].read_relaxed() == 2 && if (spurs->m.wklStat1[i].read_relaxed() == 2 &&
spurs->m.wklG1[i].wklPriority.ToBE() != 0 && spurs->m.wklG1[i].priority.ToBE() != 0 &&
spurs->m.wklMaxCnt[i].read_relaxed() & 0xf spurs->m.wklMaxCnt[i].read_relaxed() & 0xf
) )
{ {
@ -258,7 +305,7 @@ s64 spursInit(
if (spurs->m.flags1 & SF1_IS_SECOND) for (u32 i = 0; i < 16; i++) if (spurs->m.flags1 & SF1_IS_SECOND) for (u32 i = 0; i < 16; i++)
{ {
if (spurs->m.wklStat2[i].read_relaxed() == 2 && if (spurs->m.wklStat2[i].read_relaxed() == 2 &&
spurs->m.wklG2[i].wklPriority.ToBE() != 0 && spurs->m.wklG2[i].priority.ToBE() != 0 &&
spurs->m.wklMaxCnt[i].read_relaxed() & 0xf0 spurs->m.wklMaxCnt[i].read_relaxed() & 0xf0
) )
{ {
@ -951,10 +998,10 @@ s32 spursAddWorkload(
spurs->m.wklStat1[wnum].write_relaxed(1); spurs->m.wklStat1[wnum].write_relaxed(1);
spurs->m.wklD1[wnum] = 0; spurs->m.wklD1[wnum] = 0;
spurs->m.wklE1[wnum] = 0; spurs->m.wklE1[wnum] = 0;
spurs->m.wklG1[wnum].wklPm = pm; spurs->m.wklG1[wnum].pm = pm;
spurs->m.wklG1[wnum].wklArg = data; spurs->m.wklG1[wnum].data = data;
spurs->m.wklG1[wnum].wklSize = size; spurs->m.wklG1[wnum].size = size;
spurs->m.wklG1[wnum].wklPriority = *(be_t<u64>*)priorityTable; spurs->m.wklG1[wnum].priority = *(be_t<u64>*)priorityTable;
spurs->m.wklH1[wnum].nameClass = nameClass; spurs->m.wklH1[wnum].nameClass = nameClass;
spurs->m.wklH1[wnum].nameInstance = nameInstance; spurs->m.wklH1[wnum].nameInstance = nameInstance;
memset(spurs->m.wklF1[wnum].unk0, 0, 0x20); // clear struct preserving semaphore id memset(spurs->m.wklF1[wnum].unk0, 0, 0x20); // clear struct preserving semaphore id
@ -978,10 +1025,10 @@ s32 spursAddWorkload(
spurs->m.wklStat2[index].write_relaxed(1); spurs->m.wklStat2[index].write_relaxed(1);
spurs->m.wklD2[index] = 0; spurs->m.wklD2[index] = 0;
spurs->m.wklE2[index] = 0; spurs->m.wklE2[index] = 0;
spurs->m.wklG2[index].wklPm = pm; spurs->m.wklG2[index].pm = pm;
spurs->m.wklG2[index].wklArg = data; spurs->m.wklG2[index].data = data;
spurs->m.wklG2[index].wklSize = size; spurs->m.wklG2[index].size = size;
spurs->m.wklG2[index].wklPriority = *(be_t<u64>*)priorityTable; spurs->m.wklG2[index].priority = *(be_t<u64>*)priorityTable;
spurs->m.wklH2[index].nameClass = nameClass; spurs->m.wklH2[index].nameClass = nameClass;
spurs->m.wklH2[index].nameInstance = nameInstance; spurs->m.wklH2[index].nameInstance = nameInstance;
memset(spurs->m.wklF2[index].unk0, 0, 0x20); // clear struct preserving semaphore id memset(spurs->m.wklF2[index].unk0, 0, 0x20); // clear struct preserving semaphore id
@ -1034,21 +1081,21 @@ s32 spursAddWorkload(
if (mask & m) if (mask & m)
{ {
CellSpurs::_sub_str3& current = i <= 15 ? spurs->m.wklG1[i] : spurs->m.wklG2[i & 0xf]; CellSpurs::_sub_str3& current = i <= 15 ? spurs->m.wklG1[i] : spurs->m.wklG2[i & 0xf];
if (current.wklPm.addr() == wkl.wklPm.addr()) if (current.pm.addr() == wkl.pm.addr())
{ {
// if a workload with identical policy module found // if a workload with identical policy module found
res_wkl = current.wklCopy.read_relaxed(); res_wkl = current.copy.read_relaxed();
break; break;
} }
else else
{ {
k |= 0x80000000 >> current.wklCopy.read_relaxed(); k |= 0x80000000 >> current.copy.read_relaxed();
res_wkl = cntlz32(~k); res_wkl = cntlz32(~k);
} }
} }
} }
wkl.wklCopy.exchange((u8)res_wkl); wkl.copy.exchange((u8)res_wkl);
v = mask | (0x80000000u >> wnum); v = mask | (0x80000000u >> wnum);
}); });
assert(res_wkl <= 31); assert(res_wkl <= 31);

View file

@ -221,8 +221,6 @@ struct CellSpurs
struct _sub_str1 struct _sub_str1
{ {
static const uint size = 0x80;
u8 unk0[0x20]; u8 unk0[0x20];
be_t<u64> sem; // 0x20 be_t<u64> sem; // 0x20
u8 unk1[0x8]; u8 unk1[0x8];
@ -231,10 +229,10 @@ struct CellSpurs
u8 unk2[0x40]; u8 unk2[0x40];
}; };
static_assert(sizeof(_sub_str1) == 0x80, "Wrong _sub_str1 size");
struct _sub_str2 struct _sub_str2
{ {
static const uint size = 0x80;
be_t<u32> unk0; be_t<u32> unk0;
be_t<u32> unk1; be_t<u32> unk1;
be_t<u32> unk2; be_t<u32> unk2;
@ -243,17 +241,19 @@ struct CellSpurs
u8 unk_[0x68]; u8 unk_[0x68];
}; };
static_assert(sizeof(_sub_str2) == 0x80, "Wrong _sub_str2 size");
struct _sub_str3 struct _sub_str3
{ {
static const uint size = 0x20; vm::bptr<const void, 1, u64> pm; // policy module
be_t<u64> data; // spu argument
vm::bptr<const void, 1, u64> wklPm; // policy module be_t<u32> size;
be_t<u64> wklArg; // spu argument atomic_t<u8> copy;
be_t<u32> wklSize; be_t<u64> priority;
atomic_t<u8> wklCopy;
be_t<u64> wklPriority;
}; };
static_assert(sizeof(_sub_str3) == 0x20, "Wrong _sub_str3 size");
struct _sub_str4 struct _sub_str4
{ {
static const uint size = 0x10; static const uint size = 0x10;
@ -315,11 +315,7 @@ struct CellSpurs
be_t<u64> unk13; // 0x990 be_t<u64> unk13; // 0x990
u8 unknown4[0xB00 - 0x998]; u8 unknown4[0xB00 - 0x998];
_sub_str3 wklG1[0x10]; // 0xB00 _sub_str3 wklG1[0x10]; // 0xB00
be_t<u64> unk7; // 0xD00 _sub_str3 wklSysG; // 0xD00
be_t<u64> unk8; // 0xD08
be_t<u32> unk9; // 0xD10
u8 unk10; // 0xD14
u8 unknown5[0xD20 - 0xD15];
be_t<u64> ppu0; // 0xD20 be_t<u64> ppu0; // 0xD20
be_t<u64> ppu1; // 0xD28 be_t<u64> ppu1; // 0xD28
be_t<u32> spuTG; // 0xD30 be_t<u32> spuTG; // 0xD30

View file

@ -236,6 +236,7 @@ s32 sys_spu_thread_group_start(u32 id)
CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]); CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]);
if (t) if (t)
{ {
((SPUThread*)t)->SPU.Status.SetValue(SPU_STATUS_RUNNING);
t->Exec(); t->Exec();
} }
} }
@ -471,7 +472,7 @@ s32 sys_spu_thread_group_join(u32 id, vm::ptr<be_t<u32>> cause, vm::ptr<be_t<u32
{ {
while (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i])) while (CPUThread* t = Emu.GetCPU().GetThread(group_info->list[i]))
{ {
if (!t->IsRunning()) if (!t->IsAlive())
{ {
if (((SPUThread*)t)->SPU.Status.GetValue() != SPU_STATUS_STOPPED_BY_STOP) if (((SPUThread*)t)->SPU.Status.GetValue() != SPU_STATUS_STOPPED_BY_STOP)
{ {