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

@ -80,7 +80,7 @@ void SPUThread::InitRegs()
cfg.Reset();
dmac.ls_offset = m_offset;
ls_offset = m_offset;
SPU.Status.SetValue(SPU_STATUS_STOPPED);
@ -148,19 +148,27 @@ void SPUThread::DoClose()
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);
// FastStop-like routine is not defined (TODO);
// can't be called from another thread (because it doesn't make sense)
WriteLS32(0x0, 2);
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;
GPR[0]._u32[3] = 0x0;
CPUThread::Task();
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)
@ -206,11 +214,11 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
if ((addr <= 0x3ffff) && (addr + size <= 0x40000))
{
// 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))
{
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;
}
else
@ -256,13 +264,13 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
{
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;
}
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;
}
@ -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++)
{
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;
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++)
{
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);
}
@ -419,7 +427,7 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
u64 buf[16];
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])
{
changed++;
@ -464,8 +472,8 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
for (s32 i = (s32)PC; i < (s32)PC + 4 * 7; i += 4)
{
dis_asm.dump_pc = i;
dis_asm.offset = vm::get_ptr<u8>(dmac.ls_offset);
const u32 opcode = vm::read32(i + dmac.ls_offset);
dis_asm.offset = vm::get_ptr<u8>(ls_offset);
const u32 opcode = vm::read32(i + ls_offset);
(*SPU_instr::rrr_list)(&dis_asm, opcode);
if (i >= 0 && i < 0x40000)
{
@ -526,18 +534,20 @@ bool SPUThread::CheckEvents()
u32 SPUThread::GetChannelCount(u32 ch)
{
u32 res = 0xdeafbeef;
switch (ch)
{
case SPU_WrOutMbox: return SPU.Out_MBox.GetFreeCount();
case SPU_WrOutIntrMbox: return SPU.Out_IntrMBox.GetFreeCount();
case SPU_RdInMbox: return SPU.In_MBox.GetCount();
case MFC_RdTagStat: return MFC1.TagStatus.GetCount();
case MFC_RdListStallStat: return StallStat.GetCount();
case MFC_WrTagUpdate: return MFC1.TagStatus.GetCount(); // hack
case SPU_RdSigNotify1: return SPU.SNR[0].GetCount();
case SPU_RdSigNotify2: return SPU.SNR[1].GetCount();
case MFC_RdAtomicStat: return MFC1.AtomicStat.GetCount();
case SPU_RdEventStat: return CheckEvents() ? 1 : 0;
case SPU_WrOutMbox: res = SPU.Out_MBox.GetFreeCount(); break;
case SPU_WrOutIntrMbox: res = SPU.Out_IntrMBox.GetFreeCount(); break;
case SPU_RdInMbox: res = SPU.In_MBox.GetCount(); break;
case MFC_RdTagStat: res = MFC1.TagStatus.GetCount(); break;
case MFC_RdListStallStat: res = StallStat.GetCount(); break;
case MFC_WrTagUpdate: res = MFC1.TagStatus.GetCount(); break;// hack
case SPU_RdSigNotify1: res = SPU.SNR[0].GetCount(); break;
case SPU_RdSigNotify2: res = SPU.SNR[1].GetCount(); break;
case MFC_RdAtomicStat: res = MFC1.AtomicStat.GetCount(); break;
case SPU_RdEventStat: res = CheckEvents() ? 1 : 0; break;
default:
{
@ -546,12 +556,17 @@ u32 SPUThread::GetChannelCount(u32 ch)
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)
{
const u32 v = r._u32[3];
//LOG_NOTICE(Log::SPU, "%s(%s): v=0x%x", __FUNCTION__, spu_ch_name[ch], v);
switch (ch)
{
case SPU_WrOutIntrMbox:
@ -908,13 +923,27 @@ void SPUThread::ReadChannel(u128& r, u32 ch)
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;
}
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;
}
@ -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]);
//LOG_NOTICE(Log::SPU, "%s(%s) -> 0x%x", __FUNCTION__, spu_ch_name[ch], v);
}
void SPUThread::StopAndSignal(u32 code)
@ -973,6 +1004,18 @@ void SPUThread::StopAndSignal(u32 code)
switch (code)
{
case 0x001:
{
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
break;
}
case 0x002:
{
FastStop();
break;
}
case 0x110:
{
/* ===== sys_spu_thread_receive_event ===== */