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
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; 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]; DMAC_Proxy& p = proxy[proxy_pos];
p.cmd = cmd; p.cmd = cmd;
p.tag = tag; p.tag = tag;
p.lsa = lsa; p.lsa = lsa;
p.ea = ea; p.ea = ea;
p.size = size; p.size = size;
_mm_sfence(); //for DoCmd()
proxy_pos++; proxy_pos++;
_mm_sfence();
proxy_lock = 0; proxy_lock = 0;
return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL; return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL;
@ -178,8 +181,10 @@ struct DMAC
void ClearCmd() void ClearCmd()
{ {
while (_InterlockedCompareExchange(&proxy_lock, 1, 0)); while (_InterlockedExchange(&proxy_lock, 1));
_mm_lfence();
memcpy(proxy, proxy + 1, --proxy_pos * sizeof(DMAC_Proxy)); memcpy(proxy, proxy + 1, --proxy_pos * sizeof(DMAC_Proxy));
_mm_sfence();
proxy_lock = 0; //release lock 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_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_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_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_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_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 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_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); 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); //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_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 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_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_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_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; 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) __forceinline bool Pop(u32& res)
{ {
while (_InterlockedCompareExchange(&m_lock, 1, 0)); while (_InterlockedExchange(&m_lock, 1));
_mm_lfence();
if(!m_index) if(!m_index)
{ {
m_lock = 0; //release lock m_lock = 0; //release lock
return false; return false;
} }
res = m_value[--m_index]; res = m_value[--m_index];
_mm_sfence();
m_lock = 0; m_lock = 0;
return true; return true;
} }
__forceinline bool Push(u32 value) __forceinline bool Push(u32 value)
{ {
while (_InterlockedCompareExchange(&m_lock, 1, 0)); while (_InterlockedExchange(&m_lock, 1));
_mm_lfence();
if(m_index >= max_count) if(m_index >= max_count)
{ {
m_lock = 0; //release lock m_lock = 0; //release lock
return false; return false;
} }
m_value[m_index++] = value; m_value[m_index++] = value;
_mm_sfence();
m_lock = 0; m_lock = 0;
return true; 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 u32 GetCount() const
{ {
while (m_lock);
_mm_lfence();
return m_index; return m_index;
} }
u32 GetFreeCount() const u32 GetFreeCount() const
{ {
while (m_lock);
_mm_lfence();
return max_count - m_index; return max_count - m_index;
} }
@ -383,6 +415,14 @@ public:
u16 tag = (u16)size_tag; u16 tag = (u16)size_tag;
u16 size = size_tag >> 16; 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)); MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
} }
break; break;
@ -406,22 +446,6 @@ public:
case SPU_WrOutIntrMbox: case SPU_WrOutIntrMbox:
return 0;//return SPU.OutIntr_Mbox.GetFreeCount(); 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: default:
ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]);
break; break;