From 201f0f3a9fce8510a73a575b2fa18d1e9ec53108 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 15 Sep 2014 19:04:09 +0400 Subject: [PATCH] Basic stack argument support for callbacks --- rpcs3/Emu/SysCalls/CB_FUNC.h | 24 +++- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 147 ++++++++++++++++++----- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 30 ++++- rpcs3/Emu/SysCalls/lv2/lv2Fs.cpp | 4 +- 4 files changed, 165 insertions(+), 40 deletions(-) diff --git a/rpcs3/Emu/SysCalls/CB_FUNC.h b/rpcs3/Emu/SysCalls/CB_FUNC.h index b8b612eb94..8a233ef973 100644 --- a/rpcs3/Emu/SysCalls/CB_FUNC.h +++ b/rpcs3/Emu/SysCalls/CB_FUNC.h @@ -11,6 +11,11 @@ namespace cb_detail ARG_STACK, }; + // Current implementation can handle only fixed amount of stack arguments. + // This constant can be increased if necessary. + // It's possible to calculate suitable stack frame size in template, but too complicated. + static const auto FIXED_STACK_FRAME_SIZE = 0x100; + template struct _func_arg; @@ -50,25 +55,29 @@ namespace cb_detail template struct _func_arg { - static_assert(g_count <= 8, "TODO: Unsupported stack argument type (general)"); static_assert(f_count <= 12, "TODO: Unsupported stack argument type (float)"); static_assert(v_count <= 12, "TODO: Unsupported stack argument type (vector)"); static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_STACK"); __forceinline static void set_value(PPUThread& CPU, const T arg) { - // TODO + const int stack_pos = 0x70 + (g_count - 9) * 8 - FIXED_STACK_FRAME_SIZE; + static_assert(stack_pos < 0, "TODO: Increase fixed stack frame size (arg count limit broken)"); + u64 value = 0; + (T&)value = arg; + vm::write64(CPU.GPR[1] + stack_pos, value); } }; template - __forceinline static void _bind_func_args(PPUThread& CPU) + __forceinline static bool _bind_func_args(PPUThread& CPU) { // terminator + return false; } template - __forceinline static void _bind_func_args(PPUThread& CPU, T1 arg1, T... args) + __forceinline static bool _bind_func_args(PPUThread& CPU, T1 arg1, T... args) { static_assert(!std::is_pointer::value, "Invalid callback argument type (pointer)"); static_assert(!std::is_reference::value, "Invalid callback argument type (reference)"); @@ -82,7 +91,8 @@ namespace cb_detail const int v = v_count + (is_vector ? 1 : 0); _func_arg::set_value(CPU, arg1); - _bind_func_args(CPU, args...); + // return true if stack was used + return _bind_func_args(CPU, args...) || (t == ARG_STACK); } template @@ -136,8 +146,10 @@ namespace cb_detail { __forceinline static RT call(PPUThread& CPU, u32 pc, u32 rtoc, T... args) { - _bind_func_args<0, 0, 0>(CPU, args...); + const bool stack = _bind_func_args<0, 0, 0>(CPU, args...); + 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); } }; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index e7d6958b95..25fc6efe58 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "Emu/Memory/Memory.h" #include "Emu/SysCalls/Modules.h" +#include "Emu/SysCalls/Callback.h" #include "Emu/Cell/SPURSManager.h" #include "cellSpurs.h" @@ -12,17 +13,127 @@ extern u32 libsre; extern u32 libsre_rtoc; #endif +s64 spursInit( + vm::ptr spurs, + u32 arg2, + u64 arg3, + s32 nSpus, + s32 spuPriority, + s32 ppuPriority, + u32 flags, + u32 arg8, + u32 arg9, + u32 arg10, + u32 arg11, + u32 arg12, + u32 arg13) +{ + // internal function +#ifdef PRX_DEBUG + return cb_caller, u32, u64, s32, s32, s32, u32, u32, u32, u32, u32, u32, u32>::call(GetCurrentPPUThread(), libsre + 0x74E4, libsre_rtoc, + spurs, arg2, arg3, nSpus, spuPriority, ppuPriority, flags, arg8, arg9, arg10, arg11, arg12, arg13); +#else + //spurs->spurs = new SPURSManager(attr); + return CELL_OK; +#endif +} + s64 cellSpursInitialize(vm::ptr spurs, s32 nSpus, s32 spuPriority, s32 ppuPriority, bool exitIfNoWork) { - cellSpurs->Warning("cellSpursInitialize(spurs_addr=0x%x, nSpus=%d, spuPriority=%d, ppuPriority=%d, exitIfNoWork=%d)", spurs.addr(), nSpus, spuPriority, ppuPriority, exitIfNoWork); + 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 +#ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x8480, libsre_rtoc); #else - SPURSManagerAttribute *attr = new SPURSManagerAttribute(nSpus, spuPriority, ppuPriority, exitIfNoWork); - spurs->spurs = new SPURSManager(attr); + return spursInit( + vm::ptr::make(spurs.addr()), + 0, + 0, + nSpus, + spuPriority, + ppuPriority, + exitIfNoWork ? 1 : 0, + 0, + 0, + 0, + 0, + 0, + 0); +#endif +} - return CELL_OK; +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); +#else + if (!attr) + { + return CELL_SPURS_CORE_ERROR_NULL_POINTER; + } + if (attr.addr() % 8) + { + return CELL_SPURS_CORE_ERROR_ALIGN; + } + if (attr->m.arg1 > 2) + { + return CELL_SPURS_CORE_ERROR_INVAL; + } + + return spursInit( + vm::ptr::make(spurs.addr()), + attr->m.arg1, + attr->m.arg2, + attr->m.nSpus, + attr->m.spuPriority, + attr->m.ppuPriority, + (u32)attr->_u32.raw[10] | (u32)attr->_u8[20], + attr.addr() + 0x15, + attr->_u32.raw[9], + attr->_u32.raw[11], + attr.addr() + 0x38, + attr->_u32.raw[16], + attr->_u32.raw[17]); +#endif +} + +s64 cellSpursInitializeWithAttribute2(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); +#else + if (!attr) + { + return CELL_SPURS_CORE_ERROR_NULL_POINTER; + } + if (attr.addr() % 8) + { + return CELL_SPURS_CORE_ERROR_ALIGN; + } + if (attr->m.arg1 > 2) + { + return CELL_SPURS_CORE_ERROR_INVAL; + } + + return spursInit( + spurs, + attr->m.arg1, + attr->m.arg2, + attr->m.nSpus, + attr->m.spuPriority, + attr->m.ppuPriority, + (u32)attr->_u32.raw[10] | (u32)attr->_u8[20] | 4, + attr.addr() + 0x15, + attr->_u32.raw[9], + attr->_u32.raw[11], + attr.addr() + 0x38, + attr->_u32.raw[16], + attr->_u32.raw[17]); #endif } @@ -39,32 +150,6 @@ s64 cellSpursFinalize(vm::ptr spurs) #endif } -s64 cellSpursInitializeWithAttribute(vm::ptr spurs, vm::ptr attr) -{ - cellSpurs->Warning("cellSpursInitializeWithAttribute(spurs_addr=0x%x, spurs_addr=0x%x)", spurs.addr(), attr.addr()); - -#ifdef PRX_DEBUG - return GetCurrentPPUThread().FastCall2(libsre + 0x839C, libsre_rtoc); -#else - spurs->spurs = new SPURSManager(attr->attr); - - return CELL_OK; -#endif -} - -s64 cellSpursInitializeWithAttribute2(vm::ptr spurs, vm::ptr attr) -{ - cellSpurs->Warning("cellSpursInitializeWithAttribute2(spurs_addr=0x%x, spurs_addr=0x%x)", spurs.addr(), attr.addr()); - -#ifdef PRX_DEBUG - return GetCurrentPPUThread().FastCall2(libsre + 0x82B4, libsre_rtoc); -#else - spurs->spurs = new SPURSManager(attr->attr); - - return CELL_OK; -#endif -} - s64 _cellSpursAttributeInitialize(vm::ptr attr, s32 nSpus, s32 spuPriority, s32 ppuPriority, bool exitIfNoWork) { cellSpurs->Warning("_cellSpursAttributeInitialize(attr_addr=0x%x, nSpus=%d, spuPriority=%d, ppuPriority=%d, exitIfNoWork=%d)", diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index 51a92a298f..ed4f0b5651 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -94,7 +94,35 @@ struct CellSpurs2 struct CellSpursAttribute { - SPURSManagerAttribute *attr; + static const auto align = 8; + static const auto size = 512; + + union + { + // raw data + u8 _u8[size / sizeof(u8)]; + + struct + { + be_t raw[size / sizeof(u32)]; + } _u32; + + // real structure + struct + { + be_t arg1; + be_t arg2; + be_t nSpus; + be_t spuPriority; + be_t ppuPriority; + } m; + + // alternative implementation + struct + { + SPURSManagerAttribute *attr; + } c; + }; }; struct CellSpursEventFlag diff --git a/rpcs3/Emu/SysCalls/lv2/lv2Fs.cpp b/rpcs3/Emu/SysCalls/lv2/lv2Fs.cpp index 9b75ed13a7..0d68021cba 100644 --- a/rpcs3/Emu/SysCalls/lv2/lv2Fs.cpp +++ b/rpcs3/Emu/SysCalls/lv2/lv2Fs.cpp @@ -227,7 +227,7 @@ s32 cellFsClosedir(u32 fd) s32 cellFsStat(vm::ptr path, vm::ptr sb) { - sys_fs->Warning("cellFsStat(path=\"%s\", sb_addr: 0x%x)", path.get_ptr(), sb.addr()); + sys_fs->Warning("cellFsStat(path=\"%s\", sb_addr=0x%x)", path.get_ptr(), sb.addr()); LV2_LOCK(0); @@ -270,7 +270,7 @@ s32 cellFsStat(vm::ptr path, vm::ptr sb) s32 cellFsFstat(u32 fd, vm::ptr sb) { - sys_fs->Warning("cellFsFstat(fd=%d, sb_addr: 0x%x)", fd, sb.addr()); + sys_fs->Warning("cellFsFstat(fd=%d, sb_addr=0x%x)", fd, sb.addr()); LV2_LOCK(0);