From f9c592098f7d8c83e7340fc0fef651c5dc27a23e Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 23 Jun 2014 05:03:16 +0400 Subject: [PATCH] Work on RawSPU: interrupt mailbox Achievement unlocked: run spu_test! --- rpcs3/Emu/CPU/CPUThread.h | 4 + rpcs3/Emu/CPU/CPUThreadManager.cpp | 20 +++ rpcs3/Emu/CPU/CPUThreadManager.h | 2 + rpcs3/Emu/Cell/RawSPUThread.cpp | 9 +- rpcs3/Emu/Cell/SPUInterpreter.h | 36 +++- rpcs3/Emu/Cell/SPURecompilerCore.cpp | 1 + rpcs3/Emu/Cell/SPUThread.h | 42 ++++- rpcs3/Emu/SysCalls/SysCalls.cpp | 26 +-- rpcs3/Emu/SysCalls/SysCalls.h | 17 +- rpcs3/Emu/SysCalls/lv2/SC_Interrupt.cpp | 111 ++++++++++++ rpcs3/Emu/SysCalls/lv2/SC_Interrupt.h | 1 + rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp | 26 +-- rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp | 207 +++++++++++++++++++++-- rpcs3/emucore.vcxproj | 2 + rpcs3/emucore.vcxproj.filters | 6 + 15 files changed, 458 insertions(+), 52 deletions(-) create mode 100644 rpcs3/Emu/SysCalls/lv2/SC_Interrupt.cpp create mode 100644 rpcs3/Emu/SysCalls/lv2/SC_Interrupt.h diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index e725e719d9..87d9b9963d 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -130,6 +130,10 @@ public: u64 cycle; bool m_is_branch; + bool m_is_interrupt; + bool m_has_interrupt; + u64 m_interrupt_arg; + protected: CPUThread(CPUThreadType type); diff --git a/rpcs3/Emu/CPU/CPUThreadManager.cpp b/rpcs3/Emu/CPU/CPUThreadManager.cpp index b99573e6a6..b89c58fbeb 100644 --- a/rpcs3/Emu/CPU/CPUThreadManager.cpp +++ b/rpcs3/Emu/CPU/CPUThreadManager.cpp @@ -108,6 +108,26 @@ CPUThread* CPUThreadManager::GetThread(u32 id) return res; } +RawSPUThread* CPUThreadManager::GetRawSPUThread(u32 num) +{ + std::lock_guard lock(m_mtx_thread); + + for (u32 i = 0; i < m_threads.size(); i++) + { + if (m_threads[i]->GetType() == CPU_THREAD_RAW_SPU) + { + RawSPUThread* t = (RawSPUThread*)m_threads[i]; + + if (t->GetIndex() == num) + { + return t; + } + } + } + + return nullptr; +} + void CPUThreadManager::NotifyThread(const u32 id) { if (!id) return; diff --git a/rpcs3/Emu/CPU/CPUThreadManager.h b/rpcs3/Emu/CPU/CPUThreadManager.h index 6ccdf568e7..ba71cb78b9 100644 --- a/rpcs3/Emu/CPU/CPUThreadManager.h +++ b/rpcs3/Emu/CPU/CPUThreadManager.h @@ -1,5 +1,6 @@ #pragma once class CPUThread; +class RawSPUThread; enum CPUThreadType : unsigned char; class CPUThreadManager @@ -21,6 +22,7 @@ public: std::vector& GetThreads() { return m_threads; } s32 GetThreadNumById(CPUThreadType type, u32 id); CPUThread* GetThread(u32 id); + RawSPUThread* GetRawSPUThread(u32 num); void Exec(); void Task(); diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index 6d513b664d..53a1710093 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -79,7 +79,7 @@ bool RawSPUThread::Read32(const u64 addr, u32* value) 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); + //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; @@ -89,7 +89,10 @@ bool RawSPUThread::Read32(const u64 addr, u32* value) *value = SPU.MBox_Status.GetValue(); break; case SPU_RunCntl_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RunCntl)", m_index); *value = SPU.RunCntl.GetValue(); break; - case SPU_Status_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Status)", m_index); *value = SPU.Status.GetValue(); break; + case SPU_Status_offs: + //ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Status)", m_index); + *value = SPU.Status.GetValue(); + break; case SPU_NPC_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_NPC)", m_index); *value = SPU.NPC.GetValue(); break; case SPU_RdSigNotify1_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify1)", m_index); *value = SPU.SNR[0].GetValue(); break; case SPU_RdSigNotify2_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RdSigNotify2)", m_index); *value = SPU.SNR[1].GetValue(); break; @@ -199,7 +202,7 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value) 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); + //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; diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index 8522a34889..209d3c5efb 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -679,7 +679,11 @@ private: //HGT uses signed values. HLGT uses unsigned values void HGT(u32 rt, s32 ra, s32 rb) { - if(CPU.GPR[ra]._i32[3] > CPU.GPR[rb]._i32[3]) CPU.Stop(); + if (CPU.GPR[ra]._i32[3] > CPU.GPR[rb]._i32[3]) + { + CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT); + CPU.Stop(); + } } void CLZ(u32 rt, u32 ra) { @@ -806,7 +810,11 @@ private: } void HLGT(u32 rt, u32 ra, u32 rb) { - if(CPU.GPR[ra]._u32[3] > CPU.GPR[rb]._u32[3]) CPU.Stop(); + if (CPU.GPR[ra]._u32[3] > CPU.GPR[rb]._u32[3]) + { + CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT); + CPU.Stop(); + } } void DFMA(u32 rt, u32 ra, u32 rb) { @@ -1018,7 +1026,11 @@ private: } void HEQ(u32 rt, u32 ra, u32 rb) { - if(CPU.GPR[ra]._i32[3] == CPU.GPR[rb]._i32[3]) CPU.Stop(); + if (CPU.GPR[ra]._i32[3] == CPU.GPR[rb]._i32[3]) + { + CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT); + CPU.Stop(); + } } //0 - 9 @@ -1373,7 +1385,11 @@ private: } void HGTI(u32 rt, u32 ra, s32 i10) { - if(CPU.GPR[ra]._i32[3] > i10) CPU.Stop(); + if (CPU.GPR[ra]._i32[3] > i10) + { + CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT); + CPU.Stop(); + } } void CLGTI(u32 rt, u32 ra, s32 i10) { @@ -1396,7 +1412,11 @@ private: } void HLGTI(u32 rt, u32 ra, s32 i10) { - if(CPU.GPR[ra]._u32[3] > (u32)i10) CPU.Stop(); + if (CPU.GPR[ra]._u32[3] > (u32)i10) + { + CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT); + CPU.Stop(); + } } void MPYI(u32 rt, u32 ra, s32 i10) { @@ -1425,7 +1445,11 @@ private: } void HEQI(u32 rt, u32 ra, s32 i10) { - if(CPU.GPR[ra]._i32[3] == i10) CPU.Stop(); + if (CPU.GPR[ra]._i32[3] == i10) + { + CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT); + CPU.Stop(); + } } diff --git a/rpcs3/Emu/Cell/SPURecompilerCore.cpp b/rpcs3/Emu/Cell/SPURecompilerCore.cpp index 5368e3b6d5..565132430f 100644 --- a/rpcs3/Emu/Cell/SPURecompilerCore.cpp +++ b/rpcs3/Emu/Cell/SPURecompilerCore.cpp @@ -232,6 +232,7 @@ u8 SPURecompilerCore::DecodeMemory(const u64 address) if (res > 0xffff) { + CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT); CPU.Stop(); res = ~res; } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 270d92dde5..aa6d8d33a4 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -295,6 +295,22 @@ public: EventManager SPUQs; // SPU Queue Mapping SpuGroupInfo* group; // associated SPU Thread Group (null for raw spu) + struct IntrTag + { + u32 enabled; // 1 == true + u32 thread; // established interrupt PPU thread + u64 mask; + u64 stat; + + IntrTag() + : enabled(0) + , thread(0) + , mask(0) + , stat(0) + { + } + } m_intrtag[3]; + template class Channel { @@ -510,6 +526,7 @@ public: struct { Channel<1> Out_MBox; + Channel<1> Out_IntrMBox; Channel<4> In_MBox; Channel<1> MBox_Status; Channel<1> RunCntl; @@ -544,7 +561,7 @@ public: { if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence(); - if ((ea & 0xf0000000) == SYS_SPU_THREAD_BASE_LOW) + if (ea >= SYS_SPU_THREAD_BASE_LOW) { if (group) { @@ -902,9 +919,24 @@ public: case SPU_WrOutIntrMbox: if (!group) // if RawSPU { - // TODO: run PPU interrupt thread - ConLog.Error("SPU_WrOutIntrMbox interrupt unimplemented"); - Emu.Pause(); + if (Ini.HLELogging.GetValue()) ConLog.Write("SPU_WrOutIntrMbox: interrupt(v=0x%x)", v); + SPU.Out_IntrMBox.PushUncond(v); + m_intrtag[2].stat |= 1; + if (CPUThread* t = Emu.GetCPU().GetThread(m_intrtag[2].thread)) + { + while (t->IsAlive()) + { + Sleep(1); + if (Emu.IsStopped()) + { + ConLog.Warning("%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]); + return; + } + } + t->SetArg(0, t->m_interrupt_arg); + t->Run(); + t->Exec(); + } } else { @@ -1223,6 +1255,7 @@ public: // the real exit status ConLog.Write("sys_spu_thread_exit (status=0x%x)", SPU.Out_MBox.GetValue()); } + SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_STOP); Stop(); break; default: @@ -1234,6 +1267,7 @@ public: { ConLog.Error("Unknown STOP code: 0x%x (message=0x%x)", code, SPU.Out_MBox.GetValue()); } + SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_STOP); Stop(); break; } diff --git a/rpcs3/Emu/SysCalls/SysCalls.cpp b/rpcs3/Emu/SysCalls/SysCalls.cpp index 4bff0b64d7..e745ae995b 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.cpp +++ b/rpcs3/Emu/SysCalls/SysCalls.cpp @@ -102,15 +102,15 @@ static func_caller* sc_table[kSyscallTableLength] = null_func, null_func,//bind_func(sys_interrupt_tag_create) //80 (0x050) - null_func,//bind_func(sys_interrupt_tag_destroy) //81 (0x051) + bind_func(sys_interrupt_tag_destroy), //81 (0x051) bind_func(sys_event_flag_create), //82 (0x052) bind_func(sys_event_flag_destroy), //83 (0x053) - null_func,//bind_func(sys_interrupt_thread_establish) //84 (0x054) + bind_func(sys_interrupt_thread_establish), //84 (0x054) bind_func(sys_event_flag_wait), //85 (0x055) bind_func(sys_event_flag_trywait), //86 (0x056) bind_func(sys_event_flag_set), //87 (0x057) - null_func,//bind_func(sys_interrupt_thread_eoi) //88 (0x058) - null_func,//bind_func(sys_interrupt_thread_disestablish)//89 (0x059) + bind_func(sys_interrupt_thread_eoi), //88 (0x058) + bind_func(sys_interrupt_thread_disestablish), //89 (0x059) bind_func(sys_semaphore_create), //90 (0x05A) bind_func(sys_semaphore_destroy), //91 (0x05B) bind_func(sys_semaphore_wait), //92 (0x05C) @@ -174,20 +174,20 @@ static func_caller* sc_table[kSyscallTableLength] = // Unused: 149 null_func, - null_func,//bind_func(sys_raw_spu_create_interrupt_tag) //150 (0x096) - null_func,//bind_func(sys_raw_spu_set_int_mask) //151 (0x097) - null_func,//bind_func(sys_raw_spu_get_int_mask) //152 (0x098) - null_func,//bind_func(sys_raw_spu_set_int_stat) //153 (0x099) - null_func,//bind_func(sys_raw_spu_get_int_stat) //154 (0x09A) + bind_func(sys_raw_spu_create_interrupt_tag), //150 (0x096) + bind_func(sys_raw_spu_set_int_mask), //151 (0x097) + bind_func(sys_raw_spu_get_int_mask), //152 (0x098) + bind_func(sys_raw_spu_set_int_stat), //153 (0x099) + bind_func(sys_raw_spu_get_int_stat), //154 (0x09A) null_func,//bind_func(sys_spu_image_get_information?) //155 (0x09B) bind_func(sys_spu_image_open), //156 (0x09C) null_func,//bind_func(sys_spu_image_import) //157 (0x09D) null_func,//bind_func(sys_spu_image_close) //158 (0x09E) null_func,//bind_func(sys_raw_spu_load) //159 (0x09F) bind_func(sys_raw_spu_create), //160 (0x0A0) - null_func,//bind_func(sys_raw_spu_destroy) //161 (0x0A1) + bind_func(sys_raw_spu_destroy), //161 (0x0A1) null_func, // - null_func,//bind_func(sys_raw_spu_read_puint_mb) //163 (0x0A3) + bind_func(sys_raw_spu_read_puint_mb), //163 (0x0A3) null_func, // bind_func(sys_spu_thread_get_exit_status), //165 (0x0A5) bind_func(sys_spu_thread_set_argument), //166 (0x0A6) @@ -220,8 +220,8 @@ static func_caller* sc_table[kSyscallTableLength] = bind_func(sys_spu_thread_bind_queue), //193 (0x0C1) bind_func(sys_spu_thread_unbind_queue), //194 (0x0C2) null_func, // - null_func,//bind_func(sys_raw_spu_set_spu_cfg) //196 (0x0C4) - null_func,//bind_func(sys_raw_spu_get_spu_cfg) //197 (0x0C5) + bind_func(sys_raw_spu_set_spu_cfg), //196 (0x0C4) + bind_func(sys_raw_spu_get_spu_cfg), //197 (0x0C5) null_func,//bind_func(sys_spu_thread_recover_page_fault)//198 (0x0C6) null_func,//bind_func(sys_raw_spu_recover_page_fault) //199 (0x0C7) diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index 413df89e7b..584d9f1aa4 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -358,7 +358,6 @@ extern int sys_spu_thread_group_connect_event(u32 id, u32 eq, u32 et); extern int sys_spu_thread_group_disconnect_event(u32 id, u32 et); extern int sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 spup_addr); extern int sys_spu_thread_group_disconnect_event_all_threads(u32 id, u8 spup); -extern int sys_raw_spu_create(mem32_t id, u32 attr_addr); extern int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu); extern int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type); extern int sys_spu_thread_read_ls(u32 id, u32 address, mem64_t value, u32 type); @@ -371,6 +370,22 @@ extern int sys_spu_thread_disconnect_event(u32 id, u32 event_type, u8 spup); extern int sys_spu_thread_bind_queue(u32 id, u32 spuq, u32 spuq_num); extern int sys_spu_thread_unbind_queue(u32 id, u32 spuq_num); extern int sys_spu_thread_get_exit_status(u32 id, mem32_t status); +extern int sys_raw_spu_create(mem32_t id, u32 attr_addr); +extern int sys_raw_spu_destroy(u32 id); +extern int sys_raw_spu_create_interrupt_tag(u32 id, u32 class_id, u32 hwthread, mem32_t intrtag); +extern int sys_raw_spu_set_int_mask(u32 id, u32 class_id, u64 mask); +extern int sys_raw_spu_get_int_mask(u32 id, u32 class_id, mem64_t mask); +extern int sys_raw_spu_set_int_stat(u32 id, u32 class_id, u64 stat); +extern int sys_raw_spu_get_int_stat(u32 id, u32 class_id, mem64_t stat); +extern int sys_raw_spu_read_puint_mb(u32 id, mem32_t value); +extern int sys_raw_spu_set_spu_cfg(u32 id, u32 value); +extern int sys_raw_spu_get_spu_cfg(u32 id, mem32_t value); + +//sys_interrupt +extern int sys_interrupt_tag_destroy(u32 intrtag); +extern int sys_interrupt_thread_establish(mem32_t ih, u32 intrtag, u64 intrthread, u64 arg); +extern int sys_interrupt_thread_disestablish(u32 ih); +extern void sys_interrupt_thread_eoi(); //sys_time extern int sys_time_get_timezone(mem32_t timezone, mem32_t summertime); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Interrupt.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Interrupt.cpp new file mode 100644 index 0000000000..78e5a22a36 --- /dev/null +++ b/rpcs3/Emu/SysCalls/lv2/SC_Interrupt.cpp @@ -0,0 +1,111 @@ +#include "stdafx.h" +#include "Emu/ConLog.h" +#include "Emu/Memory/Memory.h" +#include "Emu/System.h" +#include "Emu/Cell/PPUThread.h" +#include "Emu/Cell/RawSPUThread.h" +#include "Emu/SysCalls/SC_FUNC.h" +#include "Emu/SysCalls/Modules.h" +#include "Emu/SysCalls/SysCalls.h" +#include "SC_Interrupt.h" + +static SysCallBase sc_int("sys_interrupt"); + +int sys_interrupt_tag_destroy(u32 intrtag) +{ + sc_int.Error("sys_interrupt_tag_destroy(intrtag=%d)", intrtag); + + u32 id = intrtag & 0xff; + u32 class_id = intrtag >> 8; + RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id); + + if (!t || class_id > 2 || class_id == 1) + { + return CELL_ESRCH; + } + + if (!t->m_intrtag[class_id].enabled) + { + return CELL_ESRCH; + } + + if (t->m_intrtag[class_id].thread) + { + return CELL_EBUSY; + } + + t->m_intrtag[class_id].enabled = 0; + return CELL_OK; +} + +int sys_interrupt_thread_establish(mem32_t ih, u32 intrtag, u64 intrthread, u64 arg) +{ + sc_int.Error("sys_interrupt_thread_establish(ih_addr=0x%x, intrtag=%d, intrthread=%lld, arg=0x%llx)", ih.GetAddr(), intrtag, intrthread, arg); + + if (!ih.IsGood()) + { + return CELL_EFAULT; + } + + u32 id = intrtag & 0xff; + u32 class_id = intrtag >> 8; + RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id); + + if (!t || class_id > 2 || class_id == 1) + { + return CELL_ESRCH; + } + + if (!t->m_intrtag[class_id].enabled) + { + return CELL_ESRCH; + } + + if (t->m_intrtag[class_id].thread) // ??? + { + return CELL_ESTAT; + } + + CPUThread* it = Emu.GetCPU().GetThread(intrthread); + if (!it) + { + return CELL_ESRCH; + } + + if (it->m_has_interrupt || !it->m_is_interrupt) + { + return CELL_EAGAIN; + } + + ih = (t->m_intrtag[class_id].thread = intrthread); + it->m_interrupt_arg = arg; + return CELL_OK; +} + +int sys_interrupt_thread_disestablish(u32 ih) +{ + sc_int.Error("sys_interrupt_thread_disestablish(ih=%d)", ih); + + CPUThread* it = Emu.GetCPU().GetThread(ih); + if (!it) + { + return CELL_ESRCH; + } + + if (!it->m_has_interrupt || !it->m_is_interrupt) + { + return CELL_ESRCH; + } + + // TODO: wait for sys_interrupt_thread_eoi() and destroy interrupt thread + + return CELL_OK; +} + +void sys_interrupt_thread_eoi() +{ + sc_int.Log("sys_interrupt_thread_eoi()"); + + GetCurrentPPUThread().Stop(); + return; +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Interrupt.h b/rpcs3/Emu/SysCalls/lv2/SC_Interrupt.h new file mode 100644 index 0000000000..7b9637ef9c --- /dev/null +++ b/rpcs3/Emu/SysCalls/lv2/SC_Interrupt.h @@ -0,0 +1 @@ +#pragma once \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp index 83316d7e45..5e37196bd8 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp @@ -49,7 +49,7 @@ int sys_ppu_thread_yield() int sys_ppu_thread_join(u64 thread_id, mem64_t vptr) { - sysPrxForUser->Warning("sys_ppu_thread_join(thread_id=%d, vptr_addr=0x%x)", thread_id, vptr.GetAddr()); + sysPrxForUser->Warning("sys_ppu_thread_join(thread_id=%lld, vptr_addr=0x%x)", thread_id, vptr.GetAddr()); CPUThread* thr = Emu.GetCPU().GetThread(thread_id); if(!thr) return CELL_ESRCH; @@ -70,7 +70,7 @@ int sys_ppu_thread_join(u64 thread_id, mem64_t vptr) int sys_ppu_thread_detach(u64 thread_id) { - sysPrxForUser->Error("sys_ppu_thread_detach(thread_id=%d)", thread_id); + sysPrxForUser->Error("sys_ppu_thread_detach(thread_id=%lld)", thread_id); CPUThread* thr = Emu.GetCPU().GetThread(thread_id); if(!thr) return CELL_ESRCH; @@ -90,7 +90,7 @@ void sys_ppu_thread_get_join_state(u32 isjoinable_addr) int sys_ppu_thread_set_priority(u64 thread_id, int prio) { - sysPrxForUser->Log("sys_ppu_thread_set_priority(thread_id=%d, prio=%d)", thread_id, prio); + sysPrxForUser->Log("sys_ppu_thread_set_priority(thread_id=%lld, prio=%d)", thread_id, prio); CPUThread* thr = Emu.GetCPU().GetThread(thread_id); if(!thr) return CELL_ESRCH; @@ -102,7 +102,7 @@ int sys_ppu_thread_set_priority(u64 thread_id, int prio) int sys_ppu_thread_get_priority(u64 thread_id, u32 prio_addr) { - sysPrxForUser->Log("sys_ppu_thread_get_priority(thread_id=%d, prio_addr=0x%x)", thread_id, prio_addr); + sysPrxForUser->Log("sys_ppu_thread_get_priority(thread_id=%lld, prio_addr=0x%x)", thread_id, prio_addr); CPUThread* thr = Emu.GetCPU().GetThread(thread_id); if(!thr) return CELL_ESRCH; @@ -129,7 +129,7 @@ int sys_ppu_thread_get_stack_information(u32 info_addr) int sys_ppu_thread_stop(u64 thread_id) { - sysPrxForUser->Warning("sys_ppu_thread_stop(thread_id=%d)", thread_id); + sysPrxForUser->Warning("sys_ppu_thread_stop(thread_id=%lld)", thread_id); CPUThread* thr = Emu.GetCPU().GetThread(thread_id); if(!thr) return CELL_ESRCH; @@ -141,7 +141,7 @@ int sys_ppu_thread_stop(u64 thread_id) int sys_ppu_thread_restart(u64 thread_id) { - sysPrxForUser->Warning("sys_ppu_thread_restart(thread_id=%d)", thread_id); + sysPrxForUser->Warning("sys_ppu_thread_restart(thread_id=%lld)", thread_id); CPUThread* thr = Emu.GetCPU().GetThread(thread_id); if(!thr) return CELL_ESRCH; @@ -158,12 +158,12 @@ int sys_ppu_thread_create(mem64_t thread_id, u32 entry, u64 arg, int prio, u32 s if (Memory.IsGoodAddr(threadname_addr)) { threadname = Memory.ReadString(threadname_addr); - sysPrxForUser->Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%x, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x('%s'))", + sysPrxForUser->Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%llx, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x('%s'))", thread_id.GetAddr(), entry, arg, prio, stacksize, flags, threadname_addr, threadname.c_str()); } else { - sysPrxForUser->Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%x, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x)", + sysPrxForUser->Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%llx, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x)", thread_id.GetAddr(), entry, arg, prio, stacksize, flags, threadname_addr); if (threadname_addr != 0) return CELL_EFAULT; } @@ -186,7 +186,6 @@ int sys_ppu_thread_create(mem64_t thread_id, u32 entry, u64 arg, int prio, u32 s } case SYS_PPU_THREAD_CREATE_INTERRUPT: { - sysPrxForUser->Error("sys_ppu_thread_create: unimplemented flag (SYS_PPU_THREAD_CREATE_INTERRUPT)"); is_interrupt = true; break; } @@ -201,12 +200,17 @@ int sys_ppu_thread_create(mem64_t thread_id, u32 entry, u64 arg, int prio, u32 s new_thread.SetPrio(prio); new_thread.SetStackSize(stacksize); //new_thread.flags = flags; + new_thread.m_has_interrupt = false; + new_thread.m_is_interrupt = is_interrupt; new_thread.SetName(threadname); ConLog.Write("*** New PPU Thread [%s] (flags=0x%llx, entry=0x%x): id = %d", new_thread.GetName().c_str(), flags, entry, new_thread.GetId()); - new_thread.Run(); - new_thread.Exec(); + if (!is_interrupt) + { + new_thread.Run(); + new_thread.Exec(); + } return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp index 3a4ebb5837..c734990b63 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp @@ -364,20 +364,6 @@ int sys_spu_thread_create(mem32_t thread_id, mem32_t entry, u64 arg, int prio, u return CELL_OK; } -//160 -int sys_raw_spu_create(mem32_t id, u32 attr_addr) -{ - sc_spu.Warning("sys_raw_spu_create(id_addr=0x%x, attr_addr=0x%x)", id.GetAddr(), attr_addr); - - //Emu.GetIdManager().GetNewID("sys_raw_spu", new u32(attr_addr)); - CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_RAW_SPU); - id = ((RawSPUThread&)new_thread).GetIndex(); - new_thread.Run(); - new_thread.Exec(); - - return CELL_OK; -} - //169 int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu) { @@ -760,3 +746,196 @@ int sys_spu_thread_group_disconnect_event_all_threads(u32 id, u8 spup) return CELL_OK; } + +//160 +int sys_raw_spu_create(mem32_t id, u32 attr_addr) +{ + sc_spu.Warning("sys_raw_spu_create(id_addr=0x%x, attr_addr=0x%x)", id.GetAddr(), attr_addr); + + //Emu.GetIdManager().GetNewID("sys_raw_spu", new u32(attr_addr)); + CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_RAW_SPU); + id = ((RawSPUThread&)new_thread).GetIndex(); + new_thread.Run(); + new_thread.Exec(); + + return CELL_OK; +} + +int sys_raw_spu_destroy(u32 id) +{ + sc_spu.Error("sys_raw_spu_destroy(id=%d)", id); + + return CELL_OK; +} + +int sys_raw_spu_create_interrupt_tag(u32 id, u32 class_id, u32 hwthread, mem32_t intrtag) +{ + sc_spu.Error("sys_raw_spu_create_interrupt_tag(id=%d, class_id=%d, hwthread=0x%x, intrtag_addr=0x%x)", id, class_id, hwthread, intrtag.GetAddr()); + + RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id); + + if (!t) + { + return CELL_ESRCH; + } + + if (class_id != 0 && class_id != 2) + { + return CELL_EINVAL; + } + + if (!intrtag.IsGood()) + { + return CELL_EFAULT; + } + + if (t->m_intrtag[class_id].enabled) + { + return CELL_EAGAIN; + } + + t->m_intrtag[class_id].enabled = 1; + intrtag = (id & 0xff) | (class_id << 8); + + return CELL_OK; +} + +int sys_raw_spu_set_int_mask(u32 id, u32 class_id, u64 mask) +{ + sc_spu.Warning("sys_raw_spu_set_int_mask(id=%d, class_id=%d, mask=0x%llx)", id, class_id, mask); + + RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id); + if (!t) + { + return CELL_ESRCH; + } + + if (class_id != 0 && class_id != 2) + { + return CELL_EINVAL; + } + + t->m_intrtag[class_id].mask = mask; // TODO: check this + return CELL_OK; +} + +int sys_raw_spu_get_int_mask(u32 id, u32 class_id, mem64_t mask) +{ + sc_spu.Log("sys_raw_spu_get_int_mask(id=%d, class_id=%d, mask_addr=0x%x)", id, class_id, mask.GetAddr()); + + if (!mask.IsGood()) + { + return CELL_EFAULT; + } + + RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id); + if (!t) + { + return CELL_ESRCH; + } + + if (class_id != 0 && class_id != 2) + { + return CELL_EINVAL; + } + + mask = t->m_intrtag[class_id].mask; + return CELL_OK; +} + +int sys_raw_spu_set_int_stat(u32 id, u32 class_id, u64 stat) +{ + sc_spu.Log("sys_raw_spu_set_int_stat(id=%d, class_id=%d, stat=0x%llx)", id, class_id, stat); + + RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id); + if (!t) + { + return CELL_ESRCH; + } + + if (class_id != 0 && class_id != 2) + { + return CELL_EINVAL; + } + + t->m_intrtag[class_id].stat = stat; // TODO: check this + return CELL_OK; +} + +int sys_raw_spu_get_int_stat(u32 id, u32 class_id, mem64_t stat) +{ + sc_spu.Log("sys_raw_spu_get_int_stat(id=%d, class_id=%d, stat_addr=0xx)", id, class_id, stat.GetAddr()); + + if (!stat.IsGood()) + { + return CELL_EFAULT; + } + + RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id); + if (!t) + { + return CELL_ESRCH; + } + + if (class_id != 0 && class_id != 2) + { + return CELL_EINVAL; + } + + stat = t->m_intrtag[class_id].stat; + return CELL_OK; +} + +int sys_raw_spu_read_puint_mb(u32 id, mem32_t value) +{ + sc_spu.Log("sys_raw_spu_read_puint_mb(id=%d, value_addr=0x%x)", id, value.GetAddr()); + + if (!value.IsGood()) + { + return CELL_EFAULT; + } + + RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id); + if (!t) + { + return CELL_ESRCH; + } + + u32 v; + t->SPU.Out_IntrMBox.PopUncond(v); + value = v; + return CELL_OK; +} + +int sys_raw_spu_set_spu_cfg(u32 id, u32 value) +{ + sc_spu.Log("sys_raw_spu_set_spu_cfg(id=%d, value=0x%x)", id, value); + + RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id); + if (!t) + { + return CELL_ESRCH; + } + + t->cfg.value = value; + return CELL_OK; +} + +int sys_raw_spu_get_spu_cfg(u32 id, mem32_t value) +{ + sc_spu.Log("sys_raw_spu_get_spu_afg(id=%d, value_addr=0x%x)", id, value.GetAddr()); + + if (!value.IsGood()) + { + return CELL_EFAULT; + } + + RawSPUThread* t = Emu.GetCPU().GetRawSPUThread(id); + if (!t) + { + return CELL_ESRCH; + } + + value = t->cfg.value; + return CELL_OK; +} diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 61140cd079..be81c1885c 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -97,6 +97,7 @@ + @@ -315,6 +316,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 7e3284658a..ef24a74336 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -578,6 +578,9 @@ Utilities + + Emu\SysCalls\lv2 + @@ -1048,5 +1051,8 @@ Emu\SysCalls\lv2 + + Emu\SysCalls\lv2 + \ No newline at end of file