1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-25 20:22:30 +01:00

offset32(): pointer-to-member arithmetic

This commit is contained in:
Nekotekina 2017-04-19 14:31:56 +03:00
parent ff5295de32
commit 9b43203111
7 changed files with 467 additions and 400 deletions

View File

@ -301,6 +301,16 @@ union alignas(16) v128
}
};
template <typename T, std::size_t N, std::size_t M>
struct offset32_array<v128::masked_array_t<T, N, M>>
{
template <typename Arg>
static inline u32 index32(const Arg& arg)
{
return SIZE_32(T) * (static_cast<u32>(arg) ^ static_cast<u32>(M));
}
};
inline v128 operator|(const v128& left, const v128& right)
{
return v128::fromV(_mm_or_si128(left.vi, right.vi));

View File

@ -12,6 +12,7 @@
#include <type_traits>
#include <utility>
#include <chrono>
#include <array>
// Assume little-endian
#define IS_LE_MACHINE 1
@ -45,9 +46,6 @@
// Return 32 bit alignof() to avoid widening/narrowing conversions with size_t
#define ALIGN_32(...) static_cast<u32>(alignof(__VA_ARGS__))
// Return 32 bit offsetof()
#define OFFSET_32(type, x) static_cast<u32>(reinterpret_cast<std::uintptr_t>(&reinterpret_cast<const volatile char&>(reinterpret_cast<type*>(0ull)->x)))
#define CONCATENATE_DETAIL(x, y) x ## y
#define CONCATENATE(x, y) CONCATENATE_DETAIL(x, y)
@ -450,6 +448,71 @@ constexpr T align(const T& value, ullong align)
return static_cast<T>((value + (align - 1)) & ~(align - 1));
}
template <typename T, typename T2>
inline u32 offset32(T T2::*const mptr)
{
#ifdef _MSC_VER
static_assert(sizeof(mptr) == sizeof(u32), "Invalid pointer-to-member size");
return reinterpret_cast<const u32&>(mptr);
#elif __GNUG__
static_assert(sizeof(mptr) == sizeof(std::size_t), "Invalid pointer-to-member size");
return static_cast<u32>(reinterpret_cast<const std::size_t&>(mptr));
#else
static_assert(sizeof(mptr) == 0, "Invalid pointer-to-member size");
#endif
}
template <typename T>
struct offset32_array
{
static_assert(std::is_array<T>::value, "Invalid pointer-to-member type (array expected)");
template <typename Arg>
static inline u32 index32(const Arg& arg)
{
return SIZE_32(std::remove_extent_t<T>) * static_cast<u32>(arg);
}
};
template <typename T, std::size_t N>
struct offset32_array<std::array<T, N>>
{
template <typename Arg>
static inline u32 index32(const Arg& arg)
{
return SIZE_32(T) * static_cast<u32>(arg);
}
};
template <typename Arg>
struct offset32_detail;
template <typename T, typename T2, typename Arg, typename... Args>
inline u32 offset32(T T2::*const mptr, const Arg& arg, const Args&... args)
{
return offset32_detail<Arg>::offset32(mptr, arg, args...);
}
template <typename Arg>
struct offset32_detail
{
template <typename T, typename T2, typename... Args>
static inline u32 offset32(T T2::*const mptr, const Arg& arg, const Args&... args)
{
return ::offset32(mptr, args...) + offset32_array<T>::index32(arg);
}
};
template <typename T3, typename T4>
struct offset32_detail<T3 T4::*>
{
template <typename T, typename T2, typename... Args>
static inline u32 offset32(T T2::*const mptr, T3 T4::*const mptr2, const Args&... args)
{
return ::offset32(mptr) + ::offset32(mptr2, args...);
}
};
inline u32 cntlz32(u32 arg, bool nonzero = false)
{
#ifdef _MSC_VER

View File

@ -1217,7 +1217,7 @@ void spursSysServiceTraceUpdate(SPUThread& spu, SpursKernelContext* ctxt, u32 ar
if (((sysSrvMsgUpdateTrace & (1 << ctxt->spuNum)) != 0) || (arg3 != 0))
{
//vm::reservation_acquire(vm::base(spu.offset + 0x80), ctxt->spurs.ptr(&CellSpurs::traceBuffer).addr(), 128);
auto spurs = vm::_ptr<CellSpurs>(spu.offset + 0x80 - OFFSET_32(CellSpurs, traceBuffer));
auto spurs = vm::_ptr<CellSpurs>(spu.offset + 0x80 - offset32(&CellSpurs::traceBuffer));
if (ctxt->traceMsgCount != 0xFF || spurs->traceBuffer.addr() == 0)
{
@ -1240,7 +1240,7 @@ void spursSysServiceTraceUpdate(SPUThread& spu, SpursKernelContext* ctxt, u32 ar
if (notify)
{
auto spurs = vm::_ptr<CellSpurs>(spu.offset + 0x2D80 - OFFSET_32(CellSpurs, wklState1));
auto spurs = vm::_ptr<CellSpurs>(spu.offset + 0x2D80 - offset32(&CellSpurs::wklState1));
sys_spu_thread_send_event(spu, spurs->spuPort, 2, 0);
}
}

View File

@ -74,8 +74,8 @@ PPUTranslator::PPUTranslator(LLVMContext& context, Module* module, u64 base)
m_base = new GlobalVariable(*module, ArrayType::get(GetType<char>(), 0x100000000)->getPointerTo(), true, GlobalValue::ExternalLinkage, 0, "__mptr");
// Thread context struct (TODO: safer member access)
const auto off0 = OFFSET_32(ppu_thread, state);
const auto off1 = OFFSET_32(ppu_thread, gpr);
const u32 off0 = offset32(&ppu_thread::state);
const u32 off1 = offset32(&ppu_thread::gpr);
std::vector<Type*> thread_struct;
thread_struct.emplace_back(ArrayType::get(GetType<char>(), off0));
thread_struct.emplace_back(GetType<u32>()); // state

File diff suppressed because it is too large Load Diff

View File

@ -188,12 +188,6 @@ namespace vm
fmt::throw_exception("Not a virtual memory pointer (%p)", real_ptr);
}
// Convert pointer-to-member to a vm address compatible offset
template<typename MT, typename T> inline u32 get_offset(MT T::*const member_ptr)
{
return static_cast<u32>(reinterpret_cast<std::uintptr_t>(&reinterpret_cast<char const volatile&>(reinterpret_cast<T*>(0ull)->*member_ptr)));
}
template<typename T>
struct cast_impl
{

View File

@ -60,31 +60,31 @@ namespace vm
}
// Get vm pointer to a struct member
template<typename MT, typename T2, typename = if_comparable_t<T, T2>>
template <typename MT, typename T2, typename = if_comparable_t<T, T2>>
_ptr_base<MT> ptr(MT T2::*const mptr) const
{
return vm::cast(vm::cast(m_addr, HERE) + get_offset(mptr));
return vm::cast(vm::cast(m_addr, HERE) + offset32(mptr));
}
// Get vm pointer to a struct member with array subscription
template<typename MT, typename T2, typename ET = std::remove_extent_t<MT>, typename = if_comparable_t<T, T2>>
template <typename MT, typename T2, typename ET = std::remove_extent_t<MT>, typename = if_comparable_t<T, T2>>
_ptr_base<ET> ptr(MT T2::*const mptr, u32 index) const
{
return vm::cast(vm::cast(m_addr, HERE) + get_offset(mptr) + SIZE_32(ET) * index);
return vm::cast(vm::cast(m_addr, HERE) + offset32(mptr) + SIZE_32(ET) * index);
}
// Get vm reference to a struct member
template<typename MT, typename T2, typename = if_comparable_t<T, T2>>
template <typename MT, typename T2, typename = if_comparable_t<T, T2>>
_ref_base<MT> ref(MT T2::*const mptr) const
{
return vm::cast(vm::cast(m_addr, HERE) + get_offset(mptr));
return vm::cast(vm::cast(m_addr, HERE) + offset32(mptr));
}
// Get vm reference to a struct member with array subscription
template<typename MT, typename T2, typename ET = std::remove_extent_t<MT>, typename = if_comparable_t<T, T2>>
template <typename MT, typename T2, typename ET = std::remove_extent_t<MT>, typename = if_comparable_t<T, T2>>
_ref_base<ET> ref(MT T2::*const mptr, u32 index) const
{
return vm::cast(vm::cast(m_addr, HERE) + get_offset(mptr) + SIZE_32(ET) * index);
return vm::cast(vm::cast(m_addr, HERE) + offset32(mptr) + SIZE_32(ET) * index);
}
// Get vm reference