MBox, some improvements

Some changes reverted (warnings), multi-thread safety fixed, MBox MMIO
modified
This commit is contained in:
Nekotekina 2013-12-13 05:35:28 +04:00
parent c9fc99c388
commit ee137323aa
3 changed files with 61 additions and 23 deletions

View File

@ -163,14 +163,17 @@ struct DMAC
return MFC_PPU_DMA_QUEUE_FULL;
}
while (_InterlockedCompareExchange(&proxy_lock, 1, 0));
while (_InterlockedExchange(&proxy_lock, 1));
_mm_lfence();
DMAC_Proxy& p = proxy[proxy_pos];
p.cmd = cmd;
p.tag = tag;
p.lsa = lsa;
p.ea = ea;
p.size = size;
_mm_sfence(); //for DoCmd()
proxy_pos++;
_mm_sfence();
proxy_lock = 0;
return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL;
@ -178,8 +181,10 @@ struct DMAC
void ClearCmd()
{
while (_InterlockedCompareExchange(&proxy_lock, 1, 0));
while (_InterlockedExchange(&proxy_lock, 1));
_mm_lfence();
memcpy(proxy, proxy + 1, --proxy_pos * sizeof(DMAC_Proxy));
_mm_sfence();
proxy_lock = 0; //release lock
}

View File

@ -62,11 +62,17 @@ bool RawSPUThread::Read32(const u64 addr, u32* value)
case MFC_EAL_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAL)", m_index); *value = MFC2.EAL.GetValue(); break;
case MFC_Size_Tag_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_Size_Tag)", m_index); *value = MFC2.Size_Tag.GetValue(); break;
case MFC_CMDStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_CMDStatus)", m_index); *value = MFC2.CMDStatus.GetValue(); break;
case MFC_QStatus_offs: *value = MFC2.QStatus.GetValue(); break;
case MFC_QStatus_offs:
ConLog.Warning("RawSPUThread[%d]: Read32(MFC_QStatus)", m_index);
*value = MFC2.QStatus.GetValue();
break;
case Prxy_QueryType_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryType)", m_index); *value = Prxy.QueryType.GetValue(); break;
case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryMask)", m_index); *value = Prxy.QueryMask.GetValue(); break;
case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_TagStatus)", m_index); *value = Prxy.TagStatus.GetValue(); break;
case SPU_Out_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Out_MBox)", m_index); while(!SPU.Out_MBox.Pop(*value) && !Emu.IsStopped()) Sleep(1); break;
case SPU_Out_MBox_offs:
ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Out_MBox)", m_index);
SPU.Out_MBox.PopUncond(*value); //if Out_MBox is empty yet, the result will be undefined
break;
case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_In_MBox)", m_index); while(!SPU.In_MBox.Pop(*value) && !Emu.IsStopped()) Sleep(1); break;
case SPU_MBox_Status_offs: //ConLog.Warning("RawSPUThread[%d]: Read32(SPU_MBox_Status)", m_index);
//SPU.MBox_Status.SetValue(SPU.Out_MBox.GetCount() ? SPU.MBox_Status.GetValue() | 1 : SPU.MBox_Status.GetValue() & ~1);
@ -183,7 +189,10 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value)
case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_QueryMask, 0x%x)", m_index, value); Prxy.QueryMask.SetValue(value); break;
case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_TagStatus, 0x%x)", m_index, value); Prxy.TagStatus.SetValue(value); break;
case SPU_Out_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_Out_MBox, 0x%x)", m_index, value); while(!SPU.Out_MBox.Push(value) && !Emu.IsStopped()) Sleep(1); break;
case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_In_MBox, 0x%x)", m_index, value); while(!SPU.In_MBox.Push(value) && !Emu.IsStopped()) Sleep(1); break;
case SPU_In_MBox_offs:
ConLog.Warning("RawSPUThread[%d]: Write32(SPU_In_MBox, 0x%x)", m_index, value);
SPU.In_MBox.PushUncond(value); //if In_MBox is already full, the last message will be overwritten
break;
case SPU_MBox_Status_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_MBox_Status, 0x%x)", m_index, value); SPU.MBox_Status.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;

View File

@ -282,37 +282,69 @@ public:
__forceinline bool Pop(u32& res)
{
while (_InterlockedCompareExchange(&m_lock, 1, 0));
while (_InterlockedExchange(&m_lock, 1));
_mm_lfence();
if(!m_index)
{
m_lock = 0; //release lock
return false;
}
res = m_value[--m_index];
_mm_sfence();
m_lock = 0;
return true;
}
__forceinline bool Push(u32 value)
{
while (_InterlockedCompareExchange(&m_lock, 1, 0));
while (_InterlockedExchange(&m_lock, 1));
_mm_lfence();
if(m_index >= max_count)
{
m_lock = 0; //release lock
return false;
}
m_value[m_index++] = value;
_mm_sfence();
m_lock = 0;
return true;
}
__forceinline void PushUncond(u32 value)
{
while (_InterlockedExchange(&m_lock, 1));
_mm_lfence();
if(m_index >= max_count)
m_value[max_count-1] = value; //last message is overwritten
else
m_value[m_index++] = value;
_mm_sfence();
m_lock = 0;
}
__forceinline void PopUncond(u32& res)
{
while (_InterlockedExchange(&m_lock, 1));
_mm_lfence();
if(!m_index)
res = 0; //result is undefined
else
res = m_value[--m_index];
_mm_sfence();
m_lock = 0;
}
u32 GetCount() const
{
while (m_lock);
_mm_lfence();
return m_index;
}
u32 GetFreeCount() const
{
while (m_lock);
_mm_lfence();
return max_count - m_index;
}
@ -383,6 +415,14 @@ public:
u16 tag = (u16)size_tag;
u16 size = size_tag >> 16;
ConLog.Warning("DMA %s:", op & MFC_PUT_CMD ? "PUT" : "GET");
ConLog.Warning("*** lsa = 0x%x", lsa);
ConLog.Warning("*** ea = 0x%llx", ea);
ConLog.Warning("*** tag = 0x%x", tag);
ConLog.Warning("*** size = 0x%x", size);
ConLog.Warning("*** cmd = 0x%x", cmd);
ConLog.SkipLn();
MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
}
break;
@ -406,22 +446,6 @@ public:
case SPU_WrOutIntrMbox:
return 0;//return SPU.OutIntr_Mbox.GetFreeCount();
case MFC_LSA:
return MFC1.LSA.max_count;
case MFC_EAH:
return MFC1.EAH.max_count;
case MFC_EAL:
return MFC1.EAL.max_count;
case MFC_Size:
case MFC_TagID:
return MFC1.Size_Tag.max_count;
case MFC_Cmd:
return MFC1.CMDStatus.max_count;
default:
ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]);
break;