rpcsx/rpcs3/Emu/Memory/vm_ref.h

195 lines
4.9 KiB
C
Raw Normal View History

#pragma once
namespace vm
{
template<typename T, typename AT = u32>
struct _ref_base
{
2015-06-13 16:48:21 +02:00
AT m_addr;
2015-02-01 08:09:24 +01:00
static_assert(!std::is_pointer<T>::value, "vm::_ref_base<> error: invalid type (pointer)");
static_assert(!std::is_reference<T>::value, "vm::_ref_base<> error: invalid type (reference)");
2014-09-01 18:16:44 +02:00
2015-06-13 16:48:21 +02:00
AT addr() const
{
return m_addr;
}
template<typename AT2 = AT> static _ref_base make(const AT2& addr)
{
return{ convert_le_be<AT>(addr) };
}
T& get_ref() const
{
return vm::get_ref<T>(vm::cast(m_addr));
}
T& priv_ref() const
{
return vm::priv_ref<T>(vm::cast(m_addr));
}
// conversion operator
//template<typename CT> operator std::enable_if_t<std::is_convertible<T, CT>::value, CT>()
//{
2015-06-13 16:48:21 +02:00
// return get_ref();
//}
2015-06-13 16:48:21 +02:00
// temporarily, because SFINAE doesn't work for some reason:
operator to_ne_t<T>() const
{
2015-06-13 16:48:21 +02:00
return get_ref();
}
operator T() const
{
2015-06-13 16:48:21 +02:00
return get_ref();
}
2015-06-13 16:48:21 +02:00
// copy assignment operator
_ref_base& operator =(const _ref_base& right)
{
2015-06-13 16:48:21 +02:00
get_ref() = right.get_ref();
return *this;
2014-09-01 23:22:07 +02:00
}
2015-06-13 16:48:21 +02:00
template<typename CT, typename AT2> std::enable_if_t<std::is_assignable<T&, CT>::value, const _ref_base&> operator =(const _ref_base<CT, AT2>& right) const
2014-09-01 23:22:07 +02:00
{
2015-06-13 16:48:21 +02:00
get_ref() = right.get_ref();
2014-09-01 23:22:07 +02:00
return *this;
}
template<typename CT> std::enable_if_t<std::is_assignable<T&, CT>::value, const _ref_base&> operator =(const CT& right) const
2014-09-01 23:22:07 +02:00
{
2015-06-13 16:48:21 +02:00
get_ref() = right;
2014-09-01 23:22:07 +02:00
return *this;
}
};
// Native endianness reference to LE data
template<typename T, typename AT = u32> using refl = _ref_base<to_le_t<T>, AT>;
// Native endianness reference to BE data
template<typename T, typename AT = u32> using refb = _ref_base<to_be_t<T>, AT>;
// BE reference to LE data
template<typename T, typename AT = u32> using brefl = _ref_base<to_le_t<T>, to_be_t<AT>>;
// BE reference to BE data
template<typename T, typename AT = u32> using brefb = _ref_base<to_be_t<T>, to_be_t<AT>>;
// LE reference to LE data
template<typename T, typename AT = u32> using lrefl = _ref_base<to_le_t<T>, to_le_t<AT>>;
// LE reference to BE data
template<typename T, typename AT = u32> using lrefb = _ref_base<to_be_t<T>, to_le_t<AT>>;
namespace ps3
{
// default reference for PS3 HLE functions (Native endianness reference to BE data)
template<typename T, typename AT = u32> using ref = refb<T, AT>;
// default reference for PS3 HLE structures (BE reference to BE data)
2015-03-09 02:57:50 +01:00
template<typename T, typename AT = u32> using bref = brefb<T, AT>;
}
namespace psv
{
// default reference for PSV HLE functions (Native endianness reference to LE data)
template<typename T, typename AT = u32> using ref = refl<T, AT>;
// default reference for PSV HLE structures (LE reference to LE data)
template<typename T, typename AT = u32> using lref = lrefl<T, AT>;
}
2014-09-01 18:16:44 +02:00
//PS3 emulation is main now, so lets it be as default
using namespace ps3;
2015-06-13 16:48:21 +02:00
}
// external specialization for is_be_t<>
template<typename T, typename AT>
struct is_be_t<vm::_ref_base<T, AT>> : public std::integral_constant<bool, is_be_t<AT>::value>
{
};
// external specialization for to_ne_t<>
template<typename T, typename AT>
struct to_ne<vm::_ref_base<T, AT>>
{
using type = vm::_ref_base<T, to_ne_t<AT>>;
};
// external specialization for to_be_t<>
template<typename T, typename AT>
struct to_be<vm::_ref_base<T, AT>>
{
using type = vm::_ref_base<T, to_be_t<AT>>;
};
// external specialization for to_le_t<> (not used)
template<typename T, typename AT>
struct to_le<vm::_ref_base<T, AT>>
{
using type = vm::_ref_base<T, to_le_t<AT>>;
};
2015-01-13 18:38:32 +01:00
namespace fmt
{
2015-03-09 02:57:50 +01:00
// external specialization for fmt::format function
template<typename T, typename AT>
2015-03-09 02:57:50 +01:00
struct unveil<vm::_ref_base<T, AT>, false>
{
using result_type = typename unveil<AT>::result_type;
2015-01-13 18:38:32 +01:00
force_inline static result_type get_value(const vm::_ref_base<T, AT>& arg)
2015-01-13 18:38:32 +01:00
{
return unveil<AT>::get_value(arg.addr());
}
};
2015-01-13 18:38:32 +01:00
}
// external specializations for PPU GPR (SC_FUNC.h, CB_FUNC.h)
template<typename T, bool is_enum>
struct cast_ppu_gpr;
template<typename T, typename AT>
2015-03-09 02:57:50 +01:00
struct cast_ppu_gpr<vm::_ref_base<T, AT>, false>
{
force_inline static u64 to_gpr(const vm::_ref_base<T, AT>& value)
{
2015-03-09 20:56:55 +01:00
return cast_ppu_gpr<AT, std::is_enum<AT>::value>::to_gpr(value.addr());
}
force_inline static vm::_ref_base<T, AT> from_gpr(const u64 reg)
{
2015-03-09 02:57:50 +01:00
return vm::_ref_base<T, AT>::make(cast_ppu_gpr<AT, std::is_enum<AT>::value>::from_gpr(reg));
}
};
2015-01-19 19:02:33 +01:00
// external specializations for ARMv7 GPR
template<typename T, bool is_enum>
struct cast_armv7_gpr;
template<typename T, typename AT>
2015-03-09 02:57:50 +01:00
struct cast_armv7_gpr<vm::_ref_base<T, AT>, false>
2015-01-19 19:02:33 +01:00
{
force_inline static u32 to_gpr(const vm::_ref_base<T, AT>& value)
2015-01-19 19:02:33 +01:00
{
2015-03-09 20:56:55 +01:00
return cast_armv7_gpr<AT, std::is_enum<AT>::value>::to_gpr(value.addr());
2015-01-19 19:02:33 +01:00
}
force_inline static vm::_ref_base<T, AT> from_gpr(const u32 reg)
2015-01-19 19:02:33 +01:00
{
2015-03-09 02:57:50 +01:00
return vm::_ref_base<T, AT>::make(cast_armv7_gpr<AT, std::is_enum<AT>::value>::from_gpr(reg));
2015-01-19 19:02:33 +01:00
}
};