diff --git a/rpcs3/Emu/CPU/CPUThreadManager.cpp b/rpcs3/Emu/CPU/CPUThreadManager.cpp index e2e3ad886d..245e01875f 100644 --- a/rpcs3/Emu/CPU/CPUThreadManager.cpp +++ b/rpcs3/Emu/CPU/CPUThreadManager.cpp @@ -110,22 +110,14 @@ CPUThread* CPUThreadManager::GetThread(u32 id) RawSPUThread* CPUThreadManager::GetRawSPUThread(u32 num) { - std::lock_guard lock(m_mtx_thread); - - for (u32 i = 0; i < m_threads.size(); i++) + if (num < sizeof(Memory.RawSPUMem) / sizeof(Memory.RawSPUMem[0])) { - if (m_threads[i]->GetType() == CPU_THREAD_RAW_SPU) - { - RawSPUThread* t = (RawSPUThread*)m_threads[i]; - - if (t->GetIndex() == num) - { - return t; - } - } + return (RawSPUThread*)Memory.RawSPUMem[num]; + } + else + { + return nullptr; } - - return nullptr; } void CPUThreadManager::NotifyThread(const u32 id) diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index 1521e35cea..2b0ab6c68e 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -28,44 +28,136 @@ bool RawSPUThread::Read32(const u64 addr, u32* value) return MemoryBlock::Read32(addr, value); } - u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET; + const u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET; + switch(offset) { - case MFC_LSA_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(MFC_LSA)", m_index); *value = MFC2.LSA.GetValue(); break; - case MFC_EAH_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(MFC_EAH)", m_index); *value = MFC2.EAH.GetValue(); break; - case MFC_EAL_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(MFC_EAL)", m_index); *value = MFC2.EAL.GetValue(); break; - case MFC_Size_Tag_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(MFC_Size_Tag)", m_index); *value = MFC2.Size_Tag.GetValue(); break; - case MFC_CMDStatus_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(MFC_CMDStatus)", m_index); *value = MFC2.CMDStatus.GetValue(); break; + case MFC_LSA_offs: + { + LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(MFC_LSA)", m_index); + *value = MFC2.LSA.GetValue(); + break; + } + + case MFC_EAH_offs: + { + LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(MFC_EAH)", m_index); + *value = MFC2.EAH.GetValue(); + break; + } + + case MFC_EAL_offs: + { + LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(MFC_EAL)", m_index); + *value = MFC2.EAL.GetValue(); + break; + } + + case MFC_Size_Tag_offs: + { + LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(MFC_Size_Tag)", m_index); + *value = MFC2.Size_Tag.GetValue(); + break; + } + + case MFC_CMDStatus_offs: + { + LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(MFC_CMDStatus)", m_index); + *value = MFC2.CMDStatus.GetValue(); + break; + } + case MFC_QStatus_offs: + { LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(MFC_QStatus)", m_index); - *value = MFC2.QStatus.GetValue(); - break; - case Prxy_QueryType_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(Prxy_QueryType)", m_index); *value = Prxy.QueryType.GetValue(); break; - case Prxy_QueryMask_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(Prxy_QueryMask)", m_index); *value = Prxy.QueryMask.GetValue(); break; - case Prxy_TagStatus_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(Prxy_TagStatus)", m_index); *value = Prxy.TagStatus.GetValue(); break; + *value = MFC2.QStatus.GetValue(); + break; + } + + case Prxy_QueryType_offs: + { + LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(Prxy_QueryType)", m_index); + *value = Prxy.QueryType.GetValue(); + break; + } + + case Prxy_QueryMask_offs: + { + LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(Prxy_QueryMask)", m_index); + *value = Prxy.QueryMask.GetValue(); + break; + } + + case Prxy_TagStatus_offs: + { + LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(Prxy_TagStatus)", m_index); + *value = Prxy.TagStatus.GetValue(); + break; + } + case SPU_Out_MBox_offs: - //LOG_WARNING(Log::SPU, "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: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(SPU_In_MBox)", m_index); while(!SPU.In_MBox.Pop(*value) && !Emu.IsStopped()) Sleep(1); break; - case SPU_MBox_Status_offs: //LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(SPU_MBox_Status)", m_index); + { + // if Out_MBox is empty, the result is undefined + SPU.Out_MBox.PopUncond(*value); + break; + } + + case SPU_In_MBox_offs: + { + LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(SPU_In_MBox)", m_index); + while (!SPU.In_MBox.Pop(*value) && !Emu.IsStopped()) Sleep(1); + break; + } + + case SPU_MBox_Status_offs: + { + //LOG_WARNING(Log::SPU, "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() & 0xff) | (SPU.In_MBox.GetFreeCount() << 8)); *value = SPU.MBox_Status.GetValue(); break; - case SPU_RunCntl_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(SPU_RunCntl)", m_index); *value = (u32)IsRunning(); break; + } + + case SPU_RunCntl_offs: + { + LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(SPU_RunCntl)", m_index); + *value = (u32)IsRunning(); + break; + } + case SPU_Status_offs: - //LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(SPU_Status)", m_index); + { *value = SPU.Status.GetValue(); break; - case SPU_NPC_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(SPU_NPC)", m_index); *value = SPU.NPC.GetValue(); break; - case SPU_RdSigNotify1_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(SPU_RdSigNotify1)", m_index); *value = SPU.SNR[0].GetValue(); break; - case SPU_RdSigNotify2_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Read32(SPU_RdSigNotify2)", m_index); *value = SPU.SNR[1].GetValue(); break; + } + + case SPU_NPC_offs: + { + LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(SPU_NPC)", m_index); + *value = SPU.NPC.GetValue(); + break; + } + + case SPU_RdSigNotify1_offs: + { + LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(SPU_RdSigNotify1)", m_index); + *value = SPU.SNR[0].GetValue(); + break; + } + + case SPU_RdSigNotify2_offs: + { + LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(SPU_RdSigNotify2)", m_index); + *value = SPU.SNR[1].GetValue(); + break; + } default: + { LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(0x%x)", m_index, offset); Emu.Pause(); - break; + return false; + } } return true; @@ -78,19 +170,48 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value) return MemoryBlock::Write32(addr, value); } - u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET; + const u32 offset = addr - GetStartAddr() - RAW_SPU_PROB_OFFSET; switch(offset) { - 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_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: + { MFC2.CMDStatus.SetValue(value); EnqMfcCmd(MFC2); - break; - case MFC_QStatus_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(MFC_QStatus, 0x%x)", m_index, value); MFC2.QStatus.SetValue(value); break; + break; + } + + case MFC_QStatus_offs: + { + LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Write32(MFC_QStatus, 0x%x)", m_index, value); + //MFC2.QStatus.SetValue(value); + break; + } + case Prxy_QueryType_offs: { LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(Prxy_QueryType, 0x%x)", m_index, value); @@ -109,16 +230,44 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value) Prxy.QueryType.SetValue(0); MFC2.QStatus.SetValue(Prxy.QueryMask.GetValue()); + break; } - break; - case Prxy_QueryMask_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(Prxy_QueryMask, 0x%x)", m_index, value); Prxy.QueryMask.SetValue(value); break; - case Prxy_TagStatus_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(Prxy_TagStatus, 0x%x)", m_index, value); Prxy.TagStatus.SetValue(value); break; - case SPU_Out_MBox_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_Out_MBox, 0x%x)", m_index, value); while(!SPU.Out_MBox.Push(value) && !Emu.IsStopped()) Sleep(1); break; + + case Prxy_QueryMask_offs: + { + LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(Prxy_QueryMask, 0x%x)", m_index, value); + Prxy.QueryMask.SetValue(value); + break; + } + + case Prxy_TagStatus_offs: + { + LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(Prxy_TagStatus, 0x%x)", m_index, value); + Prxy.TagStatus.SetValue(value); + break; + } + + case SPU_Out_MBox_offs: + { + LOG_WARNING(Log::SPU, "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: - //LOG_WARNING(Log::SPU, "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: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_MBox_Status, 0x%x)", m_index, value); SPU.MBox_Status.SetValue(value); break; + { + // if In_MBox is already full, the last message is overwritten + SPU.In_MBox.PushUncond(value); + break; + } + + case SPU_MBox_Status_offs: + { + LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_MBox_Status, 0x%x)", m_index, value); + SPU.MBox_Status.SetValue(value); + break; + } + case SPU_RunCntl_offs: { if (value == SPU_RUNCNTL_RUNNABLE) @@ -138,15 +287,41 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value) } break; } - case SPU_Status_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_Status, 0x%x)", m_index, value); SPU.Status.SetValue(value); break; - case SPU_NPC_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_NPC, 0x%x)", m_index, value); SPU.NPC.SetValue(value); break; - case SPU_RdSigNotify1_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_RdSigNotify1, 0x%x)", m_index, value); SPU.SNR[0].SetValue(value); break; - case SPU_RdSigNotify2_offs: LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_RdSigNotify2, 0x%x)", m_index, value); SPU.SNR[1].SetValue(value); break; + + case SPU_Status_offs: + { + LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_Status, 0x%x)", m_index, value); + SPU.Status.SetValue(value); + break; + } + + case SPU_NPC_offs: + { + LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_NPC, 0x%x)", m_index, value); + SPU.NPC.SetValue(value); + break; + } + + case SPU_RdSigNotify1_offs: + { + LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_RdSigNotify1, 0x%x)", m_index, value); + SPU.SNR[0].SetValue(value); + break; + } + + case SPU_RdSigNotify2_offs: + { + LOG_WARNING(Log::SPU, "RawSPUThread[%d]: Write32(SPU_RdSigNotify2, 0x%x)", m_index, value); + SPU.SNR[1].SetValue(value); + break; + } default: + { LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Write32(0x%x, 0x%x)", m_index, offset, value); Emu.Pause(); - break; + break; + } } return true; diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 28e07cc603..cd98ac713e 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -581,19 +581,26 @@ public: DMAC dmac; +#define LOG_DMAC(type, text) type(Log::SPU, "DMAC::ProcessCmd(cmd=0x%x, tag=0x%x, lsa=0x%x, ea=0x%llx, size=0x%x): " text, cmd, tag, lsa, ea, size) + bool ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size) { if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence(); if (ea >= SYS_SPU_THREAD_BASE_LOW) { - if (group) + if (ea >= 0x100000000) + { + LOG_DMAC(LOG_ERROR, "Invalid external address"); + return false; + } + else if (group) { // SPU Thread Group MMIO (LS and SNR) u32 num = (ea & SYS_SPU_THREAD_BASE_MASK) / SYS_SPU_THREAD_OFFSET; // thread number in group if (num >= group->list.size() || !group->list[num]) { - LOG_ERROR(Log::SPU, "DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx): invalid thread", ea); + LOG_DMAC(LOG_ERROR, "Invalid thread (SPU Thread Group MMIO)"); return false; } @@ -612,13 +619,13 @@ public: } else { - LOG_ERROR(Log::SPU, "DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx, size=%d, cmd=0x%x): invalid command", ea, size, cmd); + LOG_DMAC(LOG_ERROR, "Invalid register (SPU Thread Group MMIO)"); return false; } } else { - LOG_ERROR(Log::SPU, "DMAC::ProcessCmd(): SPU Thread Group MMIO Access (ea=0x%llx): group not set", ea); + LOG_DMAC(LOG_ERROR, "Thread group not set (SPU Thread Group MMIO)"); return false; } } @@ -640,14 +647,12 @@ public: default: { - LOG_ERROR(Log::SPU, "DMAC::ProcessCmd(): Unknown DMA cmd."); + LOG_DMAC(LOG_ERROR, "Unknown DMA command"); return false; } } } - //Sleep(1); // hack - switch (cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK | MFC_RESULT_MASK)) { case MFC_PUT_CMD: @@ -658,7 +663,7 @@ public: } else { - LOG_ERROR(Log::SPU, "DMAC::ProcessCmd(): PUT* cmd failed (ea=0x%llx, lsa=0x%x, size=%d)", ea, lsa, size); + LOG_DMAC(LOG_ERROR, "PUT* cmd failed"); return false; // TODO: page fault (?) } } @@ -671,19 +676,21 @@ public: } else { - LOG_ERROR(Log::SPU, "DMAC::ProcessCmd(): GET* cmd failed (ea=0x%llx, lsa=0x%x, size=%d)", ea, lsa, size); + LOG_DMAC(LOG_ERROR, "GET* cmd failed"); return false; // TODO: page fault (?) } } default: { - LOG_ERROR(Log::SPU, "DMAC::ProcessCmd(): Unknown DMA cmd."); + LOG_DMAC(LOG_ERROR, "Unknown DMA command"); return false; // ??? } } } +#undef LOG_CMD + u32 dmacCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size) { /*if(proxy_pos >= MFC_PPU_MAX_QUEUE_SPACE) diff --git a/rpcs3/Emu/GS/RSXThread.cpp b/rpcs3/Emu/GS/RSXThread.cpp index f1053be27e..3590fe4a72 100644 --- a/rpcs3/Emu/GS/RSXThread.cpp +++ b/rpcs3/Emu/GS/RSXThread.cpp @@ -5,8 +5,7 @@ #include "RSXThread.h" #include "Emu/SysCalls/lv2/sys_time.h" -//#define ARGS(x) (x >= count ? OutOfArgsCount(x, cmd, count) : Memory.Read32(Memory.RSXIOMem.GetStartAddr() + m_ctrl->get + (4*(x+1)))) -#define ARGS(x) (x >= count ? OutOfArgsCount(x, cmd, count) : Memory.Read32(Memory.RSXIOMem.RealAddr(Memory.RSXIOMem.GetStartAddr() + m_ctrl->get + (4*(x+1))))) +#define ARGS(x) (x >= count ? OutOfArgsCount(x, cmd, count, args) : args[x]) u32 methodRegisters[0xffff]; @@ -46,10 +45,7 @@ u32 GetAddress(u32 offset, u8 location) switch(location) { case CELL_GCM_LOCATION_LOCAL: return Memory.RSXFBMem.GetStartAddr() + offset; - case CELL_GCM_LOCATION_MAIN: - u64 realAddr; - Memory.RSXIOMem.getRealAddr(Memory.RSXIOMem.GetStartAddr() + offset, realAddr); // TODO: Error Check? - return realAddr; + case CELL_GCM_LOCATION_MAIN: return Memory.RSXIOMem.RealAddr(Memory.RSXIOMem.GetStartAddr() + offset); // TODO: Error Check? } LOG_ERROR(RSX, "GetAddress(offset=0x%x, location=0x%x)", location); @@ -141,7 +137,7 @@ u32 RSXVertexData::GetTypeSize() #define CMD_LOG(...) #endif -u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count) +u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count, mem32_ptr_t args) { std::string debug = GetMethodName(cmd); debug += "("; @@ -207,7 +203,7 @@ u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count) index = (cmd - a) / m; \ case a \ -void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u32 count) +void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t args, const u32 count) { #if CMD_DEBUG std::string debug = GetMethodName(cmd); @@ -2454,9 +2450,7 @@ void RSXThread::Task() } //ConLog.Write("addr = 0x%x", m_ioAddress + get); - u64 realAddr; - Memory.RSXIOMem.getRealAddr(Memory.RSXIOMem.GetStartAddr() + get, realAddr); - const u32 cmd = Memory.Read32(realAddr); + const u32 cmd = ReadIO32(get); const u32 count = (cmd >> 18) & 0x7ff; //if(cmd == 0) continue; @@ -2471,7 +2465,7 @@ void RSXThread::Task() { m_call_stack.push(get + 4); u32 offs = cmd & ~CELL_GCM_METHOD_FLAG_CALL; - u32 addr = Memory.RSXIOMem.GetStartAddr() + offs; + //u32 addr = Memory.RSXIOMem.GetStartAddr() + offs; //LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x - 0x%x", offs, addr, cmd, get); m_ctrl->get = offs; continue; @@ -2500,13 +2494,13 @@ void RSXThread::Task() continue; } + mem32_ptr_t args((u32)Memory.RSXIOMem.RealAddr(Memory.RSXIOMem.GetStartAddr() + get + 4)); + for(u32 i=0; iget = get + (count + 1) * 4; diff --git a/rpcs3/Emu/GS/RSXThread.h b/rpcs3/Emu/GS/RSXThread.h index 3dd6abbf58..e776af2214 100644 --- a/rpcs3/Emu/GS/RSXThread.h +++ b/rpcs3/Emu/GS/RSXThread.h @@ -593,8 +593,8 @@ protected: void Begin(u32 draw_mode); void End(); - u32 OutOfArgsCount(const uint x, const u32 cmd, const u32 count); - void DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u32 count); + u32 OutOfArgsCount(const uint x, const u32 cmd, const u32 count, mem32_ptr_t args); + void DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t args, const u32 count); void nativeRescale(float width, float height); virtual void OnInit() = 0; @@ -634,4 +634,16 @@ public: OnInit(); ThreadBase::Start(); } + + u32 ReadIO32(u32 addr) + { + u32 value; + Memory.RSXIOMem.Read32(Memory.RSXIOMem.GetStartAddr() + addr, &value); + return value; + } + + void WriteIO32(u32 addr, u32 value) + { + Memory.RSXIOMem.Write32(Memory.RSXIOMem.GetStartAddr() + addr, value); + } };