summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/mfpresolve.h
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2025-02-06 02:42:26 +1100
committer Vas Crabb <vas@vastheman.com>2025-02-06 02:42:26 +1100
commitcea7758f4f5b4c26dde9646caeb0785607c817a5 (patch)
treef130536d3dd01c3d1edf146ef906b6d140920b21 /src/lib/util/mfpresolve.h
parent4edf86fed7aa7ca5c94ae561f7c8449121a038a5 (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.h72
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);
}
}