From 096fc86f17f8c49f159c679198b7d676e3bf0944 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 8 Jul 2015 20:45:26 +0300 Subject: [PATCH] SC_FUNC improved (faster compilation) --- rpcs3/Emu/SysCalls/Callback.cpp | 6 +- rpcs3/Emu/SysCalls/Modules/cellAvconfExt.cpp | 2 +- rpcs3/Emu/SysCalls/SC_FUNC.h | 136 +++++++++++-------- rpcs3/Loader/ELF64.cpp | 4 +- 4 files changed, 84 insertions(+), 64 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Callback.cpp b/rpcs3/Emu/SysCalls/Callback.cpp index 74558d632e..6d75393a22 100644 --- a/rpcs3/Emu/SysCalls/Callback.cpp +++ b/rpcs3/Emu/SysCalls/Callback.cpp @@ -57,7 +57,11 @@ void CallbackManager::Init() { CHECK_EMU_STATUS; - if (!lock) lock.lock(); + if (!lock) + { + lock.lock(); + continue; + } if (m_async_cb.size()) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellAvconfExt.cpp b/rpcs3/Emu/SysCalls/Modules/cellAvconfExt.cpp index 5499ac05b4..1b77bb9b05 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAvconfExt.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAvconfExt.cpp @@ -8,7 +8,7 @@ namespace vm { using namespace ps3; } extern Module cellAvconfExt; -s32 cellVideoOutConvertCursorColor() +s32 cellVideoOutConvertCursorColor(PPUThread& CPU) { UNIMPLEMENTED_FUNC(cellAvconfExt); return CELL_OK; diff --git a/rpcs3/Emu/SysCalls/SC_FUNC.h b/rpcs3/Emu/SysCalls/SC_FUNC.h index f426a11d01..8d7eddaeaf 100644 --- a/rpcs3/Emu/SysCalls/SC_FUNC.h +++ b/rpcs3/Emu/SysCalls/SC_FUNC.h @@ -6,18 +6,18 @@ using ppu_func_caller = void(*)(PPUThread&); namespace ppu_func_detail { - enum arg_class : u8 + // argument type classification + enum arg_class : u32 { - ARG_GENERAL, - ARG_FLOAT, - ARG_VECTOR, + ARG_GENERAL, // argument is stored in GPR registers (from r3 to r10) + ARG_FLOAT, // argument is stored in FPR registers (from f1 to f12) + ARG_VECTOR, // argument is stored in VPR registers (from v2 to v13) ARG_STACK, }; - template - struct bind_arg; + template struct bind_arg; - template + template struct bind_arg { static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_GENERAL"); @@ -28,7 +28,7 @@ namespace ppu_func_detail } }; - template + template struct bind_arg { static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_FLOAT"); @@ -39,7 +39,7 @@ namespace ppu_func_detail } }; - template + template struct bind_arg { static_assert(std::is_same::value, "Invalid function argument type for ARG_VECTOR"); @@ -50,7 +50,7 @@ namespace ppu_func_detail } }; - template + template struct bind_arg { static_assert(f_count <= 13, "TODO: Unsupported stack argument type (float)"); @@ -60,7 +60,7 @@ namespace ppu_func_detail static force_inline T get_arg(PPUThread& CPU) { // TODO: check stack argument displacement - const u64 res = CPU.GetStackArg(8 + std::max(g_count - 8, 0) + std::max(f_count - 13, 0) + std::max(v_count - 12, 0)); + const u64 res = CPU.GetStackArg(8 + std::max(g_count - 8, 0) + std::max(f_count - 13, 0) + std::max(v_count - 12, 0)); return cast_from_ppu_gpr(res); } }; @@ -99,60 +99,56 @@ namespace ppu_func_detail } }; - struct arg_type_pack + // wrapper for variadic argument info list, each value contains packed argument type and counts of GENERAL, FLOAT and VECTOR arguments + template struct arg_info_pack_t; + + template struct arg_info_pack_t { - arg_class type; - u8 g_count; - u8 f_count; - u8 v_count; + static const u32 last_value = arg_info_pack_t::last_value; }; - template - struct bind_arg_packed + template struct arg_info_pack_t + { + static const u32 last_value = First; + }; + + template<> struct arg_info_pack_t<> + { + static const u32 last_value = 0; + }; + + // argument unpacker + template struct bind_arg_packed { static force_inline T get_arg(PPUThread& CPU) { - return bind_arg> 8), (type_pack >> 16), (type_pack >> 24)>::get_arg(CPU); + return bind_arg(type_pack & 0xff), (type_pack >> 8) & 0xff, (type_pack >> 16) & 0xff, (type_pack >> 24)>::get_arg(CPU); } }; - template - struct call_impl + template + force_inline RT call(PPUThread& CPU, RT(*func)(Args...), arg_info_pack_t) { - static force_inline RT call(F f, Tuple && t) - { - return call_impl::call(f, std::forward(t)); - } - }; - - template - struct call_impl - { - static force_inline RT call(F f, Tuple && t) - { - return f(std::get(std::forward(t))...); - } - }; - - template - force_inline RT call(F f, Tuple && t) - { - using ttype = std::decay_t; - return ppu_func_detail::call_impl::value, std::tuple_size::value>::call(f, std::forward(t)); + return func(bind_arg_packed::get_arg(CPU)...); } - template - force_inline std::tuple<> iterate(PPUThread& CPU) + template + force_inline RT call(PPUThread& CPU, RT(*func)(PPUThread&, Args...), arg_info_pack_t) { - // terminator - return std::tuple<>(); + return func(CPU, bind_arg_packed::get_arg(CPU)...); } - template - force_inline std::tuple iterate(PPUThread& CPU) + template + force_inline RT call(PPUThread& CPU, RT(*func)(Args...), arg_info_pack_t info) { static_assert(!std::is_pointer::value, "Invalid function argument type (pointer)"); static_assert(!std::is_reference::value, "Invalid function argument type (reference)"); + + // unpack previous type counts (0/0/0 for the first time) + const u32 g_count = (info.last_value >> 8) & 0xff; + const u32 f_count = (info.last_value >> 16) & 0xff; + const u32 v_count = (info.last_value >> 24); + // TODO: check calculations const bool is_float = std::is_floating_point::value; const bool is_vector = std::is_same::value; @@ -163,11 +159,10 @@ namespace ppu_func_detail const u32 f = f_count + (is_float ? 1 : 0); const u32 v = v_count + (is_vector ? 1 : 0); - return std::tuple_cat(std::tuple(bind_arg::get_arg(CPU)), iterate(CPU)); + return call(CPU, func, arg_info_pack_t{}); } - template - struct result_type + template struct result_type { static_assert(!std::is_pointer::value, "Invalid function result type (pointer)"); static_assert(!std::is_reference::value, "Invalid function result type (reference)"); @@ -176,17 +171,16 @@ namespace ppu_func_detail static const arg_class value = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL); }; - template - struct func_binder; + template struct func_binder; template struct func_binder { using func_t = void(*)(PPUThread&, T...); - static void do_call(PPUThread& CPU, func_t func) + static force_inline void do_call(PPUThread& CPU, func_t func) { - call(func, std::tuple_cat(std::tuple(CPU), iterate<0, 0, 0, T...>(CPU))); + call(CPU, func, arg_info_pack_t<>{}); } }; @@ -195,9 +189,31 @@ namespace ppu_func_detail { using func_t = void(*)(T...); - static void do_call(PPUThread& CPU, func_t func) + static force_inline void do_call(PPUThread& CPU, func_t func) { - call(func, iterate<0, 0, 0, T...>(CPU)); + call(CPU, func, arg_info_pack_t<>{}); + } + }; + + template<> + struct func_binder // redundant specialization to bypass internal compiler error in MSVC + { + using func_t = void(*)(); + + static force_inline void do_call(PPUThread& CPU, func_t func) + { + func(); + } + }; + + template + struct func_binder // redundant specialization to bypass internal compiler error in MSVC + { + using func_t = RT(*)(); + + static force_inline void do_call(PPUThread& CPU, func_t func) + { + bind_result::value>::put_result(CPU, func()); } }; @@ -206,9 +222,9 @@ namespace ppu_func_detail { using func_t = RT(*)(PPUThread&, T...); - static void do_call(PPUThread& CPU, func_t func) + static force_inline void do_call(PPUThread& CPU, func_t func) { - bind_result::value>::put_result(CPU, call(func, std::tuple_cat(std::tuple(CPU), iterate<0, 0, 0, T...>(CPU)))); + bind_result::value>::put_result(CPU, call(CPU, func, arg_info_pack_t<>{})); } }; @@ -217,9 +233,9 @@ namespace ppu_func_detail { using func_t = RT(*)(T...); - static void do_call(PPUThread& CPU, func_t func) + static force_inline void do_call(PPUThread& CPU, func_t func) { - bind_result::value>::put_result(CPU, call(func, iterate<0, 0, 0, T...>(CPU))); + bind_result::value>::put_result(CPU, call(CPU, func, arg_info_pack_t<>{})); } }; } diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index e66abcc3f0..23623b4f3d 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -416,7 +416,7 @@ namespace loader if (!module) { - LOG_WARNING(LOADER, "Unknown module '%s' in '%s' library", m.first.c_str(), info.name.c_str()); + LOG_ERROR(LOADER, "Unknown module '%s' in '%s' library", m.first.c_str(), info.name.c_str()); } for (auto& f : m.second.exports) @@ -680,7 +680,7 @@ namespace loader if (!module) { - LOG_WARNING(LOADER, "Unknown module '%s'", module_name.c_str()); + LOG_ERROR(LOADER, "Unknown module '%s'", module_name.c_str()); } for (u32 i = 0; i < stub->s_imports; ++i)