From c9fc99c388c9361600ef8dc8c4e024b61add94e0 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 11 Dec 2013 02:58:11 +0400 Subject: [PATCH] Basic DMA, MFC, channel changes Added new consts, thread-safe locks for critical resources, removed some warnings. Modified git-version.h --- rpcs3/Emu/Cell/MFC.h | 60 ++++++++++++++++++------------ rpcs3/Emu/Cell/RawSPUThread.cpp | 29 +++++++-------- rpcs3/Emu/Cell/SPUThread.cpp | 5 ++- rpcs3/Emu/Cell/SPUThread.h | 66 ++++++++++++++++++--------------- rpcs3/git-version.h | 4 +- 5 files changed, 93 insertions(+), 71 deletions(-) diff --git a/rpcs3/Emu/Cell/MFC.h b/rpcs3/Emu/Cell/MFC.h index c15947cbc7..54700c3285 100644 --- a/rpcs3/Emu/Cell/MFC.h +++ b/rpcs3/Emu/Cell/MFC.h @@ -3,21 +3,22 @@ enum { - MFC_PUT_CMD = 0x20, - MFC_GET_CMD = 0x40, - MFC_PUTL_CMD = 0x24, - MFC_GETL_CMD = 0x44, - MFC_GETLLAR_CMD = 0xD0, - MFC_PUTLLC_CMD = 0xB4, - MFC_PUTLLUC_CMD = 0xB0, - MFC_PUTQLLUC_CMD= 0xB8, - MFC_SNDSIG_CMD = 0xA0, - MFC_BARRIER_CMD = 0xC0, - MFC_EIEIO_CMD = 0xC8, - MFC_SYNC_CMD = 0xCC, - MFC_BARRIER_MASK= 0x01, - MFC_FENCE_MASK = 0x02, - MFC_MASK_CMD = 0xffff, + MFC_PUT_CMD = 0x20, MFC_PUTB_CMD = 0x21, MFC_PUTF_CMD = 0x22, + MFC_GET_CMD = 0x40, MFC_GETB_CMD = 0x41, MFC_GETF_CMD = 0x42, + MFC_PUTL_CMD = 0x24, MFC_PUTLB_CMD = 0x25, MFC_PUTLF_CMD = 0x26, + MFC_GETL_CMD = 0x44, MFC_GETLB_CMD = 0x45, MFC_GETLF_CMD = 0x46, + MFC_GETLLAR_CMD = 0xD0, + MFC_PUTLLC_CMD = 0xB4, + MFC_PUTLLUC_CMD = 0xB0, + MFC_PUTQLLUC_CMD = 0xB8, + MFC_SNDSIG_CMD = 0xA0, MFC_SNDSIGB_CMD = 0xA1, MFC_SNDSIGF_CMD = 0xA2, + MFC_BARRIER_CMD = 0xC0, + MFC_EIEIO_CMD = 0xC8, + MFC_SYNC_CMD = 0xCC, + + MFC_BARRIER_MASK = 0x01, + MFC_FENCE_MASK = 0x02, + MFC_MASK_CMD = 0xffff, }; enum @@ -142,11 +143,13 @@ public: struct DMAC { - DMAC_Queue queue[MFC_SPU_MAX_QUEUE_SPACE]; - DMAC_Proxy proxy[MFC_PPU_MAX_QUEUE_SPACE]; + //DMAC_Queue queue[MFC_SPU_MAX_QUEUE_SPACE]; //not used yet + DMAC_Proxy proxy[MFC_PPU_MAX_QUEUE_SPACE+MFC_SPU_MAX_QUEUE_SPACE]; //temporarily 24 u64 ls_offset; - std::atomic queue_pos; - std::atomic proxy_pos; + u32 queue_pos; + u32 proxy_pos; + u32 queue_lock; + u32 proxy_lock; u32 Cmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size) { @@ -160,31 +163,42 @@ struct DMAC return MFC_PPU_DMA_QUEUE_FULL; } - DMAC_Proxy& p = proxy[proxy_pos++]; + while (_InterlockedCompareExchange(&proxy_lock, 1, 0)); + DMAC_Proxy& p = proxy[proxy_pos]; p.cmd = cmd; p.tag = tag; p.lsa = lsa; p.ea = ea; p.size = size; + proxy_pos++; + proxy_lock = 0; return MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL; } + void ClearCmd() + { + while (_InterlockedCompareExchange(&proxy_lock, 1, 0)); + memcpy(proxy, proxy + 1, --proxy_pos * sizeof(DMAC_Proxy)); + proxy_lock = 0; //release lock + } + void DoCmd() { if(proxy_pos) { - DMAC_Proxy p = proxy[0]; - memcpy(proxy, proxy + 1, --proxy_pos * sizeof(DMAC_Proxy)); + const DMAC_Proxy& p = proxy[0]; - switch(p.cmd) + switch(p.cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK)) //barrier/fence ignored { case MFC_PUT_CMD: memcpy(Memory + p.ea, Memory + ls_offset + p.lsa, p.size); + ClearCmd(); break; case MFC_GET_CMD: memcpy(Memory + ls_offset + p.lsa, Memory + p.ea, p.size); + ClearCmd(); break; default: diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index ee0cf6c4b3..17d0512701 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -57,12 +57,12 @@ bool RawSPUThread::Read32(const u64 addr, u32* value) u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET; switch(offset) { - case MFC_LSA_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_LSA)", m_index); *value = MFC.LSA.GetValue(); break; - case MFC_EAH_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAH)", m_index); *value = MFC.EAH.GetValue(); break; - case MFC_EAL_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAL)", m_index); *value = MFC.EAL.GetValue(); break; - case MFC_Size_Tag_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_Size_Tag)", m_index); *value = MFC.Size_Tag.GetValue(); break; - case MFC_CMDStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_CMDStatus)", m_index); *value = MFC.CMDStatus.GetValue(); break; - case MFC_QStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_QStatus)", m_index); *value = MFC.QStatus.GetValue(); break; + case MFC_LSA_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_LSA)", m_index); *value = MFC2.LSA.GetValue(); break; + case MFC_EAH_offs: ConLog.Warning("RawSPUThread[%d]: Read32(MFC_EAH)", m_index); *value = MFC2.EAH.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_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 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; @@ -151,16 +151,15 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value) switch(offset) { - case MFC_LSA_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_LSA, 0x%x)", m_index, value); MFC.LSA.SetValue(value); break; - case MFC_EAH_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_EAH, 0x%x)", m_index, value); MFC.EAH.SetValue(value); break; - case MFC_EAL_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_EAL, 0x%x)", m_index, value); MFC.EAL.SetValue(value); break; - case MFC_Size_Tag_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_Size_Tag, 0x%x)", m_index, value); MFC.Size_Tag.SetValue(value); break; + case MFC_LSA_offs: MFC2.LSA.SetValue(value); break; + case MFC_EAH_offs: MFC2.EAH.SetValue(value); break; + case MFC_EAL_offs: MFC2.EAL.SetValue(value); break; + case MFC_Size_Tag_offs: MFC2.Size_Tag.SetValue(value); break; case MFC_CMDStatus_offs: - ConLog.Warning("RawSPUThread[%d]: Write32(MFC_CMDStatus, 0x%x)", m_index, value); - MFC.CMDStatus.SetValue(value); - DoMfcCmd(); + MFC2.CMDStatus.SetValue(value); + EnqMfcCmd(MFC2); break; - case MFC_QStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_QStatus, 0x%x)", m_index, value); MFC.QStatus.SetValue(value); break; + case MFC_QStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_QStatus, 0x%x)", m_index, value); MFC2.QStatus.SetValue(value); break; case Prxy_QueryType_offs: { ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_QueryType, 0x%x)", m_index, value); @@ -178,7 +177,7 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value) } Prxy.QueryType.SetValue(0); - MFC.QStatus.SetValue(Prxy.QueryMask.GetValue()); + MFC2.QStatus.SetValue(Prxy.QueryMask.GetValue()); } break; case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_QueryMask, 0x%x)", m_index, value); Prxy.QueryMask.SetValue(value); break; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 2faacb49bd..34e24b5471 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -46,11 +46,14 @@ void SPUThread::InitRegs() dmac.ls_offset = m_offset; dmac.proxy_pos = 0; dmac.queue_pos = 0; + dmac.proxy_lock = 0; + dmac.queue_lock = 0; SPU.RunCntl.SetValue(SPU_RUNCNTL_STOP); SPU.Status.SetValue(SPU_STATUS_RUNNING); Prxy.QueryType.SetValue(0); - MFC.CMDStatus.SetValue(0); + MFC1.CMDStatus.SetValue(0); + MFC2.CMDStatus.SetValue(0); //PC = SPU.NPC.GetValue(); } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 1745fc37b6..106306c181 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -265,6 +265,7 @@ public: private: u32 m_value[max_count]; u32 m_index; + u32 m_lock; public: @@ -276,19 +277,32 @@ public: void Init() { m_index = 0; + m_lock = 0; //simple lock } __forceinline bool Pop(u32& res) { - if(!m_index) return false; + while (_InterlockedCompareExchange(&m_lock, 1, 0)); + if(!m_index) + { + m_lock = 0; //release lock + return false; + } res = m_value[--m_index]; + m_lock = 0; return true; } __forceinline bool Push(u32 value) { - if(m_index >= max_count) return false; + while (_InterlockedCompareExchange(&m_lock, 1, 0)); + if(m_index >= max_count) + { + m_lock = 0; //release lock + return false; + } m_value[m_index++] = value; + m_lock = 0; return true; } @@ -313,7 +327,7 @@ public: } }; - struct + struct MFCReg { Channel<1> LSA; Channel<1> EAH; @@ -321,7 +335,7 @@ public: Channel<1> Size_Tag; Channel<1> CMDStatus; Channel<1> QStatus; - } MFC; + } MFC1, MFC2; struct { @@ -353,9 +367,9 @@ public: DMAC dmac; - void DoMfcCmd() + void EnqMfcCmd(MFCReg& MFCArgs) { - u32 cmd = MFC.CMDStatus.GetValue(); + u32 cmd = MFCArgs.CMDStatus.GetValue(); u16 op = cmd & MFC_MASK_CMD; switch(op & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK)) @@ -363,21 +377,13 @@ public: case MFC_PUT_CMD: case MFC_GET_CMD: { - u32 lsa = MFC.LSA.GetValue(); - u64 ea = (u64)MFC.EAL.GetValue() | ((u64)MFC.EAH.GetValue() << 32); - u32 size_tag = MFC.Size_Tag.GetValue(); + u32 lsa = MFCArgs.LSA.GetValue(); + u64 ea = (u64)MFCArgs.EAL.GetValue() | ((u64)MFCArgs.EAH.GetValue() << 32); + u32 size_tag = MFCArgs.Size_Tag.GetValue(); 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(); - - MFC.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size)); + MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size)); } break; @@ -401,20 +407,20 @@ public: return 0;//return SPU.OutIntr_Mbox.GetFreeCount(); case MFC_LSA: - return MFC.LSA.max_count; + return MFC1.LSA.max_count; case MFC_EAH: - return MFC.EAH.max_count; + return MFC1.EAH.max_count; case MFC_EAL: - return MFC.EAL.max_count; + return MFC1.EAL.max_count; case MFC_Size: case MFC_TagID: - return MFC.Size_Tag.max_count; + return MFC1.Size_Tag.max_count; case MFC_Cmd: - return MFC.CMDStatus.max_count; + return MFC1.CMDStatus.max_count; default: ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); @@ -455,28 +461,28 @@ public: break; case MFC_LSA: - MFC.LSA.SetValue(v); + MFC1.LSA.SetValue(v); break; case MFC_EAH: - MFC.EAH.SetValue(v); + MFC1.EAH.SetValue(v); break; case MFC_EAL: - MFC.EAL.SetValue(v); + MFC1.EAL.SetValue(v); break; case MFC_Size: - MFC.Size_Tag.SetValue((MFC.Size_Tag.GetValue() & 0xffff) | (v << 16)); + MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & 0xffff) | (v << 16)); break; case MFC_TagID: - MFC.Size_Tag.SetValue((MFC.Size_Tag.GetValue() & ~0xffff) | (v & 0xffff)); + MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & ~0xffff) | (v & 0xffff)); break; case MFC_Cmd: - MFC.CMDStatus.SetValue(v); - DoMfcCmd(); + MFC1.CMDStatus.SetValue(v); + EnqMfcCmd(MFC1); break; default: diff --git a/rpcs3/git-version.h b/rpcs3/git-version.h index 07a3d127dd..f770897486 100644 --- a/rpcs3/git-version.h +++ b/rpcs3/git-version.h @@ -1,6 +1,6 @@ // This is a generated file. -#define RPCS3_GIT_VERSION "d83a9b1" +#define RPCS3_GIT_VERSION "unknown" // If you don't want this file to update/recompile, change to 1. -#define RPCS3_GIT_VERSION_NO_UPDATE 0 +#define RPCS3_GIT_VERSION_NO_UPDATE 1