SPU Decrementer

This commit is contained in:
Nekotekina 2014-07-05 23:23:34 +04:00
parent 061fe50835
commit d16953d392
1 changed files with 85 additions and 53 deletions

View File

@ -325,6 +325,9 @@ public:
EventManager SPUQs; // SPU Queue Mapping
SpuGroupInfo* group; // associated SPU Thread Group (null for raw spu)
u64 m_dec_start; // timestamp of writing decrementer value
u32 m_dec_value; // written decrementer value
struct IntrTag
{
u32 enabled; // 1 == true
@ -937,46 +940,24 @@ public:
u32 GetChannelCount(u32 ch)
{
u32 count;
switch(ch)
{
case SPU_WrOutMbox:
return SPU.Out_MBox.GetFreeCount();
case SPU_RdInMbox:
count = SPU.In_MBox.GetCount();
//ConLog.Warning("GetChannelCount(%s) -> %d", spu_ch_name[ch], count);
return count;
case SPU_WrOutIntrMbox:
LOG_WARNING(Log::SPU, "GetChannelCount(%s) = 0", spu_ch_name[ch]);
return 0;
case MFC_RdTagStat:
return Prxy.TagStatus.GetCount();
case MFC_RdListStallStat:
return StallStat.GetCount();
case MFC_WrTagUpdate:
return Prxy.TagStatus.GetCount(); // hack
case SPU_RdSigNotify1:
return SPU.SNR[0].GetCount();
case SPU_RdSigNotify2:
return SPU.SNR[1].GetCount();
case MFC_RdAtomicStat:
return Prxy.AtomicStat.GetCount();
case SPU_WrOutMbox: return SPU.Out_MBox.GetFreeCount();
case SPU_RdInMbox: return SPU.In_MBox.GetCount();
case MFC_RdTagStat: return Prxy.TagStatus.GetCount();
case MFC_RdListStallStat: return StallStat.GetCount();
case MFC_WrTagUpdate: return Prxy.TagStatus.GetCount(); // hack
case SPU_RdSigNotify1: return SPU.SNR[0].GetCount();
case SPU_RdSigNotify2: return SPU.SNR[1].GetCount();
case MFC_RdAtomicStat: return Prxy.AtomicStat.GetCount();
default:
{
LOG_ERROR(Log::SPU, "%s error: unknown/illegal channel (%d [%s]).",
__FUNCTION__, ch, spu_ch_name[ch]);
break;
return 0;
}
}
return 0;
}
void WriteChannel(u32 ch, const SPU_GPR_hdr& r)
@ -986,6 +967,7 @@ public:
switch(ch)
{
case SPU_WrOutIntrMbox:
{
if (!group) // if RawSPU
{
if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "SPU_WrOutIntrMbox: interrupt(v=0x%x)", v);
@ -1010,7 +992,7 @@ public:
else
{
u8 code = v >> 24;
if (code < 64)
if (code < 64)
{
/* ===== sys_spu_thread_send_event ===== */
@ -1120,47 +1102,67 @@ public:
return;
}
}
break;
break;
}
case SPU_WrOutMbox:
{
//ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v);
while (!SPU.Out_MBox.Push(v) && !Emu.IsStopped()) Sleep(1);
break;
break;
}
case MFC_WrTagMask:
{
//ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v);
Prxy.QueryMask.SetValue(v);
break;
break;
}
case MFC_WrTagUpdate:
{
//ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v);
Prxy.TagStatus.PushUncond(Prxy.QueryMask.GetValue());
break;
break;
}
case MFC_LSA:
{
MFC1.LSA.SetValue(v);
break;
break;
}
case MFC_EAH:
{
MFC1.EAH.SetValue(v);
break;
break;
}
case MFC_EAL:
{
MFC1.EAL.SetValue(v);
break;
break;
}
case MFC_Size:
{
MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & 0xffff) | (v << 16));
break;
break;
}
case MFC_TagID:
{
MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & ~0xffff) | (v & 0xffff));
break;
break;
}
case MFC_Cmd:
{
MFC1.CMDStatus.SetValue(v);
EnqMfcCmd(MFC1);
break;
break;
}
case MFC_WrListStallAck:
{
@ -1177,12 +1179,21 @@ public:
}
StallList[v].MFCArgs = nullptr;
ListCmd(temp.lsa, temp.ea, temp.tag, temp.size, temp.cmd, *temp.MFCArgs);
break;
}
case SPU_WrDec:
{
m_dec_start = get_system_time();
m_dec_value = v;
break;
}
break;
default:
{
LOG_ERROR(Log::SPU, "%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]);
break;
break;
}
}
if (Emu.IsStopped()) LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]);
@ -1196,36 +1207,57 @@ public:
switch(ch)
{
case SPU_RdInMbox:
{
while (!SPU.In_MBox.Pop(v) && !Emu.IsStopped()) Sleep(1);
//ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]);
break;
break;
}
case MFC_RdTagStat:
{
while (!Prxy.TagStatus.Pop(v) && !Emu.IsStopped()) Sleep(1);
//ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]);
break;
break;
}
case SPU_RdSigNotify1:
{
while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) Sleep(1);
//ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]);
break;
break;
}
case SPU_RdSigNotify2:
{
while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) Sleep(1);
//ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]);
break;
break;
}
case MFC_RdAtomicStat:
{
while (!Prxy.AtomicStat.Pop(v) && !Emu.IsStopped()) Sleep(1);
break;
break;
}
case MFC_RdListStallStat:
{
while (!StallStat.Pop(v) && !Emu.IsStopped()) Sleep(1);
break;
break;
}
case SPU_RdDec:
{
// decrementer freq is probably 80 MHz
v = m_dec_value - (u32)(get_system_time() - m_dec_start) * 80;
break;
}
default:
{
LOG_ERROR(Log::SPU, "%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]);
break;
break;
}
}
if (Emu.IsStopped()) LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]);