diff --git a/Utilities/Log.h b/Utilities/Log.h index c1826ef727..32c0f18e81 100644 --- a/Utilities/Log.h +++ b/Utilities/Log.h @@ -1,5 +1,4 @@ #pragma once -#include #include "Utilities/MTRingbuffer.h" //#define BUFFERED_LOGGING 1 diff --git a/rpcs3/Emu/SysCalls/CB_FUNC.h b/rpcs3/Emu/SysCalls/CB_FUNC.h index 8a5eda1dc1..d989d13e2f 100644 --- a/rpcs3/Emu/SysCalls/CB_FUNC.h +++ b/rpcs3/Emu/SysCalls/CB_FUNC.h @@ -95,49 +95,37 @@ namespace cb_detail return _bind_func_args(CPU, args...) || (t == ARG_STACK); } - template + template struct _func_res { - static_assert(sizeof(RT) <= 8, "Invalid callback result type"); - static_assert(!std::is_pointer::value, "Invalid callback result type (pointer)"); - static_assert(!std::is_reference::value, "Invalid callback result type (reference)"); + static_assert(type == ARG_GENERAL, "Wrong use of _func_res template"); + static_assert(sizeof(T) <= 8, "Invalid callback result type for ARG_GENERAL"); - __forceinline static RT get_value(const PPUThread& CPU) + __forceinline static T get_value(const PPUThread& CPU) { - if (std::is_floating_point::value) - { - return (RT)CPU.FPR[1]; - } - else - { - return (RT&)CPU.GPR[3]; - } + return (T&)CPU.GPR[3]; } }; - template<> - struct _func_res + template + struct _func_res { - __forceinline static const u128 get_value(const PPUThread& CPU) + static_assert(sizeof(T) <= 8, "Invalid callback result type for ARG_FLOAT"); + + __forceinline static T get_value(const PPUThread& CPU) { - return CPU.VPR[2]; + return (T)CPU.FPR[1]; } }; - template<> - struct _func_res + template + struct _func_res { - __forceinline static const u128 get_value(const PPUThread& CPU) - { - return CPU.VPR[2]; - } - }; + static_assert(sizeof(T) == 16, "Invalid callback result type for ARG_VECTOR"); - template<> - struct _func_res - { - __forceinline static void get_value(const PPUThread& CPU) + __forceinline static T get_value(const PPUThread& CPU) { + return (T&)CPU.VPR[2]; } }; @@ -150,7 +138,14 @@ namespace cb_detail if (stack) CPU.GPR[1] -= FIXED_STACK_FRAME_SIZE; CPU.FastCall2(pc, rtoc); if (stack) CPU.GPR[1] += FIXED_STACK_FRAME_SIZE; - return _func_res::get_value(CPU); + + static_assert(!std::is_pointer::value, "Invalid callback result type (pointer)"); + static_assert(!std::is_reference::value, "Invalid callback result type (reference)"); + const bool is_float = std::is_floating_point::value; + const bool is_vector = std::is_same::value; + const _func_arg_type t = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL); + + return _func_res::get_value(CPU); } }; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 189527fd65..7d6a2d4721 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -3,6 +3,7 @@ #include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Callback.h" +#include "Emu/SysCalls/lv2/sys_spu.h" #include "Emu/Cell/SPURSManager.h" #include "cellSpurs.h" @@ -20,18 +21,18 @@ s64 spursInit( s32 nSpus, s32 spuPriority, s32 ppuPriority, - u32 flags, + u32 flags, // SpursAttrFlags const char prefix[], u32 prefixSize, u32 container, - u32 arg11, - u32 arg12, - u32 arg13) + const u8 swlPriority[], + u32 swlMaxSpu, + u32 swlIsPreem) { // internal function #ifdef PRX_DEBUG - return cb_caller, u32, u32, s32, s32, s32, u32, u32, u32, u32, u32, u32, u32>::call(GetCurrentPPUThread(), libsre + 0x74E4, libsre_rtoc, - spurs, revision, sdkVersion, nSpus, spuPriority, ppuPriority, flags, Memory.RealToVirtualAddr(prefix), prefixSize, container, arg11, arg12, arg13); + 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); #else //spurs->spurs = new SPURSManager(attr); return CELL_OK; @@ -53,11 +54,11 @@ s64 cellSpursInitialize(vm::ptr spurs, s32 nSpus, s32 spuPriority, s3 nSpus, spuPriority, ppuPriority, - exitIfNoWork ? 1 : 0, + exitIfNoWork ? SAF_EXIT_IF_NO_WORK : SAF_NONE, nullptr, 0, 0, - 0, + nullptr, 0, 0); #endif @@ -90,13 +91,13 @@ s64 cellSpursInitializeWithAttribute(vm::ptr spurs, vm::ptrm.nSpus, attr->m.spuPriority, attr->m.ppuPriority, - (u32)attr->m.flags | (attr->m.exitIfNoWork ? 1 : 0), + attr->m.flags.ToLE() | (attr->m.exitIfNoWork ? SAF_EXIT_IF_NO_WORK : 0), attr->m.prefix, attr->m.prefixSize, attr->m.container, - attr.addr() + 0x38, - attr->_u32[16], - attr->_u32[17]); + attr->m.swlPriority, + attr->m.swlMaxSpu, + attr->m.swlIsPreem); #endif } @@ -127,13 +128,13 @@ s64 cellSpursInitializeWithAttribute2(vm::ptr spurs, vm::ptrm.nSpus, attr->m.spuPriority, attr->m.ppuPriority, - (u32)attr->m.flags | (attr->m.exitIfNoWork ? 1 : 0) | 4, + attr->m.flags.ToLE() | (attr->m.exitIfNoWork ? SAF_EXIT_IF_NO_WORK : 0) | 4, // +add unknown flag attr->m.prefix, attr->m.prefixSize, attr->m.container, - attr.addr() + 0x38, - attr->_u32[16], - attr->_u32[17]); + attr->m.swlPriority, + attr->m.swlMaxSpu, + attr->m.swlIsPreem); #endif } @@ -180,13 +181,14 @@ s64 cellSpursAttributeSetMemoryContainerForSpuThread(vm::ptr { return CELL_SPURS_CORE_ERROR_ALIGN; } - if ((u32)attr->m.flags & 0x20000000) // check unknown flag + + if (attr->m.flags.ToLE() & SAF_SPU_TGT_EXCLUSIVE_NON_CONTEXT) { return CELL_SPURS_CORE_ERROR_STAT; } - attr->_u32[11] = container; - attr->m.flags |= 0x40000000; // set unknown flag + attr->m.container = container; + attr->m.flags |= SAF_SPU_MEMORY_CONTAINER_SET; return CELL_OK; #endif } @@ -220,11 +222,21 @@ s64 cellSpursAttributeSetNamePrefix(vm::ptr attr, vm::ptr attr) { -#ifdef PRX_DEBUG cellSpurs->Warning("cellSpursAttributeEnableSpuPrintfIfAvailable(attr_addr=0x%x)", attr.addr()); + +#ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x7150, libsre_rtoc); #else - UNIMPLEMENTED_FUNC(cellSpurs); + if (!attr) + { + return CELL_SPURS_CORE_ERROR_NULL_POINTER; + } + if (attr.addr() % 8) + { + return CELL_SPURS_CORE_ERROR_ALIGN; + } + + attr->m.flags |= SAF_SPU_PRINTF_ENABLED; return CELL_OK; #endif } @@ -245,45 +257,82 @@ s64 cellSpursAttributeSetSpuThreadGroupType(vm::ptr attr, s3 return CELL_SPURS_CORE_ERROR_ALIGN; } - if (type == 0x18) + if (type == SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT) { - if (attr->m.flags & 0x40000000) // check unknown flag + if (attr->m.flags.ToLE() & SAF_SPU_MEMORY_CONTAINER_SET) { return CELL_SPURS_CORE_ERROR_STAT; } - - attr->m.flags |= 0x20000000; // set unknown flag - return CELL_OK; + attr->m.flags |= SAF_SPU_TGT_EXCLUSIVE_NON_CONTEXT; // set } - else if (type) + else if (type == SYS_SPU_THREAD_GROUP_TYPE_NORMAL) + { + attr->m.flags &= ~SAF_SPU_TGT_EXCLUSIVE_NON_CONTEXT; // clear + } + else { return CELL_SPURS_CORE_ERROR_INVAL; } - else // if type == 0 - { - attr->m.flags &= ~0x20000000; // clear unknown flag - return CELL_OK; - } + return CELL_OK; #endif } -s64 cellSpursAttributeEnableSystemWorkload(vm::ptr attr, vm::ptr priority, u32 maxSpu, vm::ptr isPreemptible) +s64 cellSpursAttributeEnableSystemWorkload(vm::ptr attr, vm::ptr priority, u32 maxSpu, vm::ptr isPreemptible) { 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 +#ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0xF410, libsre_rtoc); #else - for (s32 i = 0; i < CELL_SPURS_MAX_SPU; i++) + if (!attr) { - if (priority[i] != 1 || maxSpu == 0) + return CELL_SPURS_CORE_ERROR_NULL_POINTER; + } + if (attr.addr() % 8) + { + return CELL_SPURS_CORE_ERROR_ALIGN; + } + + const u32 nSpus = attr->_u32[2]; + if (!nSpus) + { + return CELL_SPURS_CORE_ERROR_INVAL; + } + for (u32 i = 0; i < nSpus; i++) + { + if ((*priority)[i] == 1) { - cellSpurs->Error("cellSpursAttributeEnableSystemWorkload : CELL_SPURS_CORE_ERROR_INVAL"); - return CELL_SPURS_CORE_ERROR_INVAL; + if (!maxSpu) + { + return CELL_SPURS_CORE_ERROR_INVAL; + } + if (nSpus == 1 || attr->m.exitIfNoWork) + { + return CELL_SPURS_CORE_ERROR_PERM; + } + if (attr->m.flags.ToLE() & SAF_SYSTEM_WORKLOAD_ENABLED) + { + return CELL_SPURS_CORE_ERROR_BUSY; + } + + attr->m.flags |= SAF_SYSTEM_WORKLOAD_ENABLED; // set flag + *(u64*)attr->m.swlPriority = *(u64*)*priority; // copy system workload priorities + + u32 isPreem = 0; // generate mask from isPreemptible values + for (u32 j = 0; j < nSpus; j++) + { + if ((*isPreemptible)[j]) + { + isPreem |= (1 << j); + } + } + attr->m.swlMaxSpu = maxSpu; // write max spu for system workload + attr->m.swlIsPreem = isPreem; // write isPreemptible mask + return CELL_OK; } } - return CELL_OK; + return CELL_SPURS_CORE_ERROR_INVAL; #endif } diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index bfa1520751..c01d38c5c3 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -91,6 +91,17 @@ struct CellSpurs2 SPURSManager *spurs; }; +enum SpursAttrFlags : u32 +{ + SAF_NONE = 0x0, + SAF_EXIT_IF_NO_WORK = 0x1, + + SAF_SYSTEM_WORKLOAD_ENABLED = 0x02000000, + SAF_SPU_PRINTF_ENABLED = 0x10000000, + SAF_SPU_TGT_EXCLUSIVE_NON_CONTEXT = 0x20000000, + SAF_SPU_MEMORY_CONTAINER_SET = 0x40000000, +}; + struct CellSpursAttribute { static const uint align = 8; @@ -113,9 +124,13 @@ struct CellSpursAttribute bool exitIfNoWork; // 0x14 char prefix[15]; // 0x15 (not a NTS) be_t prefixSize; // 0x24 - be_t flags; // 0x28 + be_t flags; // 0x28 (SpursAttrFlags) be_t container; // 0x2C - // ... + be_t unk0; // 0x30 + be_t unk1; // 0x34 + u8 swlPriority[8]; // 0x38 + be_t swlMaxSpu; // 0x40 + be_t swlIsPreem; // 0x44 } m; // alternative implementation diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index 482805a90a..43df317feb 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -1535,7 +1535,7 @@ s32 _cellSyncLFQueuePushBody(vm::ptr queue, vm::ptr else { #ifdef PRX_DEBUG - res = cb_caller, u32, u32, u64>::call(GetCurrentPPUThread(), libsre + 0x3050, libsre_rtoc, + res = cb_call, u32, u32, u64>(GetCurrentPPUThread(), libsre + 0x3050, libsre_rtoc, queue, position_v.addr(), isBlocking, 0); position = position_v->ToLE(); #else @@ -1580,7 +1580,7 @@ s32 _cellSyncLFQueuePushBody(vm::ptr queue, vm::ptr else { #ifdef PRX_DEBUG - res = cb_caller, s32, u64>::call(GetCurrentPPUThread(), libsre + 0x355C, libsre_rtoc, + res = cb_call, s32, u64>(GetCurrentPPUThread(), libsre + 0x355C, libsre_rtoc, queue, position, 0); #else res = syncLFQueueCompletePushPointer2(queue, position, nullptr); @@ -1930,7 +1930,7 @@ s32 _cellSyncLFQueuePopBody(vm::ptr queue, vm::ptr buffer else { #ifdef PRX_DEBUG - res = cb_caller, u32, u32, u64>::call(GetCurrentPPUThread(), libsre + 0x39AC, libsre_rtoc, + res = cb_call, u32, u32, u64>(GetCurrentPPUThread(), libsre + 0x39AC, libsre_rtoc, queue, position_v.addr(), isBlocking, 0); position = position_v->ToLE(); #else @@ -1972,7 +1972,7 @@ s32 _cellSyncLFQueuePopBody(vm::ptr queue, vm::ptr buffer else { #ifdef PRX_DEBUG - res = cb_caller, s32, u64, u64>::call(GetCurrentPPUThread(), libsre + 0x3EB8, libsre_rtoc, + res = cb_call, s32, u64, u64>(GetCurrentPPUThread(), libsre + 0x3EB8, libsre_rtoc, queue, position, 0, 0); #else res = syncLFQueueCompletePopPointer2(queue, position, nullptr, 0); diff --git a/rpcs3/Emu/SysCalls/SC_FUNC.h b/rpcs3/Emu/SysCalls/SC_FUNC.h index 4a5b1da3e2..146a44131c 100644 --- a/rpcs3/Emu/SysCalls/SC_FUNC.h +++ b/rpcs3/Emu/SysCalls/SC_FUNC.h @@ -46,7 +46,7 @@ namespace detail template struct bind_arg { - static_assert(std::is_same::value, "Invalid function argument type for ARG_VECTOR"); + static_assert(sizeof(T) == 16, "Invalid function argument type for ARG_VECTOR"); static __forceinline T func(PPUThread& CPU) { @@ -69,41 +69,37 @@ namespace detail } }; - template + template struct bind_result { - static_assert(sizeof(T) <= 8, "Invalid function result type"); - static_assert(!std::is_pointer::value, "Invalid function result type (pointer)"); - static_assert(!std::is_reference::value, "Invalid function result type (reference)"); + static_assert(type == ARG_GENERAL, "Wrong use of bind_result template"); + static_assert(sizeof(T) <= 8, "Invalid function result type for ARG_GENERAL"); static __forceinline void func(PPUThread& CPU, T result) { - if (std::is_floating_point::value) - { - CPU.FPR[1] = (double)result; - } - else - { - (T&)CPU.GPR[3] = result; - } + (T&)CPU.GPR[3] = result; } }; - template<> - struct bind_result + template + struct bind_result { - static __forceinline void func(PPUThread& CPU, const u128 result) + static_assert(sizeof(T) <= 8, "Invalid function result type for ARG_FLOAT"); + + static __forceinline void func(PPUThread& CPU, T result) { - CPU.VPR[2] = result; + CPU.FPR[1] = (double)result; } }; - template<> - struct bind_result + template + struct bind_result { - static __forceinline void func(PPUThread& CPU, const u128 result) + static_assert(sizeof(T) == 16, "Invalid function result type for ARG_VECTOR"); + + static __forceinline void func(PPUThread& CPU, const T result) { - CPU.VPR[2] = result; + (T&)CPU.VPR[2] = result; } }; @@ -157,13 +153,13 @@ namespace detail return std::tuple_cat(std::tuple(bind_arg::func(CPU)), iterate(CPU)); } - template + template class func_binder; - template - class func_binder : public func_caller + template + class func_binder : public func_caller { - typedef void(*func_t)(TA...); + typedef void(*func_t)(T...); const func_t m_call; public: @@ -176,14 +172,14 @@ namespace detail virtual void operator()() { declCPU(); - call(m_call, iterate<0, 0, 0, TA...>(CPU)); + call(m_call, iterate<0, 0, 0, T...>(CPU)); } }; - template + template class func_binder : public func_caller { - typedef TR(*func_t)(TA...); + typedef RT(*func_t)(T...); const func_t m_call; public: @@ -196,13 +192,19 @@ namespace detail virtual void operator()() { declCPU(); - bind_result::func(CPU, call(m_call, iterate<0, 0, 0, TA...>(CPU))); + static_assert(!std::is_pointer::value, "Invalid function result type (pointer)"); + static_assert(!std::is_reference::value, "Invalid function result type (reference)"); + const bool is_float = std::is_floating_point::value; + const bool is_vector = std::is_same::value; + const bind_arg_type t = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL); + + bind_result::func(CPU, call(m_call, iterate<0, 0, 0, T...>(CPU))); } }; } -template -func_caller* bind_func(TR(*call)(TA...)) +template +func_caller* bind_func(RT(*call)(T...)) { - return new detail::func_binder(call); + return new detail::func_binder(call); } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/SysCalls.cpp b/rpcs3/Emu/SysCalls/SysCalls.cpp index ce1a858983..2019e4c34b 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.cpp +++ b/rpcs3/Emu/SysCalls/SysCalls.cpp @@ -11,8 +11,8 @@ #include "lv2/sys_event.h" #include "lv2/sys_event_flag.h" #include "lv2/sys_interrupt.h" -#include "lv2/sys_lwcond.h" -#include "lv2/sys_lwmutex.h" +//#include "lv2/sys_lwcond.h" +//#include "lv2/sys_lwmutex.h" #include "lv2/sys_memory.h" #include "lv2/sys_mmapper.h" #include "lv2/sys_ppu_thread.h" @@ -21,7 +21,6 @@ #include "lv2/sys_rsx.h" #include "lv2/sys_rwlock.h" #include "lv2/sys_semaphore.h" -#include "lv2/sys_spinlock.h" #include "lv2/sys_spu.h" #include "lv2/sys_time.h" #include "lv2/sys_timer.h" @@ -138,11 +137,11 @@ static func_caller* sc_table[kSyscallTableLength] = bind_func(sys_semaphore_wait), //92 (0x05C) bind_func(sys_semaphore_trywait), //93 (0x05D) bind_func(sys_semaphore_post), //94 (0x05E) - null_func,//bind_func(sys_lwmutex_create), //95 (0x05F) - null_func,//bind_func(sys_lwmutex_destroy), //96 (0x060) - null_func,//bind_func(sys_lwmutex_lock), //97 (0x061) - null_func,//bind_func(sys_lwmutex_trylock), //98 (0x062) - null_func,//bind_func(sys_lwmutex_unlock), //99 (0x063) + null_func,//bind_func(sys_lwmutex_create), //95 (0x05F) // internal, used by sys_lwmutex_create + null_func,//bind_func(sys_lwmutex_destroy), //96 (0x060) // internal, used by sys_lwmutex_destroy + null_func,//bind_func(sys_lwmutex_lock), //97 (0x061) // internal, used by sys_lwmutex_lock + null_func,//bind_func(sys_lwmutex_trylock), //98 (0x062) // internal, used by sys_lwmutex_unlock + null_func,//bind_func(sys_lwmutex_unlock), //99 (0x063) // internal, used by sys_lwmutex_trylock bind_func(sys_mutex_create), //100 (0x064) bind_func(sys_mutex_destroy), //101 (0x065) bind_func(sys_mutex_lock), //102 (0x066) @@ -160,7 +159,7 @@ static func_caller* sc_table[kSyscallTableLength] = bind_func(sys_semaphore_get_value), //114 (0x072) null_func,//bind_func(sys_semaphore_...) //115 (0x073) null_func,//bind_func(sys_semaphore_...) //116 (0x074) - null_func,//bind_func(sys_semaphore_...) //117 (0x075) + null_func,//bind_func(sys_semaphore_...) //117 (0x075) // internal, used by sys_lwmutex_unlock bind_func(sys_event_flag_clear), //118 (0x076) null_func,//bind_func(sys_event_...) //119 (0x077) ROOT bind_func(sys_rwlock_create), //120 (0x078) diff --git a/rpcs3/stdafx.h b/rpcs3/stdafx.h index 42ea227704..e1c4825f87 100644 --- a/rpcs3/stdafx.h +++ b/rpcs3/stdafx.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include