diff --git a/Utilities/BEType.h b/Utilities/BEType.h index 1a7756347c..abd557c89e 100644 --- a/Utilities/BEType.h +++ b/Utilities/BEType.h @@ -310,9 +310,8 @@ static __forceinline u128 InterlockedCompareExchange(volatile u128* dest, u128 e auto res = __sync_val_compare_and_swap((volatile __int128_t*)dest, (__int128_t&)comp, (__int128_t&)exch); return (u128&)res; #else - u128 cmp = comp; - _InterlockedCompareExchange128((volatile long long*)dest, exch._u64[1], exch._u64[0], (long long*)&cmp); - return cmp; + _InterlockedCompareExchange128((volatile long long*)dest, exch._u64[1], exch._u64[0], (long long*)&comp); + return comp; #endif } #endif @@ -326,6 +325,50 @@ static __forceinline bool InterlockedCompareExchangeTest(volatile u128* dest, u1 #endif } +#ifndef InterlockedExchange +static __forceinline u128 InterlockedExchange(volatile u128* dest, u128 value) +{ + while (true) + { + const u128 old = *(u128*)dest; + if (InterlockedCompareExchangeTest(dest, value, old)) return old; + } +} +#endif + +#ifndef InterlockedOr +static __forceinline u128 InterlockedOr(volatile u128* dest, u128 value) +{ + while (true) + { + const u128 old = *(u128*)dest; + if (InterlockedCompareExchangeTest(dest, old | value, old)) return old; + } +} +#endif + +#ifndef InterlockedAnd +static __forceinline u128 InterlockedAnd(volatile u128* dest, u128 value) +{ + while (true) + { + const u128 old = *(u128*)dest; + if (InterlockedCompareExchangeTest(dest, old & value, old)) return old; + } +} +#endif + +#ifndef InterlockedXor +static __forceinline u128 InterlockedXor(volatile u128* dest, u128 value) +{ + while (true) + { + const u128 old = *(u128*)dest; + if (InterlockedCompareExchangeTest(dest, old ^ value, old)) return old; + } +} +#endif + #define re16(val) _byteswap_ushort(val) #define re32(val) _byteswap_ulong(val) #define re64(val) _byteswap_uint64(val) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index e424ade186..0ff43cc712 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -60,6 +60,7 @@ s64 spursInit( return cb_call, u32, u32, s32, s32, s32, u32, u32, u32, u32, u32, u32, u32>(GetCurrentPPUThread(), libsre + 0x74E4, libsre_rtoc, spurs, revision, sdkVersion, nSpus, spuPriority, ppuPriority, flags, Memory.RealToVirtualAddr(prefix), prefixSize, container, Memory.RealToVirtualAddr(swlPriority), swlMaxSpu, swlIsPreem); #endif + // SPURS initialization (asserts should actually rollback and return the error instead) if (!spurs) @@ -170,6 +171,7 @@ s64 spursInit( SPU.GPR[4]._u64[1] = spurs.addr(); return SPU.FastCall(SPU.PC); #endif + // code replacement: { const u32 addr = /*SPU.ReadLS32(0x1e0) +*/ 8; //SPU.ReadLS32(0x1e4); @@ -518,6 +520,7 @@ s64 spursInit( #ifdef PRX_DEBUG_XXX return cb_call>(CPU, libsre + 0x9214, libsre_rtoc, spurs); #endif + if (spurs->m.flags & SAF_UNKNOWN_FLAG_30) { return; @@ -664,10 +667,10 @@ s64 cellSpursInitialize(vm::ptr spurs, s32 nSpus, s32 spuPriority, s3 { cellSpurs->Warning("cellSpursInitialize(spurs_addr=0x%x, nSpus=%d, spuPriority=%d, ppuPriority=%d, exitIfNoWork=%d)", spurs.addr(), nSpus, spuPriority, ppuPriority, exitIfNoWork ? 1 : 0); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x8480, libsre_rtoc); #endif + return spursInit( spurs, 0, @@ -687,10 +690,10 @@ s64 cellSpursInitialize(vm::ptr spurs, s32 nSpus, s32 spuPriority, s3 s64 cellSpursInitializeWithAttribute(vm::ptr spurs, vm::ptr attr) { cellSpurs->Warning("cellSpursInitializeWithAttribute(spurs_addr=0x%x, attr_addr=0x%x)", spurs.addr(), attr.addr()); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x839C, libsre_rtoc); #endif + if (!attr) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -723,10 +726,10 @@ s64 cellSpursInitializeWithAttribute(vm::ptr spurs, vm::ptr spurs, vm::ptr attr) { cellSpurs->Warning("cellSpursInitializeWithAttribute2(spurs_addr=0x%x, attr_addr=0x%x)", spurs.addr(), attr.addr()); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x82B4, libsre_rtoc); #endif + if (!attr) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -760,10 +763,10 @@ s64 _cellSpursAttributeInitialize(vm::ptr attr, u32 revision { cellSpurs->Warning("_cellSpursAttributeInitialize(attr_addr=0x%x, revision=%d, sdkVersion=0x%x, nSpus=%d, spuPriority=%d, ppuPriority=%d, exitIfNoWork=%d)", attr.addr(), revision, sdkVersion, nSpus, spuPriority, ppuPriority, exitIfNoWork ? 1 : 0); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x72CC, libsre_rtoc); #endif + if (!attr) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -786,10 +789,10 @@ s64 _cellSpursAttributeInitialize(vm::ptr attr, u32 revision s64 cellSpursAttributeSetMemoryContainerForSpuThread(vm::ptr attr, u32 container) { cellSpurs->Warning("cellSpursAttributeSetMemoryContainerForSpuThread(attr_addr=0x%x, container=%d)", attr.addr(), container); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x6FF8, libsre_rtoc); #endif + if (!attr) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -812,10 +815,10 @@ s64 cellSpursAttributeSetMemoryContainerForSpuThread(vm::ptr s64 cellSpursAttributeSetNamePrefix(vm::ptr attr, vm::ptr prefix, u32 size) { cellSpurs->Warning("cellSpursAttributeSetNamePrefix(attr_addr=0x%x, prefix_addr=0x%x, size=%d)", attr.addr(), prefix.addr(), size); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x7234, libsre_rtoc); #endif + if (!attr || !prefix) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -838,10 +841,10 @@ s64 cellSpursAttributeSetNamePrefix(vm::ptr attr, vm::ptr attr) { cellSpurs->Warning("cellSpursAttributeEnableSpuPrintfIfAvailable(attr_addr=0x%x)", attr.addr()); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x7150, libsre_rtoc); #endif + if (!attr) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -858,10 +861,10 @@ s64 cellSpursAttributeEnableSpuPrintfIfAvailable(vm::ptr att s64 cellSpursAttributeSetSpuThreadGroupType(vm::ptr attr, s32 type) { cellSpurs->Warning("cellSpursAttributeSetSpuThreadGroupType(attr_addr=0x%x, type=%d)", attr.addr(), type); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x70C8, libsre_rtoc); #endif + if (!attr) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -894,10 +897,10 @@ s64 cellSpursAttributeEnableSystemWorkload(vm::ptr attr, vm: { cellSpurs->Warning("cellSpursAttributeEnableSystemWorkload(attr_addr=0x%x, priority_addr=0x%x, maxSpu=%d, isPreemptible_addr=0x%x)", attr.addr(), priority.addr(), maxSpu, isPreemptible.addr()); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0xF410, libsre_rtoc); #endif + if (!attr) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -950,11 +953,11 @@ s64 cellSpursAttributeEnableSystemWorkload(vm::ptr attr, vm: s64 cellSpursFinalize(vm::ptr spurs) { - cellSpurs->Warning("cellSpursFinalize(spurs_addr=0x%x)", spurs.addr()); - + cellSpurs->Todo("cellSpursFinalize(spurs_addr=0x%x)", spurs.addr()); #ifdef PRX_DEBUG return GetCurrentPPUThread().FastCall2(libsre + 0x8568, libsre_rtoc); #endif + return CELL_OK; } @@ -964,6 +967,7 @@ s64 spursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptr po return cb_call, u32, vm::ptr, s32, bool>(GetCurrentPPUThread(), libsre + 0xAE34, libsre_rtoc, spurs, queue, port, isDynamic, wasCreated); #endif + if (!spurs || !port) { return CELL_SPURS_CORE_ERROR_NULL_POINTER; @@ -1023,10 +1027,10 @@ s64 cellSpursAttachLv2EventQueue(vm::ptr spurs, u32 queue, vm::ptrWarning("cellSpursAttachLv2EventQueue(spurs_addr=0x%x, queue=%d, port_addr=0x%x, isDynamic=%d)", spurs.addr(), queue, port.addr(), isDynamic); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0xAFE0, libsre_rtoc); #endif + return spursAttachLv2EventQueue(spurs, queue, port, isDynamic, false); } @@ -1052,37 +1056,69 @@ s64 cellSpursGetSpuGuid() #endif } -s64 cellSpursGetSpuThreadGroupId(vm::ptr spurs, vm::ptr> group) +s64 cellSpursGetSpuThreadGroupId(vm::ptr spurs, vm::ptr group) { -#ifdef PRX_DEBUG cellSpurs->Warning("cellSpursGetSpuThreadGroupId(spurs_addr=0x%x, group_addr=0x%x)", spurs.addr(), group.addr()); +#ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x8B30, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; #endif + + if (!spurs || !group) + { + return CELL_SPURS_CORE_ERROR_NULL_POINTER; + } + if (spurs.addr() % 128) + { + return CELL_SPURS_CORE_ERROR_ALIGN; + } + + *group = spurs->m.spuTG; + return CELL_OK; } -s64 cellSpursGetNumSpuThread(vm::ptr spurs, vm::ptr> nThreads) +s64 cellSpursGetNumSpuThread(vm::ptr spurs, vm::ptr nThreads) { -#ifdef PRX_DEBUG cellSpurs->Warning("cellSpursGetNumSpuThread(spurs_addr=0x%x, nThreads_addr=0x%x)", spurs.addr(), nThreads.addr()); +#ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x8B78, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; #endif + + if (!spurs || !nThreads) + { + return CELL_SPURS_CORE_ERROR_NULL_POINTER; + } + if (spurs.addr() % 128) + { + return CELL_SPURS_CORE_ERROR_ALIGN; + } + + *nThreads = (u32)spurs->m.nSpus; + return CELL_OK; } -s64 cellSpursGetSpuThreadId(vm::ptr spurs, vm::ptr> thread, vm::ptr> nThreads) +s64 cellSpursGetSpuThreadId(vm::ptr spurs, vm::ptr thread, vm::ptr nThreads) { -#ifdef PRX_DEBUG cellSpurs->Warning("cellSpursGetSpuThreadId(spurs_addr=0x%x, thread_addr=0x%x, nThreads_addr=0x%x)", spurs.addr(), thread.addr(), nThreads.addr()); +#ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x8A98, libsre_rtoc); -#else - UNIMPLEMENTED_FUNC(cellSpurs); - return CELL_OK; #endif + + if (!spurs || !thread || !nThreads) + { + return CELL_SPURS_CORE_ERROR_NULL_POINTER; + } + if (spurs.addr() % 128) + { + return CELL_SPURS_CORE_ERROR_ALIGN; + } + + const u32 count = std::min(*nThreads, spurs->m.nSpus); + for (u32 i = 0; i < count; i++) + { + thread[i] = spurs->m.spus[i]; + } + *nThreads = count; + return CELL_OK; } s64 cellSpursSetMaxContention(vm::ptr spurs, u32 workloadId, u32 maxContention) @@ -1168,6 +1204,7 @@ s64 spursWakeUp(vm::ptr spurs) #ifdef PRX_DEBUG_XXX return cb_call>(GetCurrentPPUThread(), libsre + 0x84D8, libsre_rtoc, spurs); #endif + if (!spurs) { return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; @@ -1217,6 +1254,7 @@ s32 spursAddWorkload( spurs, wid, pm, size, data, Memory.RealToVirtualAddr(priorityTable), minContention, maxContention, nameClass.addr(), nameInstance.addr(), hook.addr(), hookArg.addr()); #endif + if (!spurs || !wid || !pm) { return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; @@ -1379,7 +1417,6 @@ s64 cellSpursAddWorkload( { cellSpurs->Warning("%s(spurs_addr=0x%x, wid_addr=0x%x, pm_addr=0x%x, size=0x%x, data=0x%llx, priorityTable_addr=0x%x, minContention=0x%x, maxContention=0x%x)", __FUNCTION__, spurs.addr(), wid.addr(), pm.addr(), size, data, priorityTable.addr(), minContention, maxContention); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x9ED0, libsre_rtoc); #endif @@ -1412,10 +1449,10 @@ s64 _cellSpursWorkloadAttributeInitialize( { cellSpurs->Warning("%s(attr_addr=0x%x, revision=%d, sdkVersion=0x%x, pm_addr=0x%x, size=0x%x, data=0x%llx, priorityTable_addr=0x%x, minContention=0x%x, maxContention=0x%x)", __FUNCTION__, attr.addr(), revision, sdkVersion, pm.addr(), size, data, priorityTable.addr(), minContention, maxContention); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x9F08, libsre_rtoc); #endif + if (!attr) { return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; @@ -1452,10 +1489,10 @@ s64 _cellSpursWorkloadAttributeInitialize( s64 cellSpursWorkloadAttributeSetName(vm::ptr attr, vm::ptr nameClass, vm::ptr nameInstance) { cellSpurs->Warning("%s(attr_addr=0x%x, nameClass_addr=0x%x, nameInstance_addr=0x%x)", __FUNCTION__, attr.addr(), nameClass.addr(), nameInstance.addr()); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x9664, libsre_rtoc); #endif + if (!attr) { return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; @@ -1473,10 +1510,10 @@ s64 cellSpursWorkloadAttributeSetName(vm::ptr attr, s64 cellSpursWorkloadAttributeSetShutdownCompletionEventHook(vm::ptr attr, vm::ptr hook, vm::ptr arg) { cellSpurs->Warning("%s(attr_addr=0x%x, hook_addr=0x%x, arg=0x%x)", __FUNCTION__, attr.addr(), hook.addr(), arg.addr()); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x96A4, libsre_rtoc); #endif + if (!attr || !hook) { return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; @@ -1494,10 +1531,10 @@ s64 cellSpursWorkloadAttributeSetShutdownCompletionEventHook(vm::ptr spurs, vm::ptr wid, vm::ptr attr) { cellSpurs->Warning("%s(spurs_addr=0x%x, wid_addr=0x%x, attr_addr=0x%x)", __FUNCTION__, spurs.addr(), wid.addr(), attr.addr()); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x9E14, libsre_rtoc); #endif + if (!attr) { return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; @@ -1562,10 +1599,10 @@ s64 cellSpursShutdownWorkload() s64 _cellSpursWorkloadFlagReceiver(vm::ptr spurs, u32 wid, u32 is_set) { cellSpurs->Warning("%s(spurs_addr=0x%x, wid=%d, is_set=%d)", __FUNCTION__, spurs.addr(), wid, is_set); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0xF158, libsre_rtoc); #endif + if (!spurs) { return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; @@ -1632,10 +1669,10 @@ s64 _cellSpursWorkloadFlagReceiver(vm::ptr spurs, u32 wid, u32 is_set s64 cellSpursGetWorkloadFlag(vm::ptr spurs, vm::ptr> flag) { cellSpurs->Warning("%s(spurs_addr=0x%x, flag_addr=0x%x)", __FUNCTION__, spurs.addr(), flag.addr()); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0xEC00, libsre_rtoc); #endif + if (!spurs || !flag) { return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER; @@ -1674,10 +1711,10 @@ s64 cellSpursGetWorkloadData() s64 cellSpursReadyCountStore(vm::ptr spurs, u32 wid, u32 value) { cellSpurs->Warning("%s(spurs_addr=0x%x, wid=%d, value=0x%x)", __FUNCTION__, spurs.addr(), wid, value); - #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0xAB2C, libsre_rtoc); #endif + if (!spurs) { return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER;