summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/emumem.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/emumem.h')
-rw-r--r--src/emu/emumem.h1995
1 files changed, 1411 insertions, 584 deletions
diff --git a/src/emu/emumem.h b/src/emu/emumem.h
index 1adfb0332eb..1b9b6363622 100644
--- a/src/emu/emumem.h
+++ b/src/emu/emumem.h
@@ -17,6 +17,10 @@
#ifndef MAME_EMU_EMUMEM_H
#define MAME_EMU_EMUMEM_H
+#include "notifier.h"
+
+#include <optional>
+#include <set>
#include <type_traits>
using s8 = std::int8_t;
@@ -48,6 +52,14 @@ enum class read_or_write
};
+//**************************************************************************
+// FORWARD DECLARATIONS
+//**************************************************************************
+
+class handler_entry;
+template<int Width, int AddrShift> class handler_entry_read_passthrough;
+template<int Width, int AddrShift> class handler_entry_write_passthrough;
+
//**************************************************************************
// TYPE DEFINITIONS
@@ -80,9 +92,16 @@ struct data_accessors
};
// a line in the memory structure dump
+struct memory_entry_context {
+ memory_view *view;
+ bool disabled;
+ int slot;
+};
+
struct memory_entry {
offs_t start, end;
- class handler_entry *entry;
+ handler_entry *entry;
+ std::vector<memory_entry_context> context;
};
@@ -154,13 +173,19 @@ using write32smo_delegate = device_delegate<void (u32)>;
using write64smo_delegate = device_delegate<void (u64)>;
-namespace emu { namespace detail {
+// =====================-> Wait states delegates
+
+using ws_time_delegate = device_delegate<u64 (offs_t, u64)>;
+using ws_delay_delegate = device_delegate<u32 (offs_t)>;
+
-// TODO: replace with std::void_t when we move to C++17
+namespace emu::detail {
+
+// TODO: work out why this doesn't work with clang and/or libc++ void_t but works with this C++14 work-alike
template <typename... T> struct void_wrapper { using type = void; };
template <typename... T> using void_t = typename void_wrapper<T...>::type;
-template <typename D, typename T, typename Enable = void> struct rw_device_class { };
+template <typename D, typename T, typename Enable = void> struct rw_device_class { };
template <typename D, typename T, typename Ret, typename... Params>
struct rw_device_class<D, Ret (T::*)(Params...), std::enable_if_t<std::is_constructible<D, device_t &, const char *, Ret (T::*)(Params...), const char *>::value> > { using type = T; };
@@ -224,15 +249,6 @@ template <typename T> using rw_delegate_type_t = typename rw_delegate_type<T>::t
template <typename T> using rw_delegate_device_class_t = typename rw_delegate_type<T>::device_class;
-template <typename T>
-inline rw_delegate_type_t<T> make_delegate(device_t &base, char const *tag, T &&func, char const *name)
-{ return rw_delegate_type_t<T>(base, tag, std::forward<T>(func), name); }
-
-template <typename T>
-inline rw_delegate_type_t<T> make_delegate(rw_delegate_device_class_t<T> &object, T &&func, char const *name)
-{ return rw_delegate_type_t<T>(object, std::forward<T>(func), name); }
-
-
template <typename L>
inline std::enable_if_t<std::is_constructible<read8_delegate, device_t &, L, const char *>::value, read8_delegate> make_lr8_delegate(device_t &owner, L &&l, const char *name)
{ return read8_delegate(owner, std::forward<L>(l), name); }
@@ -427,14 +443,69 @@ inline std::enable_if_t<std::is_constructible<write64smo_delegate, device_t &, L
{ return write64smo_delegate(owner, std::forward<L>(l), name); }
+// =====================-> delegate -> Width
+
+template <typename Delegate> struct handler_width;
+template <typename Delegate> inline constexpr int handler_width_v = handler_width<Delegate>::value;
+template <> struct handler_width<read8_delegate> { static inline constexpr int value = 0; };
+template <> struct handler_width<read8m_delegate> { static inline constexpr int value = 0; };
+template <> struct handler_width<read8s_delegate> { static inline constexpr int value = 0; };
+template <> struct handler_width<read8sm_delegate> { static inline constexpr int value = 0; };
+template <> struct handler_width<read8mo_delegate> { static inline constexpr int value = 0; };
+template <> struct handler_width<read8smo_delegate> { static inline constexpr int value = 0; };
+template <> struct handler_width<write8_delegate> { static inline constexpr int value = 0; };
+template <> struct handler_width<write8m_delegate> { static inline constexpr int value = 0; };
+template <> struct handler_width<write8s_delegate> { static inline constexpr int value = 0; };
+template <> struct handler_width<write8sm_delegate> { static inline constexpr int value = 0; };
+template <> struct handler_width<write8mo_delegate> { static inline constexpr int value = 0; };
+template <> struct handler_width<write8smo_delegate> { static inline constexpr int value = 0; };
+template <> struct handler_width<read16_delegate> { static inline constexpr int value = 1; };
+template <> struct handler_width<read16m_delegate> { static inline constexpr int value = 1; };
+template <> struct handler_width<read16s_delegate> { static inline constexpr int value = 1; };
+template <> struct handler_width<read16sm_delegate> { static inline constexpr int value = 1; };
+template <> struct handler_width<read16mo_delegate> { static inline constexpr int value = 1; };
+template <> struct handler_width<read16smo_delegate> { static inline constexpr int value = 1; };
+template <> struct handler_width<write16_delegate> { static inline constexpr int value = 1; };
+template <> struct handler_width<write16m_delegate> { static inline constexpr int value = 1; };
+template <> struct handler_width<write16s_delegate> { static inline constexpr int value = 1; };
+template <> struct handler_width<write16sm_delegate> { static inline constexpr int value = 1; };
+template <> struct handler_width<write16mo_delegate> { static inline constexpr int value = 1; };
+template <> struct handler_width<write16smo_delegate> { static inline constexpr int value = 1; };
+template <> struct handler_width<read32_delegate> { static inline constexpr int value = 2; };
+template <> struct handler_width<read32m_delegate> { static inline constexpr int value = 2; };
+template <> struct handler_width<read32s_delegate> { static inline constexpr int value = 2; };
+template <> struct handler_width<read32sm_delegate> { static inline constexpr int value = 2; };
+template <> struct handler_width<read32mo_delegate> { static inline constexpr int value = 2; };
+template <> struct handler_width<read32smo_delegate> { static inline constexpr int value = 2; };
+template <> struct handler_width<write32_delegate> { static inline constexpr int value = 2; };
+template <> struct handler_width<write32m_delegate> { static inline constexpr int value = 2; };
+template <> struct handler_width<write32s_delegate> { static inline constexpr int value = 2; };
+template <> struct handler_width<write32sm_delegate> { static inline constexpr int value = 2; };
+template <> struct handler_width<write32mo_delegate> { static inline constexpr int value = 2; };
+template <> struct handler_width<write32smo_delegate> { static inline constexpr int value = 2; };
+template <> struct handler_width<read64_delegate> { static inline constexpr int value = 3; };
+template <> struct handler_width<read64m_delegate> { static inline constexpr int value = 3; };
+template <> struct handler_width<read64s_delegate> { static inline constexpr int value = 3; };
+template <> struct handler_width<read64sm_delegate> { static inline constexpr int value = 3; };
+template <> struct handler_width<read64mo_delegate> { static inline constexpr int value = 3; };
+template <> struct handler_width<read64smo_delegate> { static inline constexpr int value = 3; };
+template <> struct handler_width<write64_delegate> { static inline constexpr int value = 3; };
+template <> struct handler_width<write64m_delegate> { static inline constexpr int value = 3; };
+template <> struct handler_width<write64s_delegate> { static inline constexpr int value = 3; };
+template <> struct handler_width<write64sm_delegate> { static inline constexpr int value = 3; };
+template <> struct handler_width<write64mo_delegate> { static inline constexpr int value = 3; };
+template <> struct handler_width<write64smo_delegate> { static inline constexpr int value = 3; };
+
+
// =====================-> Width -> types
-template<int Width> struct handler_entry_size {};
-template<> struct handler_entry_size<0> { using uX = u8; };
-template<> struct handler_entry_size<1> { using uX = u16; };
-template<> struct handler_entry_size<2> { using uX = u32; };
-template<> struct handler_entry_size<3> { using uX = u64; };
+template <int Width> struct handler_entry_size;
+template <int Width> using handler_entry_size_t = typename handler_entry_size<Width>::type;
+template<> struct handler_entry_size<0> { using type = u8; };
+template<> struct handler_entry_size<1> { using type = u16; };
+template<> struct handler_entry_size<2> { using type = u32; };
+template<> struct handler_entry_size<3> { using type = u64; };
// =====================-> Address segmentation for the search tree
@@ -456,19 +527,58 @@ constexpr int handler_entry_dispatch_lowbits(int highbits, int width, int ashift
width + ashift;
}
-} } // namespace emu::detail
+
+// =====================-> Passthrough handler management structure
+
+class memory_passthrough_handler_impl
+{
+public:
+ memory_passthrough_handler_impl(address_space &space) : m_space(space) {}
+ memory_passthrough_handler_impl(memory_passthrough_handler_impl const &) = delete;
+
+ void remove();
+
+private:
+ address_space &m_space;
+ std::unordered_set<handler_entry *> m_handlers;
+
+ void add_handler(handler_entry *handler) { m_handlers.insert(handler); }
+ void remove_handler(handler_entry *handler) { m_handlers.erase(m_handlers.find(handler)); }
+
+ friend address_space;
+ template<int Width, int AddrShift> friend class ::handler_entry_read_passthrough;
+ template<int Width, int AddrShift> friend class ::handler_entry_write_passthrough;
+};
+
+} // namespace emu::detail
+
+
+namespace emu {
+
+template <typename T>
+inline detail::rw_delegate_type_t<T> rw_delegate(device_t &base, char const *tag, T &&func, char const *name)
+{ return detail::rw_delegate_type_t<T>(base, tag, std::forward<T>(func), name); }
+
+template <typename T>
+inline detail::rw_delegate_type_t<T> rw_delegate(detail::rw_delegate_device_class_t<T> &object, T &&func, char const *name)
+{ return detail::rw_delegate_type_t<T>(object, std::forward<T>(func), name); }
+
+template <typename D, bool Reqd, typename T>
+inline detail::rw_delegate_type_t<T> rw_delegate(device_finder<D, Reqd> const &finder, T &&func, char const *name)
+{ return detail::rw_delegate_type_t<T>(finder, std::forward<T>(func), name); }
+
+} // namespace emu
// ======================> memory_units_descritor forwards declaration
-template<int Width, int AddrShift, endianness_t Endian> class memory_units_descriptor;
+template<int Width, int AddrShift> class memory_units_descriptor;
// =====================-> The root class of all handlers
// Handlers the refcounting as part of the interface
-
class handler_entry
{
DISABLE_COPYING(handler_entry);
@@ -476,10 +586,15 @@ class handler_entry
template<int Level, int Width, int AddrShift, endianness_t Endian> friend class address_space_specific;
public:
- // Typing flags
- static constexpr u32 F_DISPATCH = 0x00000001; // handler that forwards the access to other handlers
- static constexpr u32 F_UNITS = 0x00000002; // handler that merges/splits an access among multiple handlers (unitmask support)
- static constexpr u32 F_PASSTHROUGH = 0x00000004; // handler that passes through the request to another handler
+ // Typing flags (low 16 bits are for the user)
+ static constexpr u32 F_UNMAP = 0x00010000; // the unmapped memory accessed handler
+ static constexpr u32 F_DISPATCH = 0x00020000; // handler that forwards the access to other handlers
+ static constexpr u32 F_UNITS = 0x00040000; // handler that merges/splits an access among multiple handlers (unitmask support)
+ static constexpr u32 F_VIEW = 0x00080000; // handler for a view (kinda like dispatch except not entirely)
+ static constexpr u32 F_PT_BITS = 24; // position of the 4-bit priority for a passthrough handler. The highest the priority the earlier it is called in the chain. 0 = not passthrough
+ static constexpr u32 F_PT_REPLACE = 1 << F_PT_BITS; // a passthrough with a odd priority can only happen once in a path
+
+ static constexpr u32 f_pt(u32 priority) { return (priority << F_PT_BITS); }
// Start/end of range flags
static constexpr u8 START = 1;
@@ -507,8 +622,10 @@ public:
inline u32 flags() const { return m_flags; }
inline bool is_dispatch() const { return m_flags & F_DISPATCH; }
+ inline bool is_view() const { return m_flags & F_VIEW; }
inline bool is_units() const { return m_flags & F_UNITS; }
- inline bool is_passthrough() const { return m_flags & F_PASSTHROUGH; }
+ inline bool is_passthrough() const { return f_get_pt() != 0; }
+ inline u32 f_get_pt() const { return (m_flags >> F_PT_BITS) & 15; }
virtual void dump_map(std::vector<memory_entry> &map) const;
@@ -516,6 +633,11 @@ public:
virtual void enumerate_references(handler_entry::reflist &refs) const;
u32 get_refcount() const { return m_refcount; }
+ virtual void select_a(int slot);
+ virtual void select_u(int slot);
+
+ virtual offs_t dispatch_entry(offs_t address) const;
+
protected:
// Address range storage
struct range {
@@ -545,18 +667,16 @@ protected:
// Provides the populate/read/get_ptr/lookup API
-template<int Width, int AddrShift, endianness_t Endian> class handler_entry_read_passthrough;
-
-template<int Width, int AddrShift, endianness_t Endian> class handler_entry_read : public handler_entry
+template<int Width, int AddrShift> class handler_entry_read : public handler_entry
{
public:
- using uX = typename emu::detail::handler_entry_size<Width>::uX;
+ using uX = emu::detail::handler_entry_size_t<Width>;
static constexpr u32 NATIVE_MASK = Width + AddrShift >= 0 ? make_bitmask<u32>(Width + AddrShift) : 0;
struct mapping {
- handler_entry_read<Width, AddrShift, Endian> *original;
- handler_entry_read<Width, AddrShift, Endian> *patched;
+ handler_entry_read<Width, AddrShift> *original;
+ handler_entry_read<Width, AddrShift> *patched;
u8 ukey;
};
@@ -564,10 +684,13 @@ public:
~handler_entry_read() {}
virtual uX read(offs_t offset, uX mem_mask) const = 0;
+ virtual uX read_interruptible(offs_t offset, uX mem_mask) const = 0;
+ virtual std::pair<uX, u16> read_flags(offs_t offset, uX mem_mask) const = 0;
+ virtual u16 lookup_flags(offs_t offset, uX mem_mask) const = 0;
virtual void *get_ptr(offs_t offset) const;
- virtual void lookup(offs_t address, offs_t &start, offs_t &end, handler_entry_read<Width, AddrShift, Endian> *&handler) const;
+ virtual void lookup(offs_t address, offs_t &start, offs_t &end, handler_entry_read<Width, AddrShift> *&handler) const;
- inline void populate(offs_t start, offs_t end, offs_t mirror, handler_entry_read<Width, AddrShift, Endian> *handler) {
+ inline void populate(offs_t start, offs_t end, offs_t mirror, handler_entry_read<Width, AddrShift> *handler) {
start &= ~NATIVE_MASK;
end |= NATIVE_MASK;
if(mirror)
@@ -576,10 +699,10 @@ public:
populate_nomirror(start, end, start, end, handler);
}
- virtual void populate_nomirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_read<Width, AddrShift, Endian> *handler);
- virtual void populate_mirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, handler_entry_read<Width, AddrShift, Endian> *handler);
+ virtual void populate_nomirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_read<Width, AddrShift> *handler);
+ virtual void populate_mirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, handler_entry_read<Width, AddrShift> *handler);
- inline void populate_mismatched(offs_t start, offs_t end, offs_t mirror, const memory_units_descriptor<Width, AddrShift, Endian> &descriptor) {
+ void populate_mismatched(offs_t start, offs_t end, offs_t mirror, const memory_units_descriptor<Width, AddrShift> &descriptor) {
start &= ~NATIVE_MASK;
end |= NATIVE_MASK;
std::vector<mapping> mappings;
@@ -589,10 +712,10 @@ public:
populate_mismatched_nomirror(start, end, start, end, descriptor, START|END, mappings);
}
- virtual void populate_mismatched_nomirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, const memory_units_descriptor<Width, AddrShift, Endian> &descriptor, u8 rkey, std::vector<mapping> &mappings);
- virtual void populate_mismatched_mirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, const memory_units_descriptor<Width, AddrShift, Endian> &descriptor, std::vector<mapping> &mappings);
+ virtual void populate_mismatched_nomirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, const memory_units_descriptor<Width, AddrShift> &descriptor, u8 rkey, std::vector<mapping> &mappings);
+ virtual void populate_mismatched_mirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, const memory_units_descriptor<Width, AddrShift> &descriptor, std::vector<mapping> &mappings);
- inline void populate_passthrough(offs_t start, offs_t end, offs_t mirror, handler_entry_read_passthrough<Width, AddrShift, Endian> *handler) {
+ void populate_passthrough(offs_t start, offs_t end, offs_t mirror, handler_entry_read_passthrough<Width, AddrShift> *handler) {
start &= ~NATIVE_MASK;
end |= NATIVE_MASK;
std::vector<mapping> mappings;
@@ -602,32 +725,33 @@ public:
populate_passthrough_nomirror(start, end, start, end, handler, mappings);
}
- virtual void populate_passthrough_nomirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_read_passthrough<Width, AddrShift, Endian> *handler, std::vector<mapping> &mappings);
- virtual void populate_passthrough_mirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, handler_entry_read_passthrough<Width, AddrShift, Endian> *handler, std::vector<mapping> &mappings);
+ virtual void populate_passthrough_nomirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_read_passthrough<Width, AddrShift> *handler, std::vector<mapping> &mappings);
+ virtual void populate_passthrough_mirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, handler_entry_read_passthrough<Width, AddrShift> *handler, std::vector<mapping> &mappings);
// Remove a set of passthrough handlers, leaving the lower handler in their place
virtual void detach(const std::unordered_set<handler_entry *> &handlers);
// Return the internal structures of the root dispatch
- virtual const handler_entry_read<Width, AddrShift, Endian> *const *get_dispatch() const;
+ virtual const handler_entry_read<Width, AddrShift> *const *get_dispatch() const;
+
+ virtual void init_handlers(offs_t start_entry, offs_t end_entry, u32 lowbits, offs_t ostart, offs_t oend, handler_entry_read<Width, AddrShift> **dispatch, handler_entry::range *ranges);
+ virtual handler_entry_read<Width, AddrShift> *dup();
};
// =====================-> The parent class of all write handlers
// Provides the populate/write/get_ptr/lookup API
-template<int Width, int AddrShift, endianness_t Endian> class handler_entry_write_passthrough;
-
-template<int Width, int AddrShift, endianness_t Endian> class handler_entry_write : public handler_entry
+template<int Width, int AddrShift> class handler_entry_write : public handler_entry
{
public:
- using uX = typename emu::detail::handler_entry_size<Width>::uX;
+ using uX = emu::detail::handler_entry_size_t<Width>;
static constexpr u32 NATIVE_MASK = Width + AddrShift >= 0 ? make_bitmask<u32>(Width + AddrShift) : 0;
struct mapping {
- handler_entry_write<Width, AddrShift, Endian> *original;
- handler_entry_write<Width, AddrShift, Endian> *patched;
+ handler_entry_write<Width, AddrShift> *original;
+ handler_entry_write<Width, AddrShift> *patched;
u8 ukey;
};
@@ -635,10 +759,13 @@ public:
virtual ~handler_entry_write() {}
virtual void write(offs_t offset, uX data, uX mem_mask) const = 0;
+ virtual void write_interruptible(offs_t offset, uX data, uX mem_mask) const = 0;
+ virtual u16 write_flags(offs_t offset, uX data, uX mem_mask) const = 0;
+ virtual u16 lookup_flags(offs_t offset, uX mem_mask) const = 0;
virtual void *get_ptr(offs_t offset) const;
- virtual void lookup(offs_t address, offs_t &start, offs_t &end, handler_entry_write<Width, AddrShift, Endian> *&handler) const;
+ virtual void lookup(offs_t address, offs_t &start, offs_t &end, handler_entry_write<Width, AddrShift> *&handler) const;
- inline void populate(offs_t start, offs_t end, offs_t mirror, handler_entry_write<Width, AddrShift, Endian> *handler) {
+ inline void populate(offs_t start, offs_t end, offs_t mirror, handler_entry_write<Width, AddrShift> *handler) {
start &= ~NATIVE_MASK;
end |= NATIVE_MASK;
if(mirror)
@@ -647,10 +774,10 @@ public:
populate_nomirror(start, end, start, end, handler);
}
- virtual void populate_nomirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_write<Width, AddrShift, Endian> *handler);
- virtual void populate_mirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, handler_entry_write<Width, AddrShift, Endian> *handler);
+ virtual void populate_nomirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_write<Width, AddrShift> *handler);
+ virtual void populate_mirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, handler_entry_write<Width, AddrShift> *handler);
- inline void populate_mismatched(offs_t start, offs_t end, offs_t mirror, const memory_units_descriptor<Width, AddrShift, Endian> &descriptor) {
+ inline void populate_mismatched(offs_t start, offs_t end, offs_t mirror, const memory_units_descriptor<Width, AddrShift> &descriptor) {
start &= ~NATIVE_MASK;
end |= NATIVE_MASK;
@@ -661,10 +788,10 @@ public:
populate_mismatched_nomirror(start, end, start, end, descriptor, START|END, mappings);
}
- virtual void populate_mismatched_nomirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, const memory_units_descriptor<Width, AddrShift, Endian> &descriptor, u8 rkey, std::vector<mapping> &mappings);
- virtual void populate_mismatched_mirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, const memory_units_descriptor<Width, AddrShift, Endian> &descriptor, std::vector<mapping> &mappings);
+ virtual void populate_mismatched_nomirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, const memory_units_descriptor<Width, AddrShift> &descriptor, u8 rkey, std::vector<mapping> &mappings);
+ virtual void populate_mismatched_mirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, const memory_units_descriptor<Width, AddrShift> &descriptor, std::vector<mapping> &mappings);
- inline void populate_passthrough(offs_t start, offs_t end, offs_t mirror, handler_entry_write_passthrough<Width, AddrShift, Endian> *handler) {
+ inline void populate_passthrough(offs_t start, offs_t end, offs_t mirror, handler_entry_write_passthrough<Width, AddrShift> *handler) {
start &= ~NATIVE_MASK;
end |= NATIVE_MASK;
std::vector<mapping> mappings;
@@ -674,39 +801,43 @@ public:
populate_passthrough_nomirror(start, end, start, end, handler, mappings);
}
- virtual void populate_passthrough_nomirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_write_passthrough<Width, AddrShift, Endian> *handler, std::vector<mapping> &mappings);
- virtual void populate_passthrough_mirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, handler_entry_write_passthrough<Width, AddrShift, Endian> *handler, std::vector<mapping> &mappings);
+ virtual void populate_passthrough_nomirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_write_passthrough<Width, AddrShift> *handler, std::vector<mapping> &mappings);
+ virtual void populate_passthrough_mirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, handler_entry_write_passthrough<Width, AddrShift> *handler, std::vector<mapping> &mappings);
// Remove a set of passthrough handlers, leaving the lower handler in their place
virtual void detach(const std::unordered_set<handler_entry *> &handlers);
// Return the internal structures of the root dispatch
- virtual const handler_entry_write<Width, AddrShift, Endian> *const *get_dispatch() const;
+ virtual const handler_entry_write<Width, AddrShift> *const *get_dispatch() const;
+
+ virtual void init_handlers(offs_t start_entry, offs_t end_entry, u32 lowbits, offs_t ostart, offs_t oend, handler_entry_write<Width, AddrShift> **dispatch, handler_entry::range *ranges);
+ virtual handler_entry_write<Width, AddrShift> *dup();
};
// =====================-> Passthrough handler management structure
class memory_passthrough_handler
{
- template<int Width, int AddrShift, endianness_t Endian> friend class handler_entry_read_passthrough;
- template<int Width, int AddrShift, endianness_t Endian> friend class handler_entry_write_passthrough;
-
public:
- memory_passthrough_handler(address_space &space) : m_space(space) {}
+ memory_passthrough_handler() : m_impl() {}
+ memory_passthrough_handler(std::shared_ptr<emu::detail::memory_passthrough_handler_impl> const &impl) : m_impl(impl) {}
- inline void remove();
+ void remove()
+ {
+ auto impl(m_impl.lock());
+ if (impl)
+ impl->remove();
+ }
private:
- address_space &m_space;
- std::unordered_set<handler_entry *> m_handlers;
+ std::weak_ptr<emu::detail::memory_passthrough_handler_impl> m_impl;
- void add_handler(handler_entry *handler) { m_handlers.insert(handler); }
- void remove_handler(handler_entry *handler) { m_handlers.erase(m_handlers.find(handler)); }
+ friend class address_space;
};
// =====================-> Forward declaration for address_space
-template<int Width, int AddrShift, endianness_t Endian> class handler_entry_read_unmapped;
-template<int Width, int AddrShift, endianness_t Endian> class handler_entry_write_unmapped;
+template<int Width, int AddrShift> class handler_entry_read_unmapped;
+template<int Width, int AddrShift> class handler_entry_write_unmapped;
// ======================> address offset -> byte offset
@@ -715,10 +846,10 @@ constexpr offs_t memory_offset_to_byte(offs_t offset, int AddrShift) { return Ad
// ======================> generic read/write decomposition routines
// generic direct read
-template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename T> typename emu::detail::handler_entry_size<TargetWidth>::uX memory_read_generic(T rop, offs_t address, typename emu::detail::handler_entry_size<TargetWidth>::uX mask)
+template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename T> emu::detail::handler_entry_size_t<TargetWidth> memory_read_generic(T rop, offs_t address, emu::detail::handler_entry_size_t<TargetWidth> mask)
{
- using TargetType = typename emu::detail::handler_entry_size<TargetWidth>::uX;
- using NativeType = typename emu::detail::handler_entry_size<Width>::uX;
+ using TargetType = emu::detail::handler_entry_size_t<TargetWidth>;
+ using NativeType = emu::detail::handler_entry_size_t<Width>;
constexpr u32 TARGET_BYTES = 1 << TargetWidth;
constexpr u32 TARGET_BITS = 8 * TARGET_BYTES;
@@ -849,9 +980,9 @@ template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Al
}
// generic direct write
-template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename T> void memory_write_generic(T wop, offs_t address, typename emu::detail::handler_entry_size<TargetWidth>::uX data, typename emu::detail::handler_entry_size<TargetWidth>::uX mask)
+template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename T> void memory_write_generic(T wop, offs_t address, emu::detail::handler_entry_size_t<TargetWidth> data, emu::detail::handler_entry_size_t<TargetWidth> mask)
{
- using NativeType = typename emu::detail::handler_entry_size<Width>::uX;
+ using NativeType = emu::detail::handler_entry_size_t<Width>;
constexpr u32 TARGET_BYTES = 1 << TargetWidth;
constexpr u32 TARGET_BITS = 8 * TARGET_BYTES;
@@ -972,33 +1103,609 @@ template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Al
}
}
+// generic direct read with flags
+template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename TF> std::pair<emu::detail::handler_entry_size_t<TargetWidth>, u16> memory_read_generic_flags(TF ropf, offs_t address, emu::detail::handler_entry_size_t<TargetWidth> mask)
+{
+ using TargetType = emu::detail::handler_entry_size_t<TargetWidth>;
+ using NativeType = emu::detail::handler_entry_size_t<Width>;
+
+ constexpr u32 TARGET_BYTES = 1 << TargetWidth;
+ constexpr u32 TARGET_BITS = 8 * TARGET_BYTES;
+ constexpr u32 NATIVE_BYTES = 1 << Width;
+ constexpr u32 NATIVE_BITS = 8 * NATIVE_BYTES;
+ constexpr u32 NATIVE_STEP = AddrShift >= 0 ? NATIVE_BYTES << iabs(AddrShift) : NATIVE_BYTES >> iabs(AddrShift);
+ constexpr u32 NATIVE_MASK = Width + AddrShift >= 0 ? make_bitmask<u32>(Width + AddrShift) : 0;
+
+ // equal to native size and aligned; simple pass-through to the native reader
+ if (NATIVE_BYTES == TARGET_BYTES && (Aligned || (address & NATIVE_MASK) == 0))
+ return ropf(address & ~NATIVE_MASK, mask);
+
+ // if native size is larger, see if we can do a single masked read (guaranteed if we're aligned)
+ if (NATIVE_BYTES > TARGET_BYTES)
+ {
+ u32 offsbits = 8 * (memory_offset_to_byte(address, AddrShift) & (NATIVE_BYTES - (Aligned ? TARGET_BYTES : 1)));
+ if (Aligned || (offsbits + TARGET_BITS <= NATIVE_BITS))
+ {
+ if (Endian != ENDIANNESS_LITTLE) offsbits = NATIVE_BITS - TARGET_BITS - offsbits;
+ auto pack = ropf(address & ~NATIVE_MASK, (NativeType)mask << offsbits);
+ pack.first >>= offsbits;
+ return pack;
+ }
+ }
+
+ // determine our alignment against the native boundaries, and mask the address
+ u32 offsbits = 8 * (memory_offset_to_byte(address, AddrShift) & (NATIVE_BYTES - 1));
+ address &= ~NATIVE_MASK;
+
+ // if we're here, and native size is larger or equal to the target, we need exactly 2 reads
+ if (NATIVE_BYTES >= TARGET_BYTES)
+ {
+ // little-endian case
+ if (Endian == ENDIANNESS_LITTLE)
+ {
+ // read lower bits from lower address
+ u16 flags = 0;
+ TargetType result = 0;
+ NativeType curmask = (NativeType)mask << offsbits;
+ if (curmask != 0) { auto pack = ropf(address, curmask); result = pack.first >> offsbits; flags = pack.second; }
+
+ // read upper bits from upper address
+ offsbits = NATIVE_BITS - offsbits;
+ curmask = mask >> offsbits;
+ if (curmask != 0) { auto pack = ropf(address + NATIVE_STEP, curmask); result |= pack.first << offsbits; flags |= pack.second; }
+ return std::pair<NativeType, u16>(result, flags);
+ }
+
+ // big-endian case
+ else
+ {
+ // left-justify the mask to the target type
+ constexpr u32 LEFT_JUSTIFY_TARGET_TO_NATIVE_SHIFT = ((NATIVE_BITS >= TARGET_BITS) ? (NATIVE_BITS - TARGET_BITS) : 0);
+ u16 flags = 0;
+ NativeType result = 0;
+ NativeType ljmask = (NativeType)mask << LEFT_JUSTIFY_TARGET_TO_NATIVE_SHIFT;
+ NativeType curmask = ljmask >> offsbits;
+
+ // read upper bits from lower address
+ if (curmask != 0) { auto pack = ropf(address, curmask); result = pack.first << offsbits; flags = pack.second; }
+ offsbits = NATIVE_BITS - offsbits;
+
+ // read lower bits from upper address
+ curmask = ljmask << offsbits;
+ if (curmask != 0) { auto pack = ropf(address + NATIVE_STEP, curmask); result |= pack.first >> offsbits; flags |= pack.second; }
+
+ // return the un-justified result
+ return std::pair<NativeType, u16>(result >> LEFT_JUSTIFY_TARGET_TO_NATIVE_SHIFT, flags);
+ }
+ }
+
+ // if we're here, then we have 2 or more reads needed to get our final result
+ else
+ {
+ // compute the maximum number of loops; we do it this way so that there are
+ // a fixed number of loops for the compiler to unroll if it desires
+ constexpr u32 MAX_SPLITS_MINUS_ONE = TARGET_BYTES / NATIVE_BYTES - 1;
+ u16 flags = 0;
+ TargetType result = 0;
+
+ // little-endian case
+ if (Endian == ENDIANNESS_LITTLE)
+ {
+ // read lowest bits from first address
+ NativeType curmask = mask << offsbits;
+ if (curmask != 0) { auto pack = ropf(address, curmask); result = pack.first >> offsbits; flags = pack.second; }
+
+ // read middle bits from subsequent addresses
+ offsbits = NATIVE_BITS - offsbits;
+ for (u32 index = 0; index < MAX_SPLITS_MINUS_ONE; index++)
+ {
+ address += NATIVE_STEP;
+ curmask = mask >> offsbits;
+ if (curmask != 0) { auto pack = ropf(address, curmask); result |= (TargetType)pack.first << offsbits; flags |= pack.second; }
+ offsbits += NATIVE_BITS;
+ }
+
+ // if we're not aligned and we still have bits left, read uppermost bits from last address
+ if (!Aligned && offsbits < TARGET_BITS)
+ {
+ curmask = mask >> offsbits;
+ if (curmask != 0) { auto pack = ropf(address + NATIVE_STEP, curmask); result |= (TargetType)pack.first << offsbits; flags |= pack.second; }
+ }
+ }
+
+ // big-endian case
+ else
+ {
+ // read highest bits from first address
+ offsbits = TARGET_BITS - (NATIVE_BITS - offsbits);
+ NativeType curmask = mask >> offsbits;
+ if (curmask != 0) { auto pack = ropf(address, curmask); result = pack.first >> offsbits; flags = pack.second; }
+
+ // read middle bits from subsequent addresses
+ for (u32 index = 0; index < MAX_SPLITS_MINUS_ONE; index++)
+ {
+ offsbits -= NATIVE_BITS;
+ address += NATIVE_STEP;
+ curmask = mask >> offsbits;
+ if (curmask != 0) { auto pack = ropf(address, curmask); result |= (TargetType)pack.first >> offsbits; flags |= pack.second; }
+ }
+
+ // if we're not aligned and we still have bits left, read lowermost bits from the last address
+ if (!Aligned && offsbits != 0)
+ {
+ offsbits = NATIVE_BITS - offsbits;
+ curmask = mask << offsbits;
+ if (curmask != 0) { auto pack = ropf(address + NATIVE_STEP, curmask); result |= (TargetType)pack.first >> offsbits; flags |= pack.second; }
+ }
+ }
+ return std::pair<NativeType, u16>(result, flags);
+ }
+}
+
+// generic direct write with flags
+template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename TF> u16 memory_write_generic_flags(TF wopf, offs_t address, emu::detail::handler_entry_size_t<TargetWidth> data, emu::detail::handler_entry_size_t<TargetWidth> mask)
+{
+ using NativeType = emu::detail::handler_entry_size_t<Width>;
+
+ constexpr u32 TARGET_BYTES = 1 << TargetWidth;
+ constexpr u32 TARGET_BITS = 8 * TARGET_BYTES;
+ constexpr u32 NATIVE_BYTES = 1 << Width;
+ constexpr u32 NATIVE_BITS = 8 * NATIVE_BYTES;
+ constexpr u32 NATIVE_STEP = AddrShift >= 0 ? NATIVE_BYTES << iabs(AddrShift) : NATIVE_BYTES >> iabs(AddrShift);
+ constexpr u32 NATIVE_MASK = Width + AddrShift >= 0 ? (1 << (Width + AddrShift)) - 1 : 0;
+
+ // equal to native size and aligned; simple pass-through to the native writer
+ if (NATIVE_BYTES == TARGET_BYTES && (Aligned || (address & NATIVE_MASK) == 0))
+ return wopf(address & ~NATIVE_MASK, data, mask);
+
+ // if native size is larger, see if we can do a single masked write (guaranteed if we're aligned)
+ if (NATIVE_BYTES > TARGET_BYTES)
+ {
+ u32 offsbits = 8 * (memory_offset_to_byte(address, AddrShift) & (NATIVE_BYTES - (Aligned ? TARGET_BYTES : 1)));
+ if (Aligned || (offsbits + TARGET_BITS <= NATIVE_BITS))
+ {
+ if (Endian != ENDIANNESS_LITTLE) offsbits = NATIVE_BITS - TARGET_BITS - offsbits;
+ return wopf(address & ~NATIVE_MASK, (NativeType)data << offsbits, (NativeType)mask << offsbits);
+ }
+ }
+
+ // determine our alignment against the native boundaries, and mask the address
+ u32 offsbits = 8 * (memory_offset_to_byte(address, AddrShift) & (NATIVE_BYTES - 1));
+ address &= ~NATIVE_MASK;
+
+ // if we're here, and native size is larger or equal to the target, we need exactly 2 writes
+ if (NATIVE_BYTES >= TARGET_BYTES)
+ {
+ // little-endian case
+ if (Endian == ENDIANNESS_LITTLE)
+ {
+ // write lower bits to lower address
+ u16 flags = 0;
+ NativeType curmask = (NativeType)mask << offsbits;
+ if (curmask != 0) flags |= wopf(address, (NativeType)data << offsbits, curmask);
+
+ // write upper bits to upper address
+ offsbits = NATIVE_BITS - offsbits;
+ curmask = mask >> offsbits;
+ if (curmask != 0) flags |= wopf(address + NATIVE_STEP, data >> offsbits, curmask);
+ return flags;
+ }
+
+ // big-endian case
+ else
+ {
+ // left-justify the mask and data to the target type
+ u16 flags = 0;
+ constexpr u32 LEFT_JUSTIFY_TARGET_TO_NATIVE_SHIFT = ((NATIVE_BITS >= TARGET_BITS) ? (NATIVE_BITS - TARGET_BITS) : 0);
+ NativeType ljdata = (NativeType)data << LEFT_JUSTIFY_TARGET_TO_NATIVE_SHIFT;
+ NativeType ljmask = (NativeType)mask << LEFT_JUSTIFY_TARGET_TO_NATIVE_SHIFT;
+ // write upper bits to lower address
+ NativeType curmask = ljmask >> offsbits;
+ if (curmask != 0) flags |= wopf(address, ljdata >> offsbits, curmask);
+ // write lower bits to upper address
+ offsbits = NATIVE_BITS - offsbits;
+ curmask = ljmask << offsbits;
+ if (curmask != 0) flags |= wopf(address + NATIVE_STEP, ljdata << offsbits, curmask);
+ return flags;
+ }
+ }
+
+ // if we're here, then we have 2 or more writes needed to get our final result
+ else
+ {
+ // compute the maximum number of loops; we do it this way so that there are
+ // a fixed number of loops for the compiler to unroll if it desires
+ constexpr u32 MAX_SPLITS_MINUS_ONE = TARGET_BYTES / NATIVE_BYTES - 1;
+ u16 flags = 0;
+
+ // little-endian case
+ if (Endian == ENDIANNESS_LITTLE)
+ {
+ // write lowest bits to first address
+ NativeType curmask = mask << offsbits;
+ if (curmask != 0) flags |= wopf(address, data << offsbits, curmask);
+
+ // write middle bits to subsequent addresses
+ offsbits = NATIVE_BITS - offsbits;
+ for (u32 index = 0; index < MAX_SPLITS_MINUS_ONE; index++)
+ {
+ address += NATIVE_STEP;
+ curmask = mask >> offsbits;
+ if (curmask != 0) flags |= wopf(address, data >> offsbits, curmask);
+ offsbits += NATIVE_BITS;
+ }
+
+ // if we're not aligned and we still have bits left, write uppermost bits to last address
+ if (!Aligned && offsbits < TARGET_BITS)
+ {
+ curmask = mask >> offsbits;
+ if (curmask != 0) flags |= wopf(address + NATIVE_STEP, data >> offsbits, curmask);
+ }
+ }
+
+ // big-endian case
+ else
+ {
+ // write highest bits to first address
+ offsbits = TARGET_BITS - (NATIVE_BITS - offsbits);
+ NativeType curmask = mask >> offsbits;
+ if (curmask != 0) flags |= wopf(address, data >> offsbits, curmask);
+
+ // write middle bits to subsequent addresses
+ for (u32 index = 0; index < MAX_SPLITS_MINUS_ONE; index++)
+ {
+ offsbits -= NATIVE_BITS;
+ address += NATIVE_STEP;
+ curmask = mask >> offsbits;
+ if (curmask != 0) flags |= wopf(address, data >> offsbits, curmask);
+ }
+
+ // if we're not aligned and we still have bits left, write lowermost bits to the last address
+ if (!Aligned && offsbits != 0)
+ {
+ offsbits = NATIVE_BITS - offsbits;
+ curmask = mask << offsbits;
+ if (curmask != 0) flags |= wopf(address + NATIVE_STEP, data << offsbits, curmask);
+ }
+ }
+ return flags;
+ }
+}
+
+//##############################################
+// generic direct read flags lookup
+template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename TF> u16 lookup_memory_read_generic_flags(TF lropf, offs_t address, emu::detail::handler_entry_size_t<TargetWidth> mask)
+{
+ using NativeType = emu::detail::handler_entry_size_t<Width>;
+
+ constexpr u32 TARGET_BYTES = 1 << TargetWidth;
+ constexpr u32 TARGET_BITS = 8 * TARGET_BYTES;
+ constexpr u32 NATIVE_BYTES = 1 << Width;
+ constexpr u32 NATIVE_BITS = 8 * NATIVE_BYTES;
+ constexpr u32 NATIVE_STEP = AddrShift >= 0 ? NATIVE_BYTES << iabs(AddrShift) : NATIVE_BYTES >> iabs(AddrShift);
+ constexpr u32 NATIVE_MASK = Width + AddrShift >= 0 ? make_bitmask<u32>(Width + AddrShift) : 0;
+
+ // equal to native size and aligned; simple pass-through to the native flags lookup
+ if (NATIVE_BYTES == TARGET_BYTES && (Aligned || (address & NATIVE_MASK) == 0))
+ return lropf(address & ~NATIVE_MASK, mask);
+
+ // if native size is larger, see if we can do a single masked flags lookup (guaranteed if we're aligned)
+ if (NATIVE_BYTES > TARGET_BYTES)
+ {
+ u32 offsbits = 8 * (memory_offset_to_byte(address, AddrShift) & (NATIVE_BYTES - (Aligned ? TARGET_BYTES : 1)));
+ if (Aligned || (offsbits + TARGET_BITS <= NATIVE_BITS))
+ {
+ if (Endian != ENDIANNESS_LITTLE) offsbits = NATIVE_BITS - TARGET_BITS - offsbits;
+ return lropf(address & ~NATIVE_MASK, (NativeType)mask << offsbits);
+ }
+ }
+
+ // determine our alignment against the native boundaries, and mask the address
+ u32 offsbits = 8 * (memory_offset_to_byte(address, AddrShift) & (NATIVE_BYTES - 1));
+ address &= ~NATIVE_MASK;
+
+ // if we're here, and native size is larger or equal to the target, we need exactly 2 reads
+ if (NATIVE_BYTES >= TARGET_BYTES)
+ {
+ // little-endian case
+ if (Endian == ENDIANNESS_LITTLE)
+ {
+ // read flags from lower address
+ u16 flags = 0;
+ NativeType curmask = (NativeType)mask << offsbits;
+ if (curmask != 0) flags |= lropf(address, curmask);
+
+ // read flags from upper address
+ offsbits = NATIVE_BITS - offsbits;
+ curmask = mask >> offsbits;
+ if (curmask != 0) flags |= lropf(address + NATIVE_STEP, curmask);
+ return flags;
+ }
+
+ // big-endian case
+ else
+ {
+ // left-justify the mask to the target type
+ constexpr u32 LEFT_JUSTIFY_TARGET_TO_NATIVE_SHIFT = ((NATIVE_BITS >= TARGET_BITS) ? (NATIVE_BITS - TARGET_BITS) : 0);
+ u16 flags = 0;
+ NativeType ljmask = (NativeType)mask << LEFT_JUSTIFY_TARGET_TO_NATIVE_SHIFT;
+ NativeType curmask = ljmask >> offsbits;
+
+ // read flags from lower address
+ if (curmask != 0) flags |= lropf(address, curmask);
+ offsbits = NATIVE_BITS - offsbits;
+
+ // read flags from upper address
+ curmask = ljmask << offsbits;
+ if (curmask != 0) flags |= lropf(address + NATIVE_STEP, curmask);
+
+ // return the result
+ return flags;
+ }
+ }
+
+ // if we're here, then we have 2 or more reads needed to get our final result
+ else
+ {
+ // compute the maximum number of loops; we do it this way so that there are
+ // a fixed number of loops for the compiler to unroll if it desires
+ constexpr u32 MAX_SPLITS_MINUS_ONE = TARGET_BYTES / NATIVE_BYTES - 1;
+ u16 flags = 0;
+
+ // little-endian case
+ if (Endian == ENDIANNESS_LITTLE)
+ {
+ // read flags from first address
+ NativeType curmask = mask << offsbits;
+ if (curmask != 0) flags |= lropf(address, curmask);
+
+ // read flags from subsequent addresses
+ offsbits = NATIVE_BITS - offsbits;
+ for (u32 index = 0; index < MAX_SPLITS_MINUS_ONE; index++)
+ {
+ address += NATIVE_STEP;
+ curmask = mask >> offsbits;
+ if (curmask != 0) flags |= lropf(address, curmask);
+ offsbits += NATIVE_BITS;
+ }
+
+ // if we're not aligned and we still have bits left, read flags from last address
+ if (!Aligned && offsbits < TARGET_BITS)
+ {
+ curmask = mask >> offsbits;
+ if (curmask != 0) flags |= lropf(address + NATIVE_STEP, curmask);
+ }
+ }
+
+ // big-endian case
+ else
+ {
+ // read flags from first address
+ offsbits = TARGET_BITS - (NATIVE_BITS - offsbits);
+ NativeType curmask = mask >> offsbits;
+ if (curmask != 0) flags |= lropf(address, curmask);
+
+ // read flags from subsequent addresses
+ for (u32 index = 0; index < MAX_SPLITS_MINUS_ONE; index++)
+ {
+ offsbits -= NATIVE_BITS;
+ address += NATIVE_STEP;
+ curmask = mask >> offsbits;
+ if (curmask != 0) flags |= lropf(address, curmask);
+ }
+
+ // if we're not aligned and we still have bits left, read flags from the last address
+ if (!Aligned && offsbits != 0)
+ {
+ offsbits = NATIVE_BITS - offsbits;
+ curmask = mask << offsbits;
+ if (curmask != 0) flags |= lropf(address + NATIVE_STEP, curmask);
+ }
+ }
+ return flags;
+ }
+}
+
+// generic direct write flags lookup
+template<int Width, int AddrShift, endianness_t Endian, int TargetWidth, bool Aligned, typename TF> u16 lookup_memory_write_generic_flags(TF lwopf, offs_t address, emu::detail::handler_entry_size_t<TargetWidth> mask)
+{
+ using NativeType = emu::detail::handler_entry_size_t<Width>;
+
+ constexpr u32 TARGET_BYTES = 1 << TargetWidth;
+ constexpr u32 TARGET_BITS = 8 * TARGET_BYTES;
+ constexpr u32 NATIVE_BYTES = 1 << Width;
+ constexpr u32 NATIVE_BITS = 8 * NATIVE_BYTES;
+ constexpr u32 NATIVE_STEP = AddrShift >= 0 ? NATIVE_BYTES << iabs(AddrShift) : NATIVE_BYTES >> iabs(AddrShift);
+ constexpr u32 NATIVE_MASK = Width + AddrShift >= 0 ? (1 << (Width + AddrShift)) - 1 : 0;
+
+ // equal to native size and aligned; simple pass-through to the native flags lookup
+ if (NATIVE_BYTES == TARGET_BYTES && (Aligned || (address & NATIVE_MASK) == 0))
+ return lwopf(address & ~NATIVE_MASK, mask);
+
+ // if native size is larger, see if we can do a single masked flags lookup (guaranteed if we're aligned)
+ if (NATIVE_BYTES > TARGET_BYTES)
+ {
+ u32 offsbits = 8 * (memory_offset_to_byte(address, AddrShift) & (NATIVE_BYTES - (Aligned ? TARGET_BYTES : 1)));
+ if (Aligned || (offsbits + TARGET_BITS <= NATIVE_BITS))
+ {
+ if (Endian != ENDIANNESS_LITTLE) offsbits = NATIVE_BITS - TARGET_BITS - offsbits;
+ return lwopf(address & ~NATIVE_MASK, (NativeType)mask << offsbits);
+ }
+ }
+
+ // determine our alignment against the native boundaries, and mask the address
+ u32 offsbits = 8 * (memory_offset_to_byte(address, AddrShift) & (NATIVE_BYTES - 1));
+ address &= ~NATIVE_MASK;
+
+ // if we're here, and native size is larger or equal to the target, we need exactly 2 lookups
+ if (NATIVE_BYTES >= TARGET_BYTES)
+ {
+ // little-endian case
+ if (Endian == ENDIANNESS_LITTLE)
+ {
+ // lookup flags from lower address
+ u16 flags = 0;
+ NativeType curmask = (NativeType)mask << offsbits;
+ if (curmask != 0) flags |= lwopf(address, curmask);
+
+ // lookup flags from upper address
+ offsbits = NATIVE_BITS - offsbits;
+ curmask = mask >> offsbits;
+ if (curmask != 0) flags |= lwopf(address + NATIVE_STEP, curmask);
+ return flags;
+ }
+
+ // big-endian case
+ else
+ {
+ // left-justify the mask to the target type
+ u16 flags = 0;
+ constexpr u32 LEFT_JUSTIFY_TARGET_TO_NATIVE_SHIFT = ((NATIVE_BITS >= TARGET_BITS) ? (NATIVE_BITS - TARGET_BITS) : 0);
+ NativeType ljmask = (NativeType)mask << LEFT_JUSTIFY_TARGET_TO_NATIVE_SHIFT;
+
+ // lookup flags from lower address
+ NativeType curmask = ljmask >> offsbits;
+ if (curmask != 0) flags |= lwopf(address, curmask);
+
+ // lookup falgs from upper address
+ offsbits = NATIVE_BITS - offsbits;
+ curmask = ljmask << offsbits;
+ if (curmask != 0) flags |= lwopf(address + NATIVE_STEP, curmask);
+ return flags;
+ }
+ }
+
+ // if we're here, then we have 2 or more lookups needed to get our final result
+ else
+ {
+ // compute the maximum number of loops; we do it this way so that there are
+ // a fixed number of loops for the compiler to unroll if it desires
+ constexpr u32 MAX_SPLITS_MINUS_ONE = TARGET_BYTES / NATIVE_BYTES - 1;
+ u16 flags = 0;
+
+ // little-endian case
+ if (Endian == ENDIANNESS_LITTLE)
+ {
+ // lookup flags from first address
+ NativeType curmask = mask << offsbits;
+ if (curmask != 0) flags |= lwopf(address, curmask);
+
+ // lookup flags from subsequent addresses
+ offsbits = NATIVE_BITS - offsbits;
+ for (u32 index = 0; index < MAX_SPLITS_MINUS_ONE; index++)
+ {
+ address += NATIVE_STEP;
+ curmask = mask >> offsbits;
+ if (curmask != 0) flags |= lwopf(address, curmask);
+ offsbits += NATIVE_BITS;
+ }
+
+ // if we're not aligned and we still have bits left, lookup flags last address
+ if (!Aligned && offsbits < TARGET_BITS)
+ {
+ curmask = mask >> offsbits;
+ if (curmask != 0) flags |= lwopf(address + NATIVE_STEP, curmask);
+ }
+ }
+
+ // big-endian case
+ else
+ {
+ // lookup flags from first address
+ offsbits = TARGET_BITS - (NATIVE_BITS - offsbits);
+ NativeType curmask = mask >> offsbits;
+ if (curmask != 0) flags |= lwopf(address, curmask);
+
+ // lookup flags from subsequent addresses
+ for (u32 index = 0; index < MAX_SPLITS_MINUS_ONE; index++)
+ {
+ offsbits -= NATIVE_BITS;
+ address += NATIVE_STEP;
+ curmask = mask >> offsbits;
+ if (curmask != 0) flags |= lwopf(address, curmask);
+ }
+
+ // if we're not aligned and we still have bits left, lookup falgs from the last address
+ if (!Aligned && offsbits != 0)
+ {
+ offsbits = NATIVE_BITS - offsbits;
+ curmask = mask << offsbits;
+ if (curmask != 0) flags |= lwopf(address + NATIVE_STEP, curmask);
+ }
+ }
+ return flags;
+ }
+}
+
// ======================> Direct dispatching
-template<int Level, int Width, int AddrShift, endianness_t Endian> typename emu::detail::handler_entry_size<Width>::uX dispatch_read(offs_t mask, offs_t offset, typename emu::detail::handler_entry_size<Width>::uX mem_mask, const handler_entry_read<Width, AddrShift, Endian> *const *dispatch)
+template<int Level, int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> dispatch_read(offs_t mask, offs_t offset, emu::detail::handler_entry_size_t<Width> mem_mask, const handler_entry_read<Width, AddrShift> *const *dispatch)
{
static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_level_to_lowbits(Level, Width, AddrShift);
return dispatch[(offset & mask) >> LowBits]->read(offset, mem_mask);
}
-template<int Level, int Width, int AddrShift, endianness_t Endian> void dispatch_write(offs_t mask, offs_t offset, typename emu::detail::handler_entry_size<Width>::uX data, typename emu::detail::handler_entry_size<Width>::uX mem_mask, const handler_entry_write<Width, AddrShift, Endian> *const *dispatch)
+template<int Level, int Width, int AddrShift> void dispatch_write(offs_t mask, offs_t offset, emu::detail::handler_entry_size_t<Width> data, emu::detail::handler_entry_size_t<Width> mem_mask, const handler_entry_write<Width, AddrShift> *const *dispatch)
{
static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_level_to_lowbits(Level, Width, AddrShift);
return dispatch[(offset & mask) >> LowBits]->write(offset, data, mem_mask);
}
+template<int Level, int Width, int AddrShift> std::pair<emu::detail::handler_entry_size_t<Width>, u16> dispatch_read_flags(offs_t mask, offs_t offset, emu::detail::handler_entry_size_t<Width> mem_mask, const handler_entry_read<Width, AddrShift> *const *dispatch)
+{
+ static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_level_to_lowbits(Level, Width, AddrShift);
+ return dispatch[(offset & mask) >> LowBits]->read_flags(offset, mem_mask);
+}
+
+
+template<int Level, int Width, int AddrShift> u16 dispatch_write_flags(offs_t mask, offs_t offset, emu::detail::handler_entry_size_t<Width> data, emu::detail::handler_entry_size_t<Width> mem_mask, const handler_entry_write<Width, AddrShift> *const *dispatch)
+{
+ static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_level_to_lowbits(Level, Width, AddrShift);
+ return dispatch[(offset & mask) >> LowBits]->write_flags(offset, data, mem_mask);
+}
+
+template<int Level, int Width, int AddrShift> u16 dispatch_lookup_read_flags(offs_t mask, offs_t offset, emu::detail::handler_entry_size_t<Width> mem_mask, const handler_entry_read<Width, AddrShift> *const *dispatch)
+{
+ static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_level_to_lowbits(Level, Width, AddrShift);
+ return dispatch[(offset & mask) >> LowBits]->lookup_flags(offset, mem_mask);
+}
+
+
+template<int Level, int Width, int AddrShift> u16 dispatch_lookup_write_flags(offs_t mask, offs_t offset, emu::detail::handler_entry_size_t<Width> mem_mask, const handler_entry_write<Width, AddrShift> *const *dispatch)
+{
+ static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_level_to_lowbits(Level, Width, AddrShift);
+ return dispatch[(offset & mask) >> LowBits]->lookup_flags(offset, mem_mask);
+}
+
+
+
+template<int Level, int Width, int AddrShift> emu::detail::handler_entry_size_t<Width> dispatch_read_interruptible(offs_t mask, offs_t offset, emu::detail::handler_entry_size_t<Width> mem_mask, const handler_entry_read<Width, AddrShift> *const *dispatch)
+{
+ static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_level_to_lowbits(Level, Width, AddrShift);
+ return dispatch[(offset & mask) >> LowBits]->read_interruptible(offset, mem_mask);
+}
+
+
+template<int Level, int Width, int AddrShift> void dispatch_write_interruptible(offs_t mask, offs_t offset, emu::detail::handler_entry_size_t<Width> data, emu::detail::handler_entry_size_t<Width> mem_mask, const handler_entry_write<Width, AddrShift> *const *dispatch)
+{
+ static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_level_to_lowbits(Level, Width, AddrShift);
+ return dispatch[(offset & mask) >> LowBits]->write_interruptible(offset, data, mem_mask);
+}
+
+
// ======================> memory_access_specific
// memory_access_specific does uncached but faster accesses by shortcutting the address_space virtual call
-namespace emu { namespace detail {
+namespace emu::detail {
template<int Level, int Width, int AddrShift, endianness_t Endian> class memory_access_specific
{
friend class ::address_space;
- using NativeType = typename emu::detail::handler_entry_size<Width>::uX;
+ using NativeType = emu::detail::handler_entry_size_t<Width>;
static constexpr u32 NATIVE_BYTES = 1 << Width;
static constexpr u32 NATIVE_MASK = Width + AddrShift >= 0 ? (1 << (Width + AddrShift)) - 1 : 0;
@@ -1016,48 +1723,136 @@ public:
return *m_space;
}
- u8 read_byte(offs_t address) { return Width == 0 ? read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 0, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xff); }
- u16 read_word(offs_t address) { return Width == 1 ? read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 1, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffff); }
- u16 read_word(offs_t address, u16 mask) { return memory_read_generic<Width, AddrShift, Endian, 1, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
- u16 read_word_unaligned(offs_t address) { return memory_read_generic<Width, AddrShift, Endian, 1, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffff); }
- u16 read_word_unaligned(offs_t address, u16 mask) { return memory_read_generic<Width, AddrShift, Endian, 1, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
- u32 read_dword(offs_t address) { return Width == 2 ? read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 2, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffffffff); }
- u32 read_dword(offs_t address, u32 mask) { return memory_read_generic<Width, AddrShift, Endian, 2, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
- u32 read_dword_unaligned(offs_t address) { return memory_read_generic<Width, AddrShift, Endian, 2, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffffffff); }
- u32 read_dword_unaligned(offs_t address, u32 mask) { return memory_read_generic<Width, AddrShift, Endian, 2, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
- u64 read_qword(offs_t address) { return Width == 3 ? read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 3, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffffffffffffffffU); }
- u64 read_qword(offs_t address, u64 mask) { return memory_read_generic<Width, AddrShift, Endian, 3, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
- u64 read_qword_unaligned(offs_t address) { return memory_read_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffffffffffffffffU); }
- u64 read_qword_unaligned(offs_t address, u64 mask) { return memory_read_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
-
- void write_byte(offs_t address, u8 data) { if (Width == 0) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 0, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xff); }
- void write_word(offs_t address, u16 data) { if (Width == 1) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 1, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffff); }
- void write_word(offs_t address, u16 data, u16 mask) { memory_write_generic<Width, AddrShift, Endian, 1, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
- void write_word_unaligned(offs_t address, u16 data) { memory_write_generic<Width, AddrShift, Endian, 1, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffff); }
- void write_word_unaligned(offs_t address, u16 data, u16 mask) { memory_write_generic<Width, AddrShift, Endian, 1, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
- void write_dword(offs_t address, u32 data) { if (Width == 2) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 2, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffffffff); }
- void write_dword(offs_t address, u32 data, u32 mask) { memory_write_generic<Width, AddrShift, Endian, 2, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
- void write_dword_unaligned(offs_t address, u32 data) { memory_write_generic<Width, AddrShift, Endian, 2, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffffffff); }
- void write_dword_unaligned(offs_t address, u32 data, u32 mask) { memory_write_generic<Width, AddrShift, Endian, 2, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
- void write_qword(offs_t address, u64 data) { if (Width == 3) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 3, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffffffffffffffffU); }
- void write_qword(offs_t address, u64 data, u64 mask) { memory_write_generic<Width, AddrShift, Endian, 3, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
- void write_qword_unaligned(offs_t address, u64 data) { memory_write_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffffffffffffffffU); }
- void write_qword_unaligned(offs_t address, u64 data, u64 mask) { memory_write_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
+ auto rop() { return [this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }; }
+ auto ropf() { return [this](offs_t offset, NativeType mask) -> std::pair<NativeType, u16> { return read_native_flags(offset, mask); }; }
+ auto lropf() { return [this](offs_t offset, NativeType mask) -> u16 { return lookup_read_native_flags(offset, mask); }; }
+ auto wop() { return [this](offs_t offset, NativeType data, NativeType mask) -> void { write_native(offset, data, mask); }; }
+ auto wopf() { return [this](offs_t offset, NativeType data, NativeType mask) -> u16 { return write_native_flags(offset, data, mask); }; }
+ auto lwopf() { return [this](offs_t offset, NativeType mask) -> u16 { return lookup_write_native_flags(offset, mask); }; }
+
+ u8 read_byte(offs_t address) { if constexpr(Width == 0) return read_native(address & ~NATIVE_MASK); else return memory_read_generic<Width, AddrShift, Endian, 0, true>(rop(), address, 0xff); }
+ u16 read_word(offs_t address) { if constexpr(Width == 1) return read_native(address & ~NATIVE_MASK); else return memory_read_generic<Width, AddrShift, Endian, 1, true>(rop(), address, 0xffff); }
+ u16 read_word(offs_t address, u16 mask) { return memory_read_generic<Width, AddrShift, Endian, 1, true>(rop(), address, mask); }
+ u16 read_word_unaligned(offs_t address) { return memory_read_generic<Width, AddrShift, Endian, 1, false>(rop(), address, 0xffff); }
+ u16 read_word_unaligned(offs_t address, u16 mask) { return memory_read_generic<Width, AddrShift, Endian, 1, false>(rop(), address, mask); }
+ u32 read_dword(offs_t address) { if constexpr(Width == 2) return read_native(address & ~NATIVE_MASK); else return memory_read_generic<Width, AddrShift, Endian, 2, true>(rop(), address, 0xffffffff); }
+ u32 read_dword(offs_t address, u32 mask) { return memory_read_generic<Width, AddrShift, Endian, 2, true>(rop(), address, mask); }
+ u32 read_dword_unaligned(offs_t address) { return memory_read_generic<Width, AddrShift, Endian, 2, false>(rop(), address, 0xffffffff); }
+ u32 read_dword_unaligned(offs_t address, u32 mask) { return memory_read_generic<Width, AddrShift, Endian, 2, false>(rop(), address, mask); }
+ u64 read_qword(offs_t address) { if constexpr(Width == 3) return read_native(address & ~NATIVE_MASK); else return memory_read_generic<Width, AddrShift, Endian, 3, true>(rop(), address, 0xffffffffffffffffU); }
+ u64 read_qword(offs_t address, u64 mask) { return memory_read_generic<Width, AddrShift, Endian, 3, true>(rop(), address, mask); }
+ u64 read_qword_unaligned(offs_t address) { return memory_read_generic<Width, AddrShift, Endian, 3, false>(rop(), address, 0xffffffffffffffffU); }
+ u64 read_qword_unaligned(offs_t address, u64 mask) { return memory_read_generic<Width, AddrShift, Endian, 3, false>(rop(), address, mask); }
+
+ void write_byte(offs_t address, u8 data) { if constexpr(Width == 0) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 0, true>(wop(), address, data, 0xff); }
+ void write_word(offs_t address, u16 data) { if constexpr(Width == 1) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 1, true>(wop(), address, data, 0xffff); }
+ void write_word(offs_t address, u16 data, u16 mask) { memory_write_generic<Width, AddrShift, Endian, 1, true>(wop(), address, data, mask); }
+ void write_word_unaligned(offs_t address, u16 data) { memory_write_generic<Width, AddrShift, Endian, 1, false>(wop(), address, data, 0xffff); }
+ void write_word_unaligned(offs_t address, u16 data, u16 mask) { memory_write_generic<Width, AddrShift, Endian, 1, false>(wop(), address, data, mask); }
+ void write_dword(offs_t address, u32 data) { if constexpr(Width == 2) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 2, true>(wop(), address, data, 0xffffffff); }
+ void write_dword(offs_t address, u32 data, u32 mask) { memory_write_generic<Width, AddrShift, Endian, 2, true>(wop(), address, data, mask); }
+ void write_dword_unaligned(offs_t address, u32 data) { memory_write_generic<Width, AddrShift, Endian, 2, false>(wop(), address, data, 0xffffffff); }
+ void write_dword_unaligned(offs_t address, u32 data, u32 mask) { memory_write_generic<Width, AddrShift, Endian, 2, false>(wop(), address, data, mask); }
+ void write_qword(offs_t address, u64 data) { if constexpr(Width == 3) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 3, true>(wop(), address, data, 0xffffffffffffffffU); }
+ void write_qword(offs_t address, u64 data, u64 mask) { memory_write_generic<Width, AddrShift, Endian, 3, true>(wop(), address, data, mask); }
+ void write_qword_unaligned(offs_t address, u64 data) { memory_write_generic<Width, AddrShift, Endian, 3, false>(wop(), address, data, 0xffffffffffffffffU); }
+ void write_qword_unaligned(offs_t address, u64 data, u64 mask) { memory_write_generic<Width, AddrShift, Endian, 3, false>(wop(), address, data, mask); }
+
+
+ std::pair<u8, u16> read_byte_flags(offs_t address) { if constexpr(Width == 0) return read_native_flags(address & ~NATIVE_MASK); else return memory_read_generic_flags<Width, AddrShift, Endian, 0, true>(ropf(), address, 0xff); }
+ std::pair<u16, u16> read_word_flags(offs_t address) { if constexpr(Width == 1) return read_native_flags(address & ~NATIVE_MASK); else return memory_read_generic_flags<Width, AddrShift, Endian, 1, true>(ropf(), address, 0xffff); }
+ std::pair<u16, u16> read_word_flags(offs_t address, u16 mask) { return memory_read_generic_flags<Width, AddrShift, Endian, 1, true>(ropf(), address, mask); }
+ std::pair<u16, u16> read_word_unaligned_flags(offs_t address) { return memory_read_generic_flags<Width, AddrShift, Endian, 1, false>(ropf(), address, 0xffff); }
+ std::pair<u16, u16> read_word_unaligned_flags(offs_t address, u16 mask) { return memory_read_generic_flags<Width, AddrShift, Endian, 1, false>(ropf(), address, mask); }
+ std::pair<u32, u16> read_dword_flags(offs_t address) { if constexpr(Width == 2) return read_native_flags(address & ~NATIVE_MASK); else return memory_read_generic_flags<Width, AddrShift, Endian, 2, true>(ropf(), address, 0xffffffff); }
+ std::pair<u32, u16> read_dword_flags(offs_t address, u32 mask) { return memory_read_generic_flags<Width, AddrShift, Endian, 2, true>(ropf(), address, mask); }
+ std::pair<u32, u16> read_dword_unaligned_flags(offs_t address) { return memory_read_generic_flags<Width, AddrShift, Endian, 2, false>(ropf(), address, 0xffffffff); }
+ std::pair<u32, u16> read_dword_unaligned_flags(offs_t address, u32 mask) { return memory_read_generic_flags<Width, AddrShift, Endian, 2, false>(ropf(), address, mask); }
+ std::pair<u64, u16> read_qword_flags(offs_t address) { if constexpr(Width == 3) return read_native_flags(address & ~NATIVE_MASK); else return memory_read_generic_flags<Width, AddrShift, Endian, 3, true>(ropf(), address, 0xffffffffffffffffU); }
+ std::pair<u64, u16> read_qword_flags(offs_t address, u64 mask) { return memory_read_generic_flags<Width, AddrShift, Endian, 3, true>(ropf(), address, mask); }
+ std::pair<u64, u16> read_qword_unaligned_flags(offs_t address) { return memory_read_generic_flags<Width, AddrShift, Endian, 3, false>(ropf(), address, 0xffffffffffffffffU); }
+ std::pair<u64, u16> read_qword_unaligned_flags(offs_t address, u64 mask) { return memory_read_generic_flags<Width, AddrShift, Endian, 3, false>(ropf(), address, mask); }
+
+ u16 write_byte_flags(offs_t address, u8 data) { if constexpr(Width == 0) return write_native_flags(address & ~NATIVE_MASK, data); else return memory_write_generic_flags<Width, AddrShift, Endian, 0, true>(wopf(), address, data, 0xff); }
+ u16 write_word_flags(offs_t address, u16 data) { if constexpr(Width == 1) return write_native_flags(address & ~NATIVE_MASK, data); else return memory_write_generic_flags<Width, AddrShift, Endian, 1, true>(wopf(), address, data, 0xffff); }
+ u16 write_word_flags(offs_t address, u16 data, u16 mask) { return memory_write_generic_flags<Width, AddrShift, Endian, 1, true>(wopf(), address, data, mask); }
+ u16 write_word_unaligned_flags(offs_t address, u16 data) { return memory_write_generic_flags<Width, AddrShift, Endian, 1, false>(wopf(), address, data, 0xffff); }
+ u16 write_word_unaligned_flags(offs_t address, u16 data, u16 mask) { return memory_write_generic_flags<Width, AddrShift, Endian, 1, false>(wopf(), address, data, mask); }
+ u16 write_dword_flags(offs_t address, u32 data) { if constexpr(Width == 2) return write_native_flags(address & ~NATIVE_MASK, data); else return memory_write_generic_flags<Width, AddrShift, Endian, 2, true>(wopf(), address, data, 0xffffffff); }
+ u16 write_dword_flags(offs_t address, u32 data, u32 mask) { return memory_write_generic_flags<Width, AddrShift, Endian, 2, true>(wopf(), address, data, mask); }
+ u16 write_dword_unaligned_flags(offs_t address, u32 data) { return memory_write_generic_flags<Width, AddrShift, Endian, 2, false>(wopf(), address, data, 0xffffffff); }
+ u16 write_dword_unaligned_flags(offs_t address, u32 data, u32 mask) { return memory_write_generic_flags<Width, AddrShift, Endian, 2, false>(wopf(), address, data, mask); }
+ u16 write_qword_flags(offs_t address, u64 data) { if constexpr(Width == 3) return write_native_flags(address & ~NATIVE_MASK, data); else return memory_write_generic_flags<Width, AddrShift, Endian, 3, true>(wopf(), address, data, 0xffffffffffffffffU); }
+ u16 write_qword_flags(offs_t address, u64 data, u64 mask) { return memory_write_generic_flags<Width, AddrShift, Endian, 3, true>(wop(), address, data, mask); }
+ u16 write_qword_unaligned_flags(offs_t address, u64 data) { return memory_write_generic_flags<Width, AddrShift, Endian, 3, false>(wopf(), address, data, 0xffffffffffffffffU); }
+ u16 write_qword_unaligned_flags(offs_t address, u64 data, u64 mask) { return memory_write_generic_flags<Width, AddrShift, Endian, 3, false>(wopf(), address, data, mask); }
+
+ u16 lookup_read_byte_flags(offs_t address) { if constexpr(Width == 0) return lookup_read_native_flags(address & ~NATIVE_MASK); else return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 0, true>(lropf(), address, 0xff); }
+ u16 lookup_read_word_flags(offs_t address) { if constexpr(Width == 1) return lookup_read_native_flags(address & ~NATIVE_MASK); else return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 1, true>(lropf(), address, 0xffff); }
+ u16 lookup_read_word_flags(offs_t address, u16 mask) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 1, true>(lropf(), address, mask); }
+ u16 lookup_read_word_unaligned_flags(offs_t address) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 1, false>(lropf(), address, 0xffff); }
+ u16 lookup_read_word_unaligned_flags(offs_t address, u16 mask) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 1, false>(lropf(), address, mask); }
+ u16 lookup_read_dword_flags(offs_t address) { if constexpr(Width == 2) return lookup_read_native_flags(address & ~NATIVE_MASK); else return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 2, true>(lropf(), address, 0xffffffff); }
+ u16 lookup_read_dword_flags(offs_t address, u32 mask) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 2, true>(lropf(), address, mask); }
+ u16 lookup_read_dword_unaligned_flags(offs_t address) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 2, false>(lropf(), address, 0xffffffff); }
+ u16 lookup_read_dword_unaligned_flags(offs_t address, u32 mask) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 2, false>(lropf(), address, mask); }
+ u16 lookup_read_qword_flags(offs_t address) { if constexpr(Width == 3) return lookup_read_native_flags(address & ~NATIVE_MASK); else return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 3, true>(lropf(), address, 0xffffffffffffffffU); }
+ u16 lookup_read_qword_flags(offs_t address, u64 mask) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 3, true>(lropf(), address, mask); }
+ u16 lookup_read_qword_unaligned_flags(offs_t address) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 3, false>(lropf(), address, 0xffffffffffffffffU); }
+ u16 lookup_read_qword_unaligned_flags(offs_t address, u64 mask) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 3, false>(lropf(), address, mask); }
+
+ u16 lookup_write_byte_flags(offs_t address) { if constexpr(Width == 0) return lookup_write_native_flags(address & ~NATIVE_MASK); else return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 0, true>(lwopf(), address, 0xff); }
+ u16 lookup_write_word_flags(offs_t address) { if constexpr(Width == 1) return lookup_write_native_flags(address & ~NATIVE_MASK); else return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 1, true>(lwopf(), address, 0xffff); }
+ u16 lookup_write_word_flags(offs_t address, u16 mask) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 1, true>(lwopf(), address, mask); }
+ u16 lookup_write_word_unaligned_flags(offs_t address) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 1, false>(lwopf(), address, 0xffff); }
+ u16 lookup_write_word_unaligned_flags(offs_t address, u16 mask) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 1, false>(lwopf(), address, mask); }
+ u16 lookup_write_dword_flags(offs_t address) { if constexpr(Width == 2) return lookup_write_native_flags(address & ~NATIVE_MASK); else return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 2, true>(lwopf(), address, 0xffffffff); }
+ u16 lookup_write_dword_flags(offs_t address, u32 mask) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 2, true>(lwopf(), address, mask); }
+ u16 lookup_write_dword_unaligned_flags(offs_t address) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 2, false>(lwopf(), address, 0xffffffff); }
+ u16 lookup_write_dword_unaligned_flags(offs_t address, u32 mask) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 2, false>(lwopf(), address, mask); }
+ u16 lookup_write_qword_flags(offs_t address) { if constexpr(Width == 3) return lookup_write_native_flags(address & ~NATIVE_MASK); else return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 3, true>(lwopf(), address, 0xffffffffffffffffU); }
+ u16 lookup_write_qword_flags(offs_t address, u64 mask) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 3, true>(wop(), address, mask); }
+ u16 lookup_write_qword_unaligned_flags(offs_t address) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 3, false>(lwopf(), address, 0xffffffffffffffffU); }
+ u16 lookup_write_qword_unaligned_flags(offs_t address, u64 mask) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 3, false>(lwopf(), address, mask); }
+
+ NativeType read_interruptible(offs_t address, NativeType mask = ~NativeType(0)) {
+ return dispatch_read_interruptible<Level, Width, AddrShift>(offs_t(-1), address & m_addrmask, mask, m_dispatch_read);
+ }
+
+ void write_interruptible(offs_t address, NativeType data, NativeType mask = ~NativeType(0)) {
+ dispatch_write_interruptible<Level, Width, AddrShift>(offs_t(-1), address & m_addrmask, data, mask, m_dispatch_write);
+ }
private:
address_space * m_space;
offs_t m_addrmask; // address mask
- const handler_entry_read<Width, AddrShift, Endian> *const *m_dispatch_read;
- const handler_entry_write<Width, AddrShift, Endian> *const *m_dispatch_write;
+ const handler_entry_read<Width, AddrShift> *const *m_dispatch_read;
+ const handler_entry_write<Width, AddrShift> *const *m_dispatch_write;
NativeType read_native(offs_t address, NativeType mask = ~NativeType(0)) {
- return dispatch_read<Level, Width, AddrShift, Endian>(offs_t(-1), address & m_addrmask, mask, m_dispatch_read);;
+ return dispatch_read<Level, Width, AddrShift>(offs_t(-1), address & m_addrmask, mask, m_dispatch_read);
}
void write_native(offs_t address, NativeType data, NativeType mask = ~NativeType(0)) {
- dispatch_write<Level, Width, AddrShift, Endian>(offs_t(-1), address & m_addrmask, data, mask, m_dispatch_write);;
+ dispatch_write<Level, Width, AddrShift>(offs_t(-1), address & m_addrmask, data, mask, m_dispatch_write);
+ }
+
+ std::pair<NativeType, u16> read_native_flags(offs_t address, NativeType mask = ~NativeType(0)) {
+ return dispatch_read_flags<Level, Width, AddrShift>(offs_t(-1), address & m_addrmask, mask, m_dispatch_read);
+ }
+
+ u16 write_native_flags(offs_t address, NativeType data, NativeType mask = ~NativeType(0)) {
+ return dispatch_write_flags<Level, Width, AddrShift>(offs_t(-1), address & m_addrmask, data, mask, m_dispatch_write);
+ }
+
+ u16 lookup_read_native_flags(offs_t address, NativeType mask = ~NativeType(0)) {
+ return dispatch_lookup_read_flags<Level, Width, AddrShift>(offs_t(-1), address & m_addrmask, mask, m_dispatch_read);
+ }
+
+ u16 lookup_write_native_flags(offs_t address, NativeType mask = ~NativeType(0)) {
+ return dispatch_lookup_write_flags<Level, Width, AddrShift>(offs_t(-1), address & m_addrmask, mask, m_dispatch_write);
}
void set(address_space *space, std::pair<const void *, const void *> rw);
@@ -1072,7 +1867,7 @@ template<int Width, int AddrShift, endianness_t Endian> class memory_access_cach
{
friend class ::address_space;
- using NativeType = typename emu::detail::handler_entry_size<Width>::uX;
+ using NativeType = emu::detail::handler_entry_size_t<Width>;
static constexpr u32 NATIVE_BYTES = 1 << Width;
static constexpr u32 NATIVE_MASK = Width + AddrShift >= 0 ? (1 << (Width + AddrShift)) - 1 : 0;
@@ -1119,33 +1914,98 @@ public:
return m_cache_r->get_ptr(address);
}
- u8 read_byte(offs_t address) { return Width == 0 ? read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 0, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xff); }
- u16 read_word(offs_t address) { return Width == 1 ? read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 1, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffff); }
- u16 read_word(offs_t address, u16 mask) { return memory_read_generic<Width, AddrShift, Endian, 1, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
- u16 read_word_unaligned(offs_t address) { return memory_read_generic<Width, AddrShift, Endian, 1, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffff); }
- u16 read_word_unaligned(offs_t address, u16 mask) { return memory_read_generic<Width, AddrShift, Endian, 1, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
- u32 read_dword(offs_t address) { return Width == 2 ? read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 2, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffffffff); }
- u32 read_dword(offs_t address, u32 mask) { return memory_read_generic<Width, AddrShift, Endian, 2, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
- u32 read_dword_unaligned(offs_t address) { return memory_read_generic<Width, AddrShift, Endian, 2, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffffffff); }
- u32 read_dword_unaligned(offs_t address, u32 mask) { return memory_read_generic<Width, AddrShift, Endian, 2, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
- u64 read_qword(offs_t address) { return Width == 3 ? read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 3, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffffffffffffffffU); }
- u64 read_qword(offs_t address, u64 mask) { return memory_read_generic<Width, AddrShift, Endian, 3, true>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
- u64 read_qword_unaligned(offs_t address) { return memory_read_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, 0xffffffffffffffffU); }
- u64 read_qword_unaligned(offs_t address, u64 mask) { return memory_read_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }, address, mask); }
-
- void write_byte(offs_t address, u8 data) { if (Width == 0) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 0, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xff); }
- void write_word(offs_t address, u16 data) { if (Width == 1) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 1, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffff); }
- void write_word(offs_t address, u16 data, u16 mask) { memory_write_generic<Width, AddrShift, Endian, 1, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
- void write_word_unaligned(offs_t address, u16 data) { memory_write_generic<Width, AddrShift, Endian, 1, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffff); }
- void write_word_unaligned(offs_t address, u16 data, u16 mask) { memory_write_generic<Width, AddrShift, Endian, 1, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
- void write_dword(offs_t address, u32 data) { if (Width == 2) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 2, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffffffff); }
- void write_dword(offs_t address, u32 data, u32 mask) { memory_write_generic<Width, AddrShift, Endian, 2, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
- void write_dword_unaligned(offs_t address, u32 data) { memory_write_generic<Width, AddrShift, Endian, 2, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffffffff); }
- void write_dword_unaligned(offs_t address, u32 data, u32 mask) { memory_write_generic<Width, AddrShift, Endian, 2, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
- void write_qword(offs_t address, u64 data) { if (Width == 3) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 3, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffffffffffffffffU); }
- void write_qword(offs_t address, u64 data, u64 mask) { memory_write_generic<Width, AddrShift, Endian, 3, true>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
- void write_qword_unaligned(offs_t address, u64 data) { memory_write_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, 0xffffffffffffffffU); }
- void write_qword_unaligned(offs_t address, u64 data, u64 mask) { memory_write_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
+ auto rop() { return [this](offs_t offset, NativeType mask) -> NativeType { return read_native(offset, mask); }; }
+ auto ropf() { return [this](offs_t offset, NativeType mask) -> std::pair<NativeType, u16> { return read_native_flags(offset, mask); }; }
+ auto lropf() { return [this](offs_t offset, NativeType mask) -> u16 { return lookup_read_native_flags(offset, mask); }; }
+ auto wop() { return [this](offs_t offset, NativeType data, NativeType mask) -> void { write_native(offset, data, mask); }; }
+ auto wopf() { return [this](offs_t offset, NativeType data, NativeType mask) -> u16 { return write_native_flags(offset, data, mask); }; }
+ auto lwopf() { return [this](offs_t offset, NativeType mask) -> u16 { return lookup_write_native_flags(offset, mask); }; }
+
+ u8 read_byte(offs_t address) { if constexpr(Width == 0) return read_native(address & ~NATIVE_MASK); else return memory_read_generic<Width, AddrShift, Endian, 0, true>(rop(), address, 0xff); }
+ u16 read_word(offs_t address) { if constexpr(Width == 1) return read_native(address & ~NATIVE_MASK); else return memory_read_generic<Width, AddrShift, Endian, 1, true>(rop(), address, 0xffff); }
+ u16 read_word(offs_t address, u16 mask) { return memory_read_generic<Width, AddrShift, Endian, 1, true>(rop(), address, mask); }
+ u16 read_word_unaligned(offs_t address) { return memory_read_generic<Width, AddrShift, Endian, 1, false>(rop(), address, 0xffff); }
+ u16 read_word_unaligned(offs_t address, u16 mask) { return memory_read_generic<Width, AddrShift, Endian, 1, false>(rop(), address, mask); }
+ u32 read_dword(offs_t address) { if constexpr(Width == 2) return read_native(address & ~NATIVE_MASK); else return memory_read_generic<Width, AddrShift, Endian, 2, true>(rop(), address, 0xffffffff); }
+ u32 read_dword(offs_t address, u32 mask) { return memory_read_generic<Width, AddrShift, Endian, 2, true>(rop(), address, mask); }
+ u32 read_dword_unaligned(offs_t address) { return memory_read_generic<Width, AddrShift, Endian, 2, false>(rop(), address, 0xffffffff); }
+ u32 read_dword_unaligned(offs_t address, u32 mask) { return memory_read_generic<Width, AddrShift, Endian, 2, false>(rop(), address, mask); }
+ u64 read_qword(offs_t address) { if constexpr(Width == 3) return read_native(address & ~NATIVE_MASK); else return memory_read_generic<Width, AddrShift, Endian, 3, true>(rop(), address, 0xffffffffffffffffU); }
+ u64 read_qword(offs_t address, u64 mask) { return memory_read_generic<Width, AddrShift, Endian, 3, true>(rop(), address, mask); }
+ u64 read_qword_unaligned(offs_t address) { return memory_read_generic<Width, AddrShift, Endian, 3, false>(rop(), address, 0xffffffffffffffffU); }
+ u64 read_qword_unaligned(offs_t address, u64 mask) { return memory_read_generic<Width, AddrShift, Endian, 3, false>(rop(), address, mask); }
+
+ void write_byte(offs_t address, u8 data) { if constexpr(Width == 0) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 0, true>(wop(), address, data, 0xff); }
+ void write_word(offs_t address, u16 data) { if constexpr(Width == 1) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 1, true>(wop(), address, data, 0xffff); }
+ void write_word(offs_t address, u16 data, u16 mask) { memory_write_generic<Width, AddrShift, Endian, 1, true>(wop(), address, data, mask); }
+ void write_word_unaligned(offs_t address, u16 data) { memory_write_generic<Width, AddrShift, Endian, 1, false>(wop(), address, data, 0xffff); }
+ void write_word_unaligned(offs_t address, u16 data, u16 mask) { memory_write_generic<Width, AddrShift, Endian, 1, false>(wop(), address, data, mask); }
+ void write_dword(offs_t address, u32 data) { if constexpr(Width == 2) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 2, true>(wop(), address, data, 0xffffffff); }
+ void write_dword(offs_t address, u32 data, u32 mask) { memory_write_generic<Width, AddrShift, Endian, 2, true>(wop(), address, data, mask); }
+ void write_dword_unaligned(offs_t address, u32 data) { memory_write_generic<Width, AddrShift, Endian, 2, false>(wop(), address, data, 0xffffffff); }
+ void write_dword_unaligned(offs_t address, u32 data, u32 mask) { memory_write_generic<Width, AddrShift, Endian, 2, false>(wop(), address, data, mask); }
+ void write_qword(offs_t address, u64 data) { if constexpr(Width == 3) write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 3, true>(wop(), address, data, 0xffffffffffffffffU); }
+ void write_qword(offs_t address, u64 data, u64 mask) { memory_write_generic<Width, AddrShift, Endian, 3, true>(wop(), address, data, mask); }
+ void write_qword_unaligned(offs_t address, u64 data) { memory_write_generic<Width, AddrShift, Endian, 3, false>(wop(), address, data, 0xffffffffffffffffU); }
+ void write_qword_unaligned(offs_t address, u64 data, u64 mask) { memory_write_generic<Width, AddrShift, Endian, 3, false>(wop(), address, data, mask); }
+
+
+ std::pair<u8, u16> read_byte_flags(offs_t address) { if constexpr(Width == 0) return read_native_flags(address & ~NATIVE_MASK); else return memory_read_generic_flags<Width, AddrShift, Endian, 0, true>(ropf(), address, 0xff); }
+ std::pair<u16, u16> read_word_flags(offs_t address) { if constexpr(Width == 1) return read_native_flags(address & ~NATIVE_MASK); else return memory_read_generic_flags<Width, AddrShift, Endian, 1, true>(ropf(), address, 0xffff); }
+ std::pair<u16, u16> read_word_flags(offs_t address, u16 mask) { return memory_read_generic_flags<Width, AddrShift, Endian, 1, true>(ropf(), address, mask); }
+ std::pair<u16, u16> read_word_unaligned_flags(offs_t address) { return memory_read_generic_flags<Width, AddrShift, Endian, 1, false>(ropf(), address, 0xffff); }
+ std::pair<u16, u16> read_word_unaligned_flags(offs_t address, u16 mask) { return memory_read_generic_flags<Width, AddrShift, Endian, 1, false>(ropf(), address, mask); }
+ std::pair<u32, u16> read_dword_flags(offs_t address) { if constexpr(Width == 2) return read_native_flags(address & ~NATIVE_MASK); else return memory_read_generic_flags<Width, AddrShift, Endian, 2, true>(ropf(), address, 0xffffffff); }
+ std::pair<u32, u16> read_dword_flags(offs_t address, u32 mask) { return memory_read_generic_flags<Width, AddrShift, Endian, 2, true>(ropf(), address, mask); }
+ std::pair<u32, u16> read_dword_unaligned_flags(offs_t address) { return memory_read_generic_flags<Width, AddrShift, Endian, 2, false>(ropf(), address, 0xffffffff); }
+ std::pair<u32, u16> read_dword_unaligned_flags(offs_t address, u32 mask) { return memory_read_generic_flags<Width, AddrShift, Endian, 2, false>(ropf(), address, mask); }
+ std::pair<u64, u16> read_qword_flags(offs_t address) { if constexpr(Width == 3) return read_native_flags(address & ~NATIVE_MASK); else return memory_read_generic_flags<Width, AddrShift, Endian, 3, true>(ropf(), address, 0xffffffffffffffffU); }
+ std::pair<u64, u16> read_qword_flags(offs_t address, u64 mask) { return memory_read_generic_flags<Width, AddrShift, Endian, 3, true>(ropf(), address, mask); }
+ std::pair<u64, u16> read_qword_unaligned_flags(offs_t address) { return memory_read_generic_flags<Width, AddrShift, Endian, 3, false>(ropf(), address, 0xffffffffffffffffU); }
+ std::pair<u64, u16> read_qword_unaligned_flags(offs_t address, u64 mask) { return memory_read_generic_flags<Width, AddrShift, Endian, 3, false>(ropf(), address, mask); }
+
+ u16 write_byte_flags(offs_t address, u8 data) { if constexpr(Width == 0) return write_native_flags(address & ~NATIVE_MASK, data); else return memory_write_generic_flags<Width, AddrShift, Endian, 0, true>(wopf(), address, data, 0xff); }
+ u16 write_word_flags(offs_t address, u16 data) { if constexpr(Width == 1) return write_native_flags(address & ~NATIVE_MASK, data); else return memory_write_generic_flags<Width, AddrShift, Endian, 1, true>(wopf(), address, data, 0xffff); }
+ u16 write_word_flags(offs_t address, u16 data, u16 mask) { return memory_write_generic_flags<Width, AddrShift, Endian, 1, true>(wopf(), address, data, mask); }
+ u16 write_word_unaligned_flags(offs_t address, u16 data) { return memory_write_generic_flags<Width, AddrShift, Endian, 1, false>(wopf(), address, data, 0xffff); }
+ u16 write_word_unaligned_flags(offs_t address, u16 data, u16 mask) { return memory_write_generic_flags<Width, AddrShift, Endian, 1, false>(wopf(), address, data, mask); }
+ u16 write_dword_flags(offs_t address, u32 data) { if constexpr(Width == 2) return write_native_flags(address & ~NATIVE_MASK, data); else return memory_write_generic_flags<Width, AddrShift, Endian, 2, true>(wopf(), address, data, 0xffffffff); }
+ u16 write_dword_flags(offs_t address, u32 data, u32 mask) { return memory_write_generic_flags<Width, AddrShift, Endian, 2, true>(wopf(), address, data, mask); }
+ u16 write_dword_unaligned_flags(offs_t address, u32 data) { return memory_write_generic_flags<Width, AddrShift, Endian, 2, false>(wopf(), address, data, 0xffffffff); }
+ u16 write_dword_unaligned_flags(offs_t address, u32 data, u32 mask) { return memory_write_generic_flags<Width, AddrShift, Endian, 2, false>(wopf(), address, data, mask); }
+ u16 write_qword_flags(offs_t address, u64 data) { if constexpr(Width == 3) return write_native_flags(address & ~NATIVE_MASK, data); else return memory_write_generic_flags<Width, AddrShift, Endian, 3, true>(wopf(), address, data, 0xffffffffffffffffU); }
+ u16 write_qword_flags(offs_t address, u64 data, u64 mask) { return memory_write_generic_flags<Width, AddrShift, Endian, 3, true>(wop(), address, data, mask); }
+ u16 write_qword_unaligned_flags(offs_t address, u64 data) { return memory_write_generic_flags<Width, AddrShift, Endian, 3, false>(wopf(), address, data, 0xffffffffffffffffU); }
+ u16 write_qword_unaligned_flags(offs_t address, u64 data, u64 mask) { return memory_write_generic_flags<Width, AddrShift, Endian, 3, false>(wopf(), address, data, mask); }
+
+
+ u16 lookup_read_byte_flags(offs_t address) { if constexpr(Width == 0) return lookup_read_native_flags(address & ~NATIVE_MASK); else return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 0, true>(lropf(), address, 0xff); }
+ u16 lookup_read_word_flags(offs_t address) { if constexpr(Width == 1) return lookup_read_native_flags(address & ~NATIVE_MASK); else return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 1, true>(lropf(), address, 0xffff); }
+ u16 lookup_read_word_flags(offs_t address, u16 mask) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 1, true>(lropf(), address, mask); }
+ u16 lookup_read_word_unaligned_flags(offs_t address) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 1, false>(lropf(), address, 0xffff); }
+ u16 lookup_read_word_unaligned_flags(offs_t address, u16 mask) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 1, false>(lropf(), address, mask); }
+ u16 lookup_read_dword_flags(offs_t address) { if constexpr(Width == 2) return lookup_read_native_flags(address & ~NATIVE_MASK); else return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 2, true>(lropf(), address, 0xffffffff); }
+ u16 lookup_read_dword_flags(offs_t address, u32 mask) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 2, true>(lropf(), address, mask); }
+ u16 lookup_read_dword_unaligned_flags(offs_t address) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 2, false>(lropf(), address, 0xffffffff); }
+ u16 lookup_read_dword_unaligned_flags(offs_t address, u32 mask) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 2, false>(lropf(), address, mask); }
+ u16 lookup_read_qword_flags(offs_t address) { if constexpr(Width == 3) return lookup_read_native_flags(address & ~NATIVE_MASK); else return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 3, true>(lropf(), address, 0xffffffffffffffffU); }
+ u16 lookup_read_qword_flags(offs_t address, u64 mask) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 3, true>(lropf(), address, mask); }
+ u16 lookup_read_qword_unaligned_flags(offs_t address) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 3, false>(lropf(), address, 0xffffffffffffffffU); }
+ u16 lookup_read_qword_unaligned_flags(offs_t address, u64 mask) { return lookup_memory_read_generic_flags<Width, AddrShift, Endian, 3, false>(lropf(), address, mask); }
+
+ u16 lookup_write_byte_flags(offs_t address) { if constexpr(Width == 0) return lookup_write_native_flags(address & ~NATIVE_MASK); else return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 0, true>(lwopf(), address, 0xff); }
+ u16 lookup_write_word_flags(offs_t address) { if constexpr(Width == 1) return lookup_write_native_flags(address & ~NATIVE_MASK); else return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 1, true>(lwopf(), address, 0xffff); }
+ u16 lookup_write_word_flags(offs_t address, u16 mask) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 1, true>(lwopf(), address, mask); }
+ u16 lookup_write_word_unaligned_flags(offs_t address) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 1, false>(lwopf(), address, 0xffff); }
+ u16 lookup_write_word_unaligned_flags(offs_t address, u16 mask) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 1, false>(lwopf(), address, mask); }
+ u16 lookup_write_dword_flags(offs_t address) { if constexpr(Width == 2) return lookup_write_native_flags(address & ~NATIVE_MASK); else return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 2, true>(lwopf(), address, 0xffffffff); }
+ u16 lookup_write_dword_flags(offs_t address, u32 mask) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 2, true>(lwopf(), address, mask); }
+ u16 lookup_write_dword_unaligned_flags(offs_t address) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 2, false>(lwopf(), address, 0xffffffff); }
+ u16 lookup_write_dword_unaligned_flags(offs_t address, u32 mask) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 2, false>(lwopf(), address, mask); }
+ u16 lookup_write_qword_flags(offs_t address) { if constexpr(Width == 3) return lookup_write_native_flags(address & ~NATIVE_MASK); else return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 3, true>(lwopf(), address, 0xffffffffffffffffU); }
+ u16 lookup_write_qword_flags(offs_t address, u64 mask) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 3, true>(wop(), address, mask); }
+ u16 lookup_write_qword_unaligned_flags(offs_t address) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 3, false>(lwopf(), address, 0xffffffffffffffffU); }
+ u16 lookup_write_qword_unaligned_flags(offs_t address, u64 mask) { return lookup_memory_write_generic_flags<Width, AddrShift, Endian, 3, false>(lwopf(), address, mask); }
private:
address_space * m_space;
@@ -1155,18 +2015,25 @@ private:
offs_t m_addrend_r; // maximum valid address for reading
offs_t m_addrstart_w; // minimum valid address for writing
offs_t m_addrend_w; // maximum valid address for writing
- handler_entry_read <Width, AddrShift, Endian> *m_cache_r; // read cache
- handler_entry_write<Width, AddrShift, Endian> *m_cache_w; // write cache
+ handler_entry_read <Width, AddrShift> *m_cache_r; // read cache
+ handler_entry_write<Width, AddrShift> *m_cache_w; // write cache
+
+ handler_entry_read <Width, AddrShift> *m_root_read; // decode tree roots
+ handler_entry_write<Width, AddrShift> *m_root_write;
- handler_entry_read <Width, AddrShift, Endian> *m_root_read; // decode tree roots
- handler_entry_write<Width, AddrShift, Endian> *m_root_write;
+ util::notifier_subscription m_subscription;
NativeType read_native(offs_t address, NativeType mask = ~NativeType(0));
void write_native(offs_t address, NativeType data, NativeType mask = ~NativeType(0));
+ std::pair<NativeType, u16> read_native_flags(offs_t address, NativeType mask = ~NativeType(0));
+ u16 write_native_flags(offs_t address, NativeType data, NativeType mask = ~NativeType(0));
+ u16 lookup_read_native_flags(offs_t address, NativeType mask = ~NativeType(0));
+ u16 lookup_write_native_flags(offs_t address, NativeType mask = ~NativeType(0));
void set(address_space *space, std::pair<void *, void *> rw);
};
-}}
+
+} // namespace emu::detail
// ======================> memory_access cache/specific type dispatcher
@@ -1230,18 +2097,246 @@ public:
// ======================> address_space
+class address_space_installer {
+public:
+ const address_space_config &space_config() const { return m_config; }
+ int data_width() const { return m_config.data_width(); }
+ int addr_width() const { return m_config.addr_width(); }
+ int logaddr_width() const { return m_config.logaddr_width(); }
+ int alignment() const { return m_config.alignment(); }
+ endianness_t endianness() const { return m_config.endianness(); }
+ int addr_shift() const { return m_config.addr_shift(); }
+ bool is_octal() const { return m_config.is_octal(); }
+
+ // address-to-byte conversion helpers
+ offs_t address_to_byte(offs_t address) const { return m_config.addr2byte(address); }
+ offs_t address_to_byte_end(offs_t address) const { return m_config.addr2byte_end(address); }
+ offs_t byte_to_address(offs_t address) const { return m_config.byte2addr(address); }
+ offs_t byte_to_address_end(offs_t address) const { return m_config.byte2addr_end(address); }
+
+ offs_t addrmask() const { return m_addrmask; }
+ u8 addrchars() const { return m_addrchars; }
+ offs_t logaddrmask() const { return m_logaddrmask; }
+ u8 logaddrchars() const { return m_logaddrchars; }
+
+ // unmap ranges (short form)
+ void unmap_read(offs_t addrstart, offs_t addrend, offs_t addrmirror = 0, u16 flags = 0) { unmap_generic(addrstart, addrend, addrmirror, flags, read_or_write::READ, false); }
+ void unmap_write(offs_t addrstart, offs_t addrend, offs_t addrmirror = 0, u16 flags = 0) { unmap_generic(addrstart, addrend, addrmirror, flags, read_or_write::WRITE, false); }
+ void unmap_readwrite(offs_t addrstart, offs_t addrend, offs_t addrmirror = 0, u16 flags = 0) { unmap_generic(addrstart, addrend, addrmirror, flags, read_or_write::READWRITE, false); }
+ void nop_read(offs_t addrstart, offs_t addrend, offs_t addrmirror = 0, u16 flags = 0) { unmap_generic(addrstart, addrend, addrmirror, flags, read_or_write::READ, true); }
+ void nop_write(offs_t addrstart, offs_t addrend, offs_t addrmirror = 0, u16 flags = 0) { unmap_generic(addrstart, addrend, addrmirror, flags, read_or_write::WRITE, true); }
+ void nop_readwrite(offs_t addrstart, offs_t addrend, offs_t addrmirror = 0, u16 flags = 0) { unmap_generic(addrstart, addrend, addrmirror, flags, read_or_write::READWRITE, true); }
+
+ // install ports, banks, RAM (short form)
+ void install_read_port(offs_t addrstart, offs_t addrend, const char *rtag) { install_read_port(addrstart, addrend, 0, 0, rtag); }
+ void install_write_port(offs_t addrstart, offs_t addrend, const char *wtag) { install_write_port(addrstart, addrend, 0, 0, wtag); }
+ void install_readwrite_port(offs_t addrstart, offs_t addrend, const char *rtag, const char *wtag) { install_readwrite_port(addrstart, addrend, 0, 0, rtag, wtag); }
+ void install_read_bank(offs_t addrstart, offs_t addrend, memory_bank *bank) { install_read_bank(addrstart, addrend, 0, 0, bank); }
+ void install_write_bank(offs_t addrstart, offs_t addrend, memory_bank *bank) { install_write_bank(addrstart, addrend, 0, 0, bank); }
+ void install_readwrite_bank(offs_t addrstart, offs_t addrend, memory_bank *bank) { install_readwrite_bank(addrstart, addrend, 0, 0, bank); }
+ void install_rom(offs_t addrstart, offs_t addrend, void *baseptr) { install_rom(addrstart, addrend, 0, 0, baseptr); }
+ void install_writeonly(offs_t addrstart, offs_t addrend, void *baseptr) { install_writeonly(addrstart, addrend, 0, 0, baseptr); }
+ void install_ram(offs_t addrstart, offs_t addrend, void *baseptr) { install_ram(addrstart, addrend, 0, 0, baseptr); }
+
+ // install ports, banks, RAM (with mirror/mask)
+ void install_read_port(offs_t addrstart, offs_t addrend, offs_t addrmirror, const char *rtag) { install_readwrite_port(addrstart, addrend, addrmirror, 0, rtag, ""); }
+ void install_write_port(offs_t addrstart, offs_t addrend, offs_t addrmirror, const char *wtag) { install_readwrite_port(addrstart, addrend, addrmirror, 0, "", wtag); }
+ void install_readwrite_port(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string rtag, std::string wtag) { install_readwrite_port(addrstart, addrend, addrmirror, 0, rtag, wtag); }
+ void install_read_bank(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_bank *bank) { install_bank_generic(addrstart, addrend, addrmirror, 0, bank, nullptr); }
+ void install_write_bank(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_bank *bank) { install_bank_generic(addrstart, addrend, addrmirror, 0, nullptr, bank); }
+ void install_readwrite_bank(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_bank *bank) { install_bank_generic(addrstart, addrend, addrmirror, 0, bank, bank); }
+ void install_rom(offs_t addrstart, offs_t addrend, offs_t addrmirror, void *baseptr) { install_ram_generic(addrstart, addrend, addrmirror, 0, read_or_write::READ, baseptr); }
+ void install_writeonly(offs_t addrstart, offs_t addrend, offs_t addrmirror, void *baseptr) { install_ram_generic(addrstart, addrend, addrmirror, 0, read_or_write::WRITE, baseptr); }
+ void install_ram(offs_t addrstart, offs_t addrend, offs_t addrmirror, void *baseptr) { install_ram_generic(addrstart, addrend, addrmirror, 0, read_or_write::READWRITE, baseptr); }
+
+ // install ports, banks, RAM (with mirror/mask/flags)
+ void install_read_port(offs_t addrstart, offs_t addrend, offs_t addrmirror, u16 flags, const char *rtag) { install_readwrite_port(addrstart, addrend, addrmirror, flags, rtag, ""); }
+ void install_write_port(offs_t addrstart, offs_t addrend, offs_t addrmirror, u16 flags, const char *wtag) { install_readwrite_port(addrstart, addrend, addrmirror, flags, "", wtag); }
+ virtual void install_readwrite_port(offs_t addrstart, offs_t addrend, offs_t addrmirror, u16 flags, std::string rtag, std::string wtag) = 0;
+ void install_read_bank(offs_t addrstart, offs_t addrend, offs_t addrmirror, u16 flags, memory_bank *bank) { install_bank_generic(addrstart, addrend, addrmirror, flags, bank, nullptr); }
+ void install_write_bank(offs_t addrstart, offs_t addrend, offs_t addrmirror, u16 flags, memory_bank *bank) { install_bank_generic(addrstart, addrend, addrmirror, flags, nullptr, bank); }
+ void install_readwrite_bank(offs_t addrstart, offs_t addrend, offs_t addrmirror, u16 flags, memory_bank *bank) { install_bank_generic(addrstart, addrend, addrmirror, flags, bank, bank); }
+ void install_rom(offs_t addrstart, offs_t addrend, offs_t addrmirror, u16 flags, void *baseptr) { install_ram_generic(addrstart, addrend, addrmirror, flags, read_or_write::READ, baseptr); }
+ void install_writeonly(offs_t addrstart, offs_t addrend, offs_t addrmirror, u16 flags, void *baseptr) { install_ram_generic(addrstart, addrend, addrmirror, flags, read_or_write::WRITE, baseptr); }
+ void install_ram(offs_t addrstart, offs_t addrend, offs_t addrmirror, u16 flags, void *baseptr) { install_ram_generic(addrstart, addrend, addrmirror, flags, read_or_write::READWRITE, baseptr); }
+
+ // install device memory maps
+ template <typename T> void install_device(offs_t addrstart, offs_t addrend, T &device, void (T::*map)(address_map &map), u64 unitmask = 0, int cswidth = 0, u16 flags = 0) {
+ address_map_constructor delegate(map, "dynamic_device_install", &device);
+ install_device_delegate(addrstart, addrend, device, delegate, unitmask, cswidth, flags);
+ }
+
+ virtual void install_device_delegate(offs_t addrstart, offs_t addrend, device_t &device, address_map_constructor &map, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+
+ // install taps without mirroring
+ memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_read_tap(addrstart, addrend, 0, name, tap, mph); }
+ memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_read_tap(addrstart, addrend, 0, name, tap, mph); }
+ memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_read_tap(addrstart, addrend, 0, name, tap, mph); }
+ memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_read_tap(addrstart, addrend, 0, name, tap, mph); }
+ memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_write_tap(addrstart, addrend, 0, name, tap, mph); }
+ memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_write_tap(addrstart, addrend, 0, name, tap, mph); }
+ memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_write_tap(addrstart, addrend, 0, name, tap, mph); }
+ memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_write_tap(addrstart, addrend, 0, name, tap, mph); }
+ memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapr, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr) { return install_readwrite_tap(addrstart, addrend, 0, name, tapr, tapw, mph); }
+ memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapr, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr) { return install_readwrite_tap(addrstart, addrend, 0, name, tapr, tapw, mph); }
+ memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapr, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr) { return install_readwrite_tap(addrstart, addrend, 0, name, tapr, tapw, mph); }
+ memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapr, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr) { return install_readwrite_tap(addrstart, addrend, 0, name, tapr, tapw, mph); }
+
+ // install taps with mirroring
+ virtual memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph = nullptr);
+ virtual memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph = nullptr);
+ virtual memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph = nullptr);
+ virtual memory_passthrough_handler install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph = nullptr);
+ virtual memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph = nullptr);
+ virtual memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph = nullptr);
+ virtual memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph = nullptr);
+ virtual memory_passthrough_handler install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph = nullptr);
+ virtual memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapr, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr);
+ virtual memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapr, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr);
+ virtual memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapr, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr);
+ virtual memory_passthrough_handler install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapr, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr);
+
+ // install views
+ void install_view(offs_t addrstart, offs_t addrend, memory_view &view) { install_view(addrstart, addrend, 0, view); }
+ virtual void install_view(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_view &view) = 0;
+
+ // install wait state handlers
+ void install_read_before_time(offs_t addrstart, offs_t addrend, ws_time_delegate ws) { install_read_before_time(addrstart, addrend, 0, ws); }
+ virtual void install_read_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) = 0;
+ void install_read_before_delay(offs_t addrstart, offs_t addrend, ws_delay_delegate ws) { install_read_before_delay(addrstart, addrend, 0, ws); }
+ virtual void install_read_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) = 0;
+ void install_read_after_delay(offs_t addrstart, offs_t addrend, ws_delay_delegate ws) { install_read_after_delay(addrstart, addrend, 0, ws); }
+ virtual void install_read_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) = 0;
+
+ void install_write_before_time(offs_t addrstart, offs_t addrend, ws_time_delegate ws) { install_write_before_time(addrstart, addrend, 0, ws); }
+ virtual void install_write_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) = 0;
+ void install_write_before_delay(offs_t addrstart, offs_t addrend, ws_delay_delegate ws) { install_write_before_delay(addrstart, addrend, 0, ws); }
+ virtual void install_write_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) = 0;
+ void install_write_after_delay(offs_t addrstart, offs_t addrend, ws_delay_delegate ws) { install_write_after_delay(addrstart, addrend, 0, ws); }
+ virtual void install_write_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) = 0;
+
+ void install_readwrite_before_time(offs_t addrstart, offs_t addrend, ws_time_delegate ws) { install_readwrite_before_time(addrstart, addrend, 0, ws); }
+ virtual void install_readwrite_before_time(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_time_delegate ws) = 0;
+ void install_readwrite_before_delay(offs_t addrstart, offs_t addrend, ws_delay_delegate ws) { install_readwrite_before_delay(addrstart, addrend, 0, ws); }
+ virtual void install_readwrite_before_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) = 0;
+ void install_readwrite_after_delay(offs_t addrstart, offs_t addrend, ws_delay_delegate ws) { install_readwrite_after_delay(addrstart, addrend, 0, ws); }
+ virtual void install_readwrite_after_delay(offs_t addrstart, offs_t addrend, offs_t addrmirror, ws_delay_delegate ws) = 0;
+
+ // install new-style delegate handlers (short form)
+ template <typename R>
+ void install_read_handler(offs_t addrstart, offs_t addrend, R &&rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0)
+ { install_read_handler(addrstart, addrend, 0, 0, 0, std::forward<R>(rhandler), unitmask, cswidth, flags); }
+ template <typename W>
+ void install_write_handler(offs_t addrstart, offs_t addrend, W &&whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0)
+ { install_write_handler(addrstart, addrend, 0, 0, 0, std::forward<W>(whandler), unitmask, cswidth, flags); }
+ template <typename R, typename W>
+ void install_readwrite_handler(offs_t addrstart, offs_t addrend, R &&rhandler, W &&whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0)
+ { install_readwrite_handler(addrstart, addrend, 0, 0, 0, std::forward<R>(rhandler), std::forward<W>(whandler), unitmask, cswidth, flags); }
+
+ // install new-style delegate handlers (with mirror/mask)
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64m_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64m_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64s_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64s_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64sm_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64mo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+ virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64smo_delegate whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0) = 0;
+
+ template <typename R, typename W>
+ void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, R &&rhandler, W &&whandler, u64 unitmask = 0, int cswidth = 0, u16 flags = 0)
+ {
+ static_assert(emu::detail::handler_width_v<std::remove_reference_t<R> > == emu::detail::handler_width_v<std::remove_reference_t<W> >, "handler widths do not match");
+ install_read_handler(addrstart, addrend, addrmask, addrmirror, addrselect, std::forward<R>(rhandler), unitmask, cswidth, flags);
+ install_write_handler(addrstart, addrend, addrmask, addrmirror, addrselect, std::forward<W>(whandler), unitmask, cswidth, flags);
+ }
+
+protected:
+ virtual void unmap_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, u16 flags, read_or_write readorwrite, bool quiet) = 0;
+ virtual void install_ram_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, u16 flags, read_or_write readorwrite, void *baseptr) = 0;
+ virtual void install_bank_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, u16 flags, memory_bank *rbank, memory_bank *wbank) = 0;
+
+ void populate_map_entry(const address_map_entry &entry, read_or_write readorwrite);
+ void adjust_addresses(offs_t &start, offs_t &end, offs_t &mask, offs_t &mirror) {
+ // adjust start/end/mask values
+ mask &= m_addrmask;
+ start &= ~mirror & m_addrmask;
+ end &= ~mirror & m_addrmask;
+ }
+
+ void check_optimize_all(const char *function, int width, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, offs_t &nstart, offs_t &nend, offs_t &nmask, offs_t &nmirror, u64 &nunitmask, int &ncswidth);
+ void check_optimize_mirror(const char *function, offs_t addrstart, offs_t addrend, offs_t addrmirror, offs_t &nstart, offs_t &nend, offs_t &nmask, offs_t &nmirror);
+ void check_address(const char *function, offs_t addrstart, offs_t addrend);
+
+ address_space_installer(const address_space_config &config, memory_manager &manager)
+ : m_config(config),
+ m_manager(manager),
+ m_addrmask(make_bitmask<offs_t>(m_config.addr_width())),
+ m_logaddrmask(make_bitmask<offs_t>(m_config.logaddr_width())),
+ m_addrchars((m_config.addr_width() + 3) / 4),
+ m_logaddrchars((m_config.logaddr_width() + 3) / 4)
+ {}
+
+ const address_space_config &m_config; // configuration of this space
+ memory_manager & m_manager; // reference to the owning manager
+ offs_t m_addrmask; // physical address mask
+ offs_t m_logaddrmask; // logical address mask
+ u8 m_addrchars; // number of characters to use for physical addresses
+ u8 m_logaddrchars; // number of characters to use for logical addresses
+};
+
// address_space holds live information about an address space
-class address_space
+class address_space : public address_space_installer
{
friend class memory_bank;
friend class memory_block;
- template<int Width, int AddrShift, endianness_t Endian> friend class handler_entry_read_unmapped;
- template<int Width, int AddrShift, endianness_t Endian> friend class handler_entry_write_unmapped;
-
- struct notifier_t {
- std::function<void (read_or_write)> m_notifier;
- int m_id;
- };
+ template<int Width, int AddrShift> friend class handler_entry_read_unmapped;
+ template<int Width, int AddrShift> friend class handler_entry_write_unmapped;
protected:
// construction/destruction
@@ -1263,7 +2358,7 @@ public:
fatalerror("Requesting cache() with data width %d while the config says %d\n", 8 << Width, m_config.data_width());
if(Endian != m_config.endianness())
fatalerror("Requesting cache() with endianness %s while the config says %s\n",
- endianness_names[Endian], endianness_names[m_config.endianness()]);
+ util::endian_to_string_view(Endian), util::endian_to_string_view(m_config.endianness()));
v.set(this, get_cache_info());
}
@@ -1277,20 +2372,19 @@ public:
fatalerror("Requesting specific() with data width %d while the config says %d\n", 8 << Width, m_config.data_width());
if(Endian != m_config.endianness())
fatalerror("Requesting spefific() with endianness %s while the config says %s\n",
- endianness_names[Endian], endianness_names[m_config.endianness()]);
+ util::endian_to_string_view(Endian), util::endian_to_string_view(m_config.endianness()));
v.set(this, get_specific_info());
}
- int add_change_notifier(std::function<void (read_or_write)> n);
- void remove_change_notifier(int id);
+ util::notifier_subscription add_change_notifier(delegate<void (read_or_write)> &&n);
+ template <typename T> util::notifier_subscription add_change_notifier(T &&n) { return add_change_notifier(delegate<void (read_or_write)>(std::forward<T>(n))); }
void invalidate_caches(read_or_write mode) {
if(u32(mode) & ~m_in_notification) {
u32 old = m_in_notification;
m_in_notification |= u32(mode);
- for(const auto &n : m_notifiers)
- n.m_notifier(mode);
+ m_notifiers(mode);
m_in_notification = old;
}
}
@@ -1299,19 +2393,11 @@ public:
virtual void remove_passthrough(std::unordered_set<handler_entry *> &handlers) = 0;
- int data_width() const { return m_config.data_width(); }
- int addr_width() const { return m_config.addr_width(); }
- int logaddr_width() const { return m_config.logaddr_width(); }
- int alignment() const { return m_config.alignment(); }
- endianness_t endianness() const { return m_config.endianness(); }
- int addr_shift() const { return m_config.addr_shift(); }
u64 unmap() const { return m_unmap; }
- bool is_octal() const { return m_config.is_octal(); }
+ void unmap_value_high() { m_unmap = ~0; }
- offs_t addrmask() const { return m_addrmask; }
- u8 addrchars() const { return m_addrchars; }
- offs_t logaddrmask() const { return m_logaddrmask; }
- u8 logaddrchars() const { return m_logaddrchars; }
+ std::shared_ptr<emu::detail::memory_passthrough_handler_impl> make_mph(memory_passthrough_handler *mph);
+ std::shared_ptr<emu::detail::memory_passthrough_handler_impl> get_default_mpl() { return m_default_mpl; }
// debug helpers
virtual std::string get_handler_string(read_or_write readorwrite, offs_t byteaddress) const = 0;
@@ -1354,283 +2440,33 @@ public:
virtual void write_qword_unaligned(offs_t address, u64 data) = 0;
virtual void write_qword_unaligned(offs_t address, u64 data, u64 mask) = 0;
- // address-to-byte conversion helpers
- offs_t address_to_byte(offs_t address) const { return m_config.addr2byte(address); }
- offs_t address_to_byte_end(offs_t address) const { return m_config.addr2byte_end(address); }
- offs_t byte_to_address(offs_t address) const { return m_config.byte2addr(address); }
- offs_t byte_to_address_end(offs_t address) const { return m_config.byte2addr_end(address); }
-
- // umap ranges (short form)
- void unmap_read(offs_t addrstart, offs_t addrend, offs_t addrmirror = 0) { unmap_generic(addrstart, addrend, addrmirror, read_or_write::READ, false); }
- void unmap_write(offs_t addrstart, offs_t addrend, offs_t addrmirror = 0) { unmap_generic(addrstart, addrend, addrmirror, read_or_write::WRITE, false); }
- void unmap_readwrite(offs_t addrstart, offs_t addrend, offs_t addrmirror = 0) { unmap_generic(addrstart, addrend, addrmirror, read_or_write::READWRITE, false); }
- void nop_read(offs_t addrstart, offs_t addrend, offs_t addrmirror = 0) { unmap_generic(addrstart, addrend, addrmirror, read_or_write::READ, true); }
- void nop_write(offs_t addrstart, offs_t addrend, offs_t addrmirror = 0) { unmap_generic(addrstart, addrend, addrmirror, read_or_write::WRITE, true); }
- void nop_readwrite(offs_t addrstart, offs_t addrend, offs_t addrmirror = 0) { unmap_generic(addrstart, addrend, addrmirror, read_or_write::READWRITE, true); }
-
- // install ports, banks, RAM (short form)
- void install_read_port(offs_t addrstart, offs_t addrend, const char *rtag) { install_read_port(addrstart, addrend, 0, rtag); }
- void install_write_port(offs_t addrstart, offs_t addrend, const char *wtag) { install_write_port(addrstart, addrend, 0, wtag); }
- void install_readwrite_port(offs_t addrstart, offs_t addrend, const char *rtag, const char *wtag) { install_readwrite_port(addrstart, addrend, 0, rtag, wtag); }
- void install_read_bank(offs_t addrstart, offs_t addrend, const char *tag) { install_read_bank(addrstart, addrend, 0, tag); }
- void install_write_bank(offs_t addrstart, offs_t addrend, const char *tag) { install_write_bank(addrstart, addrend, 0, tag); }
- void install_readwrite_bank(offs_t addrstart, offs_t addrend, const char *tag) { install_readwrite_bank(addrstart, addrend, 0, tag); }
- void install_read_bank(offs_t addrstart, offs_t addrend, memory_bank *bank) { install_read_bank(addrstart, addrend, 0, bank); }
- void install_write_bank(offs_t addrstart, offs_t addrend, memory_bank *bank) { install_write_bank(addrstart, addrend, 0, bank); }
- void install_readwrite_bank(offs_t addrstart, offs_t addrend, memory_bank *bank) { install_readwrite_bank(addrstart, addrend, 0, bank); }
- void install_rom(offs_t addrstart, offs_t addrend, void *baseptr = nullptr) { install_rom(addrstart, addrend, 0, baseptr); }
- void install_writeonly(offs_t addrstart, offs_t addrend, void *baseptr = nullptr) { install_writeonly(addrstart, addrend, 0, baseptr); }
- void install_ram(offs_t addrstart, offs_t addrend, void *baseptr = nullptr) { install_ram(addrstart, addrend, 0, baseptr); }
-
- // install ports, banks, RAM (with mirror/mask)
- void install_read_port(offs_t addrstart, offs_t addrend, offs_t addrmirror, const char *rtag) { install_readwrite_port(addrstart, addrend, addrmirror, rtag, ""); }
- void install_write_port(offs_t addrstart, offs_t addrend, offs_t addrmirror, const char *wtag) { install_readwrite_port(addrstart, addrend, addrmirror, "", wtag); }
- virtual void install_readwrite_port(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string rtag, std::string wtag) = 0;
- void install_read_bank(offs_t addrstart, offs_t addrend, offs_t addrmirror, const char *tag) { install_bank_generic(addrstart, addrend, addrmirror, tag, ""); }
- void install_write_bank(offs_t addrstart, offs_t addrend, offs_t addrmirror, const char *tag) { install_bank_generic(addrstart, addrend, addrmirror, "", tag); }
- void install_readwrite_bank(offs_t addrstart, offs_t addrend, offs_t addrmirror, const char *tag) { install_bank_generic(addrstart, addrend, addrmirror, tag, tag); }
- void install_read_bank(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_bank *bank) { install_bank_generic(addrstart, addrend, addrmirror, bank, nullptr); }
- void install_write_bank(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_bank *bank) { install_bank_generic(addrstart, addrend, addrmirror, nullptr, bank); }
- void install_readwrite_bank(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_bank *bank) { install_bank_generic(addrstart, addrend, addrmirror, bank, bank); }
- void install_rom(offs_t addrstart, offs_t addrend, offs_t addrmirror, void *baseptr = nullptr) { install_ram_generic(addrstart, addrend, addrmirror, read_or_write::READ, baseptr); }
- void install_writeonly(offs_t addrstart, offs_t addrend, offs_t addrmirror, void *baseptr = nullptr) { install_ram_generic(addrstart, addrend, addrmirror, read_or_write::WRITE, baseptr); }
- void install_ram(offs_t addrstart, offs_t addrend, offs_t addrmirror, void *baseptr = nullptr) { install_ram_generic(addrstart, addrend, addrmirror, read_or_write::READWRITE, baseptr); }
-
- // install device memory maps
- template <typename T> void install_device(offs_t addrstart, offs_t addrend, T &device, void (T::*map)(address_map &map), u64 unitmask = 0, int cswidth = 0) {
- address_map_constructor delegate(map, "dynamic_device_install", &device);
- install_device_delegate(addrstart, addrend, device, delegate, unitmask, cswidth);
- }
-
- virtual void install_device_delegate(offs_t addrstart, offs_t addrend, device_t &device, address_map_constructor &map, u64 unitmask = 0, int cswidth = 0) = 0;
-
- // install taps without mirroring
- memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_read_tap(addrstart, addrend, 0, name, tap, mph); }
- memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_read_tap(addrstart, addrend, 0, name, tap, mph); }
- memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_read_tap(addrstart, addrend, 0, name, tap, mph); }
- memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_read_tap(addrstart, addrend, 0, name, tap, mph); }
- memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_write_tap(addrstart, addrend, 0, name, tap, mph); }
- memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_write_tap(addrstart, addrend, 0, name, tap, mph); }
- memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_write_tap(addrstart, addrend, 0, name, tap, mph); }
- memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph = nullptr) { return install_write_tap(addrstart, addrend, 0, name, tap, mph); }
- memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapr, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr) { return install_readwrite_tap(addrstart, addrend, 0, name, tapr, tapw, mph); }
- memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapr, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr) { return install_readwrite_tap(addrstart, addrend, 0, name, tapr, tapw, mph); }
- memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapr, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr) { return install_readwrite_tap(addrstart, addrend, 0, name, tapr, tapw, mph); }
- memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapr, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr) { return install_readwrite_tap(addrstart, addrend, 0, name, tapr, tapw, mph); }
-
- // install taps with mirroring
- virtual memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph = nullptr);
- virtual memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph = nullptr);
- virtual memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph = nullptr);
- virtual memory_passthrough_handler *install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph = nullptr);
- virtual memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tap, memory_passthrough_handler *mph = nullptr);
- virtual memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tap, memory_passthrough_handler *mph = nullptr);
- virtual memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tap, memory_passthrough_handler *mph = nullptr);
- virtual memory_passthrough_handler *install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tap, memory_passthrough_handler *mph = nullptr);
- virtual memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapr, std::function<void (offs_t offset, u8 &data, u8 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr);
- virtual memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapr, std::function<void (offs_t offset, u16 &data, u16 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr);
- virtual memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapr, std::function<void (offs_t offset, u32 &data, u32 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr);
- virtual memory_passthrough_handler *install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapr, std::function<void (offs_t offset, u64 &data, u64 mem_mask)> tapw, memory_passthrough_handler *mph = nullptr);
-
-
- // install new-style delegate handlers (short form)
- void install_read_handler(offs_t addrstart, offs_t addrend, read8_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write8_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read8_delegate rhandler, write8_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read16_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write16_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read16_delegate rhandler, write16_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read32_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write32_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read32_delegate rhandler, write32_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read64_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write64_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read64_delegate rhandler, write64_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
-
- void install_read_handler(offs_t addrstart, offs_t addrend, read8m_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write8m_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read8m_delegate rhandler, write8m_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read16m_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write16m_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read16m_delegate rhandler, write16m_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read32m_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write32m_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read32m_delegate rhandler, write32m_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read64m_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write64m_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read64m_delegate rhandler, write64m_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
-
- void install_read_handler(offs_t addrstart, offs_t addrend, read8s_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write8s_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read8s_delegate rhandler, write8s_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read16s_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write16s_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read16s_delegate rhandler, write16s_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read32s_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write32s_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read32s_delegate rhandler, write32s_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read64s_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write64s_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read64s_delegate rhandler, write64s_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
-
- void install_read_handler(offs_t addrstart, offs_t addrend, read8sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write8sm_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read8sm_delegate rhandler, write8sm_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read16sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write16sm_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read16sm_delegate rhandler, write16sm_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read32sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write32sm_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read32sm_delegate rhandler, write32sm_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read64sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write64sm_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read64sm_delegate rhandler, write64sm_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
-
- void install_read_handler(offs_t addrstart, offs_t addrend, read8mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write8mo_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read8mo_delegate rhandler, write8mo_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read16mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write16mo_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read16mo_delegate rhandler, write16mo_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read32mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write32mo_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read32mo_delegate rhandler, write32mo_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read64mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write64mo_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read64mo_delegate rhandler, write64mo_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
-
- void install_read_handler(offs_t addrstart, offs_t addrend, read8smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write8smo_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read8smo_delegate rhandler, write8smo_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read16smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write16smo_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read16smo_delegate rhandler, write16smo_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read32smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write32smo_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read32smo_delegate rhandler, write32smo_delegate whandler, u64 unitmask = 0, int cswidth = 0) { return install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
- void install_read_handler(offs_t addrstart, offs_t addrend, read64smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0) { install_read_handler(addrstart, addrend, 0, 0, 0, rhandler, unitmask, cswidth); }
- void install_write_handler(offs_t addrstart, offs_t addrend, write64smo_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_write_handler(addrstart, addrend, 0, 0, 0, whandler, unitmask, cswidth); }
- void install_readwrite_handler(offs_t addrstart, offs_t addrend, read64smo_delegate rhandler, write64smo_delegate whandler, u64 unitmask = 0, int cswidth = 0) { install_readwrite_handler(addrstart, addrend, 0, 0, 0, rhandler, whandler, unitmask, cswidth); }
-
- // install new-style delegate handlers (with mirror/mask)
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8_delegate rhandler, write8_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16_delegate rhandler, write16_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32_delegate rhandler, write32_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64_delegate rhandler, write64_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
-
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8m_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8m_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8m_delegate rhandler, write8m_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16m_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16m_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16m_delegate rhandler, write16m_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32m_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32m_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32m_delegate rhandler, write32m_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64m_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64m_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64m_delegate rhandler, write64m_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
-
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8s_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8s_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8s_delegate rhandler, write8s_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16s_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16s_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16s_delegate rhandler, write16s_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32s_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32s_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32s_delegate rhandler, write32s_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64s_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64s_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64s_delegate rhandler, write64s_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
-
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8sm_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8sm_delegate rhandler, write8sm_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16sm_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16sm_delegate rhandler, write16sm_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32sm_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32sm_delegate rhandler, write32sm_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64sm_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64sm_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64sm_delegate rhandler, write64sm_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
-
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8mo_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8mo_delegate rhandler, write8mo_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16mo_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16mo_delegate rhandler, write16mo_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32mo_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32mo_delegate rhandler, write32mo_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64mo_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64mo_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64mo_delegate rhandler, write64mo_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
-
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write8smo_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read8smo_delegate rhandler, write8smo_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write16smo_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read16smo_delegate rhandler, write16smo_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write32smo_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read32smo_delegate rhandler, write32smo_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_read_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64smo_delegate rhandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_write_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, write64smo_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
- virtual void install_readwrite_handler(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, read64smo_delegate rhandler, write64smo_delegate whandler, u64 unitmask = 0, int cswidth = 0) = 0;
-
// setup
void prepare_map();
+ void prepare_device_map(address_map &map);
void populate_from_map(address_map *map = nullptr);
- void allocate_memory();
- void locate_memory();
- template<int Width, int AddrShift, endianness_t Endian> handler_entry_read_unmapped <Width, AddrShift, Endian> *get_unmap_r() const { return static_cast<handler_entry_read_unmapped <Width, AddrShift, Endian> *>(m_unmap_r); }
- template<int Width, int AddrShift, endianness_t Endian> handler_entry_write_unmapped<Width, AddrShift, Endian> *get_unmap_w() const { return static_cast<handler_entry_write_unmapped<Width, AddrShift, Endian> *>(m_unmap_w); }
+ template<int Width, int AddrShift> handler_entry_read_unmapped <Width, AddrShift> *get_unmap_r() const { return static_cast<handler_entry_read_unmapped <Width, AddrShift> *>(m_unmap_r); }
+ template<int Width, int AddrShift> handler_entry_write_unmapped<Width, AddrShift> *get_unmap_w() const { return static_cast<handler_entry_write_unmapped<Width, AddrShift> *>(m_unmap_w); }
+
+ handler_entry *unmap_r() const { return m_unmap_r; }
+ handler_entry *unmap_w() const { return m_unmap_w; }
+ handler_entry *nop_r() const { return m_nop_r; }
+ handler_entry *nop_w() const { return m_nop_w; }
protected:
// internal helpers
virtual std::pair<void *, void *> get_cache_info() = 0;
virtual std::pair<const void *, const void *> get_specific_info() = 0;
- void populate_map_entry(const address_map_entry &entry, read_or_write readorwrite);
- virtual void unmap_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, read_or_write readorwrite, bool quiet) = 0;
- virtual void install_ram_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, read_or_write readorwrite, void *baseptr) = 0;
- virtual void install_bank_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string rtag, std::string wtag) = 0;
- virtual void install_bank_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_bank *rbank, memory_bank *wbank) = 0;
- void adjust_addresses(offs_t &start, offs_t &end, offs_t &mask, offs_t &mirror);
- void *find_backing_memory(offs_t addrstart, offs_t addrend);
- bool needs_backing_store(const address_map_entry &entry);
- memory_bank &bank_find_or_allocate(const char *tag, offs_t addrstart, offs_t addrend, offs_t addrmirror, read_or_write readorwrite);
- address_map_entry *block_assign_intersecting(offs_t bytestart, offs_t byteend, u8 *base);
- void check_optimize_all(const char *function, int width, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, offs_t &nstart, offs_t &nend, offs_t &nmask, offs_t &nmirror, u64 &nunitmask, int &ncswidth);
- void check_optimize_mirror(const char *function, offs_t addrstart, offs_t addrend, offs_t addrmirror, offs_t &nstart, offs_t &nend, offs_t &nmask, offs_t &nmirror);
- void check_address(const char *function, offs_t addrstart, offs_t addrend);
+ void prepare_map_generic(address_map &map, bool allow_alloc);
// private state
- const address_space_config &m_config; // configuration of this space
device_t & m_device; // reference to the owning device
std::unique_ptr<address_map> m_map; // original memory map
- offs_t m_addrmask; // physical address mask
- offs_t m_logaddrmask; // logical address mask
u64 m_unmap; // unmapped value
int m_spacenum; // address space index
bool m_log_unmap; // log unmapped accesses in this space?
const char * m_name; // friendly name of the address space
- u8 m_addrchars; // number of characters to use for physical addresses
- u8 m_logaddrchars; // number of characters to use for logical addresses
handler_entry *m_unmap_r;
handler_entry *m_unmap_w;
@@ -1638,46 +2474,13 @@ protected:
handler_entry *m_nop_r;
handler_entry *m_nop_w;
- std::vector<std::unique_ptr<memory_passthrough_handler>> m_mphs;
+ std::vector<std::shared_ptr<emu::detail::memory_passthrough_handler_impl>> m_mphs;
- std::vector<notifier_t> m_notifiers; // notifier list for address map change
- int m_notifier_id; // next notifier id
+ util::notifier<read_or_write> m_notifiers; // notifier list for address map change
u32 m_in_notification; // notification(s) currently being done
- memory_manager & m_manager; // reference to the owning manager
-};
-
-// ======================> memory_block
-
-// a memory block is a chunk of RAM associated with a range of memory in a device's address space
-class memory_block
-{
- DISABLE_COPYING(memory_block);
-
-public:
- // construction/destruction
- memory_block(address_space &space, offs_t start, offs_t end, void *memory = nullptr);
- ~memory_block();
-
- // getters
- running_machine &machine() const { return m_machine; }
- offs_t addrstart() const { return m_addrstart; }
- offs_t addrend() const { return m_addrend; }
- u8 *data() const { return m_data; }
-
- // is the given range contained by this memory block?
- bool contains(address_space &space, offs_t addrstart, offs_t addrend) const
- {
- return (&space == &m_space && m_addrstart <= addrstart && m_addrend >= addrend);
- }
-
-private:
- // internal state
- running_machine & m_machine; // need the machine to free our memory
- address_space & m_space; // which address space are we associated with?
- offs_t m_addrstart, m_addrend; // start/end for verifying a match
- u8 * m_data; // pointer to the data for this block
- std::vector<u8> m_allocated; // pointer to the actually allocated block
+ // passthrough handler used for wait states
+ std::shared_ptr<emu::detail::memory_passthrough_handler_impl> m_default_mpl;
};
@@ -1686,54 +2489,17 @@ private:
// a memory bank is a global pointer to memory that can be shared across devices and changed dynamically
class memory_bank
{
- // a bank reference is an entry in a list of address spaces that reference a given bank
- class bank_reference
- {
- public:
- // construction/destruction
- bank_reference(address_space &space, read_or_write readorwrite)
- : m_space(space),
- m_readorwrite(readorwrite) { }
-
- // getters
- address_space &space() const { return m_space; }
-
- // does this reference match the space+read/write combination?
- bool matches(const address_space &space, read_or_write readorwrite) const
- {
- return (&space == &m_space && (readorwrite == read_or_write::READWRITE || readorwrite == m_readorwrite));
- }
-
- private:
- // internal state
- address_space & m_space; // address space that references us
- read_or_write m_readorwrite; // used for read or write?
-
- };
-
public:
// construction/destruction
- memory_bank(address_space &space, int index, offs_t start, offs_t end, const char *tag = nullptr);
+ memory_bank(device_t &device, std::string tag);
~memory_bank();
// getters
running_machine &machine() const { return m_machine; }
int entry() const { return m_curentry; }
- bool anonymous() const { return m_anonymous; }
- offs_t addrstart() const { return m_addrstart; }
void *base() const { return m_entries.empty() ? nullptr : m_entries[m_curentry]; }
- const char *tag() const { return m_tag.c_str(); }
- const char *name() const { return m_name.c_str(); }
-
- // compare a range against our range
- bool matches_exactly(offs_t addrstart, offs_t addrend) const { return (m_addrstart == addrstart && m_addrend == addrend); }
- bool fully_covers(offs_t addrstart, offs_t addrend) const { return (m_addrstart <= addrstart && m_addrend >= addrend); }
- bool is_covered_by(offs_t addrstart, offs_t addrend) const { return (m_addrstart >= addrstart && m_addrend <= addrend); }
- bool straddles(offs_t addrstart, offs_t addrend) const { return (m_addrstart < addrend && m_addrend > addrstart); }
-
- // track and verify address space references to this bank
- bool references_space(const address_space &space, read_or_write readorwrite) const;
- void add_reference(address_space &space, read_or_write readorwrite);
+ const std::string &tag() const { return m_tag; }
+ const std::string &name() const { return m_name; }
// set the base explicitly
void set_base(void *base);
@@ -1742,20 +2508,14 @@ public:
void configure_entry(int entrynum, void *base);
void configure_entries(int startentry, int numentries, void *base, offs_t stride);
void set_entry(int entrynum);
- void add_notifier(std::function<void (void *)> cb);
private:
// internal state
running_machine & m_machine; // need the machine to free our memory
std::vector<u8 *> m_entries; // the entries
- bool m_anonymous; // are we anonymous or explicit?
- offs_t m_addrstart; // start offset
- offs_t m_addrend; // end offset
int m_curentry; // current entry
std::string m_name; // friendly name for this bank
std::string m_tag; // tag for this bank
- std::vector<std::unique_ptr<bank_reference>> m_reflist; // list of address spaces referencing this bank
- std::vector<std::function<void (void *)>> m_alloc_notifier; // list of notifier targets when allocating
};
@@ -1766,26 +2526,28 @@ class memory_share
{
public:
// construction/destruction
- memory_share(u8 width, size_t bytes, endianness_t endianness, void *ptr = nullptr)
- : m_ptr(ptr),
- m_bytes(bytes),
- m_endianness(endianness),
- m_bitwidth(width),
- m_bytewidth(width <= 8 ? 1 : width <= 16 ? 2 : width <= 32 ? 4 : 8)
+ memory_share(std::string name, u8 width, size_t bytes, endianness_t endianness, void *ptr)
+ : m_name(name),
+ m_ptr(ptr),
+ m_bytes(bytes),
+ m_endianness(endianness),
+ m_bitwidth(width),
+ m_bytewidth(width <= 8 ? 1 : width <= 16 ? 2 : width <= 32 ? 4 : 8)
{ }
// getters
+ const std::string &name() const { return m_name; }
void *ptr() const { return m_ptr; }
size_t bytes() const { return m_bytes; }
endianness_t endianness() const { return m_endianness; }
u8 bitwidth() const { return m_bitwidth; }
u8 bytewidth() const { return m_bytewidth; }
- // setters
- void set_ptr(void *ptr) { m_ptr = ptr; }
+ std::string compare(u8 width, size_t bytes, endianness_t endianness) const;
private:
// internal state
+ std::string m_name; // share name
void * m_ptr; // pointer to the memory backing the region
size_t m_bytes; // size of the shared region in bytes
endianness_t m_endianness; // endianness of the memory
@@ -1801,18 +2563,16 @@ private:
class memory_region
{
DISABLE_COPYING(memory_region);
-
- friend class memory_manager;
public:
// construction/destruction
- memory_region(running_machine &machine, const char *name, u32 length, u8 width, endianness_t endian);
+ memory_region(running_machine &machine, std::string name, u32 length, u8 width, endianness_t endian);
// getters
running_machine &machine() const { return m_machine; }
u8 *base() { return (m_buffer.size() > 0) ? &m_buffer[0] : nullptr; }
u8 *end() { return base() + m_buffer.size(); }
u32 bytes() const { return m_buffer.size(); }
- const char *name() const { return m_name.c_str(); }
+ const std::string &name() const { return m_name; }
// flag expansion
endianness_t endianness() const { return m_endianness; }
@@ -1837,6 +2597,84 @@ private:
+// ======================> memory_view
+
+// a memory view allows switching between submaps in the map
+class memory_view
+{
+ template<int Level, int Width, int AddrShift, endianness_t Endian> friend class address_space_specific;
+ template<int Level, int Width, int AddrShift> friend class memory_view_entry_specific;
+ template<int HighBits, int Width, int AddrShift> friend class handler_entry_write_dispatch;
+ template<int HighBits, int Width, int AddrShift> friend class handler_entry_read_dispatch;
+ friend class memory_view_entry;
+ friend class address_map_entry;
+ friend class address_map;
+ friend class device_t;
+
+ DISABLE_COPYING(memory_view);
+
+public:
+ class memory_view_entry : public address_space_installer {
+ public:
+ virtual ~memory_view_entry() = default;
+
+ address_map_entry &operator()(offs_t start, offs_t end);
+
+ virtual void populate_from_map(address_map *map = nullptr) = 0;
+
+ std::string key() const;
+
+ protected:
+ memory_view &m_view;
+ std::unique_ptr<address_map> m_map;
+ int m_id;
+
+ memory_view_entry(const address_space_config &config, memory_manager &manager, memory_view &view, int id);
+ void prepare_map_generic(address_map &map, bool allow_alloc);
+ void prepare_device_map(address_map &map);
+
+ void check_range_optimize_all(const char *function, int width, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, offs_t &nstart, offs_t &nend, offs_t &nmask, offs_t &nmirror, u64 &nunitmask, int &ncswidth);
+ void check_range_optimize_mirror(const char *function, offs_t addrstart, offs_t addrend, offs_t addrmirror, offs_t &nstart, offs_t &nend, offs_t &nmask, offs_t &nmirror);
+ void check_range_address(const char *function, offs_t addrstart, offs_t addrend);
+ };
+
+ memory_view(device_t &device, std::string name);
+ ~memory_view();
+
+ memory_view_entry &operator[](int slot);
+
+ void select(int entry);
+ void disable();
+
+ std::optional<int> entry() const { return m_cur_id == -1 ? std::optional<int>() : m_cur_slot; }
+
+ const std::string &name() const { return m_name; }
+
+private:
+
+ device_t & m_device;
+ std::string m_name;
+ std::map<int, int> m_entry_mapping;
+ std::vector<std::unique_ptr<memory_view_entry>> m_entries;
+ const address_space_config * m_config;
+ offs_t m_addrstart;
+ offs_t m_addrend;
+ address_space * m_space;
+ handler_entry * m_handler_read;
+ handler_entry * m_handler_write;
+ int m_cur_id;
+ int m_cur_slot;
+ std::string m_context;
+
+ void initialize_from_address_map(offs_t addrstart, offs_t addrend, const address_space_config &config);
+ std::pair<handler_entry *, handler_entry *> make_handlers(address_space &space, offs_t addrstart, offs_t addrend);
+ void make_subdispatch(std::string context);
+ int id_to_slot(int id) const;
+ void register_state();
+};
+
+
+
// ======================> memory_manager
// holds internal state for the memory system
@@ -1844,39 +2682,54 @@ class memory_manager
{
friend class address_space;
template<int Level, int Width, int AddrShift, endianness_t Endian> friend class address_space_specific;
- friend memory_region::memory_region(running_machine &machine, const char *name, u32 length, u8 width, endianness_t endian);
public:
// construction/destruction
memory_manager(running_machine &machine);
+ ~memory_manager();
+
+ // initialize the memory spaces from the memory maps of the devices
void initialize();
// getters
running_machine &machine() const { return m_machine; }
+
+ // used for the debugger interface memory views
const std::unordered_map<std::string, std::unique_ptr<memory_bank>> &banks() const { return m_banklist; }
const std::unordered_map<std::string, std::unique_ptr<memory_region>> &regions() const { return m_regionlist; }
const std::unordered_map<std::string, std::unique_ptr<memory_share>> &shares() const { return m_sharelist; }
- // regions
- memory_region *region_alloc(const char *name, u32 length, u8 width, endianness_t endian);
- void region_free(const char *name);
- memory_region *region_containing(const void *memory, offs_t bytes) const;
+ // anonymous memory zones
+ void *anonymous_alloc(address_space &space, size_t bytes, u8 width, offs_t start, offs_t end, const std::string &key = "");
+
+ // shares
+ memory_share *share_alloc(device_t &dev, std::string name, u8 width, size_t bytes, endianness_t endianness);
+ memory_share *share_find(std::string name);
- memory_bank *find(const char *tag) const;
- memory_bank *find(address_space &space, offs_t addrstart, offs_t addrend) const;
- memory_bank *allocate(address_space &space, offs_t addrstart, offs_t addrend, const char *tag = nullptr);
+ // banks
+ memory_bank *bank_alloc(device_t &device, std::string tag);
+ memory_bank *bank_find(std::string tag);
+
+ // regions
+ memory_region *region_alloc(std::string name, u32 length, u8 width, endianness_t endian);
+ memory_region *region_find(std::string name);
+ void region_free(std::string name);
private:
- void allocate(device_memory_interface &memory);
+ struct stdlib_deleter { void operator()(void *p) const { free(p); } };
// internal state
running_machine & m_machine; // reference to the machine
- bool m_initialized; // have we completed initialization?
- std::vector<std::unique_ptr<memory_block>> m_blocklist; // head of the list of memory blocks
+ std::vector<std::unique_ptr<void, stdlib_deleter>> m_datablocks; // list of memory blocks to free on exit
+ std::unordered_map<std::string, std::unique_ptr<memory_bank>> m_banklist; // map of banks
+ std::unordered_map<std::string, std::unique_ptr<memory_share>> m_sharelist; // map of shares
+ std::unordered_map<std::string, std::unique_ptr<memory_region>> m_regionlist; // map of memory regions
- std::unordered_map<std::string, std::unique_ptr<memory_bank>> m_banklist; // data gathered for each bank
- std::unordered_map<std::string, std::unique_ptr<memory_share>> m_sharelist; // map for share lookups
- std::unordered_map<std::string, std::unique_ptr<memory_region>> m_regionlist; // list of memory regions
+ // Allocate the address spaces
+ void allocate(device_memory_interface &memory);
+
+ // Allocate some ram and register it for saving
+ void *allocate_memory(device_t &dev, int spacenum, std::string name, u8 width, size_t bytes);
};
@@ -1907,33 +2760,6 @@ private:
#define ACCESSING_BITS_32_63 ((mem_mask & 0xffffffff00000000U) != 0)
-// macros for accessing bytes and words within larger chunks
-
-// read/write a byte to a 16-bit space
-#define BYTE_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0))
-#define BYTE_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,1))
-
-// read/write a byte to a 32-bit space
-#define BYTE4_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(3,0))
-#define BYTE4_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,3))
-
-// read/write a word to a 32-bit space
-#define WORD_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(2,0))
-#define WORD_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,2))
-
-// read/write a byte to a 64-bit space
-#define BYTE8_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(7,0))
-#define BYTE8_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,7))
-
-// read/write a word to a 64-bit space
-#define WORD2_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(6,0))
-#define WORD2_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,6))
-
-// read/write a dword to a 64-bit space
-#define DWORD_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(4,0))
-#define DWORD_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,4))
-
-
// helpers for checking address alignment
#define WORD_ALIGNED(a) (((a) & 1) == 0)
#define DWORD_ALIGNED(a) (((a) & 3) == 0)
@@ -1941,9 +2767,9 @@ private:
template<int Width, int AddrShift, endianness_t Endian>
-typename emu::detail::handler_entry_size<Width>::uX
+emu::detail::handler_entry_size_t<Width>
emu::detail::memory_access_cache<Width, AddrShift, Endian>::
-read_native(offs_t address, typename emu::detail::handler_entry_size<Width>::uX mask)
+read_native(offs_t address, emu::detail::handler_entry_size_t<Width> mask)
{
address &= m_addrmask;
check_address_r(address);
@@ -1952,14 +2778,14 @@ read_native(offs_t address, typename emu::detail::handler_entry_size<Width>::uX
template<int Width, int AddrShift, endianness_t Endian>
void emu::detail::memory_access_cache<Width, AddrShift, Endian>::
-write_native(offs_t address, typename emu::detail::handler_entry_size<Width>::uX data, typename emu::detail::handler_entry_size<Width>::uX mask)
+write_native(offs_t address, emu::detail::handler_entry_size_t<Width> data, emu::detail::handler_entry_size_t<Width> mask)
{
address &= m_addrmask;
check_address_w(address);
m_cache_w->write(address, data, mask);
}
-void memory_passthrough_handler::remove()
+inline void emu::detail::memory_passthrough_handler_impl::remove()
{
m_space.remove_passthrough(m_handlers);
}
@@ -1971,8 +2797,8 @@ set(address_space *space, std::pair<const void *, const void *> rw)
{
m_space = space;
m_addrmask = space->addrmask();
- m_dispatch_read = (const handler_entry_read <Width, AddrShift, Endian> *const *)(rw.first);
- m_dispatch_write = (const handler_entry_write<Width, AddrShift, Endian> *const *)(rw.second);
+ m_dispatch_read = (const handler_entry_read <Width, AddrShift> *const *)(rw.first);
+ m_dispatch_write = (const handler_entry_write<Width, AddrShift> *const *)(rw.second);
}
@@ -1983,20 +2809,21 @@ set(address_space *space, std::pair<void *, void *> rw)
m_space = space;
m_addrmask = space->addrmask();
- space->add_change_notifier([this](read_or_write mode) {
- if(u32(mode) & u32(read_or_write::READ)) {
- m_addrend_r = 0;
- m_addrstart_r = 1;
- m_cache_r = nullptr;
- }
- if(u32(mode) & u32(read_or_write::WRITE)) {
- m_addrend_w = 0;
- m_addrstart_w = 1;
- m_cache_w = nullptr;
- }
- });
- m_root_read = (handler_entry_read <Width, AddrShift, Endian> *)(rw.first);
- m_root_write = (handler_entry_write<Width, AddrShift, Endian> *)(rw.second);
+ m_subscription = space->add_change_notifier(
+ [this] (read_or_write mode) {
+ if(u32(mode) & u32(read_or_write::READ)) {
+ m_addrend_r = 0;
+ m_addrstart_r = 1;
+ m_cache_r = nullptr;
+ }
+ if(u32(mode) & u32(read_or_write::WRITE)) {
+ m_addrend_w = 0;
+ m_addrstart_w = 1;
+ m_cache_w = nullptr;
+ }
+ });
+ m_root_read = (handler_entry_read <Width, AddrShift> *)(rw.first);
+ m_root_write = (handler_entry_write<Width, AddrShift> *)(rw.second);
// Protect against a wandering memset
m_addrstart_r = 1;