cast_armv7_gpr added

This commit is contained in:
Nekotekina 2015-01-19 21:02:33 +03:00
parent 6ec6303933
commit c4558d2ca7
6 changed files with 203 additions and 42 deletions

View File

@ -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);
}

View File

@ -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))));
}
};
}

View File

@ -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);
}
};

View File

@ -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));
}
};

View File

@ -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));
}
};

View File

@ -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);
}