diff options
Diffstat (limited to 'src/lib/netlist/plib/ppmf.cpp')
-rw-r--r-- | src/lib/netlist/plib/ppmf.cpp | 109 |
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 |