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 EventManager SPUQs; // SPU Queue Mapping
SpuGroupInfo* group; // associated SPU Thread Group (null for raw spu) 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 struct IntrTag
{ {
u32 enabled; // 1 == true u32 enabled; // 1 == true
@ -937,47 +940,25 @@ public:
u32 GetChannelCount(u32 ch) u32 GetChannelCount(u32 ch)
{ {
u32 count;
switch(ch) switch(ch)
{ {
case SPU_WrOutMbox: case SPU_WrOutMbox: return SPU.Out_MBox.GetFreeCount();
return SPU.Out_MBox.GetFreeCount(); case SPU_RdInMbox: return SPU.In_MBox.GetCount();
case MFC_RdTagStat: return Prxy.TagStatus.GetCount();
case SPU_RdInMbox: case MFC_RdListStallStat: return StallStat.GetCount();
count = SPU.In_MBox.GetCount(); case MFC_WrTagUpdate: return Prxy.TagStatus.GetCount(); // hack
//ConLog.Warning("GetChannelCount(%s) -> %d", spu_ch_name[ch], count); case SPU_RdSigNotify1: return SPU.SNR[0].GetCount();
return count; case SPU_RdSigNotify2: return SPU.SNR[1].GetCount();
case MFC_RdAtomicStat: return Prxy.AtomicStat.GetCount();
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();
default: default:
{
LOG_ERROR(Log::SPU, "%s error: unknown/illegal channel (%d [%s]).", LOG_ERROR(Log::SPU, "%s error: unknown/illegal channel (%d [%s]).",
__FUNCTION__, ch, spu_ch_name[ch]); __FUNCTION__, ch, spu_ch_name[ch]);
break;
}
return 0; return 0;
} }
}
}
void WriteChannel(u32 ch, const SPU_GPR_hdr& r) void WriteChannel(u32 ch, const SPU_GPR_hdr& r)
{ {
@ -986,6 +967,7 @@ public:
switch(ch) switch(ch)
{ {
case SPU_WrOutIntrMbox: case SPU_WrOutIntrMbox:
{
if (!group) // if RawSPU if (!group) // if RawSPU
{ {
if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "SPU_WrOutIntrMbox: interrupt(v=0x%x)", v); if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "SPU_WrOutIntrMbox: interrupt(v=0x%x)", v);
@ -1121,46 +1103,66 @@ public:
} }
} }
break; break;
}
case SPU_WrOutMbox: case SPU_WrOutMbox:
{
//ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v); //ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v);
while (!SPU.Out_MBox.Push(v) && !Emu.IsStopped()) Sleep(1); while (!SPU.Out_MBox.Push(v) && !Emu.IsStopped()) Sleep(1);
break; break;
}
case MFC_WrTagMask: case MFC_WrTagMask:
{
//ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v); //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:
{
//ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v); //ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v);
Prxy.TagStatus.PushUncond(Prxy.QueryMask.GetValue()); Prxy.TagStatus.PushUncond(Prxy.QueryMask.GetValue());
break; break;
}
case MFC_LSA: case MFC_LSA:
{
MFC1.LSA.SetValue(v); MFC1.LSA.SetValue(v);
break; break;
}
case MFC_EAH: case MFC_EAH:
{
MFC1.EAH.SetValue(v); MFC1.EAH.SetValue(v);
break; break;
}
case MFC_EAL: case MFC_EAL:
{
MFC1.EAL.SetValue(v); MFC1.EAL.SetValue(v);
break; break;
}
case MFC_Size: case MFC_Size:
{
MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & 0xffff) | (v << 16)); MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & 0xffff) | (v << 16));
break; break;
}
case MFC_TagID: case MFC_TagID:
{
MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & ~0xffff) | (v & 0xffff)); MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & ~0xffff) | (v & 0xffff));
break; break;
}
case MFC_Cmd: case MFC_Cmd:
{
MFC1.CMDStatus.SetValue(v); MFC1.CMDStatus.SetValue(v);
EnqMfcCmd(MFC1); EnqMfcCmd(MFC1);
break; break;
}
case MFC_WrListStallAck: case MFC_WrListStallAck:
{ {
@ -1177,13 +1179,22 @@ public:
} }
StallList[v].MFCArgs = nullptr; StallList[v].MFCArgs = nullptr;
ListCmd(temp.lsa, temp.ea, temp.tag, temp.size, temp.cmd, *temp.MFCArgs); ListCmd(temp.lsa, temp.ea, temp.tag, temp.size, temp.cmd, *temp.MFCArgs);
}
break; break;
}
case SPU_WrDec:
{
m_dec_start = get_system_time();
m_dec_value = v;
break;
}
default: default:
{
LOG_ERROR(Log::SPU, "%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); 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]); if (Emu.IsStopped()) LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]);
} }
@ -1196,37 +1207,58 @@ public:
switch(ch) switch(ch)
{ {
case SPU_RdInMbox: case SPU_RdInMbox:
{
while (!SPU.In_MBox.Pop(v) && !Emu.IsStopped()) Sleep(1); while (!SPU.In_MBox.Pop(v) && !Emu.IsStopped()) Sleep(1);
//ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]); //ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]);
break; break;
}
case MFC_RdTagStat: case MFC_RdTagStat:
{
while (!Prxy.TagStatus.Pop(v) && !Emu.IsStopped()) Sleep(1); while (!Prxy.TagStatus.Pop(v) && !Emu.IsStopped()) Sleep(1);
//ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]); //ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]);
break; break;
}
case SPU_RdSigNotify1: case SPU_RdSigNotify1:
{
while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) Sleep(1); while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) Sleep(1);
//ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]); //ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]);
break; break;
}
case SPU_RdSigNotify2: case SPU_RdSigNotify2:
{
while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) Sleep(1); while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) Sleep(1);
//ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]); //ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]);
break; break;
}
case MFC_RdAtomicStat: case MFC_RdAtomicStat:
{
while (!Prxy.AtomicStat.Pop(v) && !Emu.IsStopped()) Sleep(1); while (!Prxy.AtomicStat.Pop(v) && !Emu.IsStopped()) Sleep(1);
break; break;
}
case MFC_RdListStallStat: case MFC_RdListStallStat:
{
while (!StallStat.Pop(v) && !Emu.IsStopped()) Sleep(1); 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: default:
{
LOG_ERROR(Log::SPU, "%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); 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]); if (Emu.IsStopped()) LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]);
} }