summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/plib/ppmf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/plib/ppmf.cpp')
-rw-r--r--src/lib/netlist/plib/ppmf.cpp109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/lib/netlist/plib/ppmf.cpp b/src/lib/netlist/plib/ppmf.cpp
new file mode 100644
index 00000000000..85088b25638
--- /dev/null
+++ b/src/lib/netlist/plib/ppmf.cpp
@@ -0,0 +1,109 @@
+// license:BSD-3-Clause
+// copyright-holders:Couriersud
+
+#include "ppmf.h"
+
+#if PPMF_USE_MAME_DELEGATES
+#include "../../util/delegate.cpp"
+#else
+
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpmf-conversions"
+#pragma GCC diagnostic ignored "-Wpedantic"
+#endif
+
+namespace plib {
+
+ void mfp_raw<ppmf_type::INTERNAL_ITANIUM>::convert_to_generic(generic_function &func, mfp_generic_class *&object) const
+ {
+ // apply the "this" delta to the object first
+ // NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult,cppcoreguidelines-pro-type-reinterpret-cast)
+ auto *o_p_delta = reinterpret_cast<mfp_generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
+
+ // if the low bit of the vtable index is clear, then it is just a raw function pointer
+ if ((m_function & 1) == 0)
+ {
+ // NOLINTNEXTLINE(performance-no-int-to-ptr,cppcoreguidelines-pro-type-reinterpret-cast)
+ func = reinterpret_cast<generic_function>(m_function);
+ }
+ else
+ {
+ // otherwise, it is the byte index into the vtable where the actual function lives
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(o_p_delta);
+ if (compile_info::abi_vtable_function_descriptors::value)
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ func = reinterpret_cast<generic_function>(uintptr_t(vtable_base + m_function - 1));
+ else
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ func = *reinterpret_cast<generic_function *>(vtable_base + m_function - 1);
+ }
+ object = o_p_delta;
+ }
+
+ void mfp_raw<ppmf_type::INTERNAL_ARM>::convert_to_generic(generic_function &func, mfp_generic_class *&object) const
+ {
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ object = reinterpret_cast<mfp_generic_class *>(reinterpret_cast<std::uint8_t *>(object) + (m_this_delta >> 1));
+ if ((m_this_delta & 1) == 0)
+ {
+ // NOLINTNEXTLINE(performance-no-int-to-ptr,cppcoreguidelines-pro-type-reinterpret-cast)
+ func = reinterpret_cast<generic_function>(m_function);
+ }
+ else
+ {
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(object) + m_function;
+ if (compile_info::abi_vtable_function_descriptors::value)
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ func = reinterpret_cast<generic_function>(uintptr_t(vtable_base));
+ else
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ func = *reinterpret_cast<generic_function *>(vtable_base);
+ }
+ }
+
+ struct unknown_base_equiv_novtdisp { mfp_raw<ppmf_type::INTERNAL_MSC>::generic_function fptr; int thisdisp, vptrdisp; };
+
+ void mfp_raw<ppmf_type::INTERNAL_MSC>::convert_to_generic(generic_function &func, mfp_generic_class *&object) const
+ {
+ //printf("%lx, %lx, %lx, %lx %lx\n", m_function, m_this_delta, m_vptr_offs, m_vt_index, m_size);
+
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ auto *byteptr = reinterpret_cast<std::uint8_t *>(object);
+
+ // test for pointer to member function cast across virtual inheritance relationship
+ //if ((sizeof(unknown_base_equiv) == m_size) && m_vt_index)
+ if ((sizeof(unknown_base_equiv) == m_size) || (sizeof(unknown_base_equiv_novtdisp) == m_size))
+ {
+ // add index from "this" pointer to location of vptr. This actually is an index,
+ // it needs to be multiplied by sizeof(void *)
+ byteptr += (m_vptr_index * static_cast<ptrdiff_t>(sizeof(void *)));
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ std::uint8_t const *const vptr = *reinterpret_cast<std::uint8_t const *const *>(byteptr);
+ // and add offset to virtual base from vtable
+ if (sizeof(unknown_base_equiv) == m_size)
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ byteptr += *reinterpret_cast<int const *>(vptr + m_vt_index);
+ }
+
+ // add "this" pointer displacement if present in the pointer to member function
+ if (sizeof(single_base_equiv) < m_size)
+ byteptr += m_this_delta;
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ object = reinterpret_cast<mfp_generic_class *>(byteptr);
+
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast,performance-no-int-to-ptr)
+ auto const *funcx = reinterpret_cast<std::uint8_t const *>(m_function);
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast,performance-no-int-to-ptr)
+ func = reinterpret_cast<generic_function>(std::uintptr_t(funcx));
+ }
+
+} // namespace plib
+
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+#endif