diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.h b/rpcs3/Emu/ARMv7/ARMv7Thread.h index ce63376273..22e655188d 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.h +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.h @@ -1,5 +1,4 @@ #pragma once - #include "Emu/CPU/CPUThread.h" #include "Emu/Memory/Memory.h" @@ -210,3 +209,131 @@ public: return *this; } }; + +template::value> +struct cast_armv7_gpr +{ + static_assert(is_enum, "Invalid type for cast_armv7_gpr"); + + typedef typename std::underlying_type::type underlying_type; + + __forceinline static u32 to_gpr(const T& value) + { + return cast_armv7_gpr::to_gpr(static_cast(value)); + } + + __forceinline static T from_gpr(const u32 reg) + { + return static_cast(cast_armv7_gpr::from_gpr(reg)); + } +}; + +template<> +struct cast_armv7_gpr +{ + __forceinline static u32 to_gpr(const u8& value) + { + return value; + } + + __forceinline static u8 from_gpr(const u32 reg) + { + return static_cast(reg); + } +}; + +template<> +struct cast_armv7_gpr +{ + __forceinline static u32 to_gpr(const u16& value) + { + return value; + } + + __forceinline static u16 from_gpr(const u32 reg) + { + return static_cast(reg); + } +}; + +template<> +struct cast_armv7_gpr +{ + __forceinline static u32 to_gpr(const u32& value) + { + return value; + } + + __forceinline static u32 from_gpr(const u32 reg) + { + return reg; + } +}; + +template<> +struct cast_armv7_gpr +{ + __forceinline static u32 to_gpr(const s8& value) + { + return value; + } + + __forceinline static s8 from_gpr(const u32 reg) + { + return static_cast(reg); + } +}; + +template<> +struct cast_armv7_gpr +{ + __forceinline static u32 to_gpr(const s16& value) + { + return value; + } + + __forceinline static s16 from_gpr(const u32 reg) + { + return static_cast(reg); + } +}; + +template<> +struct cast_armv7_gpr +{ + __forceinline static u32 to_gpr(const s32& value) + { + return value; + } + + __forceinline static s32 from_gpr(const u32 reg) + { + return static_cast(reg); + } +}; + +template<> +struct cast_armv7_gpr +{ + __forceinline static u32 to_gpr(const bool& value) + { + return value; + } + + __forceinline static bool from_gpr(const u32 reg) + { + return reinterpret_cast(reg); + } +}; + +template +__forceinline u32 cast_to_armv7_gpr(const T& value) +{ + return cast_armv7_gpr::to_gpr(value); +} + +template +__forceinline T cast_from_armv7_gpr(const u32 reg) +{ + return cast_armv7_gpr::from_gpr(reg); +} diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.h b/rpcs3/Emu/ARMv7/PSVFuncList.h index dfd97f6166..9fe75a647a 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.h +++ b/rpcs3/Emu/ARMv7/PSVFuncList.h @@ -425,7 +425,7 @@ namespace psv_func_detail static __forceinline T func(ARMv7Thread& CPU) { - return (T&)CPU.GPR[g_count - 1]; + return cast_from_armv7_gpr(CPU.GPR[g_count - 1]); } }; @@ -444,7 +444,7 @@ namespace psv_func_detail struct bind_arg { static_assert(v_count <= 0, "TODO: Unsupported argument type (vector)"); - static_assert(sizeof(T) == 16, "Invalid function argument type for ARG_VECTOR"); + static_assert(std::is_same::value, "Invalid function argument type for ARG_VECTOR"); static __forceinline T func(ARMv7Thread& CPU) { @@ -460,8 +460,9 @@ namespace psv_func_detail static __forceinline T func(ARMv7Thread& CPU) { + // TODO: check const u32 res = CPU.GetStackArg(g_count); - return (T&)res; + return cast_from_armv7_gpr(res); } }; @@ -473,10 +474,9 @@ namespace psv_func_detail static_assert(type == ARG_GENERAL, "Wrong use of bind_result template"); static_assert(sizeof(T) <= 4, "Invalid function result type for ARG_GENERAL"); - static __forceinline void func(ARMv7Thread& CPU, T result) + static __forceinline void func(ARMv7Thread& CPU, const T& result) { - CPU.GPR[0] = 0; // TODO - (T&)CPU.GPR[0] = result; + CPU.GPR[0] = cast_to_armv7_gpr(result); } }; @@ -485,7 +485,7 @@ namespace psv_func_detail //{ // static_assert(sizeof(T) <= 8, "Invalid function result type for ARG_FLOAT"); - // static __forceinline void func(ARMv7Thread& CPU, T result) + // static __forceinline void func(ARMv7Thread& CPU, const T& result) // { // } //}; @@ -493,9 +493,9 @@ namespace psv_func_detail //template //struct bind_result //{ - // static_assert(sizeof(T) == 16, "Invalid function result type for ARG_VECTOR"); + // static_assert(std::is_same::value, "Invalid function result type for ARG_VECTOR"); - // static __forceinline void func(ARMv7Thread& CPU, const T result) + // static __forceinline void func(ARMv7Thread& CPU, const T& result) // { // } //}; @@ -550,6 +550,16 @@ namespace psv_func_detail return std::tuple_cat(std::tuple(bind_arg::func(CPU)), iterate(CPU)); } + 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)"); + static const bool is_float = std::is_floating_point::value; + static const bool is_vector = std::is_same::value; + static const bind_arg_type value = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL); + }; + template class func_binder; @@ -606,13 +616,7 @@ namespace psv_func_detail virtual void operator()(ARMv7Thread& 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))); + bind_result::value>::func(CPU, call(m_call, iterate<0, 0, 0, T...>(CPU))); } }; @@ -631,13 +635,7 @@ namespace psv_func_detail virtual void operator()(ARMv7Thread& 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, std::tuple_cat(std::tuple(CPU), iterate<0, 0, 0, T...>(CPU)))); + bind_result::value>::func(CPU, call(m_call, std::tuple_cat(std::tuple(CPU), iterate<0, 0, 0, T...>(CPU)))); } }; } diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 0a11d9a724..2c5c13246d 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -971,7 +971,7 @@ struct cast_ppu_gpr __forceinline static bool from_gpr(const u64 reg) { - return (bool&)reg; + return reinterpret_cast(reg); } }; diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index 8e7cc289c1..c628a4b8a0 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -568,3 +568,22 @@ struct cast_ppu_gpr, false> return vm::ps3::ptr::make(cast_ppu_gpr::value>::from_gpr(reg)); } }; + +// external specializations for ARMv7 GPR + +template +struct cast_armv7_gpr; + +template +struct cast_armv7_gpr, false> +{ + __forceinline static u32 to_gpr(const vm::psv::ptr& value) + { + return value.addr(); + } + + __forceinline static vm::psv::ptr from_gpr(const u32 reg) + { + return vm::psv::ptr::make(cast_armv7_gpr::value>::from_gpr(reg)); + } +}; diff --git a/rpcs3/Emu/Memory/vm_ref.h b/rpcs3/Emu/Memory/vm_ref.h index 237997ed02..d8e6092540 100644 --- a/rpcs3/Emu/Memory/vm_ref.h +++ b/rpcs3/Emu/Memory/vm_ref.h @@ -166,3 +166,22 @@ struct cast_ppu_gpr, false> return vm::ps3::ref::make(cast_ppu_gpr::value>::from_gpr(reg)); } }; + +// external specializations for ARMv7 GPR + +template +struct cast_armv7_gpr; + +template +struct cast_armv7_gpr, false> +{ + __forceinline static u32 to_gpr(const vm::psv::ref& value) + { + return value.addr(); + } + + __forceinline static vm::psv::ref from_gpr(const u32 reg) + { + return vm::psv::ref::make(cast_armv7_gpr::value>::from_gpr(reg)); + } +}; diff --git a/rpcs3/Emu/SysCalls/SC_FUNC.h b/rpcs3/Emu/SysCalls/SC_FUNC.h index 0fd40217ca..1a025f2f63 100644 --- a/rpcs3/Emu/SysCalls/SC_FUNC.h +++ b/rpcs3/Emu/SysCalls/SC_FUNC.h @@ -8,7 +8,7 @@ public: virtual ~func_caller(){}; }; -namespace detail +namespace ppu_func_detail { enum bind_arg_type { @@ -125,7 +125,7 @@ namespace detail __forceinline RT call(F f, Tuple && t) { typedef typename std::decay::type ttype; - return detail::call_impl::value, std::tuple_size::value>::call(f, std::forward(t)); + return ppu_func_detail::call_impl::value, std::tuple_size::value>::call(f, std::forward(t)); } template @@ -153,6 +153,16 @@ namespace detail return std::tuple_cat(std::tuple(bind_arg::func(CPU)), iterate(CPU)); } + 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)"); + static const bool is_float = std::is_floating_point::value; + static const bool is_vector = std::is_same::value; + static const bind_arg_type value = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL); + }; + template class func_binder; @@ -209,13 +219,7 @@ namespace detail virtual void operator()(PPUThread& 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))); + bind_result::value>::func(CPU, call(m_call, iterate<0, 0, 0, T...>(CPU))); } }; @@ -234,13 +238,7 @@ namespace detail virtual void operator()(PPUThread& 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, std::tuple_cat(std::tuple(CPU), iterate<0, 0, 0, T...>(CPU)))); + bind_result::value>::func(CPU, call(m_call, std::tuple_cat(std::tuple(CPU), iterate<0, 0, 0, T...>(CPU)))); } }; } @@ -248,5 +246,5 @@ namespace detail template func_caller* bind_func(RT(*call)(T...)) { - return new detail::func_binder(call); + return new ppu_func_detail::func_binder(call); }