diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index a687eab5d4..9a7e150170 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -1,5 +1,7 @@ #pragma once +class PPUThread; + namespace vm { template @@ -319,7 +321,9 @@ namespace vm public: typedef RT(*type)(T...); - RT operator()(T... args) const; // defined in Callback.h (CB_FUNC.h) + RT call(PPUThread& CPU, T... args) const; // call using specified PPU thread context, defined in Callback.h (CB_FUNC.h) + + RT operator()(T... args) const; // call using current PPU thread context, defined in Callback.h (CB_FUNC.h) AT addr() const { diff --git a/rpcs3/Emu/SysCalls/CB_FUNC.h b/rpcs3/Emu/SysCalls/CB_FUNC.h index 83d1de2c0b..9d35e3d885 100644 --- a/rpcs3/Emu/SysCalls/CB_FUNC.h +++ b/rpcs3/Emu/SysCalls/CB_FUNC.h @@ -3,51 +3,148 @@ namespace vm { - template - struct _func_arg + enum _func_arg_type { - static_assert(!std::is_floating_point::value, "TODO: Unsupported callback argument type (floating point)"); - static_assert(!std::is_same::value, "TODO: Unsupported callback argument type (vector)"); + ARG_GENERAL, + ARG_FLOAT, + ARG_VECTOR, + ARG_STACK, + }; - static_assert(sizeof(TT) <= 8, "Invalid callback argument type"); - static_assert(!std::is_pointer::value, "Invalid callback argument type (pointer)"); - static_assert(!std::is_reference::value, "Invalid callback argument type (reference)"); + template + struct _func_arg; - __forceinline static u64 get_value(const TT& arg) + template + struct _func_arg + { + static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_GENERAL"); + + __forceinline static void set_value(PPUThread& CPU, const T arg) { - u64 res = 0; - (TT&)res = arg; - return res; + (T&)CPU.GPR[g_count + 2] = arg; } }; + template + struct _func_arg + { + static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_FLOAT"); + + __forceinline static void set_value(PPUThread& CPU, const T arg) + { + CPU.FPR[f_count] = arg; + } + }; + + template + struct _func_arg + { + static_assert(std::is_same::value, "Invalid callback argument type for ARG_VECTOR"); + + __forceinline static void set_value(PPUThread& CPU, const T arg) + { + (T&)CPU.VPR[v_count + 1] = arg; + } + }; + + 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 + } + }; + + template + __forceinline static void _bind_func_args(PPUThread& CPU) + { + // terminator + } + + template + __forceinline static void _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)"); + const bool is_float = std::is_floating_point::value; + const bool is_vector = std::is_same::value; + const _func_arg_type t = is_float + ? ((f_count >= 12) ? ARG_STACK : ARG_FLOAT) + : (is_vector ? ((v_count >= 12) ? ARG_STACK : ARG_VECTOR) : ((g_count >= 8) ? ARG_STACK : ARG_GENERAL)); + const int g = g_count + (is_float || is_vector ? 0 : 1); + const int f = f_count + (is_float ? 1 : 0); + const int v = v_count + (is_vector ? 1 : 0); + + _func_arg::set_value(CPU, arg1); + _bind_func_args(CPU, args...); + } + template struct _func_res { - static_assert(!std::is_floating_point::value, "TODO: Unsupported callback result type (floating point)"); - static_assert(!std::is_same::value, "TODO: Unsupported callback result type (vector)"); - 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)"); - __forceinline static RT get_value(const u64 res) + __forceinline static RT get_value(const PPUThread& CPU) { - return (RT&)res; + if (std::is_floating_point::value) + { + return (RT)CPU.FPR[1]; + } + else + { + return (RT&)CPU.GPR[3]; + } + } + }; + + template<> + struct _func_res + { + __forceinline static u128 get_value(const PPUThread& CPU) + { + return CPU.VPR[2]; } }; template<> struct _func_res { - __forceinline static void get_value(const u64 res) + __forceinline static void get_value(const PPUThread& CPU) { } }; - template - RT _ptr_base::operator ()(T... args) const + template + struct _func_caller { - return _func_res::get_value(GetCurrentPPUThread().FastCall(vm::read32(m_addr), vm::read32(m_addr + 4), _func_arg::get_value(args)...)); + __forceinline static RT call(PPUThread& CPU, u32 pc, u32 rtoc, T... args) + { + _bind_func_args<0, 0, 0>(CPU, args...); + CPU.FastCall2(pc, rtoc); + return _func_res::get_value(CPU); + } + }; + + template + __forceinline RT _ptr_base::call(PPUThread& CPU, T... args) const + { + const u32 pc = vm::get_ref>(m_addr); + const u32 rtoc = vm::get_ref>(m_addr + 4); + + return _func_caller::call(CPU, pc, rtoc, args...); + } + + template + __forceinline RT _ptr_base::operator ()(T... args) const + { + return call(GetCurrentPPUThread(), args...); } } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Callback.h b/rpcs3/Emu/SysCalls/Callback.h index 6402ca84b6..f5747e6ac5 100644 --- a/rpcs3/Emu/SysCalls/Callback.h +++ b/rpcs3/Emu/SysCalls/Callback.h @@ -1,8 +1,6 @@ #pragma once #include "CB_FUNC.h" -class CPUThread; - class CallbackManager { std::vector> m_cb_list; diff --git a/rpcs3/Emu/SysCalls/SC_FUNC.h b/rpcs3/Emu/SysCalls/SC_FUNC.h index f01cc741d4..16e16cd2ab 100644 --- a/rpcs3/Emu/SysCalls/SC_FUNC.h +++ b/rpcs3/Emu/SysCalls/SC_FUNC.h @@ -59,7 +59,7 @@ namespace detail { 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 function argument type (ARG_STACK)"); + static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_STACK"); static __forceinline T func(PPUThread& CPU) { @@ -126,6 +126,7 @@ namespace detail template static __forceinline std::tuple<> iterate(PPUThread& CPU) { + // terminator return std::tuple<>(); } @@ -143,6 +144,7 @@ namespace detail const int g = g_count + (is_float || is_vector ? 0 : 1); const int f = f_count + (is_float ? 1 : 0); const int v = v_count + (is_vector ? 1 : 0); + return std::tuple_cat(std::tuple(bind_arg::func(CPU)), iterate(CPU)); }