diff --git a/Utilities/SMutex.h b/Utilities/SMutex.h index ebab2f0cff..e62361b304 100644 --- a/Utilities/SMutex.h +++ b/Utilities/SMutex.h @@ -1,4 +1,5 @@ #pragma once +#include "Emu/Memory/vm_atomic.h" bool SM_IsAborted(); void SM_Sleep(); @@ -24,9 +25,9 @@ template > class SMutexBase { - static_assert(sizeof(T) == sizeof(std::atomic), "Invalid SMutexBase type"); + static_assert(sizeof(T) == sizeof(vm::atomic_le), "Invalid SMutexBase type"); T owner; - typedef std::atomic AT; + typedef vm::atomic_le AT; public: static const T GetFreeValue() @@ -46,11 +47,6 @@ public: owner = GetFreeValue(); } - //SMutexBase() - //{ - // initialize(); - //} - void finalize() { owner = GetDeadValue(); @@ -67,9 +63,9 @@ public: { return SMR_ABORT; } - T old = GetFreeValue(); + T old = reinterpret_cast(owner).compare_and_swap(GetFreeValue(), tid); - if (!reinterpret_cast(owner).compare_exchange_strong(old, tid)) + if (old != GetFreeValue()) { if (old == tid) { @@ -91,9 +87,9 @@ public: { return SMR_ABORT; } - T old = tid; + T old = reinterpret_cast(owner).compare_and_swap(tid, to); - if (!reinterpret_cast(owner).compare_exchange_strong(old, to)) + if (old != tid) { if (old == GetFreeValue()) { @@ -132,5 +128,4 @@ public: } }; -typedef SMutexBase - SMutex; +typedef SMutexBase SMutex; diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index fd3ab07d38..af24ccf86e 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -204,4 +204,5 @@ namespace vm #include "vm_ref.h" #include "vm_ptr.h" -#include "vm_var.h" \ No newline at end of file +#include "vm_var.h" +#include "vm_atomic.h" diff --git a/rpcs3/Emu/Memory/vm_atomic.h b/rpcs3/Emu/Memory/vm_atomic.h new file mode 100644 index 0000000000..c292f1a7ed --- /dev/null +++ b/rpcs3/Emu/Memory/vm_atomic.h @@ -0,0 +1,63 @@ +#pragma once + +namespace vm +{ + template + struct _to_atomic + { + static_assert(size == 4 || size == 8, "Invalid atomic type"); + + typedef T type; + }; + + template + struct _to_atomic + { + typedef uint32_t type; + }; + + template + struct _to_atomic + { + typedef uint64_t type; + }; + + template + class _atomic_base + { + T data; + typedef typename _to_atomic::type atomic_type; + + public: + T compare_and_swap(T cmp, T exch) + { + const atomic_type res = InterlockedCompareExchange((volatile atomic_type*)&data, (atomic_type&)exch, (atomic_type&)cmp); + return (T&)res; + } + + }; + + template struct atomic_le : public _atomic_base + { + }; + + template struct atomic_be : public _atomic_base::type> + { + }; + + namespace ps3 + { + template struct atomic : public atomic_be + { + }; + } + + namespace psv + { + template struct atomic : public atomic_le + { + }; + } + + using namespace ps3; +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 7562cd0806..4a2e215efa 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -207,6 +207,37 @@ s64 spursInit( assert(ppu1); spurs->m.ppu1 = ppu1->GetId(); + // enable exception event handler + if (spurs->m.enableEH.compare_and_swap(be_t::MakeFromBE(0), be_t::MakeFromBE(se32(1))).ToBE() != 0) + { + assert(sys_spu_thread_group_connect_event(spurs->m.spuTG, spurs->m.queue, SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION) == CELL_OK); + } + + spurs->m.unk22 = 0; + // can also use cellLibprof if available (omitted) + + // some unknown subroutine + spurs->m.sub3.unk1 = spurs.addr() + 0xc9; + spurs->m.sub3.unk2 = 3; // unknown const + spurs->m.sub3.port = (u64)spurs->m.port; + + if (flags & SAF_SYSTEM_WORKLOAD_ENABLED) // initialize system workload + { + s32 res; +#ifdef PRX_DEBUG + res = cb_call, u32, u32, u32>(GetCurrentPPUThread(), libsre + 0x10428, libsre_rtoc, + spurs, Memory.RealToVirtualAddr(swlPriority), swlMaxSpu, swlIsPreem); +#else + res = -1; +#endif + assert(res == CELL_OK); + } + else if (flags & SAF_EXIT_IF_NO_WORK) // wakeup + { +#ifdef PRX_DEBUG + return cb_call>(GetCurrentPPUThread(), libsre + 0x84D8, libsre_rtoc, spurs); +#endif + } return CELL_OK; #endif } @@ -1657,7 +1688,7 @@ s64 cellSpursAddWorkload() #endif } -s64 cellSpursWakeUp() +s64 cellSpursWakeUp(vm::ptr spurs) { #ifdef PRX_DEBUG cellSpurs->Warning("%s()", __FUNCTION__); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index a85c4c928d..717e9afe94 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -149,8 +149,21 @@ struct CellSpurs { static const uint size = 0x80; - be_t sem; - u8 unk_[0x78]; + u8 unk0[0x20]; + be_t sem; // 0x20 + u8 unk_[0x58]; + }; + + struct _sub_str2 + { + static const uint size = 0x80; + + be_t unk0; + be_t unk1; + be_t unk2; + be_t unk3; + be_t port; // 0x10 + u8 unk_[0x68]; }; union @@ -173,9 +186,10 @@ struct CellSpurs be_t unk0; // 0x0B0 u8 unknown2[0xC0 - 0xB4]; u8 unk6[0x10]; // 0x0C0 - u8 unknown1[0x120 - 0x0D0]; - _sub_str1 sub1[0x10]; // 0x120 - u8 unknown7[0x980 - 0x920]; + u8 unknown1[0x100 - 0x0D0]; + _sub_str1 sub1[0x10]; // 0x100 + be_t unk22; // 0x900 + u8 unknown7[0x980 - 0x908]; be_t semPrv; // 0x980 be_t unk11; // 0x988 be_t unk12; // 0x98C @@ -193,7 +207,9 @@ struct CellSpurs u8 unknown3[0xD5C - 0xD54]; be_t queue; // 0xD5C be_t port; // 0xD60 - u8 unk19[0xC]; // 0xD64 + be_t unk19; // 0xD64 + vm::atomic enableEH; // 0xD68 + be_t unk21; // 0xD6C sys_spu_image spuImg; // 0xD70 be_t flags; // 0xD80 be_t spuPriority;// 0xD84 @@ -206,8 +222,10 @@ struct CellSpurs u8 unknown8[0xDB0 - 0xDA8]; sys_lwmutex_t mutex; // 0xDB0 sys_lwcond_t cond; // 0xDC8 - u8 unknown6[0x1220 - 0xDD0]; - _sub_str1 sub2[0x10]; // 0x1220 + u8 unknown9[0xF00 - 0xDD0]; + _sub_str2 sub3; // 0xF00 + u8 unknown6[0x1200 - 0xF80]; + _sub_str1 sub2[0x10]; // 0x1200 // ... } m; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp index f9cd0f3ec2..385115d47f 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp @@ -210,12 +210,12 @@ s32 sys_ppu_thread_create(vm::ptr> thread_id, u32 entry, u64 arg, s32 return CELL_OK; } -void sys_ppu_thread_once(PPUThread& CPU, vm::ptr>> once_ctrl, vm::ptr init) +void sys_ppu_thread_once(PPUThread& CPU, vm::ptr> once_ctrl, vm::ptr init) { sys_ppu_thread.Warning("sys_ppu_thread_once(once_ctrl_addr=0x%x, init_addr=0x%x)", once_ctrl.addr(), init.addr()); - be_t old = be_t::MakeFromBE(se32(SYS_PPU_THREAD_ONCE_INIT)); - if (once_ctrl->compare_exchange_weak(old, be_t::MakeFromBE(se32(SYS_PPU_THREAD_DONE_INIT)))) + auto cmp = to_be(SYS_PPU_THREAD_ONCE_INIT); + if (once_ctrl->compare_and_swap(cmp, to_be(SYS_PPU_THREAD_DONE_INIT)) == cmp) { init.call(CPU); } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h index 4b79c4f7e9..b5d8540d32 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h @@ -2,10 +2,10 @@ class PPUThread; -enum +enum : u32 { - SYS_PPU_THREAD_ONCE_INIT, - SYS_PPU_THREAD_DONE_INIT, + SYS_PPU_THREAD_ONCE_INIT = 0, + SYS_PPU_THREAD_DONE_INIT = 1, }; enum ppu_thread_flags : u64 @@ -30,6 +30,6 @@ s32 sys_ppu_thread_get_stack_information(PPUThread& CPU, u32 info_addr); s32 sys_ppu_thread_stop(u64 thread_id); s32 sys_ppu_thread_restart(u64 thread_id); s32 sys_ppu_thread_create(vm::ptr> thread_id, u32 entry, u64 arg, s32 prio, u32 stacksize, u64 flags, vm::ptr threadname); -void sys_ppu_thread_once(PPUThread& CPU, vm::ptr>> once_ctrl, vm::ptr init); +void sys_ppu_thread_once(PPUThread& CPU, vm::ptr> once_ctrl, vm::ptr init); s32 sys_ppu_thread_get_id(PPUThread& CPU, vm::ptr> thread_id); s32 sys_ppu_thread_rename(u64 thread_id, vm::ptr name); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.h b/rpcs3/Emu/SysCalls/lv2/sys_spu.h index 53edee68bc..526334fe36 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.h @@ -18,6 +18,20 @@ enum SYS_SPU_THREAD_GROUP_JOIN_TERMINATED = 0x0004 }; +enum +{ + SYS_SPU_THREAD_GROUP_EVENT_RUN = 1, + SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION = 2, + SYS_SPU_THREAD_GROUP_EVENT_SYSTEM_MODULE = 4, +}; + +enum : u64 +{ + SYS_SPU_THREAD_GROUP_EVENT_RUN_KEY = 0xFFFFFFFF53505500ull, + SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION_KEY = 0xFFFFFFFF53505503ull, + SYS_SPU_THREAD_GROUP_EVENT_SYSTEM_MODULE_KEY = 0xFFFFFFFF53505504ull, +}; + enum { SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED, diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index f09d6a99d5..e46932a9d3 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -311,6 +311,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 038502f880..573ebd2fed 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1219,5 +1219,8 @@ Emu\SysCalls + + Emu\Memory + \ No newline at end of file