diff options
author | 2025-02-06 02:42:26 +1100 | |
---|---|---|
committer | 2025-02-06 02:42:26 +1100 | |
commit | cea7758f4f5b4c26dde9646caeb0785607c817a5 (patch) | |
tree | f130536d3dd01c3d1edf146ef906b6d140920b21 /src/lib/util/mfpresolve.h | |
parent | 4edf86fed7aa7ca5c94ae561f7c8449121a038a5 (diff) |
-cpu/drcbex64.cpp: Fixed handling of address map global mask.
* Fixed Final Furlong failing to boot.
-util/mfpresolve.cpp, emu/emumem_aspace.cpp: Moved some member function
pointer manipulation stuff into the library. Gives another slight
reduction in the size of libemu.
Diffstat (limited to 'src/lib/util/mfpresolve.h')
-rw-r--r-- | src/lib/util/mfpresolve.h | 72 |
1 files changed, 66 insertions, 6 deletions
diff --git a/src/lib/util/mfpresolve.h b/src/lib/util/mfpresolve.h index 7661623572a..3c67cd543ff 100644 --- a/src/lib/util/mfpresolve.h +++ b/src/lib/util/mfpresolve.h @@ -17,6 +17,7 @@ #include <cassert> #include <cstddef> #include <cstdint> +#include <tuple> #include <utility> @@ -24,9 +25,26 @@ namespace util { namespace detail { +struct mfp_itanium_equiv +{ + std::uintptr_t function; + std::ptrdiff_t delta; + + constexpr std::ptrdiff_t this_delta() const noexcept { return delta >> ((MAME_ABI_CXX_ITANIUM_MFP_TYPE == MAME_ABI_CXX_ITANIUM_MFP_ARM) ? 1 : 0); } + constexpr bool is_virtual() const noexcept { return ((MAME_ABI_CXX_ITANIUM_MFP_TYPE == MAME_ABI_CXX_ITANIUM_MFP_ARM) ? delta : function) & 1; } +}; + +struct mfp_msvc_single_equiv { std::uintptr_t entrypoint; }; +struct mfp_msvc_multi_equiv { std::uintptr_t entrypoint; int delta; }; +struct mfp_msvc_virtual_equiv { std::uintptr_t entrypoint; int delta; int vindex; }; +struct mfp_msvc_unknown_equiv { std::uintptr_t entrypoint; int delta; int voffset; int vindex; }; + std::pair<std::uintptr_t, std::uintptr_t> resolve_member_function_itanium(std::uintptr_t function, std::ptrdiff_t delta, void const *object) noexcept; +std::tuple<std::uintptr_t, std::ptrdiff_t, bool> resolve_member_function_itanium(std::uintptr_t function, std::ptrdiff_t delta) noexcept; std::pair<std::uintptr_t, std::uintptr_t> resolve_member_function_msvc(void const *funcptr, std::size_t size, void const *object) noexcept; +std::tuple<std::uintptr_t, std::ptrdiff_t, bool> resolve_member_function_msvc(void const *funcptr, std::size_t size) noexcept; std::uintptr_t bypass_member_function_thunks(std::uintptr_t entrypoint, void const *object) noexcept; +std::pair<std::uintptr_t, bool> bypass_member_function_thunks(std::uintptr_t entrypoint) noexcept; } // namespace detail @@ -46,10 +64,10 @@ inline std::pair<std::uintptr_t, std::uintptr_t> resolve_member_function(Ret (T: { if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_ITANIUM) { - struct { std::uintptr_t ptr; std::ptrdiff_t adj; } equiv; + detail::mfp_itanium_equiv equiv; assert(sizeof(function) == sizeof(equiv)); *reinterpret_cast<decltype(function) *>(&equiv) = function; - return detail::resolve_member_function_itanium(equiv.ptr, equiv.adj, &object); + return detail::resolve_member_function_itanium(equiv.function, equiv.delta, &object); } else if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_MSVC) { @@ -57,7 +75,7 @@ inline std::pair<std::uintptr_t, std::uintptr_t> resolve_member_function(Ret (T: } else { - return std::make_pair(std::uintptr_t(nullptr), std::uintptr_t(nullptr)); + return std::make_pair(std::uintptr_t(static_cast<void (*)()>(nullptr)), std::uintptr_t(nullptr)); } } @@ -67,10 +85,10 @@ inline std::pair<std::uintptr_t, std::uintptr_t> resolve_member_function(Ret (T: { if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_ITANIUM) { - struct { std::uintptr_t ptr; std::ptrdiff_t adj; } equiv; + detail::mfp_itanium_equiv equiv; assert(sizeof(function) == sizeof(equiv)); *reinterpret_cast<decltype(function) *>(&equiv) = function; - return detail::resolve_member_function_itanium(equiv.ptr, equiv.adj, &object); + return detail::resolve_member_function_itanium(equiv.function, equiv.delta, &object); } else if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_MSVC) { @@ -78,7 +96,49 @@ inline std::pair<std::uintptr_t, std::uintptr_t> resolve_member_function(Ret (T: } else { - return std::make_pair(std::uintptr_t(nullptr), std::uintptr_t(nullptr)); + return std::make_pair(std::uintptr_t(static_cast<void (*)()>(nullptr)), std::uintptr_t(nullptr)); + } +} + + +template <typename T, typename Ret, typename... Params> +inline std::tuple<std::uintptr_t, std::ptrdiff_t, bool> resolve_member_function(Ret (T::*function)(Params...)) noexcept +{ + if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_ITANIUM) + { + detail::mfp_itanium_equiv equiv; + assert(sizeof(function) == sizeof(equiv)); + *reinterpret_cast<decltype(function) *>(&equiv) = function; + return detail::resolve_member_function_itanium(equiv.function, equiv.delta); + } + else if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_MSVC) + { + return detail::resolve_member_function_msvc(&function, sizeof(function)); + } + else + { + return std::make_tuple(std::uintptr_t(static_cast<void (*)()>(nullptr)), std::ptrdiff_t(0), false); + } +} + + +template <typename T, typename Ret, typename... Params> +inline std::tuple<std::uintptr_t, std::ptrdiff_t, bool> resolve_member_function(Ret (T::*function)(Params...) const) noexcept +{ + if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_ITANIUM) + { + detail::mfp_itanium_equiv equiv; + assert(sizeof(function) == sizeof(equiv)); + *reinterpret_cast<decltype(function) *>(&equiv) = function; + return detail::resolve_member_function_itanium(equiv.function, equiv.delta); + } + else if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_MSVC) + { + return detail::resolve_member_function_msvc(&function, sizeof(function)); + } + else + { + return std::make_tuple(std::uintptr_t(static_cast<void (*)()>(nullptr)), std::ptrdiff_t(0), false); } } |