mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 03:55:32 +00:00
cast_armv7_gpr added
This commit is contained in:
parent
6ec6303933
commit
c4558d2ca7
6 changed files with 203 additions and 42 deletions
|
@ -1,5 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
#include "Emu/CPU/CPUThread.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
|
||||
|
@ -210,3 +209,131 @@ public:
|
|||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, bool is_enum = std::is_enum<T>::value>
|
||||
struct cast_armv7_gpr
|
||||
{
|
||||
static_assert(is_enum, "Invalid type for cast_armv7_gpr");
|
||||
|
||||
typedef typename std::underlying_type<T>::type underlying_type;
|
||||
|
||||
__forceinline static u32 to_gpr(const T& value)
|
||||
{
|
||||
return cast_armv7_gpr<underlying_type>::to_gpr(static_cast<underlying_type>(value));
|
||||
}
|
||||
|
||||
__forceinline static T from_gpr(const u32 reg)
|
||||
{
|
||||
return static_cast<T>(cast_armv7_gpr<underlying_type>::from_gpr(reg));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct cast_armv7_gpr<u8, false>
|
||||
{
|
||||
__forceinline static u32 to_gpr(const u8& value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
__forceinline static u8 from_gpr(const u32 reg)
|
||||
{
|
||||
return static_cast<u8>(reg);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct cast_armv7_gpr<u16, false>
|
||||
{
|
||||
__forceinline static u32 to_gpr(const u16& value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
__forceinline static u16 from_gpr(const u32 reg)
|
||||
{
|
||||
return static_cast<u16>(reg);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct cast_armv7_gpr<u32, false>
|
||||
{
|
||||
__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<s8, false>
|
||||
{
|
||||
__forceinline static u32 to_gpr(const s8& value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
__forceinline static s8 from_gpr(const u32 reg)
|
||||
{
|
||||
return static_cast<s8>(reg);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct cast_armv7_gpr<s16, false>
|
||||
{
|
||||
__forceinline static u32 to_gpr(const s16& value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
__forceinline static s16 from_gpr(const u32 reg)
|
||||
{
|
||||
return static_cast<s16>(reg);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct cast_armv7_gpr<s32, false>
|
||||
{
|
||||
__forceinline static u32 to_gpr(const s32& value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
__forceinline static s32 from_gpr(const u32 reg)
|
||||
{
|
||||
return static_cast<s32>(reg);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct cast_armv7_gpr<bool, false>
|
||||
{
|
||||
__forceinline static u32 to_gpr(const bool& value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
__forceinline static bool from_gpr(const u32 reg)
|
||||
{
|
||||
return reinterpret_cast<const bool&>(reg);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
__forceinline u32 cast_to_armv7_gpr(const T& value)
|
||||
{
|
||||
return cast_armv7_gpr<T>::to_gpr(value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
__forceinline T cast_from_armv7_gpr(const u32 reg)
|
||||
{
|
||||
return cast_armv7_gpr<T>::from_gpr(reg);
|
||||
}
|
||||
|
|
|
@ -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<T>(CPU.GPR[g_count - 1]);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -444,7 +444,7 @@ namespace psv_func_detail
|
|||
struct bind_arg<T, ARG_VECTOR, g_count, f_count, v_count>
|
||||
{
|
||||
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<T, u128>::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<T>(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<T>(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<typename T>
|
||||
//struct bind_result<T, ARG_VECTOR>
|
||||
//{
|
||||
// static_assert(sizeof(T) == 16, "Invalid function result type for ARG_VECTOR");
|
||||
// static_assert(std::is_same<T, u128>::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<T>(bind_arg<T, t, g, f, v>::func(CPU)), iterate<g, f, v, A...>(CPU));
|
||||
}
|
||||
|
||||
template<typename RT>
|
||||
struct result_type
|
||||
{
|
||||
static_assert(!std::is_pointer<RT>::value, "Invalid function result type (pointer)");
|
||||
static_assert(!std::is_reference<RT>::value, "Invalid function result type (reference)");
|
||||
static const bool is_float = std::is_floating_point<RT>::value;
|
||||
static const bool is_vector = std::is_same<RT, u128>::value;
|
||||
static const bind_arg_type value = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL);
|
||||
};
|
||||
|
||||
template<typename RT, typename... T>
|
||||
class func_binder;
|
||||
|
||||
|
@ -606,13 +616,7 @@ namespace psv_func_detail
|
|||
|
||||
virtual void operator()(ARMv7Thread& CPU)
|
||||
{
|
||||
static_assert(!std::is_pointer<RT>::value, "Invalid function result type (pointer)");
|
||||
static_assert(!std::is_reference<RT>::value, "Invalid function result type (reference)");
|
||||
const bool is_float = std::is_floating_point<RT>::value;
|
||||
const bool is_vector = std::is_same<RT, u128>::value;
|
||||
const bind_arg_type t = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL);
|
||||
|
||||
bind_result<RT, t>::func(CPU, call<RT>(m_call, iterate<0, 0, 0, T...>(CPU)));
|
||||
bind_result<RT, result_type<RT>::value>::func(CPU, call<RT>(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<RT>::value, "Invalid function result type (pointer)");
|
||||
static_assert(!std::is_reference<RT>::value, "Invalid function result type (reference)");
|
||||
const bool is_float = std::is_floating_point<RT>::value;
|
||||
const bool is_vector = std::is_same<RT, u128>::value;
|
||||
const bind_arg_type t = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL);
|
||||
|
||||
bind_result<RT, t>::func(CPU, call<RT>(m_call, std::tuple_cat(std::tuple<ARMv7Thread&>(CPU), iterate<0, 0, 0, T...>(CPU))));
|
||||
bind_result<RT, result_type<RT>::value>::func(CPU, call<RT>(m_call, std::tuple_cat(std::tuple<ARMv7Thread&>(CPU), iterate<0, 0, 0, T...>(CPU))));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -971,7 +971,7 @@ struct cast_ppu_gpr<bool, false>
|
|||
|
||||
__forceinline static bool from_gpr(const u64 reg)
|
||||
{
|
||||
return (bool&)reg;
|
||||
return reinterpret_cast<const bool&>(reg);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -568,3 +568,22 @@ struct cast_ppu_gpr<vm::ps3::ptr<T, lvl, AT>, false>
|
|||
return vm::ps3::ptr<T, lvl, AT>::make(cast_ppu_gpr<AT, std::is_enum<AT>::value>::from_gpr(reg));
|
||||
}
|
||||
};
|
||||
|
||||
// external specializations for ARMv7 GPR
|
||||
|
||||
template<typename T, bool is_enum>
|
||||
struct cast_armv7_gpr;
|
||||
|
||||
template<typename T, int lvl, typename AT>
|
||||
struct cast_armv7_gpr<vm::psv::ptr<T, lvl, AT>, false>
|
||||
{
|
||||
__forceinline static u32 to_gpr(const vm::psv::ptr<T, lvl, AT>& value)
|
||||
{
|
||||
return value.addr();
|
||||
}
|
||||
|
||||
__forceinline static vm::psv::ptr<T, lvl, AT> from_gpr(const u32 reg)
|
||||
{
|
||||
return vm::psv::ptr<T, lvl, AT>::make(cast_armv7_gpr<AT, std::is_enum<AT>::value>::from_gpr(reg));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -166,3 +166,22 @@ struct cast_ppu_gpr<vm::ps3::ref<T, AT>, false>
|
|||
return vm::ps3::ref<T, AT>::make(cast_ppu_gpr<AT, std::is_enum<AT>::value>::from_gpr(reg));
|
||||
}
|
||||
};
|
||||
|
||||
// external specializations for ARMv7 GPR
|
||||
|
||||
template<typename T, bool is_enum>
|
||||
struct cast_armv7_gpr;
|
||||
|
||||
template<typename T, typename AT>
|
||||
struct cast_armv7_gpr<vm::psv::ref<T, AT>, false>
|
||||
{
|
||||
__forceinline static u32 to_gpr(const vm::psv::ref<T, AT>& value)
|
||||
{
|
||||
return value.addr();
|
||||
}
|
||||
|
||||
__forceinline static vm::psv::ref<T, AT> from_gpr(const u32 reg)
|
||||
{
|
||||
return vm::psv::ref<T, AT>::make(cast_armv7_gpr<AT, std::is_enum<AT>::value>::from_gpr(reg));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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<Tuple>::type ttype;
|
||||
return detail::call_impl<RT, F, Tuple, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value>::call(f, std::forward<Tuple>(t));
|
||||
return ppu_func_detail::call_impl<RT, F, Tuple, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value>::call(f, std::forward<Tuple>(t));
|
||||
}
|
||||
|
||||
template<int g_count, int f_count, int v_count>
|
||||
|
@ -153,6 +153,16 @@ namespace detail
|
|||
return std::tuple_cat(std::tuple<T>(bind_arg<T, t, g, f, v>::func(CPU)), iterate<g, f, v, A...>(CPU));
|
||||
}
|
||||
|
||||
template<typename RT>
|
||||
struct result_type
|
||||
{
|
||||
static_assert(!std::is_pointer<RT>::value, "Invalid function result type (pointer)");
|
||||
static_assert(!std::is_reference<RT>::value, "Invalid function result type (reference)");
|
||||
static const bool is_float = std::is_floating_point<RT>::value;
|
||||
static const bool is_vector = std::is_same<RT, u128>::value;
|
||||
static const bind_arg_type value = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL);
|
||||
};
|
||||
|
||||
template<typename RT, typename... T>
|
||||
class func_binder;
|
||||
|
||||
|
@ -209,13 +219,7 @@ namespace detail
|
|||
|
||||
virtual void operator()(PPUThread& CPU)
|
||||
{
|
||||
static_assert(!std::is_pointer<RT>::value, "Invalid function result type (pointer)");
|
||||
static_assert(!std::is_reference<RT>::value, "Invalid function result type (reference)");
|
||||
const bool is_float = std::is_floating_point<RT>::value;
|
||||
const bool is_vector = std::is_same<RT, u128>::value;
|
||||
const bind_arg_type t = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL);
|
||||
|
||||
bind_result<RT, t>::func(CPU, call<RT>(m_call, iterate<0, 0, 0, T...>(CPU)));
|
||||
bind_result<RT, result_type<RT>::value>::func(CPU, call<RT>(m_call, iterate<0, 0, 0, T...>(CPU)));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -234,13 +238,7 @@ namespace detail
|
|||
|
||||
virtual void operator()(PPUThread& CPU)
|
||||
{
|
||||
static_assert(!std::is_pointer<RT>::value, "Invalid function result type (pointer)");
|
||||
static_assert(!std::is_reference<RT>::value, "Invalid function result type (reference)");
|
||||
const bool is_float = std::is_floating_point<RT>::value;
|
||||
const bool is_vector = std::is_same<RT, u128>::value;
|
||||
const bind_arg_type t = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL);
|
||||
|
||||
bind_result<RT, t>::func(CPU, call<RT>(m_call, std::tuple_cat(std::tuple<PPUThread&>(CPU), iterate<0, 0, 0, T...>(CPU))));
|
||||
bind_result<RT, result_type<RT>::value>::func(CPU, call<RT>(m_call, std::tuple_cat(std::tuple<PPUThread&>(CPU), iterate<0, 0, 0, T...>(CPU))));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -248,5 +246,5 @@ namespace detail
|
|||
template<typename RT, typename... T>
|
||||
func_caller* bind_func(RT(*call)(T...))
|
||||
{
|
||||
return new detail::func_binder<RT, T...>(call);
|
||||
return new ppu_func_detail::func_binder<RT, T...>(call);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue