2014-07-31 18:08:02 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
namespace vm
|
|
|
|
|
{
|
2015-09-26 22:46:04 +02:00
|
|
|
// Tag which allows to construct vm objects from the address value
|
|
|
|
|
static struct addr_tag_t {} constexpr addr{};
|
2015-08-18 14:31:48 +02:00
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
template<typename T, typename AT> class _ptr_base;
|
|
|
|
|
|
|
|
|
|
template<typename T, typename AT = u32> class _ref_base
|
2014-08-01 18:27:48 +02:00
|
|
|
{
|
2015-09-26 22:46:04 +02:00
|
|
|
AT m_addr;
|
2014-08-01 18:27:48 +02:00
|
|
|
|
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)");
|
2015-06-14 23:52:22 +02:00
|
|
|
static_assert(!std::is_function<T>::value, "vm::_ref_base<> error: invalid type (function)");
|
|
|
|
|
static_assert(!std::is_void<T>::value, "vm::_ref_base<> error: invalid type (void)");
|
2014-09-01 18:16:44 +02:00
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
public:
|
|
|
|
|
using type = T;
|
|
|
|
|
using addr_type = std::remove_cv_t<AT>;
|
|
|
|
|
|
|
|
|
|
_ref_base() = default;
|
|
|
|
|
|
|
|
|
|
_ref_base(const _ref_base&) = default;
|
|
|
|
|
|
|
|
|
|
constexpr _ref_base(addr_type addr, const addr_tag_t&)
|
|
|
|
|
: m_addr(addr)
|
2015-06-13 16:48:21 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
constexpr addr_type addr() const
|
2015-06-13 16:48:21 +02:00
|
|
|
{
|
2015-09-26 22:46:04 +02:00
|
|
|
return m_addr;
|
2015-06-13 16:48:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
T& get_ref() const
|
|
|
|
|
{
|
2015-09-26 22:46:04 +02:00
|
|
|
return *static_cast<T*>(vm::base(VM_CAST(m_addr)));
|
2015-06-13 16:48:21 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
// convert to vm pointer
|
|
|
|
|
vm::_ptr_base<T, u32> ptr() const
|
2015-06-13 16:48:21 +02:00
|
|
|
{
|
2015-09-26 22:46:04 +02:00
|
|
|
return{ VM_CAST(m_addr), vm::addr };
|
2015-06-13 16:48:21 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-13 03:31:45 +02:00
|
|
|
operator to_ne_t<T>() const
|
2014-08-01 18:27:48 +02:00
|
|
|
{
|
2015-06-13 16:48:21 +02:00
|
|
|
return get_ref();
|
2014-08-01 18:27:48 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
operator T&() const
|
2015-06-15 13:37:01 +02:00
|
|
|
{
|
|
|
|
|
return get_ref();
|
|
|
|
|
}
|
2014-08-01 18:27:48 +02:00
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
T& operator =(const _ref_base& right)
|
2015-08-18 14:31:48 +02:00
|
|
|
{
|
2015-09-26 22:46:04 +02:00
|
|
|
return get_ref() = right.get_ref();
|
2015-08-18 14:31:48 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
T& operator =(const T& right) const
|
2014-08-01 18:27:48 +02:00
|
|
|
{
|
2015-09-26 22:46:04 +02:00
|
|
|
return get_ref() = right;
|
|
|
|
|
}
|
2015-06-15 18:02:16 +02:00
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
decltype(auto) operator ++(int)
|
|
|
|
|
{
|
|
|
|
|
return get_ref()++;
|
2014-09-01 23:22:07 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
decltype(auto) operator ++()
|
2014-09-01 23:22:07 +02:00
|
|
|
{
|
2015-09-26 22:46:04 +02:00
|
|
|
return ++get_ref();
|
2014-09-01 23:22:07 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
decltype(auto) operator --(int)
|
2014-09-01 23:22:07 +02:00
|
|
|
{
|
2015-09-26 22:46:04 +02:00
|
|
|
return get_ref()--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
decltype(auto) operator --()
|
|
|
|
|
{
|
|
|
|
|
return --get_ref();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename T2> decltype(auto) operator +=(const T2& right)
|
|
|
|
|
{
|
|
|
|
|
return get_ref() += right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename T2> decltype(auto) operator -=(const T2& right)
|
|
|
|
|
{
|
|
|
|
|
return get_ref() -= right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename T2> decltype(auto) operator *=(const T2& right)
|
|
|
|
|
{
|
|
|
|
|
return get_ref() *= right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename T2> decltype(auto) operator /=(const T2& right)
|
|
|
|
|
{
|
|
|
|
|
return get_ref() /= right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename T2> decltype(auto) operator %=(const T2& right)
|
|
|
|
|
{
|
|
|
|
|
return get_ref() %= right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename T2> decltype(auto) operator &=(const T2& right)
|
|
|
|
|
{
|
|
|
|
|
return get_ref() &= right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename T2> decltype(auto) operator |=(const T2& right)
|
|
|
|
|
{
|
|
|
|
|
return get_ref() |= right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename T2> decltype(auto) operator ^=(const T2& right)
|
|
|
|
|
{
|
|
|
|
|
return get_ref() ^= right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename T2> decltype(auto) operator <<=(const T2& right)
|
|
|
|
|
{
|
|
|
|
|
return get_ref() <<= right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename T2> decltype(auto) operator >>=(const T2& right)
|
|
|
|
|
{
|
|
|
|
|
return get_ref() >>= right;
|
2014-09-01 23:22:07 +02:00
|
|
|
}
|
2014-08-01 18:27:48 +02:00
|
|
|
};
|
|
|
|
|
|
2015-05-27 05:11:59 +02:00
|
|
|
// Native endianness reference to LE data
|
2015-06-13 03:31:45 +02:00
|
|
|
template<typename T, typename AT = u32> using refl = _ref_base<to_le_t<T>, AT>;
|
2014-08-01 18:27:48 +02:00
|
|
|
|
2015-05-27 05:11:59 +02:00
|
|
|
// Native endianness reference to BE data
|
2015-06-13 03:31:45 +02:00
|
|
|
template<typename T, typename AT = u32> using refb = _ref_base<to_be_t<T>, AT>;
|
2015-05-27 05:11:59 +02:00
|
|
|
|
|
|
|
|
// BE reference to LE data
|
2015-06-13 03:31:45 +02:00
|
|
|
template<typename T, typename AT = u32> using brefl = _ref_base<to_le_t<T>, to_be_t<AT>>;
|
2015-05-27 05:11:59 +02:00
|
|
|
|
|
|
|
|
// BE reference to BE data
|
2015-06-13 03:31:45 +02:00
|
|
|
template<typename T, typename AT = u32> using brefb = _ref_base<to_be_t<T>, to_be_t<AT>>;
|
2014-08-01 18:27:48 +02:00
|
|
|
|
2015-05-27 05:11:59 +02:00
|
|
|
// LE reference to LE data
|
2015-06-13 03:31:45 +02:00
|
|
|
template<typename T, typename AT = u32> using lrefl = _ref_base<to_le_t<T>, to_le_t<AT>>;
|
2014-08-01 18:27:48 +02:00
|
|
|
|
2015-05-27 05:11:59 +02:00
|
|
|
// LE reference to BE data
|
2015-06-13 03:31:45 +02:00
|
|
|
template<typename T, typename AT = u32> using lrefb = _ref_base<to_be_t<T>, to_le_t<AT>>;
|
2014-08-01 18:27:48 +02:00
|
|
|
|
|
|
|
|
namespace ps3
|
|
|
|
|
{
|
2015-05-27 05:11:59 +02:00
|
|
|
// default reference for PS3 HLE functions (Native endianness reference to BE data)
|
|
|
|
|
template<typename T, typename AT = u32> using ref = refb<T, AT>;
|
2014-08-01 18:27:48 +02:00
|
|
|
|
2015-05-27 05:11:59 +02:00
|
|
|
// 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>;
|
2014-08-01 18:27:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace psv
|
|
|
|
|
{
|
2015-05-27 05:11:59 +02:00
|
|
|
// default reference for PSV HLE functions (Native endianness reference to LE data)
|
2015-06-14 23:52:22 +02:00
|
|
|
template<typename T> using ref = refl<T>;
|
2015-05-27 05:11:59 +02:00
|
|
|
|
|
|
|
|
// default reference for PSV HLE structures (LE reference to LE data)
|
2015-06-14 23:52:22 +02:00
|
|
|
template<typename T> using lref = lrefl<T>;
|
2014-08-01 18:27:48 +02:00
|
|
|
}
|
2015-06-13 16:48:21 +02:00
|
|
|
}
|
2015-06-13 03:31:45 +02:00
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
// external specialization for to_se<> (change AT's endianness to BE/LE)
|
2015-06-13 03:31:45 +02:00
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
template<typename T, typename AT, bool Se> struct to_se<vm::_ref_base<T, AT>, Se>
|
2015-06-13 03:31:45 +02:00
|
|
|
{
|
2015-09-26 22:46:04 +02:00
|
|
|
using type = vm::_ref_base<T, typename to_se<AT, Se>::type>;
|
2015-06-13 03:31:45 +02:00
|
|
|
};
|
|
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
// external specialization for to_ne<> (change AT's endianness to native)
|
2015-06-13 03:31:45 +02:00
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
template<typename T, typename AT> struct to_ne<vm::_ref_base<T, AT>>
|
2015-06-13 03:31:45 +02:00
|
|
|
{
|
2015-09-26 22:46:04 +02:00
|
|
|
using type = vm::_ref_base<T, typename to_ne<AT>::type>;
|
2015-06-13 03:31:45 +02:00
|
|
|
};
|
2015-01-13 18:38:32 +01:00
|
|
|
|
|
|
|
|
namespace fmt
|
|
|
|
|
{
|
2015-03-09 02:57:50 +01:00
|
|
|
// external specialization for fmt::format function
|
2015-01-18 23:54:56 +01:00
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
template<typename T, typename AT> struct unveil<vm::_ref_base<T, AT>, false>
|
2015-01-18 23:54:56 +01:00
|
|
|
{
|
2015-06-13 03:31:45 +02:00
|
|
|
using result_type = typename unveil<AT>::result_type;
|
2015-01-13 18:38:32 +01:00
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
static inline result_type get_value(const vm::_ref_base<T, AT>& arg)
|
2015-01-13 18:38:32 +01:00
|
|
|
{
|
2015-01-18 23:54:56 +01:00
|
|
|
return unveil<AT>::get_value(arg.addr());
|
|
|
|
|
}
|
|
|
|
|
};
|
2015-01-13 18:38:32 +01:00
|
|
|
}
|
2015-01-19 15:16:31 +01:00
|
|
|
|
|
|
|
|
// external specializations for PPU GPR (SC_FUNC.h, CB_FUNC.h)
|
|
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
template<typename T, bool is_enum> struct cast_ppu_gpr;
|
2015-01-19 15:16:31 +01:00
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
template<typename T, typename AT> struct cast_ppu_gpr<vm::_ref_base<T, AT>, false>
|
2015-01-19 15:16:31 +01:00
|
|
|
{
|
2015-09-26 22:46:04 +02:00
|
|
|
static inline u64 to_gpr(const vm::_ref_base<T, AT>& value)
|
2015-01-19 15:16:31 +01:00
|
|
|
{
|
2015-03-09 20:56:55 +01:00
|
|
|
return cast_ppu_gpr<AT, std::is_enum<AT>::value>::to_gpr(value.addr());
|
2015-01-19 15:16:31 +01:00
|
|
|
}
|
|
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
static inline vm::_ref_base<T, AT> from_gpr(const u64 reg)
|
2015-01-19 15:16:31 +01:00
|
|
|
{
|
2015-09-26 22:46:04 +02:00
|
|
|
return{ cast_ppu_gpr<AT, std::is_enum<AT>::value>::from_gpr(reg), vm::addr };
|
2015-01-19 15:16:31 +01:00
|
|
|
}
|
|
|
|
|
};
|
2015-01-19 19:02:33 +01:00
|
|
|
|
|
|
|
|
// external specializations for ARMv7 GPR
|
|
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
template<typename T, bool is_enum> struct cast_armv7_gpr;
|
2015-01-19 19:02:33 +01:00
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
template<typename T, typename AT> struct cast_armv7_gpr<vm::_ref_base<T, AT>, false>
|
2015-01-19 19:02:33 +01:00
|
|
|
{
|
2015-09-26 22:46:04 +02:00
|
|
|
static inline 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
|
|
|
}
|
|
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
static inline vm::_ref_base<T, AT> from_gpr(const u32 reg)
|
2015-01-19 19:02:33 +01:00
|
|
|
{
|
2015-09-26 22:46:04 +02:00
|
|
|
return{ cast_armv7_gpr<AT, std::is_enum<AT>::value>::from_gpr(reg), vm::addr };
|
2015-01-19 19:02:33 +01:00
|
|
|
}
|
|
|
|
|
};
|