mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 03:25:16 +00:00
Float/vector arg support for callbacks
This commit is contained in:
parent
85f2009175
commit
5a4aa9096b
4 changed files with 125 additions and 24 deletions
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
class PPUThread;
|
||||
|
||||
namespace vm
|
||||
{
|
||||
template<typename T, int lvl = 1, typename AT = u32>
|
||||
|
@ -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
|
||||
{
|
||||
|
|
|
@ -3,51 +3,148 @@
|
|||
|
||||
namespace vm
|
||||
{
|
||||
template<typename TT>
|
||||
struct _func_arg
|
||||
enum _func_arg_type
|
||||
{
|
||||
static_assert(!std::is_floating_point<TT>::value, "TODO: Unsupported callback argument type (floating point)");
|
||||
static_assert(!std::is_same<TT, u128>::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<TT>::value, "Invalid callback argument type (pointer)");
|
||||
static_assert(!std::is_reference<TT>::value, "Invalid callback argument type (reference)");
|
||||
template<typename T, _func_arg_type type, int g_count, int f_count, int v_count>
|
||||
struct _func_arg;
|
||||
|
||||
__forceinline static u64 get_value(const TT& arg)
|
||||
template<typename T, int g_count, int f_count, int v_count>
|
||||
struct _func_arg<T, ARG_GENERAL, g_count, f_count, v_count>
|
||||
{
|
||||
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<typename T, int g_count, int f_count, int v_count>
|
||||
struct _func_arg<T, ARG_FLOAT, g_count, f_count, v_count>
|
||||
{
|
||||
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<typename T, int g_count, int f_count, int v_count>
|
||||
struct _func_arg<T, ARG_VECTOR, g_count, f_count, v_count>
|
||||
{
|
||||
static_assert(std::is_same<T, u128>::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<typename T, int g_count, int f_count, int v_count>
|
||||
struct _func_arg<T, ARG_STACK, g_count, f_count, v_count>
|
||||
{
|
||||
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<int g_count, int f_count, int v_count>
|
||||
__forceinline static void _bind_func_args(PPUThread& CPU)
|
||||
{
|
||||
// terminator
|
||||
}
|
||||
|
||||
template<int g_count, int f_count, int v_count, typename T1, typename... T>
|
||||
__forceinline static void _bind_func_args(PPUThread& CPU, T1 arg1, T... args)
|
||||
{
|
||||
static_assert(!std::is_pointer<T1>::value, "Invalid callback argument type (pointer)");
|
||||
static_assert(!std::is_reference<T1>::value, "Invalid callback argument type (reference)");
|
||||
const bool is_float = std::is_floating_point<T1>::value;
|
||||
const bool is_vector = std::is_same<T1, u128>::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<T1, t, g, f, v>::set_value(CPU, arg1);
|
||||
_bind_func_args<g, f, v>(CPU, args...);
|
||||
}
|
||||
|
||||
template<typename RT>
|
||||
struct _func_res
|
||||
{
|
||||
static_assert(!std::is_floating_point<RT>::value, "TODO: Unsupported callback result type (floating point)");
|
||||
static_assert(!std::is_same<RT, u128>::value, "TODO: Unsupported callback result type (vector)");
|
||||
|
||||
static_assert(sizeof(RT) <= 8, "Invalid callback result type");
|
||||
static_assert(!std::is_pointer<RT>::value, "Invalid callback result type (pointer)");
|
||||
static_assert(!std::is_reference<RT>::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<RT>::value)
|
||||
{
|
||||
return (RT)CPU.FPR[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
return (RT&)CPU.GPR[3];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct _func_res<u128>
|
||||
{
|
||||
__forceinline static u128 get_value(const PPUThread& CPU)
|
||||
{
|
||||
return CPU.VPR[2];
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct _func_res<void>
|
||||
{
|
||||
__forceinline static void get_value(const u64 res)
|
||||
__forceinline static void get_value(const PPUThread& CPU)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<typename AT, typename RT, typename... T>
|
||||
RT _ptr_base<RT(*)(T...), 1, AT>::operator ()(T... args) const
|
||||
template<typename RT, typename... T>
|
||||
struct _func_caller
|
||||
{
|
||||
return _func_res<RT>::get_value(GetCurrentPPUThread().FastCall(vm::read32(m_addr), vm::read32(m_addr + 4), _func_arg<T>::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<RT>::get_value(CPU);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename AT, typename RT, typename... T>
|
||||
__forceinline RT _ptr_base<RT(*)(T...), 1, AT>::call(PPUThread& CPU, T... args) const
|
||||
{
|
||||
const u32 pc = vm::get_ref<be_t<u32>>(m_addr);
|
||||
const u32 rtoc = vm::get_ref<be_t<u32>>(m_addr + 4);
|
||||
|
||||
return _func_caller<RT, T...>::call(CPU, pc, rtoc, args...);
|
||||
}
|
||||
|
||||
template<typename AT, typename RT, typename... T>
|
||||
__forceinline RT _ptr_base<RT(*)(T...), 1, AT>::operator ()(T... args) const
|
||||
{
|
||||
return call(GetCurrentPPUThread(), args...);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
#pragma once
|
||||
#include "CB_FUNC.h"
|
||||
|
||||
class CPUThread;
|
||||
|
||||
class CallbackManager
|
||||
{
|
||||
std::vector<std::function<s32()>> m_cb_list;
|
||||
|
|
|
@ -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<int g_count, int f_count, int v_count>
|
||||
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<T>(bind_arg<T, t, g, f, v>::func(CPU)), iterate<g, f, v, A...>(CPU));
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue