summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu')
-rw-r--r--src/emu/addrmap.cpp77
-rw-r--r--src/emu/addrmap.h10
-rw-r--r--src/emu/debug/debugcmd.cpp11
-rw-r--r--src/emu/emufwd.h1
-rw-r--r--src/emu/emumem.cpp1327
-rw-r--r--src/emu/emumem.h388
-rw-r--r--src/emu/emumem_aspace.cpp1200
-rw-r--r--src/emu/emumem_hedr.h26
-rw-r--r--src/emu/emumem_hedr.ipp320
-rw-r--r--src/emu/emumem_hedr0.cpp26
-rw-r--r--src/emu/emumem_hedw.h26
-rw-r--r--src/emu/emumem_hedw.ipp318
-rw-r--r--src/emu/emumem_hedw0.cpp30
-rw-r--r--src/emu/emumem_heu.cpp30
-rw-r--r--src/emu/emumem_heu.h4
-rw-r--r--src/emu/emumem_mview.cpp995
16 files changed, 3212 insertions, 1577 deletions
diff --git a/src/emu/addrmap.cpp b/src/emu/addrmap.cpp
index ebc0331a767..246a4306d87 100644
--- a/src/emu/addrmap.cpp
+++ b/src/emu/addrmap.cpp
@@ -19,39 +19,6 @@
#define DETECT_OVERLAPPING_MEMORY (0)
-/*-------------------------------------------------
- core_i64_hex_format - i64 format printf helper
- why isn't fatalerror going through the same
- channels as logerror exactly?
--------------------------------------------------*/
-
-static char *core_i64_hex_format(u64 value, u8 mindigits)
-{
- static char buffer[16][64];
- // TODO: this can overflow - e.g. when a lot of unmapped writes are logged
- static int index;
- char *bufbase = &buffer[index++ % 16][0];
- char *bufptr = bufbase;
- s8 curdigit;
-
- for (curdigit = 15; curdigit >= 0; curdigit--)
- {
- int nibble = (value >> (curdigit * 4)) & 0xf;
- if (nibble != 0 || curdigit < mindigits)
- {
- mindigits = curdigit;
- *bufptr++ = "0123456789ABCDEF"[nibble];
- }
- }
- if (bufptr == bufbase)
- *bufptr++ = '0';
- *bufptr = 0;
-
- return bufbase;
-}
-
-
-
//**************************************************************************
// ADDRESS MAP ENTRY
//**************************************************************************
@@ -201,6 +168,15 @@ address_map_entry &address_map_entry::m(device_t *device, address_map_constructo
return *this;
}
+void address_map_entry::view(memory_view &mv)
+{
+ m_read.m_type = AMH_VIEW;
+ m_read.m_tag = nullptr;
+ m_write.m_type = AMH_VIEW;
+ m_write.m_tag = nullptr;
+ m_view = &mv;
+ mv.initialize_from_address_map(m_addrstart, m_addrend, m_map.get_config());
+}
//-------------------------------------------------
// r/w/rw - handler setters for
@@ -787,8 +763,9 @@ bool address_map_entry::unitmask_is_appropriate(u8 width, u64 unitmask, const ch
address_map::address_map(device_t &device, int spacenum)
: m_spacenum(spacenum),
m_device(&device),
+ m_view(nullptr),
m_unmapval(0),
- m_globalmask(0)
+ m_globalmask(0)
{
// get our memory interface
const device_memory_interface *memintf;
@@ -796,8 +773,8 @@ address_map::address_map(device_t &device, int spacenum)
throw emu_fatalerror("No memory interface defined for device '%s'\n", m_device->tag());
// and then the configuration for the current address space
- const address_space_config *spaceconfig = memintf->space_config(spacenum);
- if (spaceconfig == nullptr)
+ m_config = memintf->space_config(spacenum);
+ if (m_config == nullptr)
throw emu_fatalerror("No memory address space configuration found for device '%s', space %d\n", m_device->tag(), spacenum);
// append the map provided by the owner
@@ -809,8 +786,8 @@ address_map::address_map(device_t &device, int spacenum)
}
// construct the internal device map (last so it takes priority)
- if (!spaceconfig->m_internal_map.isnull())
- spaceconfig->m_internal_map(*this);
+ if (!m_config->m_internal_map.isnull())
+ m_config->m_internal_map(*this);
}
@@ -822,6 +799,7 @@ address_map::address_map(device_t &device, int spacenum)
address_map::address_map(device_t &device, address_map_entry *entry)
: m_spacenum(AS_PROGRAM),
m_device(&device),
+ m_view(nullptr),
m_unmapval(0),
m_globalmask(0)
{
@@ -839,6 +817,7 @@ address_map::address_map(device_t &device, address_map_entry *entry)
address_map::address_map(const address_space &space, offs_t start, offs_t end, u64 unitmask, int cswidth, device_t &device, address_map_constructor submap_delegate)
: m_spacenum(space.spacenum()),
m_device(&device),
+ m_view(nullptr),
m_unmapval(space.unmap()),
m_globalmask(space.addrmask())
{
@@ -846,6 +825,21 @@ address_map::address_map(const address_space &space, offs_t start, offs_t end, u
}
+//----------------------------------------------------------
+// address_map - constructor memory view mapping case
+//----------------------------------------------------------
+
+address_map::address_map(memory_view &view)
+ : m_spacenum(-1),
+ m_device(&view.m_device),
+ m_view(&view),
+ m_config(view.m_config),
+ m_unmapval(0),
+ m_globalmask(0)
+{
+}
+
+
//-------------------------------------------------
// ~address_map - destructor
//-------------------------------------------------
@@ -981,7 +975,7 @@ void address_map::import_submaps(running_machine &machine, device_t &owner, int
subentry_ratio ++;
subentry_ratio = data_width / subentry_ratio;
if (ratio * subentry_ratio > data_width / 8)
- fatalerror("import_submap: In range %x-%x mask %x mirror %x select %x of device %s, the import unitmask of %s combined with an entry unitmask of %s does not fit in %d bits.\n", subentry->m_addrstart, subentry->m_addrend, subentry->m_addrmask, subentry->m_addrmirror, subentry->m_addrselect, entry->m_read.m_tag, core_i64_hex_format(entry->m_mask, data_width/4), core_i64_hex_format(subentry->m_mask, data_width/4), data_width);
+ fatalerror("import_submap: In range %x-%x mask %x mirror %x select %x of device %s, the import unitmask of %0*x combined with an entry unitmask of %0*x does not fit in %d bits.\n", subentry->m_addrstart, subentry->m_addrend, subentry->m_addrmask, subentry->m_addrmirror, subentry->m_addrselect, entry->m_read.m_tag, data_width/4, entry->m_mask, data_width/4, subentry->m_mask, data_width);
// Regenerate the unitmask
u64 newmask = 0;
@@ -1394,3 +1388,8 @@ void address_map::map_validity_check(validity_checker &valid, int spacenum) cons
valid.validate_tag(entry.m_share);
}
}
+
+const address_space_config &address_map::get_config() const
+{
+ return *m_config;
+}
diff --git a/src/emu/addrmap.h b/src/emu/addrmap.h
index 229db15caa1..6f2f903306d 100644
--- a/src/emu/addrmap.h
+++ b/src/emu/addrmap.h
@@ -40,7 +40,8 @@ enum map_handler_type
AMH_DEVICE_DELEGATE_SMO,
AMH_PORT,
AMH_BANK,
- AMH_DEVICE_SUBMAP
+ AMH_DEVICE_SUBMAP,
+ AMH_VIEW
};
@@ -184,6 +185,8 @@ public:
address_map_entry &m(const char *tag, address_map_constructor func);
address_map_entry &m(device_t *device, address_map_constructor func);
+ // view initialization
+ void view(memory_view &mv);
// implicit base -> delegate converter
template <typename T, typename Ret, typename... Params>
@@ -404,6 +407,7 @@ public:
device_t *m_submap_device;
address_map_constructor m_submap_delegate;
+ memory_view *m_view;
// information used during processing
void * m_memory; // pointer to memory backing this entry
@@ -477,6 +481,7 @@ class address_map
public:
// construction/destruction
address_map(device_t &device, int spacenum);
+ address_map(memory_view &view);
address_map(device_t &device, address_map_entry *entry);
address_map(const address_space &space, offs_t start, offs_t end, u64 unitmask, int cswidth, device_t &device, address_map_constructor submap_delegate);
~address_map();
@@ -492,12 +497,15 @@ public:
// public data
int m_spacenum; // space number of the map
device_t * m_device; // associated device
+ memory_view * m_view; // view, when in one
+ const address_space_config * m_config; // space configuration
u8 m_unmapval; // unmapped memory value
offs_t m_globalmask; // global mask
simple_list<address_map_entry> m_entrylist; // list of entries
void import_submaps(running_machine &machine, device_t &owner, int data_width, endianness_t endian, int addr_shift);
void map_validity_check(validity_checker &valid, int spacenum) const;
+ const address_space_config &get_config() const;
};
#endif // MAME_EMU_ADDRMAP_H
diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp
index a5856a9b794..949f1194061 100644
--- a/src/emu/debug/debugcmd.cpp
+++ b/src/emu/debug/debugcmd.cpp
@@ -3767,10 +3767,15 @@ void debugger_commands::execute_memdump(int ref, const std::vector<std::string>
for (memory_entry &entry : entries[mode])
{
if (octal)
- fprintf(file, "%0*o - %0*o", nc, entry.start, nc, entry.end);
+ fprintf(file, "%0*o - %0*o:", nc, entry.start, nc, entry.end);
else
- fprintf(file, "%0*x - %0*x", nc, entry.start, nc, entry.end);
- fprintf(file, ": %s\n", entry.entry->name().c_str());
+ fprintf(file, "%0*x - %0*x:", nc, entry.start, nc, entry.end);
+ for(const auto &c : entry.context)
+ if(c.disabled)
+ fprintf(file, " %s[off]", c.view->name().c_str());
+ else
+ fprintf(file, " %s[%d]", c.view->name().c_str(), c.slot);
+ fprintf(file, " %s\n", entry.entry->name().c_str());
}
fprintf(file, "\n");
}
diff --git a/src/emu/emufwd.h b/src/emu/emufwd.h
index be33acf32ed..1b6b48af522 100644
--- a/src/emu/emufwd.h
+++ b/src/emu/emufwd.h
@@ -149,6 +149,7 @@ class memory_bank;
class memory_manager;
class memory_region;
class memory_share;
+class memory_view;
// declared in emuopts.h
class emu_options;
diff --git a/src/emu/emumem.cpp b/src/emu/emumem.cpp
index 4e8bfb26363..51eab43fcf7 100644
--- a/src/emu/emumem.cpp
+++ b/src/emu/emumem.cpp
@@ -48,6 +48,16 @@ void handler_entry::dump_map(std::vector<memory_entry> &map) const
fatalerror("dump_map called on non-dispatching class\n");
}
+void handler_entry::select_a(int slot)
+{
+ fatalerror("select_a called on non-view\n");
+}
+
+void handler_entry::select_u(int slot)
+{
+ fatalerror("select_u called on non-view\n");
+}
+
void handler_entry::reflist::add(const handler_entry *entry)
{
refcounts[entry]++;
@@ -132,11 +142,22 @@ template<int Width, int AddrShift, endianness_t Endian> void *handler_entry_read
return nullptr;
}
+template<int Width, int AddrShift, endianness_t Endian> handler_entry_read<Width, AddrShift, Endian> *handler_entry_read<Width, AddrShift, Endian>::dup()
+{
+ ref();
+ return this;
+}
+
template<int Width, int AddrShift, endianness_t Endian> void handler_entry_read<Width, AddrShift, Endian>::detach(const std::unordered_set<handler_entry *> &handlers)
{
fatalerror("detach called on non-dispatching class\n");
}
+template<int Width, int AddrShift, endianness_t Endian> void handler_entry_read<Width, AddrShift, Endian>::init_handlers(offs_t start_entry, offs_t end_entry, u32 lowbits, handler_entry_read<Width, AddrShift, Endian> **dispatch, handler_entry::range *ranges)
+{
+ fatalerror("init_handlers called on non-view class\n");
+}
+
template<int Width, int AddrShift, endianness_t Endian> const handler_entry_write<Width, AddrShift, Endian> *const *handler_entry_write<Width, AddrShift, Endian>::get_dispatch() const
{
@@ -183,651 +204,75 @@ template<int Width, int AddrShift, endianness_t Endian> void *handler_entry_writ
return nullptr;
}
-template<int Width, int AddrShift, endianness_t Endian> void handler_entry_write<Width, AddrShift, Endian>::detach(const std::unordered_set<handler_entry *> &handlers)
+template<int Width, int AddrShift, endianness_t Endian> handler_entry_write<Width, AddrShift, Endian> *handler_entry_write<Width, AddrShift, Endian>::dup()
{
- fatalerror("detach called on non-dispatching class\n");
+ ref();
+ return this;
}
-
-
-/*-------------------------------------------------
- core_i64_hex_format - i64 format printf helper
--------------------------------------------------*/
-
-static char *core_i64_hex_format(u64 value, u8 mindigits)
+template<int Width, int AddrShift, endianness_t Endian> void handler_entry_write<Width, AddrShift, Endian>::detach(const std::unordered_set<handler_entry *> &handlers)
{
- static char buffer[16][64];
- // TODO: this can overflow - e.g. when a lot of unmapped writes are logged
- static int index;
- char *bufbase = &buffer[index++ % 16][0];
- char *bufptr = bufbase;
- s8 curdigit;
-
- for (curdigit = 15; curdigit >= 0; curdigit--)
- {
- int nibble = (value >> (curdigit * 4)) & 0xf;
- if (nibble != 0 || curdigit < mindigits)
- {
- mindigits = curdigit;
- *bufptr++ = "0123456789ABCDEF"[nibble];
- }
- }
- if (bufptr == bufbase)
- *bufptr++ = '0';
- *bufptr = 0;
-
- return bufbase;
+ fatalerror("detach called on non-dispatching class\n");
}
-
-
-//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-namespace {
-
-template <typename Delegate> struct handler_width;
-template <> struct handler_width<read8_delegate> { static constexpr int value = 0; };
-template <> struct handler_width<read8m_delegate> { static constexpr int value = 0; };
-template <> struct handler_width<read8s_delegate> { static constexpr int value = 0; };
-template <> struct handler_width<read8sm_delegate> { static constexpr int value = 0; };
-template <> struct handler_width<read8mo_delegate> { static constexpr int value = 0; };
-template <> struct handler_width<read8smo_delegate> { static constexpr int value = 0; };
-template <> struct handler_width<write8_delegate> { static constexpr int value = 0; };
-template <> struct handler_width<write8m_delegate> { static constexpr int value = 0; };
-template <> struct handler_width<write8s_delegate> { static constexpr int value = 0; };
-template <> struct handler_width<write8sm_delegate> { static constexpr int value = 0; };
-template <> struct handler_width<write8mo_delegate> { static constexpr int value = 0; };
-template <> struct handler_width<write8smo_delegate> { static constexpr int value = 0; };
-template <> struct handler_width<read16_delegate> { static constexpr int value = 1; };
-template <> struct handler_width<read16m_delegate> { static constexpr int value = 1; };
-template <> struct handler_width<read16s_delegate> { static constexpr int value = 1; };
-template <> struct handler_width<read16sm_delegate> { static constexpr int value = 1; };
-template <> struct handler_width<read16mo_delegate> { static constexpr int value = 1; };
-template <> struct handler_width<read16smo_delegate> { static constexpr int value = 1; };
-template <> struct handler_width<write16_delegate> { static constexpr int value = 1; };
-template <> struct handler_width<write16m_delegate> { static constexpr int value = 1; };
-template <> struct handler_width<write16s_delegate> { static constexpr int value = 1; };
-template <> struct handler_width<write16sm_delegate> { static constexpr int value = 1; };
-template <> struct handler_width<write16mo_delegate> { static constexpr int value = 1; };
-template <> struct handler_width<write16smo_delegate> { static constexpr int value = 1; };
-template <> struct handler_width<read32_delegate> { static constexpr int value = 2; };
-template <> struct handler_width<read32m_delegate> { static constexpr int value = 2; };
-template <> struct handler_width<read32s_delegate> { static constexpr int value = 2; };
-template <> struct handler_width<read32sm_delegate> { static constexpr int value = 2; };
-template <> struct handler_width<read32mo_delegate> { static constexpr int value = 2; };
-template <> struct handler_width<read32smo_delegate> { static constexpr int value = 2; };
-template <> struct handler_width<write32_delegate> { static constexpr int value = 2; };
-template <> struct handler_width<write32m_delegate> { static constexpr int value = 2; };
-template <> struct handler_width<write32s_delegate> { static constexpr int value = 2; };
-template <> struct handler_width<write32sm_delegate> { static constexpr int value = 2; };
-template <> struct handler_width<write32mo_delegate> { static constexpr int value = 2; };
-template <> struct handler_width<write32smo_delegate> { static constexpr int value = 2; };
-template <> struct handler_width<read64_delegate> { static constexpr int value = 3; };
-template <> struct handler_width<read64m_delegate> { static constexpr int value = 3; };
-template <> struct handler_width<read64s_delegate> { static constexpr int value = 3; };
-template <> struct handler_width<read64sm_delegate> { static constexpr int value = 3; };
-template <> struct handler_width<read64mo_delegate> { static constexpr int value = 3; };
-template <> struct handler_width<read64smo_delegate> { static constexpr int value = 3; };
-template <> struct handler_width<write64_delegate> { static constexpr int value = 3; };
-template <> struct handler_width<write64m_delegate> { static constexpr int value = 3; };
-template <> struct handler_width<write64s_delegate> { static constexpr int value = 3; };
-template <> struct handler_width<write64sm_delegate> { static constexpr int value = 3; };
-template <> struct handler_width<write64mo_delegate> { static constexpr int value = 3; };
-template <> struct handler_width<write64smo_delegate> { static constexpr int value = 3; };
-} // anonymous namespace
-
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> address_space_specific
-
-// this is a derived class of address_space with specific width, endianness, and table size
-template<int Level, int Width, int AddrShift, endianness_t Endian>
-class address_space_specific : public address_space
-{
- using uX = typename emu::detail::handler_entry_size<Width>::uX;
- using NativeType = uX;
- using this_type = address_space_specific<Level, Width, AddrShift, Endian>;
-
- // constants describing the native size
- static constexpr u32 NATIVE_BYTES = 1 << Width;
- static constexpr u32 NATIVE_STEP = AddrShift >= 0 ? NATIVE_BYTES << iabs(AddrShift) : NATIVE_BYTES >> iabs(AddrShift);
- static constexpr u32 NATIVE_MASK = NATIVE_STEP - 1;
- static constexpr u32 NATIVE_BITS = 8 * NATIVE_BYTES;
-
- static constexpr offs_t offset_to_byte(offs_t offset) { return AddrShift < 0 ? offset << iabs(AddrShift) : offset >> iabs(AddrShift); }
-
-public:
- const handler_entry_read<Width, AddrShift, Endian> *const *m_dispatch_read;
- const handler_entry_write<Width, AddrShift, Endian> *const *m_dispatch_write;
-
- std::string get_handler_string(read_or_write readorwrite, offs_t byteaddress) const override;
- void dump_maps(std::vector<memory_entry> &read_map, std::vector<memory_entry> &write_map) const override;
-
- void unmap_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, read_or_write readorwrite, bool quiet) override;
- void install_ram_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, read_or_write readorwrite, void *baseptr) override;
- void install_bank_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_bank *rbank, memory_bank *wbank) override;
- void install_readwrite_port(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string rtag, std::string wtag) override;
- void install_device_delegate(offs_t addrstart, offs_t addrend, device_t &device, address_map_constructor &map, u64 unitmask = 0, int cswidth = 0) override;
-
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
-
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
-
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
-
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
-
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
-
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
- 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) override
- { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
- 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) override
- { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
- 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) override
- { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
-
- using address_space::install_read_tap;
- using address_space::install_write_tap;
- using address_space::install_readwrite_tap;
-
- 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, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) override;
- 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, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) override;
- 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, uX &data, uX mem_mask)> tapr, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapw, memory_passthrough_handler *mph) override;
-
- // construction/destruction
- address_space_specific(memory_manager &manager, device_memory_interface &memory, int spacenum, int address_width)
- : address_space(manager, memory, spacenum)
- {
- m_unmap_r = new handler_entry_read_unmapped <Width, AddrShift, Endian>(this);
- m_unmap_w = new handler_entry_write_unmapped<Width, AddrShift, Endian>(this);
- m_nop_r = new handler_entry_read_nop <Width, AddrShift, Endian>(this);
- m_nop_w = new handler_entry_write_nop<Width, AddrShift, Endian>(this);
-
- handler_entry::range r{ 0, 0xffffffff >> (32 - address_width) };
-
- switch (address_width) {
- case 1: m_root_read = new handler_entry_read_dispatch< std::max(1, Width), Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< std::max(1, Width), Width, AddrShift, Endian>(this, r, nullptr); break;
- case 2: m_root_read = new handler_entry_read_dispatch< std::max(2, Width), Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< std::max(2, Width), Width, AddrShift, Endian>(this, r, nullptr); break;
- case 3: m_root_read = new handler_entry_read_dispatch< std::max(3, Width), Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< std::max(3, Width), Width, AddrShift, Endian>(this, r, nullptr); break;
- case 4: m_root_read = new handler_entry_read_dispatch< 4, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< 4, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 5: m_root_read = new handler_entry_read_dispatch< 5, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< 5, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 6: m_root_read = new handler_entry_read_dispatch< 6, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< 6, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 7: m_root_read = new handler_entry_read_dispatch< 7, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< 7, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 8: m_root_read = new handler_entry_read_dispatch< 8, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< 8, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 9: m_root_read = new handler_entry_read_dispatch< 9, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< 9, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 10: m_root_read = new handler_entry_read_dispatch<10, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<10, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 11: m_root_read = new handler_entry_read_dispatch<11, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<11, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 12: m_root_read = new handler_entry_read_dispatch<12, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<12, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 13: m_root_read = new handler_entry_read_dispatch<13, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<13, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 14: m_root_read = new handler_entry_read_dispatch<14, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<14, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 15: m_root_read = new handler_entry_read_dispatch<15, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<15, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 16: m_root_read = new handler_entry_read_dispatch<16, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<16, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 17: m_root_read = new handler_entry_read_dispatch<17, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<17, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 18: m_root_read = new handler_entry_read_dispatch<18, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<18, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 19: m_root_read = new handler_entry_read_dispatch<19, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<19, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 20: m_root_read = new handler_entry_read_dispatch<20, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<20, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 21: m_root_read = new handler_entry_read_dispatch<21, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<21, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 22: m_root_read = new handler_entry_read_dispatch<22, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<22, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 23: m_root_read = new handler_entry_read_dispatch<23, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<23, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 24: m_root_read = new handler_entry_read_dispatch<24, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<24, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 25: m_root_read = new handler_entry_read_dispatch<25, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<25, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 26: m_root_read = new handler_entry_read_dispatch<26, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<26, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 27: m_root_read = new handler_entry_read_dispatch<27, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<27, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 28: m_root_read = new handler_entry_read_dispatch<28, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<28, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 29: m_root_read = new handler_entry_read_dispatch<29, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<29, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 30: m_root_read = new handler_entry_read_dispatch<30, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<30, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 31: m_root_read = new handler_entry_read_dispatch<31, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<31, Width, AddrShift, Endian>(this, r, nullptr); break;
- case 32: m_root_read = new handler_entry_read_dispatch<32, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<32, Width, AddrShift, Endian>(this, r, nullptr); break;
- default: fatalerror("Unhandled address bus width %d\n", address_width);
- }
-
- m_dispatch_read = m_root_read ->get_dispatch();
- m_dispatch_write = m_root_write->get_dispatch();
- }
-
- ~address_space_specific() {
- m_root_read->unref();
- m_root_write->unref();
- }
-
- std::pair<void *, void *> get_cache_info() override {
- std::pair<void *, void *> rw;
- rw.first = m_root_read;
- rw.second = m_root_write;
- return rw;
- }
-
- std::pair<const void *, const void *> get_specific_info() override {
- std::pair<const void *, const void *> rw;
- rw.first = m_dispatch_read;
- rw.second = m_dispatch_write;
- return rw;
- }
-
- void delayed_ref(handler_entry *e) {
- e->ref();
- m_delayed_unrefs.insert(e);
- }
-
- void delayed_unref(handler_entry *e) {
- m_delayed_unrefs.erase(m_delayed_unrefs.find(e));
- e->unref();
- }
-
- void validate_reference_counts() const override {
- handler_entry::reflist refs;
- refs.add(m_root_read);
- refs.add(m_root_write);
- refs.add(m_unmap_r);
- refs.add(m_unmap_w);
- refs.add(m_nop_r);
- refs.add(m_nop_w);
- for(handler_entry *e : m_delayed_unrefs)
- refs.add(e);
- refs.propagate();
- refs.check();
- }
-
- virtual void remove_passthrough(std::unordered_set<handler_entry *> &handlers) override {
- invalidate_caches(read_or_write::READWRITE);
- m_root_read->detach(handlers);
- m_root_write->detach(handlers);
- }
-
- // generate accessor table
- virtual void accessors(data_accessors &accessors) const override
- {
- accessors.read_byte = reinterpret_cast<u8 (*)(address_space &, offs_t)>(&read_byte_static);
- accessors.read_word = reinterpret_cast<u16 (*)(address_space &, offs_t)>(&read_word_static);
- accessors.read_word_masked = reinterpret_cast<u16 (*)(address_space &, offs_t, u16)>(&read_word_masked_static);
- accessors.read_dword = reinterpret_cast<u32 (*)(address_space &, offs_t)>(&read_dword_static);
- accessors.read_dword_masked = reinterpret_cast<u32 (*)(address_space &, offs_t, u32)>(&read_dword_masked_static);
- accessors.read_qword = reinterpret_cast<u64 (*)(address_space &, offs_t)>(&read_qword_static);
- accessors.read_qword_masked = reinterpret_cast<u64 (*)(address_space &, offs_t, u64)>(&read_qword_masked_static);
- accessors.write_byte = reinterpret_cast<void (*)(address_space &, offs_t, u8)>(&write_byte_static);
- accessors.write_word = reinterpret_cast<void (*)(address_space &, offs_t, u16)>(&write_word_static);
- accessors.write_word_masked = reinterpret_cast<void (*)(address_space &, offs_t, u16, u16)>(&write_word_masked_static);
- accessors.write_dword = reinterpret_cast<void (*)(address_space &, offs_t, u32)>(&write_dword_static);
- accessors.write_dword_masked = reinterpret_cast<void (*)(address_space &, offs_t, u32, u32)>(&write_dword_masked_static);
- accessors.write_qword = reinterpret_cast<void (*)(address_space &, offs_t, u64)>(&write_qword_static);
- accessors.write_qword_masked = reinterpret_cast<void (*)(address_space &, offs_t, u64, u64)>(&write_qword_masked_static);
- }
-
- // return a pointer to the read bank, or nullptr if none
- virtual void *get_read_ptr(offs_t address) const override
- {
- return m_root_read->get_ptr(address);
- }
-
- // return a pointer to the write bank, or nullptr if none
- virtual void *get_write_ptr(offs_t address) const override
- {
- return m_root_write->get_ptr(address);
- }
-
- // native read
- NativeType read_native(offs_t offset, NativeType mask)
- {
- return dispatch_read<Level, Width, AddrShift, Endian>(offs_t(-1), offset & m_addrmask, mask, m_dispatch_read);
- }
-
- // mask-less native read
- NativeType read_native(offs_t offset)
- {
- return dispatch_read<Level, Width, AddrShift, Endian>(offs_t(-1), offset & m_addrmask, uX(0xffffffffffffffffU), m_dispatch_read);
- }
-
- // native write
- void write_native(offs_t offset, NativeType data, NativeType mask)
- {
- dispatch_write<Level, Width, AddrShift, Endian>(offs_t(-1), offset & m_addrmask, data, mask, m_dispatch_write);
- }
-
- // mask-less native write
- void write_native(offs_t offset, NativeType data)
- {
- dispatch_write<Level, Width, AddrShift, Endian>(offs_t(-1), offset & m_addrmask, data, uX(0xffffffffffffffffU), m_dispatch_write);
- }
-
- // virtual access to these functions
- u8 read_byte(offs_t address) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { memory_write_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
-
- // static access to these functions
- static u8 read_byte_static(this_type &space, offs_t address) { return Width == 0 ? space.read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 0, true>([&space](offs_t offset, NativeType mask) -> NativeType { return space.read_native(offset, mask); }, address, 0xff); }
- static u16 read_word_static(this_type &space, offs_t address) { return Width == 1 ? space.read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 1, true>([&space](offs_t offset, NativeType mask) -> NativeType { return space.read_native(offset, mask); }, address, 0xffff); }
- static u16 read_word_masked_static(this_type &space, offs_t address, u16 mask) { return memory_read_generic<Width, AddrShift, Endian, 1, true>([&space](offs_t offset, NativeType mask) -> NativeType { return space.read_native(offset, mask); }, address, mask); }
- static u32 read_dword_static(this_type &space, offs_t address) { return Width == 2 ? space.read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 2, true>([&space](offs_t offset, NativeType mask) -> NativeType { return space.read_native(offset, mask); }, address, 0xffffffff); }
- static u32 read_dword_masked_static(this_type &space, offs_t address, u32 mask) { return memory_read_generic<Width, AddrShift, Endian, 2, true>([&space](offs_t offset, NativeType mask) -> NativeType { return space.read_native(offset, mask); }, address, mask); }
- static u64 read_qword_static(this_type &space, offs_t address) { return Width == 3 ? space.read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 3, true>([&space](offs_t offset, NativeType mask) -> NativeType { return space.read_native(offset, mask); }, address, 0xffffffffffffffffU); }
- static u64 read_qword_masked_static(this_type &space, offs_t address, u64 mask) { return memory_read_generic<Width, AddrShift, Endian, 3, true>([&space](offs_t offset, NativeType mask) -> NativeType { return space.read_native(offset, mask); }, address, mask); }
- static void write_byte_static(this_type &space, offs_t address, u8 data) { if (Width == 0) space.write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 0, true>([&space](offs_t offset, NativeType data, NativeType mask) { space.write_native(offset, data, mask); }, address, data, 0xff); }
- static void write_word_static(this_type &space, offs_t address, u16 data) { if (Width == 1) space.write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 1, true>([&space](offs_t offset, NativeType data, NativeType mask) { space.write_native(offset, data, mask); }, address, data, 0xffff); }
- static void write_word_masked_static(this_type &space, offs_t address, u16 data, u16 mask) { memory_write_generic<Width, AddrShift, Endian, 1, true>([&space](offs_t offset, NativeType data, NativeType mask) { space.write_native(offset, data, mask); }, address, data, mask); }
- static void write_dword_static(this_type &space, offs_t address, u32 data) { if (Width == 2) space.write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 2, true>([&space](offs_t offset, NativeType data, NativeType mask) { space.write_native(offset, data, mask); }, address, data, 0xffffffff); }
- static void write_dword_masked_static(this_type &space, offs_t address, u32 data, u32 mask) { memory_write_generic<Width, AddrShift, Endian, 2, true>([&space](offs_t offset, NativeType data, NativeType mask) { space.write_native(offset, data, mask); }, address, data, mask); }
- static void write_qword_static(this_type &space, offs_t address, u64 data) { if (Width == 3) space.write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 3, false>([&space](offs_t offset, NativeType data, NativeType mask) { space.write_native(offset, data, mask); }, address, data, 0xffffffffffffffffU); }
- static void write_qword_masked_static(this_type &space, offs_t address, u64 data, u64 mask) { memory_write_generic<Width, AddrShift, Endian, 3, false>([&space](offs_t offset, NativeType data, NativeType mask) { space.write_native(offset, data, mask); }, address, data, mask); }
-
- handler_entry_read <Width, AddrShift, Endian> *m_root_read;
- handler_entry_write<Width, AddrShift, Endian> *m_root_write;
-
- std::unordered_set<handler_entry *> m_delayed_unrefs;
-
-private:
- template<typename READ>
- void install_read_handler_impl(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, READ &handler_r)
- {
- try { handler_r.resolve(); }
- catch (const binding_type_exception &) {
- osd_printf_error("Binding error while installing read handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_r.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask);
- throw;
- }
- install_read_handler_helper<handler_width<READ>::value>(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, handler_r);
- }
-
- template<typename WRITE>
- void install_write_handler_impl(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, WRITE &handler_w)
- {
- try { handler_w.resolve(); }
- catch (const binding_type_exception &) {
- osd_printf_error("Binding error while installing write handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_w.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask);
- throw;
- }
- install_write_handler_helper<handler_width<WRITE>::value>(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, handler_w);
- }
-
- template<typename READ, typename WRITE>
- void install_readwrite_handler_impl(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, READ &handler_r, WRITE &handler_w)
- {
- static_assert(handler_width<READ>::value == handler_width<WRITE>::value, "handler widths do not match");
- try { handler_r.resolve(); }
- catch (const binding_type_exception &) {
- osd_printf_error("Binding error while installing read handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_r.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask);
- throw;
- }
- try { handler_w.resolve(); }
- catch (const binding_type_exception &) {
- osd_printf_error("Binding error while installing write handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_w.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask);
- throw;
- }
- install_readwrite_handler_helper<handler_width<READ>::value>(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, handler_r, handler_w);
- }
-
-
- template<int AccessWidth, typename READ>
- void install_read_handler_helper(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, const READ &handler_r)
- {
- if constexpr (Width < AccessWidth) {
- fatalerror("install_read_handler: cannot install a %d-wide handler in a %d-wide bus", 8 << AccessWidth, 8 << Width);
- } else {
- VPRINTF("address_space::install_read_handler(%*x-%*x mask=%*x mirror=%*x, space width=%d, handler width=%d, %s, %*x)\n",
- m_addrchars, addrstart, m_addrchars, addrend,
- m_addrchars, addrmask, m_addrchars, addrmirror,
- 8 << Width, 8 << AccessWidth,
- handler_r.name(), data_width() / 4, unitmask);
-
- offs_t nstart, nend, nmask, nmirror;
- u64 nunitmask;
- int ncswidth;
- check_optimize_all("install_read_handler", 8 << AccessWidth, addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, nstart, nend, nmask, nmirror, nunitmask, ncswidth);
-
- if constexpr (Width == AccessWidth) {
- auto hand_r = new handler_entry_read_delegate<Width, AddrShift, Endian, READ>(this, handler_r);
- hand_r->set_address_info(nstart, nmask);
- m_root_read->populate(nstart, nend, nmirror, hand_r);
- } else {
- auto hand_r = new handler_entry_read_delegate<AccessWidth, -AccessWidth, Endian, READ>(this, handler_r);
- memory_units_descriptor<Width, AddrShift, Endian> descriptor(AccessWidth, Endian, hand_r, nstart, nend, nmask, nunitmask, ncswidth);
- hand_r->set_address_info(descriptor.get_handler_start(), descriptor.get_handler_mask());
- m_root_read->populate_mismatched(nstart, nend, nmirror, descriptor);
- hand_r->unref();
- }
- invalidate_caches(read_or_write::READ);
- }
- }
-
- template<int AccessWidth, typename WRITE>
- void install_write_handler_helper(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, const WRITE &handler_w)
- {
- if constexpr (Width < AccessWidth) {
- fatalerror("install_write_handler: cannot install a %d-wide handler in a %d-wide bus", 8 << AccessWidth, 8 << Width);
- } else {
- VPRINTF("address_space::install_write_handler(%*x-%*x mask=%*x mirror=%*x, space width=%d, handler width=%d, %s, %*x)\n",
- m_addrchars, addrstart, m_addrchars, addrend,
- m_addrchars, addrmask, m_addrchars, addrmirror,
- 8 << Width, 8 << AccessWidth,
- handler_w.name(), data_width() / 4, unitmask);
-
- offs_t nstart, nend, nmask, nmirror;
- u64 nunitmask;
- int ncswidth;
- check_optimize_all("install_write_handler", 8 << AccessWidth, addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, nstart, nend, nmask, nmirror, nunitmask, ncswidth);
-
- if constexpr (Width == AccessWidth) {
- auto hand_w = new handler_entry_write_delegate<Width, AddrShift, Endian, WRITE>(this, handler_w);
- hand_w->set_address_info(nstart, nmask);
- m_root_write->populate(nstart, nend, nmirror, hand_w);
- } else {
- auto hand_w = new handler_entry_write_delegate<AccessWidth, -AccessWidth, Endian, WRITE>(this, handler_w);
- memory_units_descriptor<Width, AddrShift, Endian> descriptor(AccessWidth, Endian, hand_w, nstart, nend, nmask, nunitmask, ncswidth);
- hand_w->set_address_info(descriptor.get_handler_start(), descriptor.get_handler_mask());
- m_root_write->populate_mismatched(nstart, nend, nmirror, descriptor);
- hand_w->unref();
- }
- invalidate_caches(read_or_write::WRITE);
- }
- }
-
- template<int AccessWidth, typename READ, typename WRITE>
- void install_readwrite_handler_helper(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth,
- const READ &handler_r,
- const WRITE &handler_w)
- {
- if constexpr (Width < AccessWidth) {
- fatalerror("install_readwrite_handler: cannot install a %d-wide handler in a %d-wide bus", 8 << AccessWidth, 8 << Width);
- } else {
- VPRINTF("address_space::install_readwrite_handler(%*x-%*x mask=%*x mirror=%*x, space width=%d, handler width=%d, %s, %s, %*x)\n",
- m_addrchars, addrstart, m_addrchars, addrend,
- m_addrchars, addrmask, m_addrchars, addrmirror,
- 8 << Width, 8 << AccessWidth,
- handler_r.name(), handler_w.name(), data_width() / 4, unitmask);
-
- offs_t nstart, nend, nmask, nmirror;
- u64 nunitmask;
- int ncswidth;
- check_optimize_all("install_readwrite_handler", 8 << AccessWidth, addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, nstart, nend, nmask, nmirror, nunitmask, ncswidth);
-
- if constexpr (Width == AccessWidth) {
- auto hand_r = new handler_entry_read_delegate <Width, AddrShift, Endian, READ>(this, handler_r);
- hand_r->set_address_info(nstart, nmask);
- m_root_read ->populate(nstart, nend, nmirror, hand_r);
-
- auto hand_w = new handler_entry_write_delegate<Width, AddrShift, Endian, WRITE>(this, handler_w);
- hand_w->set_address_info(nstart, nmask);
- m_root_write->populate(nstart, nend, nmirror, hand_w);
- } else {
- auto hand_r = new handler_entry_read_delegate <AccessWidth, -AccessWidth, Endian, READ>(this, handler_r);
- memory_units_descriptor<Width, AddrShift, Endian> descriptor(AccessWidth, Endian, hand_r, nstart, nend, nmask, nunitmask, ncswidth);
- hand_r->set_address_info(descriptor.get_handler_start(), descriptor.get_handler_mask());
- m_root_read ->populate_mismatched(nstart, nend, nmirror, descriptor);
- hand_r->unref();
-
- auto hand_w = new handler_entry_write_delegate<AccessWidth, -AccessWidth, Endian, WRITE>(this, handler_w);
- descriptor.set_subunit_handler(hand_w);
- hand_w->set_address_info(descriptor.get_handler_start(), descriptor.get_handler_mask());
- m_root_write->populate_mismatched(nstart, nend, nmirror, descriptor);
- hand_w->unref();
- }
- invalidate_caches(read_or_write::READWRITE);
- }
- }
-};
-
-
+template<int Width, int AddrShift, endianness_t Endian> void handler_entry_write<Width, AddrShift, Endian>::init_handlers(offs_t start_entry, offs_t end_entry, u32 lowbits, handler_entry_write<Width, AddrShift, Endian> **dispatch, handler_entry::range *ranges)
+{
+ fatalerror("init_handlers called on non-view class\n");
+}
+
+template class handler_entry_read<0, 1, ENDIANNESS_LITTLE>;
+template class handler_entry_read<0, 1, ENDIANNESS_BIG>;
+template class handler_entry_read<0, 0, ENDIANNESS_LITTLE>;
+template class handler_entry_read<0, 0, ENDIANNESS_BIG>;
+template class handler_entry_read<1, 3, ENDIANNESS_LITTLE>;
+template class handler_entry_read<1, 3, ENDIANNESS_BIG>;
+template class handler_entry_read<1, 0, ENDIANNESS_LITTLE>;
+template class handler_entry_read<1, 0, ENDIANNESS_BIG>;
+template class handler_entry_read<1, -1, ENDIANNESS_LITTLE>;
+template class handler_entry_read<1, -1, ENDIANNESS_BIG>;
+template class handler_entry_read<2, 3, ENDIANNESS_LITTLE>;
+template class handler_entry_read<2, 3, ENDIANNESS_BIG>;
+template class handler_entry_read<2, 0, ENDIANNESS_LITTLE>;
+template class handler_entry_read<2, 0, ENDIANNESS_BIG>;
+template class handler_entry_read<2, -1, ENDIANNESS_LITTLE>;
+template class handler_entry_read<2, -1, ENDIANNESS_BIG>;
+template class handler_entry_read<2, -2, ENDIANNESS_LITTLE>;
+template class handler_entry_read<2, -2, ENDIANNESS_BIG>;
+template class handler_entry_read<3, 0, ENDIANNESS_LITTLE>;
+template class handler_entry_read<3, 0, ENDIANNESS_BIG>;
+template class handler_entry_read<3, -1, ENDIANNESS_LITTLE>;
+template class handler_entry_read<3, -1, ENDIANNESS_BIG>;
+template class handler_entry_read<3, -2, ENDIANNESS_LITTLE>;
+template class handler_entry_read<3, -2, ENDIANNESS_BIG>;
+template class handler_entry_read<3, -3, ENDIANNESS_LITTLE>;
+template class handler_entry_read<3, -3, ENDIANNESS_BIG>;
+
+template class handler_entry_write<0, 1, ENDIANNESS_LITTLE>;
+template class handler_entry_write<0, 1, ENDIANNESS_BIG>;
+template class handler_entry_write<0, 0, ENDIANNESS_LITTLE>;
+template class handler_entry_write<0, 0, ENDIANNESS_BIG>;
+template class handler_entry_write<1, 3, ENDIANNESS_LITTLE>;
+template class handler_entry_write<1, 3, ENDIANNESS_BIG>;
+template class handler_entry_write<1, 0, ENDIANNESS_LITTLE>;
+template class handler_entry_write<1, 0, ENDIANNESS_BIG>;
+template class handler_entry_write<1, -1, ENDIANNESS_LITTLE>;
+template class handler_entry_write<1, -1, ENDIANNESS_BIG>;
+template class handler_entry_write<2, 3, ENDIANNESS_LITTLE>;
+template class handler_entry_write<2, 3, ENDIANNESS_BIG>;
+template class handler_entry_write<2, 0, ENDIANNESS_LITTLE>;
+template class handler_entry_write<2, 0, ENDIANNESS_BIG>;
+template class handler_entry_write<2, -1, ENDIANNESS_LITTLE>;
+template class handler_entry_write<2, -1, ENDIANNESS_BIG>;
+template class handler_entry_write<2, -2, ENDIANNESS_LITTLE>;
+template class handler_entry_write<2, -2, ENDIANNESS_BIG>;
+template class handler_entry_write<3, 0, ENDIANNESS_LITTLE>;
+template class handler_entry_write<3, 0, ENDIANNESS_BIG>;
+template class handler_entry_write<3, -1, ENDIANNESS_LITTLE>;
+template class handler_entry_write<3, -1, ENDIANNESS_BIG>;
+template class handler_entry_write<3, -2, ENDIANNESS_LITTLE>;
+template class handler_entry_write<3, -2, ENDIANNESS_BIG>;
+template class handler_entry_write<3, -3, ENDIANNESS_LITTLE>;
+template class handler_entry_write<3, -3, ENDIANNESS_BIG>;
//**************************************************************************
// MEMORY MANAGER
@@ -851,94 +296,6 @@ memory_manager::~memory_manager()
}
//-------------------------------------------------
-// allocate - allocate memory spaces
-//-------------------------------------------------
-
-void memory_manager::allocate(device_memory_interface &memory)
-{
- for (int spacenum = 0; spacenum < memory.max_space_count(); ++spacenum)
- {
- // if there is a configuration for this space, we need an address space
- address_space_config const *const spaceconfig = memory.space_config(spacenum);
- if (spaceconfig)
- {
- int level = emu::detail::handler_entry_dispatch_level(spaceconfig->addr_width());
- // allocate one of the appropriate type
- switch ((level << 8) | (spaceconfig->endianness() == ENDIANNESS_BIG ? 0x1000 : 0) |spaceconfig->data_width() | (spaceconfig->addr_shift() + 4))
- {
- case 0x0000|0x000| 8|(4+1): memory.allocate<address_space_specific<0, 0, 1, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x000| 8|(4+1): memory.allocate<address_space_specific<0, 0, 1, ENDIANNESS_BIG >>(*this, spacenum); break;
- case 0x0000|0x100| 8|(4+1): memory.allocate<address_space_specific<1, 0, 1, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x100| 8|(4+1): memory.allocate<address_space_specific<1, 0, 1, ENDIANNESS_BIG >>(*this, spacenum); break;
-
- case 0x0000|0x000| 8|(4-0): memory.allocate<address_space_specific<0, 0, 0, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x000| 8|(4-0): memory.allocate<address_space_specific<0, 0, 0, ENDIANNESS_BIG >>(*this, spacenum); break;
- case 0x0000|0x100| 8|(4-0): memory.allocate<address_space_specific<1, 0, 0, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x100| 8|(4-0): memory.allocate<address_space_specific<1, 0, 0, ENDIANNESS_BIG >>(*this, spacenum); break;
-
- case 0x0000|0x000|16|(4+3): memory.allocate<address_space_specific<0, 1, 3, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x000|16|(4+3): memory.allocate<address_space_specific<0, 1, 3, ENDIANNESS_BIG >>(*this, spacenum); break;
- case 0x0000|0x100|16|(4+3): memory.allocate<address_space_specific<1, 1, 3, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x100|16|(4+3): memory.allocate<address_space_specific<1, 1, 3, ENDIANNESS_BIG >>(*this, spacenum); break;
-
- case 0x0000|0x000|16|(4-0): memory.allocate<address_space_specific<0, 1, 0, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x000|16|(4-0): memory.allocate<address_space_specific<0, 1, 0, ENDIANNESS_BIG >>(*this, spacenum); break;
- case 0x0000|0x100|16|(4-0): memory.allocate<address_space_specific<1, 1, 0, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x100|16|(4-0): memory.allocate<address_space_specific<1, 1, 0, ENDIANNESS_BIG >>(*this, spacenum); break;
-
- case 0x0000|0x000|16|(4-1): memory.allocate<address_space_specific<0, 1, -1, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x000|16|(4-1): memory.allocate<address_space_specific<0, 1, -1, ENDIANNESS_BIG >>(*this, spacenum); break;
- case 0x0000|0x100|16|(4-1): memory.allocate<address_space_specific<1, 1, -1, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x100|16|(4-1): memory.allocate<address_space_specific<1, 1, -1, ENDIANNESS_BIG >>(*this, spacenum); break;
-
- case 0x0000|0x000|32|(4+3): memory.allocate<address_space_specific<0, 2, 3, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x000|32|(4+3): memory.allocate<address_space_specific<0, 2, 3, ENDIANNESS_BIG >>(*this, spacenum); break;
- case 0x0000|0x100|32|(4+3): memory.allocate<address_space_specific<1, 2, 3, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x100|32|(4+3): memory.allocate<address_space_specific<1, 2, 3, ENDIANNESS_BIG >>(*this, spacenum); break;
-
- case 0x0000|0x000|32|(4-0): memory.allocate<address_space_specific<0, 2, 0, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x000|32|(4-0): memory.allocate<address_space_specific<0, 2, 0, ENDIANNESS_BIG >>(*this, spacenum); break;
- case 0x0000|0x100|32|(4-0): memory.allocate<address_space_specific<1, 2, 0, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x100|32|(4-0): memory.allocate<address_space_specific<1, 2, 0, ENDIANNESS_BIG >>(*this, spacenum); break;
-
- case 0x0000|0x000|32|(4-1): memory.allocate<address_space_specific<0, 2, -1, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x000|32|(4-1): memory.allocate<address_space_specific<0, 2, -1, ENDIANNESS_BIG >>(*this, spacenum); break;
- case 0x0000|0x100|32|(4-1): memory.allocate<address_space_specific<1, 2, -1, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x100|32|(4-1): memory.allocate<address_space_specific<1, 2, -1, ENDIANNESS_BIG >>(*this, spacenum); break;
-
- case 0x0000|0x000|32|(4-2): memory.allocate<address_space_specific<0, 2, -2, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x000|32|(4-2): memory.allocate<address_space_specific<0, 2, -2, ENDIANNESS_BIG >>(*this, spacenum); break;
- case 0x0000|0x100|32|(4-2): memory.allocate<address_space_specific<1, 2, -2, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x100|32|(4-2): memory.allocate<address_space_specific<1, 2, -2, ENDIANNESS_BIG >>(*this, spacenum); break;
-
- case 0x0000|0x000|64|(4-0): memory.allocate<address_space_specific<0, 3, 0, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x000|64|(4-0): memory.allocate<address_space_specific<0, 3, 0, ENDIANNESS_BIG >>(*this, spacenum); break;
- case 0x0000|0x100|64|(4-0): memory.allocate<address_space_specific<1, 3, 0, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x100|64|(4-0): memory.allocate<address_space_specific<1, 3, 0, ENDIANNESS_BIG >>(*this, spacenum); break;
-
- case 0x0000|0x000|64|(4-1): memory.allocate<address_space_specific<0, 3, -1, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x000|64|(4-1): memory.allocate<address_space_specific<0, 3, -1, ENDIANNESS_BIG >>(*this, spacenum); break;
- case 0x0000|0x100|64|(4-1): memory.allocate<address_space_specific<1, 3, -1, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x100|64|(4-1): memory.allocate<address_space_specific<1, 3, -1, ENDIANNESS_BIG >>(*this, spacenum); break;
-
- case 0x0000|0x000|64|(4-2): memory.allocate<address_space_specific<0, 3, -2, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x000|64|(4-2): memory.allocate<address_space_specific<0, 3, -2, ENDIANNESS_BIG >>(*this, spacenum); break;
- case 0x0000|0x100|64|(4-2): memory.allocate<address_space_specific<1, 3, -2, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x100|64|(4-2): memory.allocate<address_space_specific<1, 3, -2, ENDIANNESS_BIG >>(*this, spacenum); break;
-
- case 0x0000|0x000|64|(4-3): memory.allocate<address_space_specific<0, 3, -3, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x000|64|(4-3): memory.allocate<address_space_specific<0, 3, -3, ENDIANNESS_BIG >>(*this, spacenum); break;
- case 0x0000|0x100|64|(4-3): memory.allocate<address_space_specific<1, 3, -3, ENDIANNESS_LITTLE>>(*this, spacenum); break;
- case 0x1000|0x100|64|(4-3): memory.allocate<address_space_specific<1, 3, -3, ENDIANNESS_BIG >>(*this, spacenum); break;
-
- default:
- throw emu_fatalerror("Invalid width %d/shift %d specified for address_space::allocate", spaceconfig->data_width(), spaceconfig->addr_shift());
- }
- }
- }
-}
-
-//-------------------------------------------------
// initialize - initialize the memory system
//-------------------------------------------------
@@ -1021,12 +378,12 @@ void memory_manager::region_free(std::string name)
//-------------------------------------------------
-// anonymous_alloc - allocates a anonymousd memory zone
+// anonymous_alloc - allocates a anonymous memory zone
//-------------------------------------------------
-void *memory_manager::anonymous_alloc(address_space &space, size_t bytes, u8 width, offs_t start, offs_t end)
+void *memory_manager::anonymous_alloc(address_space &space, size_t bytes, u8 width, offs_t start, offs_t end, const std::string &key)
{
- std::string name = util::string_format("%x-%x", start, end);
+ std::string name = util::string_format("%s%x-%x", key, start, end);
return allocate_memory(space.device(), space.spacenum(), name, width, bytes);
}
@@ -1146,58 +503,7 @@ address_space_config::address_space_config(const char *name, endianness_t endian
}
-//**************************************************************************
-// ADDRESS SPACE
-//**************************************************************************
-
-//-------------------------------------------------
-// address_space - constructor
-//-------------------------------------------------
-
-address_space::address_space(memory_manager &manager, device_memory_interface &memory, int spacenum)
- : m_config(*memory.space_config(spacenum)),
- m_device(memory.device()),
- m_addrmask(make_bitmask<offs_t>(m_config.addr_width())),
- m_logaddrmask(make_bitmask<offs_t>(m_config.logaddr_width())),
- m_unmap(0),
- m_spacenum(spacenum),
- m_log_unmap(true),
- m_name(memory.space_config(spacenum)->name()),
- m_addrchars((m_config.addr_width() + 3) / 4),
- m_logaddrchars((m_config.logaddr_width() + 3) / 4),
- m_notifier_id(0),
- m_in_notification(0),
- m_manager(manager)
-{
-}
-
-
-//-------------------------------------------------
-// ~address_space - destructor
-//-------------------------------------------------
-
-address_space::~address_space()
-{
- m_unmap_r->unref();
- m_unmap_w->unref();
- m_nop_r->unref();
- m_nop_w->unref();
-}
-
-//-------------------------------------------------
-// adjust_addresses - adjust addresses for a
-// given address space in a standard fashion
-//-------------------------------------------------
-
-inline void address_space::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 address_space::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 address_space_installer::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)
{
if (addrstart > addrend)
fatalerror("%s: In range %x-%x mask %x mirror %x select %x, start address is after the end address.\n", function, addrstart, addrend, addrmask, addrmirror, addrselect);
@@ -1265,7 +571,7 @@ void address_space::check_optimize_all(const char *function, int width, offs_t a
while (cmask != 0 && (cmask & block_mask) == 0)
cmask >>= width;
if (cmask != 0 && cmask != block_mask)
- fatalerror("%s: In range %x-%x mask %x mirror %x select %x, the unitmask of %s has incorrect granularity for %d-bit chip selection.\n", function, addrstart, addrend, addrmask, addrmirror, addrselect, core_i64_hex_format(unitmask, 16), cswidth);
+ fatalerror("%s: In range %x-%x mask %x mirror %x select %x, the unitmask of %016x has incorrect granularity for %d-bit chip selection.\n", function, addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth);
}
}
@@ -1291,7 +597,7 @@ void address_space::check_optimize_all(const char *function, int width, offs_t a
}
}
-void address_space::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 address_space_installer::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)
{
if (addrstart > addrend)
fatalerror("%s: In range %x-%x mirror %x, start address is after the end address.\n", function, addrstart, addrend, addrmirror);
@@ -1341,7 +647,7 @@ void address_space::check_optimize_mirror(const char *function, offs_t addrstart
}
}
-void address_space::check_address(const char *function, offs_t addrstart, offs_t addrend)
+void address_space_installer::check_address(const char *function, offs_t addrstart, offs_t addrend)
{
if (addrstart > addrend)
fatalerror("%s: In range %x-%x, start address is after the end address.\n", function, addrstart, addrend);
@@ -1359,140 +665,12 @@ void address_space::check_address(const char *function, offs_t addrstart, offs_t
//-------------------------------------------------
-// prepare_map - allocate the address map and
-// walk through it to find implicit memory regions
-// and identify shared regions
-//-------------------------------------------------
-
-void address_space::prepare_map()
-{
- memory_region *devregion = (m_spacenum == 0) ? m_device.memregion(DEVICE_SELF) : nullptr;
- u32 devregionsize = (devregion != nullptr) ? devregion->bytes() : 0;
-
- // allocate the address map
- m_map = std::make_unique<address_map>(m_device, m_spacenum);
-
- // merge in the submaps
- m_map->import_submaps(m_manager.machine(), m_device.owner() ? *m_device.owner() : m_device, data_width(), endianness(), addr_shift());
-
- // extract global parameters specified by the map
- m_unmap = (m_map->m_unmapval == 0) ? 0 : ~0;
- if (m_map->m_globalmask != 0)
- {
- if (m_map->m_globalmask & ~m_addrmask)
- fatalerror("Can't set a global address mask of %08x on a %d-bits address width bus.\n", m_map->m_globalmask, addr_width());
-
- m_addrmask = m_map->m_globalmask;
- }
-
- // make a pass over the address map, adjusting for the device and getting memory pointers
- for (address_map_entry &entry : m_map->m_entrylist)
- {
- // computed adjusted addresses first
- adjust_addresses(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror);
-
- // if we have a share entry, add it to our map
- if (entry.m_share != nullptr)
- {
- // if we can't find it, add it to our map
- std::string fulltag = entry.m_devbase.subtag(entry.m_share);
- memory_share *share = m_manager.share_find(fulltag);
- if (!share)
- {
- VPRINTF("Creating share '%s' of length 0x%X\n", fulltag.c_str(), entry.m_addrend + 1 - entry.m_addrstart);
- share = m_manager.share_alloc(m_device, fulltag, m_config.data_width(), address_to_byte(entry.m_addrend + 1 - entry.m_addrstart), endianness());
- }
- else
- {
- std::string result = share->compare(m_config.data_width(), address_to_byte(entry.m_addrend + 1 - entry.m_addrstart), endianness());
- if (!result.empty())
- fatalerror("%s\n", result);
- }
- entry.m_memory = share->ptr();
- }
-
- // if this is a ROM handler without a specified region and not shared, attach it to the implicit region
- if (m_spacenum == AS_PROGRAM && entry.m_read.m_type == AMH_ROM && entry.m_region == nullptr && entry.m_share == nullptr)
- {
- // make sure it fits within the memory region before doing so, however
- if (entry.m_addrend < devregionsize)
- {
- entry.m_region = m_device.tag();
- entry.m_rgnoffs = address_to_byte(entry.m_addrstart);
- }
- }
-
- // validate adjusted addresses against implicit regions
- if (entry.m_region != nullptr)
- {
- // determine full tag
- std::string fulltag = entry.m_devbase.subtag(entry.m_region);
-
- // find the region
- memory_region *region = m_manager.machine().root_device().memregion(fulltag);
- if (region == nullptr)
- fatalerror("device '%s' %s space memory map entry %X-%X references nonexistent region \"%s\"\n", m_device.tag(), m_name, entry.m_addrstart, entry.m_addrend, entry.m_region);
-
- // validate the region
- if (entry.m_rgnoffs + m_config.addr2byte(entry.m_addrend - entry.m_addrstart + 1) > region->bytes())
- fatalerror("device '%s' %s space memory map entry %X-%X extends beyond region \"%s\" size (%X)\n", m_device.tag(), m_name, entry.m_addrstart, entry.m_addrend, entry.m_region, region->bytes());
-
- if (entry.m_share != nullptr)
- fatalerror("device '%s' %s space memory map entry %X-%X has both .region() and .share()\n", m_device.tag(), m_name, entry.m_addrstart, entry.m_addrend);
- }
-
- // convert any region-relative entries to their memory pointers
- if (entry.m_region != nullptr)
- {
- // determine full tag
- std::string fulltag = entry.m_devbase.subtag(entry.m_region);
-
- // set the memory address
- entry.m_memory = m_manager.machine().root_device().memregion(fulltag)->base() + entry.m_rgnoffs;
- }
-
- // allocate anonymous ram when needed
- if (!entry.m_memory && (entry.m_read.m_type == AMH_RAM || entry.m_write.m_type == AMH_RAM))
- entry.m_memory = m_manager.anonymous_alloc(*this, address_to_byte(entry.m_addrend + 1 - entry.m_addrstart), m_config.data_width(), entry.m_addrstart, entry.m_addrend);
- }
-}
-
-
-//-------------------------------------------------
-// populate_from_map - walk the map in reverse
-// order and install the appropriate handler for
-// each case
-//-------------------------------------------------
-
-void address_space::populate_from_map(address_map *map)
-{
- // no map specified, use the space-specific one
- if (map == nullptr)
- map = m_map.get();
-
- // no map, nothing to do
- if (map == nullptr)
- return;
-
- // install the handlers, using the original, unadjusted memory map
- for (const address_map_entry &entry : map->m_entrylist) {
- // map both read and write halves
- populate_map_entry(entry, read_or_write::READ);
- populate_map_entry(entry, read_or_write::WRITE);
- }
-
- if(VALIDATE_REFCOUNTS)
- validate_reference_counts();
-}
-
-
-//-------------------------------------------------
// populate_map_entry - map a single read or
// write entry based on information from an
// address map entry
//-------------------------------------------------
-void address_space::populate_map_entry(const address_map_entry &entry, read_or_write readorwrite)
+void address_space_installer::populate_map_entry(const address_map_entry &entry, read_or_write readorwrite)
{
const map_handler_data &data = (readorwrite == read_or_write::READ) ? entry.m_read : entry.m_write;
// based on the handler type, alter the bits, name, funcptr, and object
@@ -1653,363 +831,77 @@ void address_space::populate_map_entry(const address_map_entry &entry, read_or_w
case AMH_DEVICE_SUBMAP:
throw emu_fatalerror("Internal mapping error: leftover mapping of '%s'.\n", data.m_tag);
+
+ case AMH_VIEW:
+ if (readorwrite == read_or_write::READ)
+ install_view(entry.m_addrstart, entry.m_addrend, entry.m_addrmirror, *entry.m_view);
+ break;
}
}
-memory_passthrough_handler *address_space::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)
+memory_passthrough_handler *address_space_installer::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)
{
fatalerror("Trying to install a 8-bits wide bus read tap in a %d-bits wide bus\n", data_width());
}
-memory_passthrough_handler *address_space::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)
+memory_passthrough_handler *address_space_installer::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)
{
fatalerror("Trying to install a 16-bits wide bus read tap in a %d-bits wide bus\n", data_width());
}
-memory_passthrough_handler *address_space::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)
+memory_passthrough_handler *address_space_installer::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)
{
fatalerror("Trying to install a 32-bits wide bus read tap in a %d-bits wide bus\n", data_width());
}
-memory_passthrough_handler *address_space::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)
+memory_passthrough_handler *address_space_installer::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)
{
fatalerror("Trying to install a 64-bits wide bus read tap in a %d-bits wide bus\n", data_width());
}
-memory_passthrough_handler *address_space::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)
+memory_passthrough_handler *address_space_installer::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)
{
fatalerror("Trying to install a 8-bits wide bus write tap in a %d-bits wide bus\n", data_width());
}
-memory_passthrough_handler *address_space::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)
+memory_passthrough_handler *address_space_installer::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)
{
fatalerror("Trying to install a 16-bits wide bus write tap in a %d-bits wide bus\n", data_width());
}
-memory_passthrough_handler *address_space::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)
+memory_passthrough_handler *address_space_installer::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)
{
fatalerror("Trying to install a 32-bits wide bus write tap in a %d-bits wide bus\n", data_width());
}
-memory_passthrough_handler *address_space::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)
+memory_passthrough_handler *address_space_installer::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)
{
fatalerror("Trying to install a 64-bits wide bus write tap in a %d-bits wide bus\n", data_width());
}
-memory_passthrough_handler *address_space::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)
+memory_passthrough_handler *address_space_installer::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)
{
fatalerror("Trying to install a 8-bits wide bus read/write tap in a %d-bits wide bus\n", data_width());
}
-memory_passthrough_handler *address_space::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)
+memory_passthrough_handler *address_space_installer::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)
{
fatalerror("Trying to install a 16-bits wide bus read/write tap in a %d-bits wide bus\n", data_width());
}
-memory_passthrough_handler *address_space::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)> tap, memory_passthrough_handler *mph)
+memory_passthrough_handler *address_space_installer::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)> tap, memory_passthrough_handler *mph)
{
fatalerror("Tryingw to install a 32-bits wide bus read/write tap in a %d-bits wide bus\n", data_width());
}
-memory_passthrough_handler *address_space::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)
+memory_passthrough_handler *address_space_installer::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)
{
fatalerror("Trying to install a 64-bits wide bus read/write tap in a %d-bits wide bus\n", data_width());
}
-
-//-------------------------------------------------
-// get_handler_string - return a string
-// describing the handler at a particular offset
-//-------------------------------------------------
-
-template<int Level, int Width, int AddrShift, endianness_t Endian> std::string address_space_specific<Level, Width, AddrShift, Endian>::get_handler_string(read_or_write readorwrite, offs_t address) const
-{
- if (readorwrite == read_or_write::READ) {
- offs_t start, end;
- handler_entry_read<Width, AddrShift, Endian> *handler;
- m_root_read->lookup(address, start, end, handler);
- return handler->name();
- } else {
- offs_t start, end;
- handler_entry_write<Width, AddrShift, Endian> *handler;
- m_root_write->lookup(address, start, end, handler);
- return handler->name();
- }
-}
-
-template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::dump_maps(std::vector<memory_entry> &read_map, std::vector<memory_entry> &write_map) const
-{
- read_map.clear();
- write_map.clear();
- m_root_read->dump_map(read_map);
- m_root_write->dump_map(write_map);
-}
-
-
-//**************************************************************************
-// DYNAMIC ADDRESS SPACE MAPPING
-//**************************************************************************
-
-//-------------------------------------------------
-// unmap - unmap a section of address space
-//-------------------------------------------------
-
-template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::unmap_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, read_or_write readorwrite, bool quiet)
-{
- VPRINTF("address_space::unmap(%*x-%*x mirror=%*x, %s, %s)\n",
- m_addrchars, addrstart, m_addrchars, addrend,
- m_addrchars, addrmirror,
- (readorwrite == read_or_write::READ) ? "read" : (readorwrite == read_or_write::WRITE) ? "write" : (readorwrite == read_or_write::READWRITE) ? "read/write" : "??",
- quiet ? "quiet" : "normal");
-
- offs_t nstart, nend, nmask, nmirror;
- check_optimize_mirror("unmap_generic", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
-
- // read space
- if (readorwrite == read_or_write::READ || readorwrite == read_or_write::READWRITE) {
- auto handler = static_cast<handler_entry_read<Width, AddrShift, Endian> *>(quiet ? m_nop_r : m_unmap_r);
- handler->ref();
- m_root_read->populate(nstart, nend, nmirror, handler);
- }
-
- // write space
- if (readorwrite == read_or_write::WRITE || readorwrite == read_or_write::READWRITE) {
- auto handler = static_cast<handler_entry_write<Width, AddrShift, Endian> *>(quiet ? m_nop_w : m_unmap_w);
- handler->ref();
- m_root_write->populate(nstart, nend, nmirror, handler);
- }
-
- invalidate_caches(readorwrite);
-}
-
-//-------------------------------------------------
-// install_read_tap - install a read tap on the bus
-//-------------------------------------------------
-
-template<int Level, int Width, int AddrShift, endianness_t Endian> memory_passthrough_handler *address_space_specific<Level, Width, AddrShift, Endian>::install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph)
-{
- offs_t nstart, nend, nmask, nmirror;
- check_optimize_mirror("install_read_tap", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
- if(!mph) {
- m_mphs.emplace_back(std::make_unique<memory_passthrough_handler>(*this));
- mph = m_mphs.back().get();
- }
-
- auto handler = new handler_entry_read_tap<Width, AddrShift, Endian>(this, *mph, name, tap);
- m_root_read->populate_passthrough(nstart, nend, nmirror, handler);
- handler->unref();
-
- invalidate_caches(read_or_write::READ);
-
- return mph;
-}
-
-//-------------------------------------------------
-// install_write_tap - install a write tap on the bus
-//-------------------------------------------------
-
-template<int Level, int Width, int AddrShift, endianness_t Endian> memory_passthrough_handler *address_space_specific<Level, Width, AddrShift, Endian>::install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph)
-{
- offs_t nstart, nend, nmask, nmirror;
- check_optimize_mirror("install_write_tap", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
- if(!mph) {
- m_mphs.emplace_back(std::make_unique<memory_passthrough_handler>(*this));
- mph = m_mphs.back().get();
- }
-
- auto handler = new handler_entry_write_tap<Width, AddrShift, Endian>(this, *mph, name, tap);
- m_root_write->populate_passthrough(nstart, nend, nmirror, handler);
- handler->unref();
-
- invalidate_caches(read_or_write::WRITE);
-
- return mph;
-}
-//-------------------------------------------------
-// install_write_tap - install a read and a write tap on the bus
-//-------------------------------------------------
-
-template<int Level, int Width, int AddrShift, endianness_t Endian> memory_passthrough_handler *address_space_specific<Level, Width, AddrShift, Endian>::install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapr, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapw, memory_passthrough_handler *mph)
-{
- offs_t nstart, nend, nmask, nmirror;
- check_optimize_mirror("install_readwrite_tap", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
- if(!mph) {
- m_mphs.emplace_back(std::make_unique<memory_passthrough_handler>(*this));
- mph = m_mphs.back().get();
- }
-
- auto rhandler = new handler_entry_read_tap <Width, AddrShift, Endian>(this, *mph, name, tapr);
- m_root_read ->populate_passthrough(nstart, nend, nmirror, rhandler);
- rhandler->unref();
-
- auto whandler = new handler_entry_write_tap<Width, AddrShift, Endian>(this, *mph, name, tapw);
- m_root_write->populate_passthrough(nstart, nend, nmirror, whandler);
- whandler->unref();
-
- invalidate_caches(read_or_write::READWRITE);
-
- return mph;
-}
-
-
-
-
-
-//-------------------------------------------------
-// install_device_delegate - install the memory map
-// of a live device into this address space
-//-------------------------------------------------
-
-template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_device_delegate(offs_t addrstart, offs_t addrend, device_t &device, address_map_constructor &delegate, u64 unitmask, int cswidth)
-{
- check_address("install_device_delegate", addrstart, addrend);
- address_map map(*this, addrstart, addrend, unitmask, cswidth, m_device, delegate);
- map.import_submaps(m_manager.machine(), device, data_width(), endianness(), addr_shift());
- populate_from_map(&map);
-}
-
-
-
-//-------------------------------------------------
-// install_readwrite_port - install a new I/O port
-// handler into this address space
-//-------------------------------------------------
-
-template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_readwrite_port(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string rtag, std::string wtag)
-{
- VPRINTF("address_space::install_readwrite_port(%*x-%*x mirror=%*x, read=\"%s\" / write=\"%s\")\n",
- m_addrchars, addrstart, m_addrchars, addrend,
- m_addrchars, addrmirror,
- rtag.empty() ? "(none)" : rtag.c_str(), wtag.empty() ? "(none)" : wtag.c_str());
-
- offs_t nstart, nend, nmask, nmirror;
- check_optimize_mirror("install_readwrite_port", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
-
- // read handler
- if (rtag != "")
- {
- // find the port
- ioport_port *port = device().owner()->ioport(rtag);
- if (port == nullptr)
- throw emu_fatalerror("Attempted to map non-existent port '%s' for read in space %s of device '%s'\n", rtag.c_str(), m_name, m_device.tag());
-
- // map the range and set the ioport
- auto hand_r = new handler_entry_read_ioport<Width, AddrShift, Endian>(this, port);
- m_root_read->populate(nstart, nend, nmirror, hand_r);
- }
-
- if (wtag != "")
- {
- // find the port
- ioport_port *port = device().owner()->ioport(wtag);
- if (port == nullptr)
- fatalerror("Attempted to map non-existent port '%s' for write in space %s of device '%s'\n", wtag.c_str(), m_name, m_device.tag());
-
- // map the range and set the ioport
- auto hand_w = new handler_entry_write_ioport<Width, AddrShift, Endian>(this, port);
- m_root_write->populate(nstart, nend, nmirror, hand_w);
- }
-
- invalidate_caches(rtag != "" ? wtag != "" ? read_or_write::READWRITE : read_or_write::READ : read_or_write::WRITE);
-}
-
-
-//-------------------------------------------------
-// install_bank_generic - install a range as
-// mapping to a particular bank
-//-------------------------------------------------
-
-template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_bank_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_bank *rbank, memory_bank *wbank)
-{
- VPRINTF("address_space::install_readwrite_bank(%*x-%*x mirror=%*x, read=\"%s\" / write=\"%s\")\n",
- m_addrchars, addrstart, m_addrchars, addrend,
- m_addrchars, addrmirror,
- (rbank != nullptr) ? rbank->tag() : "(none)", (wbank != nullptr) ? wbank->tag() : "(none)");
-
- offs_t nstart, nend, nmask, nmirror;
- check_optimize_mirror("install_bank_generic", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
-
- // map the read bank
- if (rbank != nullptr)
- {
- auto hand_r = new handler_entry_read_memory_bank<Width, AddrShift, Endian>(this, *rbank);
- hand_r->set_address_info(nstart, nmask);
- m_root_read->populate(nstart, nend, nmirror, hand_r);
- }
-
- // map the write bank
- if (wbank != nullptr)
- {
- auto hand_w = new handler_entry_write_memory_bank<Width, AddrShift, Endian>(this, *wbank);
- hand_w->set_address_info(nstart, nmask);
- m_root_write->populate(nstart, nend, nmirror, hand_w);
- }
-
- invalidate_caches(rbank ? wbank ? read_or_write::READWRITE : read_or_write::READ : read_or_write::WRITE);
-}
-
-
-//-------------------------------------------------
-// install_ram_generic - install a simple fixed
-// RAM region into the given address space
-//-------------------------------------------------
-
-template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_ram_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, read_or_write readorwrite, void *baseptr)
-{
- VPRINTF("address_space::install_ram_generic(%s-%s mirror=%s, %s, %p)\n",
- m_addrchars, addrstart, m_addrchars, addrend,
- m_addrchars, addrmirror,
- (readorwrite == read_or_write::READ) ? "read" : (readorwrite == read_or_write::WRITE) ? "write" : (readorwrite == read_or_write::READWRITE) ? "read/write" : "??",
- baseptr);
-
- offs_t nstart, nend, nmask, nmirror;
- check_optimize_mirror("install_ram_generic", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
-
- // map for read
- if (readorwrite == read_or_write::READ || readorwrite == read_or_write::READWRITE)
- {
- auto hand_r = new handler_entry_read_memory<Width, AddrShift, Endian>(this, baseptr);
- hand_r->set_address_info(nstart, nmask);
- m_root_read->populate(nstart, nend, nmirror, hand_r);
- }
-
- // map for write
- if (readorwrite == read_or_write::WRITE || readorwrite == read_or_write::READWRITE)
- {
- auto hand_w = new handler_entry_write_memory<Width, AddrShift, Endian>(this, baseptr);
- hand_w->set_address_info(nstart, nmask);
- m_root_write->populate(nstart, nend, nmirror, hand_w);
- }
-
- invalidate_caches(readorwrite);
-}
-
-
-//**************************************************************************
-// MEMORY MAPPING HELPERS
-//**************************************************************************
-
-int address_space::add_change_notifier(std::function<void (read_or_write)> n)
-{
- int id = m_notifier_id++;
- m_notifiers.emplace_back(notifier_t{ std::move(n), id });
- return id;
-}
-
-void address_space::remove_change_notifier(int id)
-{
- for(auto i = m_notifiers.begin(); i != m_notifiers.end(); i++)
- if(i->m_id == id) {
- m_notifiers.erase(i);
- return;
- }
- fatalerror("Unknown notifier id %d, double remove?\n", id);
-}
-
-
//**************************************************************************
// MEMORY BANK
//**************************************************************************
@@ -2141,4 +1033,3 @@ std::string memory_share::compare(u8 width, size_t bytes, endianness_t endiannes
m_endianness == ENDIANNESS_LITTLE ? "little" : "big");
return "";
}
-
diff --git a/src/emu/emumem.h b/src/emu/emumem.h
index e9a2fe0029a..be26838b91e 100644
--- a/src/emu/emumem.h
+++ b/src/emu/emumem.h
@@ -80,9 +80,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;
+ std::vector<memory_entry_context> context;
};
@@ -480,6 +487,7 @@ public:
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
+ static constexpr u32 F_VIEW = 0x00000008; // handler for a view (kinda like dispatch except not entirely)
// Start/end of range flags
static constexpr u8 START = 1;
@@ -507,6 +515,7 @@ 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; }
@@ -516,6 +525,9 @@ 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);
+
protected:
// Address range storage
struct range {
@@ -610,6 +622,9 @@ public:
// Return the internal structures of the root dispatch
virtual const handler_entry_read<Width, AddrShift, Endian> *const *get_dispatch() const;
+
+ virtual void init_handlers(offs_t start_entry, offs_t end_entry, u32 lowbits, handler_entry_read<Width, AddrShift, Endian> **dispatch, handler_entry::range *ranges);
+ virtual handler_entry_read<Width, AddrShift, Endian> *dup();
};
// =====================-> The parent class of all write handlers
@@ -682,6 +697,9 @@ public:
// Return the internal structures of the root dispatch
virtual const handler_entry_write<Width, AddrShift, Endian> *const *get_dispatch() const;
+
+ virtual void init_handlers(offs_t start_entry, offs_t end_entry, u32 lowbits, handler_entry_write<Width, AddrShift, Endian> **dispatch, handler_entry::range *ranges);
+ virtual handler_entry_write<Width, AddrShift, Endian> *dup();
};
// =====================-> Passthrough handler management structure
@@ -1231,137 +1249,29 @@ public:
// ======================> address_space
-// address_space holds live information about an address space
-class address_space
-{
- 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;
- };
-
-protected:
- // construction/destruction
- address_space(memory_manager &manager, device_memory_interface &memory, int spacenum);
-
+class address_space_installer {
public:
- virtual ~address_space();
-
- // getters
- device_t &device() const { return m_device; }
- const char *name() const { return m_name; }
- int spacenum() const { return m_spacenum; }
- address_map *map() const { return m_map.get(); }
-
- template<int Width, int AddrShift, endianness_t Endian> void cache(emu::detail::memory_access_cache<Width, AddrShift, Endian> &v) {
- if(AddrShift != m_config.addr_shift())
- fatalerror("Requesting cache() with address shift %d while the config says %d\n", AddrShift, m_config.addr_shift());
- if(8 << Width != m_config.data_width())
- 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()]);
-
- v.set(this, get_cache_info());
- }
-
- template<int Level, int Width, int AddrShift, endianness_t Endian> void specific(emu::detail::memory_access_specific<Level, Width, AddrShift, Endian> &v) {
- if(Level != emu::detail::handler_entry_dispatch_level(m_config.addr_width()))
- fatalerror("Requesting specific() with wrong level, bad address width (the config says %d)\n", m_config.addr_width());
- if(AddrShift != m_config.addr_shift())
- fatalerror("Requesting specific() with address shift %d while the config says %d\n", AddrShift, m_config.addr_shift());
- if(8 << Width != m_config.data_width())
- 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()]);
-
- v.set(this, get_specific_info());
- }
-
- int add_change_notifier(std::function<void (read_or_write)> n);
- void remove_change_notifier(int id);
-
- 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_in_notification = old;
- }
- }
-
- virtual void validate_reference_counts() const = 0;
-
- virtual void remove_passthrough(std::unordered_set<handler_entry *> &handlers) = 0;
-
+ 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(); }
- u64 unmap() const { return m_unmap; }
bool is_octal() const { return m_config.is_octal(); }
- 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; }
-
- // debug helpers
- virtual std::string get_handler_string(read_or_write readorwrite, offs_t byteaddress) const = 0;
- virtual void dump_maps(std::vector<memory_entry> &read_map, std::vector<memory_entry> &write_map) const = 0;
- bool log_unmap() const { return m_log_unmap; }
- void set_log_unmap(bool log) { m_log_unmap = log; }
-
- // general accessors
- virtual void accessors(data_accessors &accessors) const = 0;
- virtual void *get_read_ptr(offs_t address) const = 0;
- virtual void *get_write_ptr(offs_t address) const = 0;
-
- // read accessors
- virtual u8 read_byte(offs_t address) = 0;
- virtual u16 read_word(offs_t address) = 0;
- virtual u16 read_word(offs_t address, u16 mask) = 0;
- virtual u16 read_word_unaligned(offs_t address) = 0;
- virtual u16 read_word_unaligned(offs_t address, u16 mask) = 0;
- virtual u32 read_dword(offs_t address) = 0;
- virtual u32 read_dword(offs_t address, u32 mask) = 0;
- virtual u32 read_dword_unaligned(offs_t address) = 0;
- virtual u32 read_dword_unaligned(offs_t address, u32 mask) = 0;
- virtual u64 read_qword(offs_t address) = 0;
- virtual u64 read_qword(offs_t address, u64 mask) = 0;
- virtual u64 read_qword_unaligned(offs_t address) = 0;
- virtual u64 read_qword_unaligned(offs_t address, u64 mask) = 0;
-
- // write accessors
- virtual void write_byte(offs_t address, u8 data) = 0;
- virtual void write_word(offs_t address, u16 data) = 0;
- virtual void write_word(offs_t address, u16 data, u16 mask) = 0;
- virtual void write_word_unaligned(offs_t address, u16 data) = 0;
- virtual void write_word_unaligned(offs_t address, u16 data, u16 mask) = 0;
- virtual void write_dword(offs_t address, u32 data) = 0;
- virtual void write_dword(offs_t address, u32 data, u32 mask) = 0;
- virtual void write_dword_unaligned(offs_t address, u32 data) = 0;
- virtual void write_dword_unaligned(offs_t address, u32 data, u32 mask) = 0;
- virtual void write_qword(offs_t address, u64 data) = 0;
- virtual void write_qword(offs_t address, u64 data, u64 mask) = 0;
- 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)
+ 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) { 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); }
@@ -1427,6 +1337,9 @@ public:
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 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); }
@@ -1586,6 +1499,154 @@ public:
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;
+protected:
+ 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, 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 : 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;
+ };
+
+protected:
+ // construction/destruction
+ address_space(memory_manager &manager, device_memory_interface &memory, int spacenum);
+
+public:
+ virtual ~address_space();
+
+ // getters
+ device_t &device() const { return m_device; }
+ const char *name() const { return m_name; }
+ int spacenum() const { return m_spacenum; }
+ address_map *map() const { return m_map.get(); }
+
+ template<int Width, int AddrShift, endianness_t Endian> void cache(emu::detail::memory_access_cache<Width, AddrShift, Endian> &v) {
+ if(AddrShift != m_config.addr_shift())
+ fatalerror("Requesting cache() with address shift %d while the config says %d\n", AddrShift, m_config.addr_shift());
+ if(8 << Width != m_config.data_width())
+ 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()]);
+
+ v.set(this, get_cache_info());
+ }
+
+ template<int Level, int Width, int AddrShift, endianness_t Endian> void specific(emu::detail::memory_access_specific<Level, Width, AddrShift, Endian> &v) {
+ if(Level != emu::detail::handler_entry_dispatch_level(m_config.addr_width()))
+ fatalerror("Requesting specific() with wrong level, bad address width (the config says %d)\n", m_config.addr_width());
+ if(AddrShift != m_config.addr_shift())
+ fatalerror("Requesting specific() with address shift %d while the config says %d\n", AddrShift, m_config.addr_shift());
+ if(8 << Width != m_config.data_width())
+ 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()]);
+
+ v.set(this, get_specific_info());
+ }
+
+ int add_change_notifier(std::function<void (read_or_write)> n);
+ void remove_change_notifier(int id);
+
+ 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_in_notification = old;
+ }
+ }
+
+ virtual void validate_reference_counts() const = 0;
+
+ virtual void remove_passthrough(std::unordered_set<handler_entry *> &handlers) = 0;
+
+ u64 unmap() const { return m_unmap; }
+
+ memory_passthrough_handler *make_mph();
+
+ // debug helpers
+ virtual std::string get_handler_string(read_or_write readorwrite, offs_t byteaddress) const = 0;
+ virtual void dump_maps(std::vector<memory_entry> &read_map, std::vector<memory_entry> &write_map) const = 0;
+ bool log_unmap() const { return m_log_unmap; }
+ void set_log_unmap(bool log) { m_log_unmap = log; }
+
+ // general accessors
+ virtual void accessors(data_accessors &accessors) const = 0;
+ virtual void *get_read_ptr(offs_t address) const = 0;
+ virtual void *get_write_ptr(offs_t address) const = 0;
+
+ // read accessors
+ virtual u8 read_byte(offs_t address) = 0;
+ virtual u16 read_word(offs_t address) = 0;
+ virtual u16 read_word(offs_t address, u16 mask) = 0;
+ virtual u16 read_word_unaligned(offs_t address) = 0;
+ virtual u16 read_word_unaligned(offs_t address, u16 mask) = 0;
+ virtual u32 read_dword(offs_t address) = 0;
+ virtual u32 read_dword(offs_t address, u32 mask) = 0;
+ virtual u32 read_dword_unaligned(offs_t address) = 0;
+ virtual u32 read_dword_unaligned(offs_t address, u32 mask) = 0;
+ virtual u64 read_qword(offs_t address) = 0;
+ virtual u64 read_qword(offs_t address, u64 mask) = 0;
+ virtual u64 read_qword_unaligned(offs_t address) = 0;
+ virtual u64 read_qword_unaligned(offs_t address, u64 mask) = 0;
+
+ // write accessors
+ virtual void write_byte(offs_t address, u8 data) = 0;
+ virtual void write_word(offs_t address, u16 data) = 0;
+ virtual void write_word(offs_t address, u16 data, u16 mask) = 0;
+ virtual void write_word_unaligned(offs_t address, u16 data) = 0;
+ virtual void write_word_unaligned(offs_t address, u16 data, u16 mask) = 0;
+ virtual void write_dword(offs_t address, u32 data) = 0;
+ virtual void write_dword(offs_t address, u32 data, u32 mask) = 0;
+ virtual void write_dword_unaligned(offs_t address, u32 data) = 0;
+ virtual void write_dword_unaligned(offs_t address, u32 data, u32 mask) = 0;
+ virtual void write_qword(offs_t address, u64 data) = 0;
+ virtual void write_qword(offs_t address, u64 data, u64 mask) = 0;
+ virtual void write_qword_unaligned(offs_t address, u64 data) = 0;
+ virtual void write_qword_unaligned(offs_t address, u64 data, u64 mask) = 0;
+
// setup
void prepare_map();
void populate_from_map(address_map *map = nullptr);
@@ -1593,32 +1654,23 @@ public:
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); }
+ 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, memory_bank *rbank, memory_bank *wbank) = 0;
- void adjust_addresses(offs_t &start, offs_t &end, offs_t &mask, offs_t &mirror);
- 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);
-
// 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;
@@ -1631,7 +1683,6 @@ protected:
std::vector<notifier_t> m_notifiers; // notifier list for address map change
int m_notifier_id; // next notifier id
u32 m_in_notification; // notification(s) currently being done
- memory_manager & m_manager; // reference to the owning manager
};
@@ -1748,6 +1799,79 @@ 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, endianness_t Endian> friend class memory_view_entry_specific;
+ template<int HighBits, int Width, int AddrShift, endianness_t Endian> friend class handler_entry_write_dispatch;
+ template<int HighBits, int Width, int AddrShift, endianness_t Endian> friend class handler_entry_read_dispatch;
+ friend class memory_view_entry;
+ friend class address_map_entry;
+ friend class address_map;
+
+ 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 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_entry &operator[](int slot);
+
+ void select(int entry);
+ void disable();
+
+ 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;
+ std::function<void (int)> m_select_a;
+ std::function<void (int)> m_select_u;
+ 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;
+};
+
+
+
// ======================> memory_manager
// holds internal state for the memory system
@@ -1772,7 +1896,7 @@ public:
const std::unordered_map<std::string, std::unique_ptr<memory_share>> &shares() const { return m_sharelist; }
// anonymous memory zones
- void *anonymous_alloc(address_space &space, size_t bytes, u8 width, offs_t start, offs_t end);
+ 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);
diff --git a/src/emu/emumem_aspace.cpp b/src/emu/emumem_aspace.cpp
new file mode 100644
index 00000000000..f9029b9422f
--- /dev/null
+++ b/src/emu/emumem_aspace.cpp
@@ -0,0 +1,1200 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles,Olivier Galibert
+/***************************************************************************
+
+ emumem.cpp
+
+ Functions which handle device memory access.
+ Address-space related functions
+
+***************************************************************************/
+
+#include "emu.h"
+#include <list>
+#include <map>
+#include "emuopts.h"
+#include "debug/debugcpu.h"
+
+#include "emumem_mud.h"
+#include "emumem_hea.h"
+#include "emumem_hem.h"
+#include "emumem_hedp.h"
+#include "emumem_heun.h"
+#include "emumem_heu.h"
+#include "emumem_hedr.h"
+#include "emumem_hedw.h"
+#include "emumem_hep.h"
+#include "emumem_het.h"
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define VERBOSE 0
+
+#if VERBOSE
+template <typename Format, typename... Params> static void VPRINTF(Format &&fmt, Params &&...args)
+{
+ util::stream_format(std::cerr, std::forward<Format>(fmt), std::forward<Params>(args)...);
+}
+#else
+template <typename Format, typename... Params> static void VPRINTF(Format &&, Params &&...) {}
+#endif
+
+#define VALIDATE_REFCOUNTS 0
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+namespace {
+
+template <typename Delegate> struct handler_width;
+template <> struct handler_width<read8_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<read8m_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<read8s_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<read8sm_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<read8mo_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<read8smo_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<write8_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<write8m_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<write8s_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<write8sm_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<write8mo_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<write8smo_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<read16_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<read16m_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<read16s_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<read16sm_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<read16mo_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<read16smo_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<write16_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<write16m_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<write16s_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<write16sm_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<write16mo_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<write16smo_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<read32_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<read32m_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<read32s_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<read32sm_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<read32mo_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<read32smo_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<write32_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<write32m_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<write32s_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<write32sm_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<write32mo_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<write32smo_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<read64_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<read64m_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<read64s_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<read64sm_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<read64mo_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<read64smo_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<write64_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<write64m_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<write64s_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<write64sm_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<write64mo_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<write64smo_delegate> { static constexpr int value = 3; };
+} // anonymous namespace
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> address_space_specific
+
+// this is a derived class of address_space with specific width, endianness, and table size
+template<int Level, int Width, int AddrShift, endianness_t Endian>
+class address_space_specific : public address_space
+{
+ using uX = typename emu::detail::handler_entry_size<Width>::uX;
+ using NativeType = uX;
+ using this_type = address_space_specific<Level, Width, AddrShift, Endian>;
+
+ // constants describing the native size
+ static constexpr u32 NATIVE_BYTES = 1 << Width;
+ static constexpr u32 NATIVE_STEP = AddrShift >= 0 ? NATIVE_BYTES << iabs(AddrShift) : NATIVE_BYTES >> iabs(AddrShift);
+ static constexpr u32 NATIVE_MASK = NATIVE_STEP - 1;
+ static constexpr u32 NATIVE_BITS = 8 * NATIVE_BYTES;
+
+ static constexpr offs_t offset_to_byte(offs_t offset) { return AddrShift < 0 ? offset << iabs(AddrShift) : offset >> iabs(AddrShift); }
+
+public:
+ const handler_entry_read<Width, AddrShift, Endian> *const *m_dispatch_read;
+ const handler_entry_write<Width, AddrShift, Endian> *const *m_dispatch_write;
+
+ std::string get_handler_string(read_or_write readorwrite, offs_t byteaddress) const override;
+ void dump_maps(std::vector<memory_entry> &read_map, std::vector<memory_entry> &write_map) const override;
+
+ void unmap_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, read_or_write readorwrite, bool quiet) override;
+ void install_ram_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, read_or_write readorwrite, void *baseptr) override;
+ void install_bank_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_bank *rbank, memory_bank *wbank) override;
+ void install_readwrite_port(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string rtag, std::string wtag) override;
+ void install_device_delegate(offs_t addrstart, offs_t addrend, device_t &device, address_map_constructor &map, u64 unitmask = 0, int cswidth = 0) override;
+ void install_view(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_view &view) override;
+
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+
+ using address_space::install_read_tap;
+ using address_space::install_write_tap;
+ using address_space::install_readwrite_tap;
+
+ 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, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) override;
+ 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, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) override;
+ 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, uX &data, uX mem_mask)> tapr, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapw, memory_passthrough_handler *mph) override;
+
+ // construction/destruction
+ address_space_specific(memory_manager &manager, device_memory_interface &memory, int spacenum, int address_width)
+ : address_space(manager, memory, spacenum)
+ {
+ m_unmap_r = new handler_entry_read_unmapped <Width, AddrShift, Endian>(this);
+ m_unmap_w = new handler_entry_write_unmapped<Width, AddrShift, Endian>(this);
+ m_nop_r = new handler_entry_read_nop <Width, AddrShift, Endian>(this);
+ m_nop_w = new handler_entry_write_nop<Width, AddrShift, Endian>(this);
+
+ handler_entry::range r{ 0, 0xffffffff >> (32 - address_width) };
+
+ switch (address_width) {
+ case 1: m_root_read = new handler_entry_read_dispatch< std::max(1, Width), Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< std::max(1, Width), Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 2: m_root_read = new handler_entry_read_dispatch< std::max(2, Width), Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< std::max(2, Width), Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 3: m_root_read = new handler_entry_read_dispatch< std::max(3, Width), Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< std::max(3, Width), Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 4: m_root_read = new handler_entry_read_dispatch< 4, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< 4, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 5: m_root_read = new handler_entry_read_dispatch< 5, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< 5, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 6: m_root_read = new handler_entry_read_dispatch< 6, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< 6, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 7: m_root_read = new handler_entry_read_dispatch< 7, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< 7, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 8: m_root_read = new handler_entry_read_dispatch< 8, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< 8, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 9: m_root_read = new handler_entry_read_dispatch< 9, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch< 9, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 10: m_root_read = new handler_entry_read_dispatch<10, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<10, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 11: m_root_read = new handler_entry_read_dispatch<11, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<11, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 12: m_root_read = new handler_entry_read_dispatch<12, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<12, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 13: m_root_read = new handler_entry_read_dispatch<13, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<13, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 14: m_root_read = new handler_entry_read_dispatch<14, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<14, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 15: m_root_read = new handler_entry_read_dispatch<15, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<15, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 16: m_root_read = new handler_entry_read_dispatch<16, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<16, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 17: m_root_read = new handler_entry_read_dispatch<17, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<17, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 18: m_root_read = new handler_entry_read_dispatch<18, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<18, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 19: m_root_read = new handler_entry_read_dispatch<19, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<19, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 20: m_root_read = new handler_entry_read_dispatch<20, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<20, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 21: m_root_read = new handler_entry_read_dispatch<21, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<21, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 22: m_root_read = new handler_entry_read_dispatch<22, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<22, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 23: m_root_read = new handler_entry_read_dispatch<23, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<23, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 24: m_root_read = new handler_entry_read_dispatch<24, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<24, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 25: m_root_read = new handler_entry_read_dispatch<25, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<25, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 26: m_root_read = new handler_entry_read_dispatch<26, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<26, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 27: m_root_read = new handler_entry_read_dispatch<27, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<27, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 28: m_root_read = new handler_entry_read_dispatch<28, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<28, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 29: m_root_read = new handler_entry_read_dispatch<29, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<29, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 30: m_root_read = new handler_entry_read_dispatch<30, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<30, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 31: m_root_read = new handler_entry_read_dispatch<31, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<31, Width, AddrShift, Endian>(this, r, nullptr); break;
+ case 32: m_root_read = new handler_entry_read_dispatch<32, Width, AddrShift, Endian>(this, r, nullptr); m_root_write = new handler_entry_write_dispatch<32, Width, AddrShift, Endian>(this, r, nullptr); break;
+ default: fatalerror("Unhandled address bus width %d\n", address_width);
+ }
+
+ m_dispatch_read = m_root_read ->get_dispatch();
+ m_dispatch_write = m_root_write->get_dispatch();
+ }
+
+ std::pair<void *, void *> get_cache_info() override {
+ std::pair<void *, void *> rw;
+ rw.first = m_root_read;
+ rw.second = m_root_write;
+ return rw;
+ }
+
+ std::pair<const void *, const void *> get_specific_info() override {
+ std::pair<const void *, const void *> rw;
+ rw.first = m_dispatch_read;
+ rw.second = m_dispatch_write;
+ return rw;
+ }
+
+ void delayed_ref(handler_entry *e) {
+ e->ref();
+ m_delayed_unrefs.insert(e);
+ }
+
+ void delayed_unref(handler_entry *e) {
+ m_delayed_unrefs.erase(m_delayed_unrefs.find(e));
+ e->unref();
+ }
+
+ void validate_reference_counts() const override {
+ handler_entry::reflist refs;
+ refs.add(m_root_read);
+ refs.add(m_root_write);
+ refs.add(m_unmap_r);
+ refs.add(m_unmap_w);
+ refs.add(m_nop_r);
+ refs.add(m_nop_w);
+ for(handler_entry *e : m_delayed_unrefs)
+ refs.add(e);
+ refs.propagate();
+ refs.check();
+ }
+
+ virtual void remove_passthrough(std::unordered_set<handler_entry *> &handlers) override {
+ invalidate_caches(read_or_write::READWRITE);
+ m_root_read->detach(handlers);
+ m_root_write->detach(handlers);
+ }
+
+ // generate accessor table
+ virtual void accessors(data_accessors &accessors) const override
+ {
+ accessors.read_byte = reinterpret_cast<u8 (*)(address_space &, offs_t)>(&read_byte_static);
+ accessors.read_word = reinterpret_cast<u16 (*)(address_space &, offs_t)>(&read_word_static);
+ accessors.read_word_masked = reinterpret_cast<u16 (*)(address_space &, offs_t, u16)>(&read_word_masked_static);
+ accessors.read_dword = reinterpret_cast<u32 (*)(address_space &, offs_t)>(&read_dword_static);
+ accessors.read_dword_masked = reinterpret_cast<u32 (*)(address_space &, offs_t, u32)>(&read_dword_masked_static);
+ accessors.read_qword = reinterpret_cast<u64 (*)(address_space &, offs_t)>(&read_qword_static);
+ accessors.read_qword_masked = reinterpret_cast<u64 (*)(address_space &, offs_t, u64)>(&read_qword_masked_static);
+ accessors.write_byte = reinterpret_cast<void (*)(address_space &, offs_t, u8)>(&write_byte_static);
+ accessors.write_word = reinterpret_cast<void (*)(address_space &, offs_t, u16)>(&write_word_static);
+ accessors.write_word_masked = reinterpret_cast<void (*)(address_space &, offs_t, u16, u16)>(&write_word_masked_static);
+ accessors.write_dword = reinterpret_cast<void (*)(address_space &, offs_t, u32)>(&write_dword_static);
+ accessors.write_dword_masked = reinterpret_cast<void (*)(address_space &, offs_t, u32, u32)>(&write_dword_masked_static);
+ accessors.write_qword = reinterpret_cast<void (*)(address_space &, offs_t, u64)>(&write_qword_static);
+ accessors.write_qword_masked = reinterpret_cast<void (*)(address_space &, offs_t, u64, u64)>(&write_qword_masked_static);
+ }
+
+ // return a pointer to the read bank, or nullptr if none
+ virtual void *get_read_ptr(offs_t address) const override
+ {
+ return m_root_read->get_ptr(address);
+ }
+
+ // return a pointer to the write bank, or nullptr if none
+ virtual void *get_write_ptr(offs_t address) const override
+ {
+ return m_root_write->get_ptr(address);
+ }
+
+ // native read
+ NativeType read_native(offs_t offset, NativeType mask)
+ {
+ return dispatch_read<Level, Width, AddrShift, Endian>(offs_t(-1), offset & m_addrmask, mask, m_dispatch_read);
+ }
+
+ // mask-less native read
+ NativeType read_native(offs_t offset)
+ {
+ return dispatch_read<Level, Width, AddrShift, Endian>(offs_t(-1), offset & m_addrmask, uX(0xffffffffffffffffU), m_dispatch_read);
+ }
+
+ // native write
+ void write_native(offs_t offset, NativeType data, NativeType mask)
+ {
+ dispatch_write<Level, Width, AddrShift, Endian>(offs_t(-1), offset & m_addrmask, data, mask, m_dispatch_write);
+ }
+
+ // mask-less native write
+ void write_native(offs_t offset, NativeType data)
+ {
+ dispatch_write<Level, Width, AddrShift, Endian>(offs_t(-1), offset & m_addrmask, data, uX(0xffffffffffffffffU), m_dispatch_write);
+ }
+
+ // virtual access to these functions
+ u8 read_byte(offs_t address) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { 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) override { memory_write_generic<Width, AddrShift, Endian, 3, false>([this](offs_t offset, NativeType data, NativeType mask) { write_native(offset, data, mask); }, address, data, mask); }
+
+ // static access to these functions
+ static u8 read_byte_static(this_type &space, offs_t address) { return Width == 0 ? space.read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 0, true>([&space](offs_t offset, NativeType mask) -> NativeType { return space.read_native(offset, mask); }, address, 0xff); }
+ static u16 read_word_static(this_type &space, offs_t address) { return Width == 1 ? space.read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 1, true>([&space](offs_t offset, NativeType mask) -> NativeType { return space.read_native(offset, mask); }, address, 0xffff); }
+ static u16 read_word_masked_static(this_type &space, offs_t address, u16 mask) { return memory_read_generic<Width, AddrShift, Endian, 1, true>([&space](offs_t offset, NativeType mask) -> NativeType { return space.read_native(offset, mask); }, address, mask); }
+ static u32 read_dword_static(this_type &space, offs_t address) { return Width == 2 ? space.read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 2, true>([&space](offs_t offset, NativeType mask) -> NativeType { return space.read_native(offset, mask); }, address, 0xffffffff); }
+ static u32 read_dword_masked_static(this_type &space, offs_t address, u32 mask) { return memory_read_generic<Width, AddrShift, Endian, 2, true>([&space](offs_t offset, NativeType mask) -> NativeType { return space.read_native(offset, mask); }, address, mask); }
+ static u64 read_qword_static(this_type &space, offs_t address) { return Width == 3 ? space.read_native(address & ~NATIVE_MASK) : memory_read_generic<Width, AddrShift, Endian, 3, true>([&space](offs_t offset, NativeType mask) -> NativeType { return space.read_native(offset, mask); }, address, 0xffffffffffffffffU); }
+ static u64 read_qword_masked_static(this_type &space, offs_t address, u64 mask) { return memory_read_generic<Width, AddrShift, Endian, 3, true>([&space](offs_t offset, NativeType mask) -> NativeType { return space.read_native(offset, mask); }, address, mask); }
+ static void write_byte_static(this_type &space, offs_t address, u8 data) { if (Width == 0) space.write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 0, true>([&space](offs_t offset, NativeType data, NativeType mask) { space.write_native(offset, data, mask); }, address, data, 0xff); }
+ static void write_word_static(this_type &space, offs_t address, u16 data) { if (Width == 1) space.write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 1, true>([&space](offs_t offset, NativeType data, NativeType mask) { space.write_native(offset, data, mask); }, address, data, 0xffff); }
+ static void write_word_masked_static(this_type &space, offs_t address, u16 data, u16 mask) { memory_write_generic<Width, AddrShift, Endian, 1, true>([&space](offs_t offset, NativeType data, NativeType mask) { space.write_native(offset, data, mask); }, address, data, mask); }
+ static void write_dword_static(this_type &space, offs_t address, u32 data) { if (Width == 2) space.write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 2, true>([&space](offs_t offset, NativeType data, NativeType mask) { space.write_native(offset, data, mask); }, address, data, 0xffffffff); }
+ static void write_dword_masked_static(this_type &space, offs_t address, u32 data, u32 mask) { memory_write_generic<Width, AddrShift, Endian, 2, true>([&space](offs_t offset, NativeType data, NativeType mask) { space.write_native(offset, data, mask); }, address, data, mask); }
+ static void write_qword_static(this_type &space, offs_t address, u64 data) { if (Width == 3) space.write_native(address & ~NATIVE_MASK, data); else memory_write_generic<Width, AddrShift, Endian, 3, false>([&space](offs_t offset, NativeType data, NativeType mask) { space.write_native(offset, data, mask); }, address, data, 0xffffffffffffffffU); }
+ static void write_qword_masked_static(this_type &space, offs_t address, u64 data, u64 mask) { memory_write_generic<Width, AddrShift, Endian, 3, false>([&space](offs_t offset, NativeType data, NativeType mask) { space.write_native(offset, data, mask); }, address, data, mask); }
+
+ handler_entry_read <Width, AddrShift, Endian> *m_root_read;
+ handler_entry_write<Width, AddrShift, Endian> *m_root_write;
+
+ std::unordered_set<handler_entry *> m_delayed_unrefs;
+
+private:
+ template<typename READ>
+ void install_read_handler_impl(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, READ &handler_r)
+ {
+ try { handler_r.resolve(); }
+ catch (const binding_type_exception &) {
+ osd_printf_error("Binding error while installing read handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_r.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask);
+ throw;
+ }
+ install_read_handler_helper<handler_width<READ>::value>(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, handler_r);
+ }
+
+ template<typename WRITE>
+ void install_write_handler_impl(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, WRITE &handler_w)
+ {
+ try { handler_w.resolve(); }
+ catch (const binding_type_exception &) {
+ osd_printf_error("Binding error while installing write handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_w.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask);
+ throw;
+ }
+ install_write_handler_helper<handler_width<WRITE>::value>(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, handler_w);
+ }
+
+ template<typename READ, typename WRITE>
+ void install_readwrite_handler_impl(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, READ &handler_r, WRITE &handler_w)
+ {
+ static_assert(handler_width<READ>::value == handler_width<WRITE>::value, "handler widths do not match");
+ try { handler_r.resolve(); }
+ catch (const binding_type_exception &) {
+ osd_printf_error("Binding error while installing read handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_r.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask);
+ throw;
+ }
+ try { handler_w.resolve(); }
+ catch (const binding_type_exception &) {
+ osd_printf_error("Binding error while installing write handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_w.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask);
+ throw;
+ }
+ install_readwrite_handler_helper<handler_width<READ>::value>(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, handler_r, handler_w);
+ }
+
+ template<int AccessWidth, typename READ>
+ void install_read_handler_helper(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, const READ &handler_r)
+ {
+ if constexpr (Width < AccessWidth) {
+ fatalerror("install_read_handler: cannot install a %d-wide handler in a %d-wide bus", 8 << AccessWidth, 8 << Width);
+ } else {
+ VPRINTF("address_space::install_read_handler(%*x-%*x mask=%*x mirror=%*x, space width=%d, handler width=%d, %s, %*x)\n",
+ m_addrchars, addrstart, m_addrchars, addrend,
+ m_addrchars, addrmask, m_addrchars, addrmirror,
+ 8 << Width, 8 << AccessWidth,
+ handler_r.name(), data_width() / 4, unitmask);
+
+ offs_t nstart, nend, nmask, nmirror;
+ u64 nunitmask;
+ int ncswidth;
+ check_optimize_all("install_read_handler", 8 << AccessWidth, addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, nstart, nend, nmask, nmirror, nunitmask, ncswidth);
+
+ if constexpr (Width == AccessWidth) {
+ auto hand_r = new handler_entry_read_delegate<Width, AddrShift, Endian, READ>(this, handler_r);
+ hand_r->set_address_info(nstart, nmask);
+ m_root_read->populate(nstart, nend, nmirror, hand_r);
+ } else {
+ auto hand_r = new handler_entry_read_delegate<AccessWidth, -AccessWidth, Endian, READ>(this, handler_r);
+ memory_units_descriptor<Width, AddrShift, Endian> descriptor(AccessWidth, Endian, hand_r, nstart, nend, nmask, nunitmask, ncswidth);
+ hand_r->set_address_info(descriptor.get_handler_start(), descriptor.get_handler_mask());
+ m_root_read->populate_mismatched(nstart, nend, nmirror, descriptor);
+ hand_r->unref();
+ }
+ invalidate_caches(read_or_write::READ);
+ }
+ }
+
+ template<int AccessWidth, typename WRITE>
+ void install_write_handler_helper(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth,
+ const WRITE &handler_w)
+ {
+ if constexpr (Width < AccessWidth) {
+ fatalerror("install_write_handler: cannot install a %d-wide handler in a %d-wide bus", 8 << AccessWidth, 8 << Width);
+ } else {
+ VPRINTF("address_space::install_write_handler(%*x-%*x mask=%*x mirror=%*x, space width=%d, handler width=%d, %s, %*x)\n",
+ m_addrchars, addrstart, m_addrchars, addrend,
+ m_addrchars, addrmask, m_addrchars, addrmirror,
+ 8 << Width, 8 << AccessWidth,
+ handler_w.name(), data_width() / 4, unitmask);
+
+ offs_t nstart, nend, nmask, nmirror;
+ u64 nunitmask;
+ int ncswidth;
+ check_optimize_all("install_write_handler", 8 << AccessWidth, addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, nstart, nend, nmask, nmirror, nunitmask, ncswidth);
+
+ if constexpr (Width == AccessWidth) {
+ auto hand_w = new handler_entry_write_delegate<Width, AddrShift, Endian, WRITE>(this, handler_w);
+ hand_w->set_address_info(nstart, nmask);
+ m_root_write->populate(nstart, nend, nmirror, hand_w);
+ } else {
+ auto hand_w = new handler_entry_write_delegate<AccessWidth, -AccessWidth, Endian, WRITE>(this, handler_w);
+ memory_units_descriptor<Width, AddrShift, Endian> descriptor(AccessWidth, Endian, hand_w, nstart, nend, nmask, nunitmask, ncswidth);
+ hand_w->set_address_info(descriptor.get_handler_start(), descriptor.get_handler_mask());
+ m_root_write->populate_mismatched(nstart, nend, nmirror, descriptor);
+ hand_w->unref();
+ }
+ invalidate_caches(read_or_write::WRITE);
+ }
+ }
+
+ template<int AccessWidth, typename READ, typename WRITE>
+ void install_readwrite_handler_helper(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth,
+ const READ &handler_r,
+ const WRITE &handler_w)
+ {
+ if constexpr (Width < AccessWidth) {
+ fatalerror("install_readwrite_handler: cannot install a %d-wide handler in a %d-wide bus", 8 << AccessWidth, 8 << Width);
+ } else {
+ VPRINTF("address_space::install_readwrite_handler(%*x-%*x mask=%*x mirror=%*x, space width=%d, handler width=%d, %s, %s, %*x)\n",
+ m_addrchars, addrstart, m_addrchars, addrend,
+ m_addrchars, addrmask, m_addrchars, addrmirror,
+ 8 << Width, 8 << AccessWidth,
+ handler_r.name(), handler_w.name(), data_width() / 4, unitmask);
+
+ offs_t nstart, nend, nmask, nmirror;
+ u64 nunitmask;
+ int ncswidth;
+ check_optimize_all("install_readwrite_handler", 8 << AccessWidth, addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, nstart, nend, nmask, nmirror, nunitmask, ncswidth);
+
+ if constexpr (Width == AccessWidth) {
+ auto hand_r = new handler_entry_read_delegate <Width, AddrShift, Endian, READ>(this, handler_r);
+ hand_r->set_address_info(nstart, nmask);
+ m_root_read ->populate(nstart, nend, nmirror, hand_r);
+
+ auto hand_w = new handler_entry_write_delegate<Width, AddrShift, Endian, WRITE>(this, handler_w);
+ hand_w->set_address_info(nstart, nmask);
+ m_root_write->populate(nstart, nend, nmirror, hand_w);
+ } else {
+ auto hand_r = new handler_entry_read_delegate <AccessWidth, -AccessWidth, Endian, READ>(this, handler_r);
+ memory_units_descriptor<Width, AddrShift, Endian> descriptor(AccessWidth, Endian, hand_r, nstart, nend, nmask, nunitmask, ncswidth);
+ hand_r->set_address_info(descriptor.get_handler_start(), descriptor.get_handler_mask());
+ m_root_read ->populate_mismatched(nstart, nend, nmirror, descriptor);
+ hand_r->unref();
+
+ auto hand_w = new handler_entry_write_delegate<AccessWidth, -AccessWidth, Endian, WRITE>(this, handler_w);
+ descriptor.set_subunit_handler(hand_w);
+ hand_w->set_address_info(descriptor.get_handler_start(), descriptor.get_handler_mask());
+ m_root_write->populate_mismatched(nstart, nend, nmirror, descriptor);
+ hand_w->unref();
+ }
+ invalidate_caches(read_or_write::READWRITE);
+ }
+ }
+};
+
+
+
+//-------------------------------------------------
+// allocate - allocate memory spaces
+//-------------------------------------------------
+
+void memory_manager::allocate(device_memory_interface &memory)
+{
+ for (int spacenum = 0; spacenum < memory.max_space_count(); ++spacenum)
+ {
+ // if there is a configuration for this space, we need an address space
+ address_space_config const *const spaceconfig = memory.space_config(spacenum);
+ if (spaceconfig)
+ {
+ int level = emu::detail::handler_entry_dispatch_level(spaceconfig->addr_width());
+ // allocate one of the appropriate type
+ switch ((level << 8) | (spaceconfig->endianness() == ENDIANNESS_BIG ? 0x1000 : 0) |spaceconfig->data_width() | (spaceconfig->addr_shift() + 4))
+ {
+ case 0x0000|0x000| 8|(4+1): memory.allocate<address_space_specific<0, 0, 1, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x000| 8|(4+1): memory.allocate<address_space_specific<0, 0, 1, ENDIANNESS_BIG >>(*this, spacenum); break;
+ case 0x0000|0x100| 8|(4+1): memory.allocate<address_space_specific<1, 0, 1, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x100| 8|(4+1): memory.allocate<address_space_specific<1, 0, 1, ENDIANNESS_BIG >>(*this, spacenum); break;
+
+ case 0x0000|0x000| 8|(4-0): memory.allocate<address_space_specific<0, 0, 0, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x000| 8|(4-0): memory.allocate<address_space_specific<0, 0, 0, ENDIANNESS_BIG >>(*this, spacenum); break;
+ case 0x0000|0x100| 8|(4-0): memory.allocate<address_space_specific<1, 0, 0, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x100| 8|(4-0): memory.allocate<address_space_specific<1, 0, 0, ENDIANNESS_BIG >>(*this, spacenum); break;
+
+ case 0x0000|0x000|16|(4+3): memory.allocate<address_space_specific<0, 1, 3, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x000|16|(4+3): memory.allocate<address_space_specific<0, 1, 3, ENDIANNESS_BIG >>(*this, spacenum); break;
+ case 0x0000|0x100|16|(4+3): memory.allocate<address_space_specific<1, 1, 3, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x100|16|(4+3): memory.allocate<address_space_specific<1, 1, 3, ENDIANNESS_BIG >>(*this, spacenum); break;
+
+ case 0x0000|0x000|16|(4-0): memory.allocate<address_space_specific<0, 1, 0, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x000|16|(4-0): memory.allocate<address_space_specific<0, 1, 0, ENDIANNESS_BIG >>(*this, spacenum); break;
+ case 0x0000|0x100|16|(4-0): memory.allocate<address_space_specific<1, 1, 0, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x100|16|(4-0): memory.allocate<address_space_specific<1, 1, 0, ENDIANNESS_BIG >>(*this, spacenum); break;
+
+ case 0x0000|0x000|16|(4-1): memory.allocate<address_space_specific<0, 1, -1, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x000|16|(4-1): memory.allocate<address_space_specific<0, 1, -1, ENDIANNESS_BIG >>(*this, spacenum); break;
+ case 0x0000|0x100|16|(4-1): memory.allocate<address_space_specific<1, 1, -1, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x100|16|(4-1): memory.allocate<address_space_specific<1, 1, -1, ENDIANNESS_BIG >>(*this, spacenum); break;
+
+ case 0x0000|0x000|32|(4+3): memory.allocate<address_space_specific<0, 2, 3, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x000|32|(4+3): memory.allocate<address_space_specific<0, 2, 3, ENDIANNESS_BIG >>(*this, spacenum); break;
+ case 0x0000|0x100|32|(4+3): memory.allocate<address_space_specific<1, 2, 3, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x100|32|(4+3): memory.allocate<address_space_specific<1, 2, 3, ENDIANNESS_BIG >>(*this, spacenum); break;
+
+ case 0x0000|0x000|32|(4-0): memory.allocate<address_space_specific<0, 2, 0, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x000|32|(4-0): memory.allocate<address_space_specific<0, 2, 0, ENDIANNESS_BIG >>(*this, spacenum); break;
+ case 0x0000|0x100|32|(4-0): memory.allocate<address_space_specific<1, 2, 0, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x100|32|(4-0): memory.allocate<address_space_specific<1, 2, 0, ENDIANNESS_BIG >>(*this, spacenum); break;
+
+ case 0x0000|0x000|32|(4-1): memory.allocate<address_space_specific<0, 2, -1, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x000|32|(4-1): memory.allocate<address_space_specific<0, 2, -1, ENDIANNESS_BIG >>(*this, spacenum); break;
+ case 0x0000|0x100|32|(4-1): memory.allocate<address_space_specific<1, 2, -1, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x100|32|(4-1): memory.allocate<address_space_specific<1, 2, -1, ENDIANNESS_BIG >>(*this, spacenum); break;
+
+ case 0x0000|0x000|32|(4-2): memory.allocate<address_space_specific<0, 2, -2, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x000|32|(4-2): memory.allocate<address_space_specific<0, 2, -2, ENDIANNESS_BIG >>(*this, spacenum); break;
+ case 0x0000|0x100|32|(4-2): memory.allocate<address_space_specific<1, 2, -2, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x100|32|(4-2): memory.allocate<address_space_specific<1, 2, -2, ENDIANNESS_BIG >>(*this, spacenum); break;
+
+ case 0x0000|0x000|64|(4-0): memory.allocate<address_space_specific<0, 3, 0, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x000|64|(4-0): memory.allocate<address_space_specific<0, 3, 0, ENDIANNESS_BIG >>(*this, spacenum); break;
+ case 0x0000|0x100|64|(4-0): memory.allocate<address_space_specific<1, 3, 0, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x100|64|(4-0): memory.allocate<address_space_specific<1, 3, 0, ENDIANNESS_BIG >>(*this, spacenum); break;
+
+ case 0x0000|0x000|64|(4-1): memory.allocate<address_space_specific<0, 3, -1, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x000|64|(4-1): memory.allocate<address_space_specific<0, 3, -1, ENDIANNESS_BIG >>(*this, spacenum); break;
+ case 0x0000|0x100|64|(4-1): memory.allocate<address_space_specific<1, 3, -1, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x100|64|(4-1): memory.allocate<address_space_specific<1, 3, -1, ENDIANNESS_BIG >>(*this, spacenum); break;
+
+ case 0x0000|0x000|64|(4-2): memory.allocate<address_space_specific<0, 3, -2, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x000|64|(4-2): memory.allocate<address_space_specific<0, 3, -2, ENDIANNESS_BIG >>(*this, spacenum); break;
+ case 0x0000|0x100|64|(4-2): memory.allocate<address_space_specific<1, 3, -2, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x100|64|(4-2): memory.allocate<address_space_specific<1, 3, -2, ENDIANNESS_BIG >>(*this, spacenum); break;
+
+ case 0x0000|0x000|64|(4-3): memory.allocate<address_space_specific<0, 3, -3, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x000|64|(4-3): memory.allocate<address_space_specific<0, 3, -3, ENDIANNESS_BIG >>(*this, spacenum); break;
+ case 0x0000|0x100|64|(4-3): memory.allocate<address_space_specific<1, 3, -3, ENDIANNESS_LITTLE>>(*this, spacenum); break;
+ case 0x1000|0x100|64|(4-3): memory.allocate<address_space_specific<1, 3, -3, ENDIANNESS_BIG >>(*this, spacenum); break;
+
+ default:
+ throw emu_fatalerror("Invalid width %d/shift %d specified for address_space::allocate", spaceconfig->data_width(), spaceconfig->addr_shift());
+ }
+ }
+ }
+}
+
+//**************************************************************************
+// ADDRESS SPACE
+//**************************************************************************
+
+//-------------------------------------------------
+// address_space - constructor
+//-------------------------------------------------
+
+address_space::address_space(memory_manager &manager, device_memory_interface &memory, int spacenum)
+ : address_space_installer(*memory.space_config(spacenum), manager),
+ m_device(memory.device()),
+ m_unmap(0),
+ m_spacenum(spacenum),
+ m_log_unmap(true),
+ m_name(memory.space_config(spacenum)->name()),
+ m_notifier_id(0),
+ m_in_notification(0)
+{
+}
+
+
+//-------------------------------------------------
+// ~address_space - destructor
+//-------------------------------------------------
+
+address_space::~address_space()
+{
+ m_unmap_r->unref();
+ m_unmap_w->unref();
+ m_nop_r->unref();
+ m_nop_w->unref();
+}
+
+
+//-------------------------------------------------
+// prepare_map - allocate the address map and
+// walk through it to find implicit memory regions
+// and identify shared regions
+//-------------------------------------------------
+
+void address_space::prepare_map()
+{
+ memory_region *devregion = (m_spacenum == 0) ? m_device.memregion(DEVICE_SELF) : nullptr;
+ u32 devregionsize = (devregion != nullptr) ? devregion->bytes() : 0;
+
+ // allocate the address map
+ m_map = std::make_unique<address_map>(m_device, m_spacenum);
+
+ // merge in the submaps
+ m_map->import_submaps(m_manager.machine(), m_device.owner() ? *m_device.owner() : m_device, data_width(), endianness(), addr_shift());
+
+ // extract global parameters specified by the map
+ m_unmap = (m_map->m_unmapval == 0) ? 0 : ~0;
+ if (m_map->m_globalmask != 0)
+ {
+ if (m_map->m_globalmask & ~m_addrmask)
+ fatalerror("Can't set a global address mask of %08x on a %d-bits address width bus.\n", m_map->m_globalmask, addr_width());
+
+ m_addrmask = m_map->m_globalmask;
+ }
+
+ // make a pass over the address map, adjusting for the device and getting memory pointers
+ for (address_map_entry &entry : m_map->m_entrylist)
+ {
+ // computed adjusted addresses first
+ adjust_addresses(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror);
+
+ // if we have a share entry, add it to our map
+ if (entry.m_share != nullptr)
+ {
+ // if we can't find it, add it to our map
+ std::string fulltag = entry.m_devbase.subtag(entry.m_share);
+ memory_share *share = m_manager.share_find(fulltag);
+ if (!share)
+ {
+ VPRINTF("Creating share '%s' of length 0x%X\n", fulltag, entry.m_addrend + 1 - entry.m_addrstart);
+ share = m_manager.share_alloc(m_device, fulltag, m_config.data_width(), address_to_byte(entry.m_addrend + 1 - entry.m_addrstart), endianness());
+ }
+ else
+ {
+ std::string result = share->compare(m_config.data_width(), address_to_byte(entry.m_addrend + 1 - entry.m_addrstart), endianness());
+ if (!result.empty())
+ fatalerror("%s\n", result);
+ }
+ entry.m_memory = share->ptr();
+ }
+
+ // if this is a ROM handler without a specified region and not shared, attach it to the implicit region
+ if (m_spacenum == AS_PROGRAM && entry.m_read.m_type == AMH_ROM && entry.m_region == nullptr && entry.m_share == nullptr)
+ {
+ // make sure it fits within the memory region before doing so, however
+ if (entry.m_addrend < devregionsize)
+ {
+ entry.m_region = m_device.tag();
+ entry.m_rgnoffs = address_to_byte(entry.m_addrstart);
+ }
+ }
+
+ // validate adjusted addresses against implicit regions
+ if (entry.m_region != nullptr)
+ {
+ // determine full tag
+ std::string fulltag = entry.m_devbase.subtag(entry.m_region);
+
+ // find the region
+ memory_region *region = m_manager.machine().root_device().memregion(fulltag);
+ if (region == nullptr)
+ fatalerror("device '%s' %s space memory map entry %X-%X references nonexistent region \"%s\"\n", m_device.tag(), m_name, entry.m_addrstart, entry.m_addrend, entry.m_region);
+
+ // validate the region
+ if (entry.m_rgnoffs + m_config.addr2byte(entry.m_addrend - entry.m_addrstart + 1) > region->bytes())
+ fatalerror("device '%s' %s space memory map entry %X-%X extends beyond region \"%s\" size (%X)\n", m_device.tag(), m_name, entry.m_addrstart, entry.m_addrend, entry.m_region, region->bytes());
+
+ if (entry.m_share != nullptr)
+ fatalerror("device '%s' %s space memory map entry %X-%X has both .region() and .share()\n", m_device.tag(), m_name, entry.m_addrstart, entry.m_addrend);
+ }
+
+ // convert any region-relative entries to their memory pointers
+ if (entry.m_region != nullptr)
+ {
+ // determine full tag
+ std::string fulltag = entry.m_devbase.subtag(entry.m_region);
+
+ // set the memory address
+ entry.m_memory = m_manager.machine().root_device().memregion(fulltag)->base() + entry.m_rgnoffs;
+ }
+
+ // allocate anonymous ram when needed
+ if (!entry.m_memory && (entry.m_read.m_type == AMH_RAM || entry.m_write.m_type == AMH_RAM))
+ entry.m_memory = m_manager.anonymous_alloc(*this, address_to_byte(entry.m_addrend + 1 - entry.m_addrstart), m_config.data_width(), entry.m_addrstart, entry.m_addrend);
+ }
+}
+
+
+//-------------------------------------------------
+// populate_from_map - walk the map in reverse
+// order and install the appropriate handler for
+// each case
+//-------------------------------------------------
+
+void address_space::populate_from_map(address_map *map)
+{
+ // no map specified, use the space-specific one
+ if (map == nullptr)
+ map = m_map.get();
+
+ // no map, nothing to do
+ if (map == nullptr)
+ return;
+
+ // install the handlers, using the original, unadjusted memory map
+ for (const address_map_entry &entry : map->m_entrylist) {
+ // map both read and write halves
+ populate_map_entry(entry, read_or_write::READ);
+ populate_map_entry(entry, read_or_write::WRITE);
+ }
+
+ if (VALIDATE_REFCOUNTS)
+ validate_reference_counts();
+}
+
+//-------------------------------------------------
+// get_handler_string - return a string
+// describing the handler at a particular offset
+//-------------------------------------------------
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> std::string address_space_specific<Level, Width, AddrShift, Endian>::get_handler_string(read_or_write readorwrite, offs_t address) const
+{
+ if (readorwrite == read_or_write::READ) {
+ offs_t start, end;
+ handler_entry_read<Width, AddrShift, Endian> *handler;
+ m_root_read->lookup(address, start, end, handler);
+ return handler->name();
+ } else {
+ offs_t start, end;
+ handler_entry_write<Width, AddrShift, Endian> *handler;
+ m_root_write->lookup(address, start, end, handler);
+ return handler->name();
+ }
+}
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::dump_maps(std::vector<memory_entry> &read_map, std::vector<memory_entry> &write_map) const
+{
+ read_map.clear();
+ write_map.clear();
+ m_root_read->dump_map(read_map);
+ m_root_write->dump_map(write_map);
+}
+
+
+//**************************************************************************
+// DYNAMIC ADDRESS SPACE MAPPING
+//**************************************************************************
+
+//-------------------------------------------------
+// unmap - unmap a section of address space
+//-------------------------------------------------
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::unmap_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, read_or_write readorwrite, bool quiet)
+{
+ VPRINTF("address_space::unmap(%*x-%*x mirror=%*x, %s, %s)\n",
+ m_addrchars, addrstart, m_addrchars, addrend,
+ m_addrchars, addrmirror,
+ (readorwrite == read_or_write::READ) ? "read" : (readorwrite == read_or_write::WRITE) ? "write" : (readorwrite == read_or_write::READWRITE) ? "read/write" : "??",
+ quiet ? "quiet" : "normal");
+
+ offs_t nstart, nend, nmask, nmirror;
+ check_optimize_mirror("unmap_generic", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
+
+ // read space
+ if (readorwrite == read_or_write::READ || readorwrite == read_or_write::READWRITE) {
+ auto handler = static_cast<handler_entry_read<Width, AddrShift, Endian> *>(quiet ? m_nop_r : m_unmap_r);
+ handler->ref();
+ m_root_read->populate(nstart, nend, nmirror, handler);
+ }
+
+ // write space
+ if (readorwrite == read_or_write::WRITE || readorwrite == read_or_write::READWRITE) {
+ auto handler = static_cast<handler_entry_write<Width, AddrShift, Endian> *>(quiet ? m_nop_w : m_unmap_w);
+ handler->ref();
+ m_root_write->populate(nstart, nend, nmirror, handler);
+ }
+
+ invalidate_caches(readorwrite);
+}
+
+//-------------------------------------------------
+// install_view - install a view on the bus
+//-------------------------------------------------
+template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_view(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_view &view)
+{
+ offs_t nstart, nend, nmask, nmirror;
+ check_optimize_mirror("install_view", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
+
+ auto handlers = view.make_handlers(*this, addrstart, addrend);
+ m_root_read ->populate(nstart, nend, nmirror, static_cast<handler_entry_read <Width, AddrShift, Endian> *>(handlers.first));
+ m_root_write->populate(nstart, nend, nmirror, static_cast<handler_entry_write<Width, AddrShift, Endian> *>(handlers.second));
+ view.make_subdispatch(""); // Must be called after populate
+}
+
+memory_passthrough_handler *address_space::make_mph()
+{
+ m_mphs.emplace_back(std::make_unique<memory_passthrough_handler>(*this));
+ return m_mphs.back().get();
+}
+
+//-------------------------------------------------
+// install_read_tap - install a read tap on the bus
+//-------------------------------------------------
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> memory_passthrough_handler *address_space_specific<Level, Width, AddrShift, Endian>::install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph)
+{
+ offs_t nstart, nend, nmask, nmirror;
+ check_optimize_mirror("install_read_tap", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
+ if (!mph)
+ mph = make_mph();
+
+ auto handler = new handler_entry_read_tap<Width, AddrShift, Endian>(this, *mph, name, tap);
+ m_root_read->populate_passthrough(nstart, nend, nmirror, handler);
+ handler->unref();
+
+ invalidate_caches(read_or_write::READ);
+
+ return mph;
+}
+
+//-------------------------------------------------
+// install_write_tap - install a write tap on the bus
+//-------------------------------------------------
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> memory_passthrough_handler *address_space_specific<Level, Width, AddrShift, Endian>::install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph)
+{
+ offs_t nstart, nend, nmask, nmirror;
+ check_optimize_mirror("install_write_tap", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
+ if (!mph)
+ mph = make_mph();
+
+ auto handler = new handler_entry_write_tap<Width, AddrShift, Endian>(this, *mph, name, tap);
+ m_root_write->populate_passthrough(nstart, nend, nmirror, handler);
+ handler->unref();
+
+ invalidate_caches(read_or_write::WRITE);
+
+ return mph;
+}
+//-------------------------------------------------
+// install_write_tap - install a read and a write tap on the bus
+//-------------------------------------------------
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> memory_passthrough_handler *address_space_specific<Level, Width, AddrShift, Endian>::install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapr, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapw, memory_passthrough_handler *mph)
+{
+ offs_t nstart, nend, nmask, nmirror;
+ check_optimize_mirror("install_readwrite_tap", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
+ if (!mph)
+ mph = make_mph();
+
+ auto rhandler = new handler_entry_read_tap <Width, AddrShift, Endian>(this, *mph, name, tapr);
+ m_root_read ->populate_passthrough(nstart, nend, nmirror, rhandler);
+ rhandler->unref();
+
+ auto whandler = new handler_entry_write_tap<Width, AddrShift, Endian>(this, *mph, name, tapw);
+ m_root_write->populate_passthrough(nstart, nend, nmirror, whandler);
+ whandler->unref();
+
+ invalidate_caches(read_or_write::READWRITE);
+
+ return mph;
+}
+
+
+
+
+
+//-------------------------------------------------
+// install_device_delegate - install the memory map
+// of a live device into this address space
+//-------------------------------------------------
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_device_delegate(offs_t addrstart, offs_t addrend, device_t &device, address_map_constructor &delegate, u64 unitmask, int cswidth)
+{
+ check_address("install_device_delegate", addrstart, addrend);
+ address_map map(*this, addrstart, addrend, unitmask, cswidth, m_device, delegate);
+ map.import_submaps(m_manager.machine(), device, data_width(), endianness(), addr_shift());
+ populate_from_map(&map);
+}
+
+
+
+//-------------------------------------------------
+// install_readwrite_port - install a new I/O port
+// handler into this address space
+//-------------------------------------------------
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_readwrite_port(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string rtag, std::string wtag)
+{
+ VPRINTF("address_space::install_readwrite_port(%*x-%*x mirror=%*x, read=\"%s\" / write=\"%s\")\n",
+ m_addrchars, addrstart, m_addrchars, addrend,
+ m_addrchars, addrmirror,
+ rtag.empty() ? "(none)" : rtag, wtag.empty() ? "(none)" : wtag);
+
+ offs_t nstart, nend, nmask, nmirror;
+ check_optimize_mirror("install_readwrite_port", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
+
+ // read handler
+ if (rtag != "")
+ {
+ // find the port
+ ioport_port *port = device().owner()->ioport(rtag);
+ if (port == nullptr)
+ throw emu_fatalerror("Attempted to map non-existent port '%s' for read in space %s of device '%s'\n", rtag, m_name, m_device.tag());
+
+ // map the range and set the ioport
+ auto hand_r = new handler_entry_read_ioport<Width, AddrShift, Endian>(this, port);
+ m_root_read->populate(nstart, nend, nmirror, hand_r);
+ }
+
+ if (wtag != "")
+ {
+ // find the port
+ ioport_port *port = device().owner()->ioport(wtag);
+ if (port == nullptr)
+ fatalerror("Attempted to map non-existent port '%s' for write in space %s of device '%s'\n", wtag, m_name, m_device.tag());
+
+ // map the range and set the ioport
+ auto hand_w = new handler_entry_write_ioport<Width, AddrShift, Endian>(this, port);
+ m_root_write->populate(nstart, nend, nmirror, hand_w);
+ }
+
+ invalidate_caches(rtag != "" ? wtag != "" ? read_or_write::READWRITE : read_or_write::READ : read_or_write::WRITE);
+}
+
+
+//-------------------------------------------------
+// install_bank_generic - install a range as
+// mapping to a particular bank
+//-------------------------------------------------
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_bank_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_bank *rbank, memory_bank *wbank)
+{
+ VPRINTF("address_space::install_readwrite_bank(%*x-%*x mirror=%*x, read=\"%s\" / write=\"%s\")\n",
+ m_addrchars, addrstart, m_addrchars, addrend,
+ m_addrchars, addrmirror,
+ (rbank != nullptr) ? rbank->tag() : "(none)", (wbank != nullptr) ? wbank->tag() : "(none)");
+
+ offs_t nstart, nend, nmask, nmirror;
+ check_optimize_mirror("install_bank_generic", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
+
+ // map the read bank
+ if (rbank != nullptr)
+ {
+ auto hand_r = new handler_entry_read_memory_bank<Width, AddrShift, Endian>(this, *rbank);
+ hand_r->set_address_info(nstart, nmask);
+ m_root_read->populate(nstart, nend, nmirror, hand_r);
+ }
+
+ // map the write bank
+ if (wbank != nullptr)
+ {
+ auto hand_w = new handler_entry_write_memory_bank<Width, AddrShift, Endian>(this, *wbank);
+ hand_w->set_address_info(nstart, nmask);
+ m_root_write->populate(nstart, nend, nmirror, hand_w);
+ }
+
+ invalidate_caches(rbank ? wbank ? read_or_write::READWRITE : read_or_write::READ : read_or_write::WRITE);
+}
+
+
+//-------------------------------------------------
+// install_ram_generic - install a simple fixed
+// RAM region into the given address space
+//-------------------------------------------------
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> void address_space_specific<Level, Width, AddrShift, Endian>::install_ram_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, read_or_write readorwrite, void *baseptr)
+{
+ VPRINTF("address_space::install_ram_generic(%s-%s mirror=%s, %s, %p)\n",
+ m_addrchars, addrstart, m_addrchars, addrend,
+ m_addrchars, addrmirror,
+ (readorwrite == read_or_write::READ) ? "read" : (readorwrite == read_or_write::WRITE) ? "write" : (readorwrite == read_or_write::READWRITE) ? "read/write" : "??",
+ baseptr);
+
+ offs_t nstart, nend, nmask, nmirror;
+ check_optimize_mirror("install_ram_generic", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
+
+ // map for read
+ if (readorwrite == read_or_write::READ || readorwrite == read_or_write::READWRITE)
+ {
+ auto hand_r = new handler_entry_read_memory<Width, AddrShift, Endian>(this, baseptr);
+ hand_r->set_address_info(nstart, nmask);
+ m_root_read->populate(nstart, nend, nmirror, hand_r);
+ }
+
+ // map for write
+ if (readorwrite == read_or_write::WRITE || readorwrite == read_or_write::READWRITE)
+ {
+ auto hand_w = new handler_entry_write_memory<Width, AddrShift, Endian>(this, baseptr);
+ hand_w->set_address_info(nstart, nmask);
+ m_root_write->populate(nstart, nend, nmirror, hand_w);
+ }
+
+ invalidate_caches(readorwrite);
+}
+
+//**************************************************************************
+// MEMORY MAPPING HELPERS
+//**************************************************************************
+
+int address_space::add_change_notifier(std::function<void (read_or_write)> n)
+{
+ int id = m_notifier_id++;
+ m_notifiers.emplace_back(notifier_t{ std::move(n), id });
+ return id;
+}
+
+void address_space::remove_change_notifier(int id)
+{
+ for(auto i = m_notifiers.begin(); i != m_notifiers.end(); i++)
+ if (i->m_id == id) {
+ m_notifiers.erase(i);
+ return;
+ }
+ fatalerror("Unknown notifier id %d, double remove?\n", id);
+}
diff --git a/src/emu/emumem_hedr.h b/src/emu/emumem_hedr.h
index 30e819bd990..0ef50471e8f 100644
--- a/src/emu/emumem_hedr.h
+++ b/src/emu/emumem_hedr.h
@@ -3,7 +3,8 @@
// handler_entry_read_dispatch
-// dispatches an access among multiple handlers indexed on part of the address
+// dispatches an access among multiple handlers indexed on part of the
+// address and when appropriate a selected view
template<int HighBits, int Width, int AddrShift, endianness_t Endian> class handler_entry_read_dispatch : public handler_entry_read<Width, AddrShift, Endian>
{
@@ -13,6 +14,8 @@ public:
using mapping = typename inh::mapping;
handler_entry_read_dispatch(address_space *space, const handler_entry::range &init, handler_entry_read<Width, AddrShift, Endian> *handler);
+ handler_entry_read_dispatch(address_space *space, memory_view &view);
+ handler_entry_read_dispatch(handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian> *src);
~handler_entry_read_dispatch();
uX read(offs_t offset, uX mem_mask) const override;
@@ -35,9 +38,13 @@ public:
void enumerate_references(handler_entry::reflist &refs) const override;
- virtual const handler_entry_read<Width, AddrShift, Endian> *const *get_dispatch() const override;
+ const handler_entry_read<Width, AddrShift, Endian> *const *get_dispatch() const override;
+ void select_a(int slot) override;
+ void select_u(int slot) override;
+ void init_handlers(offs_t start_entry, offs_t end_entry, u32 lowbits, handler_entry_read<Width, AddrShift, Endian> **dispatch, handler_entry::range *ranges) override;
+ handler_entry_read<Width, AddrShift, Endian> *dup() override;
-protected:
+private:
static constexpr int Level = emu::detail::handler_entry_dispatch_level(HighBits);
static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_lowbits(HighBits, Width, AddrShift);
static constexpr u32 BITCOUNT = HighBits > LowBits ? HighBits - LowBits : 0;
@@ -47,10 +54,17 @@ protected:
static constexpr offs_t HIGHMASK = make_bitmask<offs_t>(HighBits) ^ LOWMASK;
static constexpr offs_t UPMASK = ~make_bitmask<offs_t>(HighBits);
- handler_entry_read<Width, AddrShift, Endian> *m_dispatch[COUNT];
- handler_entry::range m_ranges[COUNT];
+ memory_view *m_view;
+
+ std::vector<std::array<handler_entry_read<Width, AddrShift, Endian> *, COUNT>> m_dispatch_array;
+ std::vector<std::array<handler_entry::range, COUNT>> m_ranges_array;
+
+ handler_entry_read<Width, AddrShift, Endian> **m_a_dispatch;
+ handler_entry::range *m_a_ranges;
+
+ handler_entry_read<Width, AddrShift, Endian> **m_u_dispatch;
+ handler_entry::range *m_u_ranges;
-private:
void populate_nomirror_subdispatch(offs_t entry, offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_read<Width, AddrShift, Endian> *handler);
void populate_mirror_subdispatch(offs_t entry, offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, handler_entry_read<Width, AddrShift, Endian> *handler);
diff --git a/src/emu/emumem_hedr.ipp b/src/emu/emumem_hedr.ipp
index 844cae6dd90..41a209f75ec 100644
--- a/src/emu/emumem_hedr.ipp
+++ b/src/emu/emumem_hedr.ipp
@@ -11,71 +11,125 @@
template<int HighBits, int Width, int AddrShift, endianness_t Endian> const handler_entry_read<Width, AddrShift, Endian> *const *handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::get_dispatch() const
{
- return m_dispatch;
+ return m_a_dispatch;
}
-template<int HighBits, int Width, int AddrShift, endianness_t Endian> handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::handler_entry_read_dispatch(address_space *space, const handler_entry::range &init, handler_entry_read<Width, AddrShift, Endian> *handler) : handler_entry_read<Width, AddrShift, Endian>(space, handler_entry::F_DISPATCH)
+template<int HighBits, int Width, int AddrShift, endianness_t Endian> handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::handler_entry_read_dispatch(address_space *space, const handler_entry::range &init, handler_entry_read<Width, AddrShift, Endian> *handler) : handler_entry_read<Width, AddrShift, Endian>(space, handler_entry::F_DISPATCH), m_view(nullptr)
{
+ m_ranges_array.resize(1);
+ m_dispatch_array.resize(1);
+ m_a_ranges = m_ranges_array[0].data();
+ m_a_dispatch = m_dispatch_array[0].data();
+ m_u_ranges = m_ranges_array[0].data();
+ m_u_dispatch = m_dispatch_array[0].data();
+
if (!handler)
handler = space->get_unmap_r<Width, AddrShift, Endian>();
handler->ref(COUNT);
for(unsigned int i=0; i != COUNT; i++) {
- m_dispatch[i] = handler;
- m_ranges[i] = init;
+ m_u_dispatch[i] = handler;
+ m_u_ranges[i] = init;
+ }
+}
+
+template<int HighBits, int Width, int AddrShift, endianness_t Endian> handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::handler_entry_read_dispatch(address_space *space, memory_view &view) : handler_entry_read<Width, AddrShift, Endian>(space, handler_entry::F_VIEW), m_view(&view), m_a_dispatch(nullptr), m_a_ranges(nullptr), m_u_dispatch(nullptr), m_u_ranges(nullptr)
+{
+}
+
+template<int HighBits, int Width, int AddrShift, endianness_t Endian> handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::handler_entry_read_dispatch(handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian> *src) : handler_entry_read<Width, AddrShift, Endian>(src->m_space, handler_entry::F_DISPATCH), m_view(nullptr)
+{
+ m_ranges_array.resize(1);
+ m_dispatch_array.resize(1);
+ m_a_ranges = m_ranges_array[0].data();
+ m_a_dispatch = m_dispatch_array[0].data();
+ m_u_ranges = m_ranges_array[0].data();
+ m_u_dispatch = m_dispatch_array[0].data();
+
+ for(unsigned int i=0; i != COUNT; i++) {
+ m_u_dispatch[i] = src->m_u_dispatch[i];
+ m_u_ranges[i] = src->m_u_ranges[i];
}
}
+
template<int HighBits, int Width, int AddrShift, endianness_t Endian> handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::~handler_entry_read_dispatch()
{
- for(unsigned int i=0; i != COUNT; i++)
- m_dispatch[i]->unref();
+ for(auto &d : m_dispatch_array)
+ for(auto p : d)
+ if(p)
+ p->unref();
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::enumerate_references(handler_entry::reflist &refs) const
{
- for(unsigned int i=0; i != COUNT; i++)
- refs.add(m_dispatch[i]);
+ for(auto &d : m_dispatch_array)
+ for(auto p : d)
+ if(p)
+ refs.add(p);
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::dump_map(std::vector<memory_entry> &map) const
{
- offs_t cur = map.empty() ? 0 : map.back().end + 1;
- offs_t base = cur & UPMASK;
- do {
- offs_t entry = (cur >> LowBits) & BITMASK;
- if(m_dispatch[entry]->is_dispatch())
- m_dispatch[entry]->dump_map(map);
- else
- map.emplace_back(memory_entry{ m_ranges[entry].start, m_ranges[entry].end, m_dispatch[entry] });
- cur = map.back().end + 1;
- } while(cur && !((cur ^ base) & UPMASK));
-
+ if(m_view) {
+ for(u32 i = 0; i != m_dispatch_array.size(); i++) {
+ u32 j = map.size();
+ offs_t cur = map.empty() ? m_view->m_addrstart & HIGHMASK : map.back().end + 1;
+ offs_t end = m_view->m_addrend + 1;
+ do {
+ offs_t entry = (cur >> LowBits) & BITMASK;
+ if(m_dispatch_array[i][entry]->is_dispatch() || m_dispatch_array[i][entry]->is_view())
+ m_dispatch_array[i][entry]->dump_map(map);
+ else
+ map.emplace_back(memory_entry{ m_ranges_array[i][entry].start, m_ranges_array[i][entry].end, m_dispatch_array[i][entry] });
+ cur = map.back().end + 1;
+ } while(cur != end);
+ if(i == 0) {
+ for(u32 k = j; k != map.size(); k++)
+ map[k].context.emplace(map[k].context.begin(), memory_entry_context{ m_view, true, 0 });
+ } else {
+ int slot = m_view->id_to_slot(int(i)-1);
+ for(u32 k = j; k != map.size(); k++)
+ map[k].context.emplace(map[k].context.begin(), memory_entry_context{ m_view, false, slot });
+ }
+ }
+ } else {
+ offs_t cur = map.empty() ? 0 : map.back().end + 1;
+ offs_t base = cur & UPMASK;
+ do {
+ offs_t entry = (cur >> LowBits) & BITMASK;
+ if(m_a_dispatch[entry]->is_dispatch() || m_a_dispatch[entry]->is_view())
+ m_a_dispatch[entry]->dump_map(map);
+ else
+ map.emplace_back(memory_entry{ m_a_ranges[entry].start, m_a_ranges[entry].end, m_a_dispatch[entry] });
+ cur = map.back().end + 1;
+ } while(cur && !((cur ^ base) & UPMASK));
+ }
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> typename emu::detail::handler_entry_size<Width>::uX handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::read(offs_t offset, uX mem_mask) const
{
- return dispatch_read<Level, Width, AddrShift, Endian>(HIGHMASK, offset, mem_mask, m_dispatch);
+ return dispatch_read<Level, Width, AddrShift, Endian>(HIGHMASK, offset, mem_mask, m_a_dispatch);
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void *handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::get_ptr(offs_t offset) const
{
- return m_dispatch[(offset & HIGHMASK) >> LowBits]->get_ptr(offset);
+ return m_a_dispatch[(offset & HIGHMASK) >> LowBits]->get_ptr(offset);
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> std::string handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::name() const
{
- return "dispatch";
+ return m_view ? "view" : "dispatch";
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::lookup(offs_t address, offs_t &start, offs_t &end, handler_entry_read<Width, AddrShift, Endian> *&handler) const
{
offs_t slot = (address >> LowBits) & BITMASK;
- auto h = m_dispatch[slot];
- if(h->is_dispatch())
+ auto h = m_a_dispatch[slot];
+ if(h->is_dispatch() || h->is_view())
h->lookup(address, start, end, handler);
else {
- start = m_ranges[slot].start;
- end = m_ranges[slot].end;
+ start = m_a_ranges[slot].start;
+ end = m_a_ranges[slot].end;
handler = h;
}
}
@@ -83,62 +137,66 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::range_cut_before(offs_t address, int start)
{
while(--start >= 0) {
- if(int(LowBits) > -AddrShift && m_dispatch[start]->is_dispatch()) {
- static_cast<handler_entry_read_dispatch<LowBits, Width, AddrShift, Endian> *>(m_dispatch[start])->range_cut_before(address);
+ if(int(LowBits) > -AddrShift && m_u_dispatch[start]->is_dispatch()) {
+ static_cast<handler_entry_read_dispatch<LowBits, Width, AddrShift, Endian> *>(m_u_dispatch[start])->range_cut_before(address);
break;
}
- if(m_ranges[start].end <= address)
+ if(m_u_ranges[start].end <= address)
break;
- m_ranges[start].end = address;
+ m_u_ranges[start].end = address;
}
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::range_cut_after(offs_t address, int start)
{
while(++start < COUNT) {
- if(int(LowBits) > -AddrShift && m_dispatch[start]->is_dispatch()) {
- static_cast<handler_entry_read_dispatch<LowBits, Width, AddrShift, Endian> *>(m_dispatch[start])->range_cut_after(address);
+ if(int(LowBits) > -AddrShift && m_u_dispatch[start]->is_dispatch()) {
+ static_cast<handler_entry_read_dispatch<LowBits, Width, AddrShift, Endian> *>(m_u_dispatch[start])->range_cut_after(address);
break;
}
- if(m_ranges[start].start >= address)
+ if(m_u_ranges[start].start >= address)
break;
- m_ranges[start].start = address;
+ m_u_ranges[start].start = address;
}
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::populate_nomirror_subdispatch(offs_t entry, offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_read<Width, AddrShift, Endian> *handler)
{
- auto cur = m_dispatch[entry];
+ auto cur = m_u_dispatch[entry];
if(cur->is_dispatch())
cur->populate_nomirror(start, end, ostart, oend, handler);
else {
- auto subdispatch = new handler_entry_read_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_ranges[entry], cur);
+ auto subdispatch = new handler_entry_read_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_u_ranges[entry], cur);
cur->unref();
- m_dispatch[entry] = subdispatch;
+ m_u_dispatch[entry] = subdispatch;
subdispatch->populate_nomirror(start, end, ostart, oend, handler);
}
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::populate_nomirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_read<Width, AddrShift, Endian> *handler)
{
- offs_t start_entry = start >> LowBits;
- offs_t end_entry = end >> LowBits;
+ offs_t start_entry = (start & HIGHMASK) >> LowBits;
+ offs_t end_entry = (end & HIGHMASK) >> LowBits;
range_cut_before(ostart-1, start_entry);
range_cut_after(oend+1, end_entry);
if(LowBits <= Width + AddrShift) {
+ if(handler->is_view())
+ handler->init_handlers(start_entry, end_entry, LowBits, m_u_dispatch, m_u_ranges);
handler->ref(end_entry - start_entry);
for(offs_t ent = start_entry; ent <= end_entry; ent++) {
- m_dispatch[ent]->unref();
- m_dispatch[ent] = handler;
- m_ranges[ent].set(ostart, oend);
+ m_u_dispatch[ent]->unref();
+ m_u_dispatch[ent] = handler;
+ m_u_ranges[ent].set(ostart, oend);
}
} else if(start_entry == end_entry) {
if(!(start & LOWMASK) && (end & LOWMASK) == LOWMASK) {
- m_dispatch[start_entry]->unref();
- m_dispatch[start_entry] = handler;
- m_ranges[start_entry].set(ostart, oend);
+ if(handler->is_view())
+ handler->init_handlers(start_entry, end_entry, LowBits, m_u_dispatch, m_u_ranges);
+ m_u_dispatch[start_entry]->unref();
+ m_u_dispatch[start_entry] = handler;
+ m_u_ranges[start_entry].set(ostart, oend);
} else
populate_nomirror_subdispatch(start_entry, start & LOWMASK, end & LOWMASK, ostart, oend, handler);
@@ -157,24 +215,26 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
}
if(start_entry <= end_entry) {
+ if(handler->is_view())
+ handler->init_handlers(start_entry, end_entry, LowBits, m_u_dispatch, m_u_ranges);
handler->ref(end_entry - start_entry);
for(offs_t ent = start_entry; ent <= end_entry; ent++) {
- m_dispatch[ent]->unref();
- m_dispatch[ent] = handler;
- m_ranges[ent].set(ostart, oend);
+ m_u_dispatch[ent]->unref();
+ m_u_dispatch[ent] = handler;
+ m_u_ranges[ent].set(ostart, oend);
}
}
}
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::populate_mirror_subdispatch(offs_t entry, offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, handler_entry_read<Width, AddrShift, Endian> *handler)
{
- auto cur = m_dispatch[entry];
+ auto cur = m_u_dispatch[entry];
if(cur->is_dispatch())
cur->populate_mirror(start, end, ostart, oend, mirror, handler);
else {
- auto subdispatch = new handler_entry_read_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_ranges[entry], cur);
+ auto subdispatch = new handler_entry_read_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_u_ranges[entry], cur);
cur->unref();
- m_dispatch[entry] = subdispatch;
+ m_u_dispatch[entry] = subdispatch;
subdispatch->populate_mirror(start, end, ostart, oend, mirror, handler);
}
}
@@ -236,13 +296,13 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::populate_mismatched_nomirror_subdispatch(offs_t entry, 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)
{
- auto cur = m_dispatch[entry];
+ auto cur = m_u_dispatch[entry];
if(cur->is_dispatch())
cur->populate_mismatched_nomirror(start, end, ostart, oend, descriptor, rkey, mappings);
else {
- auto subdispatch = new handler_entry_read_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_ranges[entry], cur);
+ auto subdispatch = new handler_entry_read_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_u_ranges[entry], cur);
cur->unref();
- m_dispatch[entry] = subdispatch;
+ m_u_dispatch[entry] = subdispatch;
subdispatch->populate_mismatched_nomirror(start, end, ostart, oend, descriptor, rkey, mappings);
}
}
@@ -261,17 +321,17 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
rkey1 &= ~handler_entry::START;
if(ent != end_entry)
rkey1 &= ~handler_entry::END;
- mismatched_patch(descriptor, rkey1, mappings, m_dispatch[ent]);
- m_ranges[ent].set(ostart, oend);
+ mismatched_patch(descriptor, rkey1, mappings, m_u_dispatch[ent]);
+ m_u_ranges[ent].set(ostart, oend);
}
} else if(start_entry == end_entry) {
if(!(start & LOWMASK) && (end & LOWMASK) == LOWMASK) {
- if(m_dispatch[start_entry]->is_dispatch())
- m_dispatch[start_entry]->populate_mismatched_nomirror(start & LOWMASK, end & LOWMASK, ostart, oend, descriptor, rkey, mappings);
+ if(m_u_dispatch[start_entry]->is_dispatch())
+ m_u_dispatch[start_entry]->populate_mismatched_nomirror(start & LOWMASK, end & LOWMASK, ostart, oend, descriptor, rkey, mappings);
else {
- mismatched_patch(descriptor, rkey, mappings, m_dispatch[start_entry]);
- m_ranges[start_entry].set(ostart, oend);
+ mismatched_patch(descriptor, rkey, mappings, m_u_dispatch[start_entry]);
+ m_u_ranges[start_entry].set(ostart, oend);
}
} else
populate_mismatched_nomirror_subdispatch(start_entry, start & LOWMASK, end & LOWMASK, ostart, oend, descriptor, rkey, mappings);
@@ -295,11 +355,11 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
rkey1 &= ~handler_entry::START;
if(ent != end_entry)
rkey1 &= ~handler_entry::END;
- if(m_dispatch[ent]->is_dispatch())
- m_dispatch[ent]->populate_mismatched_nomirror(start & LOWMASK, end & LOWMASK, ostart, oend, descriptor, rkey1, mappings);
+ if(m_u_dispatch[ent]->is_dispatch())
+ m_u_dispatch[ent]->populate_mismatched_nomirror(start & LOWMASK, end & LOWMASK, ostart, oend, descriptor, rkey1, mappings);
else {
- mismatched_patch(descriptor, rkey1, mappings, m_dispatch[ent]);
- m_ranges[ent].set(ostart, oend);
+ mismatched_patch(descriptor, rkey1, mappings, m_u_dispatch[ent]);
+ m_u_ranges[ent].set(ostart, oend);
}
}
}
@@ -308,13 +368,13 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::populate_mismatched_mirror_subdispatch(offs_t entry, 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)
{
- auto cur = m_dispatch[entry];
+ auto cur = m_u_dispatch[entry];
if(cur->is_dispatch())
cur->populate_mismatched_mirror(start, end, ostart, oend, mirror, descriptor, mappings);
else {
- auto subdispatch = new handler_entry_read_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_ranges[entry], cur);
+ auto subdispatch = new handler_entry_read_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_u_ranges[entry], cur);
cur->unref();
- m_dispatch[entry] = subdispatch;
+ m_u_dispatch[entry] = subdispatch;
subdispatch->populate_mismatched_mirror(start, end, ostart, oend, mirror, descriptor, mappings);
}
}
@@ -367,13 +427,13 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::populate_passthrough_nomirror_subdispatch(offs_t entry, offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_read_passthrough<Width, AddrShift, Endian> *handler, std::vector<mapping> &mappings)
{
- auto cur = m_dispatch[entry];
+ auto cur = m_u_dispatch[entry];
if(cur->is_dispatch())
cur->populate_passthrough_nomirror(start, end, ostart, oend, handler, mappings);
else {
- auto subdispatch = new handler_entry_read_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_ranges[entry], cur);
+ auto subdispatch = new handler_entry_read_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_u_ranges[entry], cur);
cur->unref();
- m_dispatch[entry] = subdispatch;
+ m_u_dispatch[entry] = subdispatch;
subdispatch->populate_passthrough_nomirror(start, end, ostart, oend, handler, mappings);
}
}
@@ -387,14 +447,14 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
if(LowBits <= Width + AddrShift) {
for(offs_t ent = start_entry; ent <= end_entry; ent++) {
- passthrough_patch(handler, mappings, m_dispatch[ent]);
- m_ranges[ent].intersect(ostart, oend);
+ passthrough_patch(handler, mappings, m_u_dispatch[ent]);
+ m_u_ranges[ent].intersect(ostart, oend);
}
} else if(start_entry == end_entry) {
if(!(start & LOWMASK) && (end & LOWMASK) == LOWMASK) {
- passthrough_patch(handler, mappings, m_dispatch[start_entry]);
- m_ranges[start_entry].intersect(ostart, oend);
+ passthrough_patch(handler, mappings, m_u_dispatch[start_entry]);
+ m_u_ranges[start_entry].intersect(ostart, oend);
} else
populate_passthrough_nomirror_subdispatch(start_entry, start & LOWMASK, end & LOWMASK, ostart, oend, handler, mappings);
@@ -410,11 +470,11 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
if(start_entry <= end_entry) {
for(offs_t ent = start_entry; ent <= end_entry; ent++) {
- if(m_dispatch[ent]->is_dispatch())
- m_dispatch[ent]->populate_passthrough_nomirror(start & LOWMASK, end & LOWMASK, ostart, oend, handler, mappings);
+ if(m_u_dispatch[ent]->is_dispatch())
+ m_u_dispatch[ent]->populate_passthrough_nomirror(start & LOWMASK, end & LOWMASK, ostart, oend, handler, mappings);
else {
- passthrough_patch(handler, mappings, m_dispatch[ent]);
- m_ranges[ent].intersect(ostart, oend);
+ passthrough_patch(handler, mappings, m_u_dispatch[ent]);
+ m_u_ranges[ent].intersect(ostart, oend);
}
}
}
@@ -423,13 +483,13 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::populate_passthrough_mirror_subdispatch(offs_t entry, 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)
{
- auto cur = m_dispatch[entry];
+ auto cur = m_u_dispatch[entry];
if(cur->is_dispatch())
cur->populate_passthrough_mirror(start, end, ostart, oend, mirror, handler, mappings);
else {
- auto subdispatch = new handler_entry_read_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_ranges[entry], cur);
+ auto subdispatch = new handler_entry_read_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_u_ranges[entry], cur);
cur->unref();
- m_dispatch[entry] = subdispatch;
+ m_u_dispatch[entry] = subdispatch;
subdispatch->populate_passthrough_mirror(start, end, ostart, oend, mirror, handler, mappings);
}
}
@@ -464,22 +524,108 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::detach(const std::unordered_set<handler_entry *> &handlers)
{
for(unsigned int i=0; i != COUNT; i++) {
- if(m_dispatch[i]->is_dispatch()) {
- m_dispatch[i]->detach(handlers);
+ if(m_u_dispatch[i]->is_dispatch()) {
+ m_u_dispatch[i]->detach(handlers);
continue;
}
- if(!m_dispatch[i]->is_passthrough())
+ if(!m_u_dispatch[i]->is_passthrough())
continue;
- auto np = static_cast<handler_entry_read_passthrough<Width, AddrShift, Endian> *>(m_dispatch[i]);
+ auto np = static_cast<handler_entry_read_passthrough<Width, AddrShift, Endian> *>(m_u_dispatch[i]);
if(handlers.find(np) != handlers.end()) {
- m_dispatch[i] = np->get_subhandler();
- m_dispatch[i]->ref();
+ m_u_dispatch[i] = np->get_subhandler();
+ m_u_dispatch[i]->ref();
np->unref();
} else
np->detach(handlers);
}
}
+
+template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::init_handlers(offs_t start_entry, offs_t end_entry, u32 lowbits, handler_entry_read<Width, AddrShift, Endian> **dispatch, handler_entry::range *ranges)
+{
+ if(!m_view)
+ fatalerror("init_handlers called on non-view handler_entry_read_dispatch.");
+ if(!m_dispatch_array.empty())
+ fatalerror("init_handlers called twice on handler_entry_read_dispatch.");
+
+ m_ranges_array.resize(1);
+ m_dispatch_array.resize(1);
+ m_a_ranges = m_ranges_array[0].data();
+ m_a_dispatch = m_dispatch_array[0].data();
+ m_u_ranges = m_ranges_array[0].data();
+ m_u_dispatch = m_dispatch_array[0].data();
+
+ auto filter = [s = m_view->m_addrstart, e = m_view->m_addrend] (handler_entry::range r) {
+ r.intersect(s, e);
+ return r;
+ };
+
+ if(lowbits != LowBits) {
+ u32 dt = lowbits - LowBits;
+ u32 ne = 1 << dt;
+ for(offs_t entry = start_entry; entry <= end_entry; entry++) {
+ m_u_dispatch[entry]->ref(ne);
+ u32 e0 = (entry << dt) & BITMASK;
+ for(offs_t e = 0; e != ne; e++) {
+ m_u_dispatch[e0 | e] = dispatch[entry];
+ m_u_ranges[e0 | e] = filter(ranges[entry]);
+ }
+ }
+
+ } else {
+ for(offs_t entry = start_entry; entry <= end_entry; entry++) {
+ m_u_dispatch[entry & BITMASK] = dispatch[entry];
+ m_u_ranges[entry & BITMASK] = filter(ranges[entry]);
+ dispatch[entry]->ref();
+ }
+ }
+}
+
+template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::select_a(int id)
+{
+ u32 i = id+1;
+ if(i >= m_dispatch_array.size())
+ fatalerror("out-of-range view selection.");
+
+ m_a_ranges = m_ranges_array[i].data();
+ m_a_dispatch = m_dispatch_array[i].data();
+}
+
+template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::select_u(int id)
+{
+ u32 i = id+1;
+ if(i > m_dispatch_array.size())
+ fatalerror("out-of-range view update selection.");
+ else if(i == m_dispatch_array.size()) {
+ u32 aid = (std::array<handler_entry_read<Width, AddrShift, Endian> *, COUNT> *)(m_a_dispatch) - m_dispatch_array.data();
+
+ m_dispatch_array.resize(i+1);
+ m_ranges_array.resize(i+1);
+ m_a_ranges = m_ranges_array[aid].data();
+ m_a_dispatch = m_dispatch_array[aid].data();
+ m_u_ranges = m_ranges_array[i].data();
+ m_u_dispatch = m_dispatch_array[i].data();
+
+ for(u32 entry = 0; entry != COUNT; entry++) {
+ m_u_dispatch[entry] = m_dispatch_array[0][entry]->dup();
+ m_u_ranges[entry] = m_ranges_array[0][entry];
+ }
+
+ } else {
+ m_u_ranges = m_ranges_array[i].data();
+ m_u_dispatch = m_dispatch_array[i].data();
+ }
+}
+
+template<int HighBits, int Width, int AddrShift, endianness_t Endian> handler_entry_read<Width, AddrShift, Endian> *handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>::dup()
+{
+ if(m_view) {
+ handler_entry::ref();
+ return this;
+ }
+
+ return new handler_entry_read_dispatch<HighBits, Width, AddrShift, Endian>(this);
+}
diff --git a/src/emu/emumem_hedr0.cpp b/src/emu/emumem_hedr0.cpp
index 536c64e6274..0dbd929412e 100644
--- a/src/emu/emumem_hedr0.cpp
+++ b/src/emu/emumem_hedr0.cpp
@@ -5,6 +5,8 @@
#include "emumem_hedr.ipp"
+template class handler_entry_read_dispatch< 0, 0, 1, ENDIANNESS_LITTLE>;
+template class handler_entry_read_dispatch< 0, 0, 1, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 1, 0, 1, ENDIANNESS_LITTLE>;
template class handler_entry_read_dispatch< 1, 0, 1, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 2, 0, 1, ENDIANNESS_LITTLE>;
@@ -22,6 +24,8 @@ template class handler_entry_read_dispatch< 7, 0, 1, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 8, 0, 1, ENDIANNESS_LITTLE>;
template class handler_entry_read_dispatch< 8, 0, 1, ENDIANNESS_BIG>;
+template class handler_entry_read_dispatch< 0, 0, 0, ENDIANNESS_LITTLE>;
+template class handler_entry_read_dispatch< 0, 0, 0, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 1, 0, 0, ENDIANNESS_LITTLE>;
template class handler_entry_read_dispatch< 1, 0, 0, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 2, 0, 0, ENDIANNESS_LITTLE>;
@@ -39,6 +43,8 @@ template class handler_entry_read_dispatch< 7, 0, 0, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 8, 0, 0, ENDIANNESS_LITTLE>;
template class handler_entry_read_dispatch< 8, 0, 0, ENDIANNESS_BIG>;
+template class handler_entry_read_dispatch< 0, 1, 3, ENDIANNESS_LITTLE>;
+template class handler_entry_read_dispatch< 0, 1, 3, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 1, 1, 3, ENDIANNESS_LITTLE>;
template class handler_entry_read_dispatch< 1, 1, 3, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 2, 1, 3, ENDIANNESS_LITTLE>;
@@ -73,6 +79,8 @@ template class handler_entry_read_dispatch< 7, 1, 0, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 8, 1, 0, ENDIANNESS_LITTLE>;
template class handler_entry_read_dispatch< 8, 1, 0, ENDIANNESS_BIG>;
+template class handler_entry_read_dispatch< 0, 1, -1, ENDIANNESS_LITTLE>;
+template class handler_entry_read_dispatch< 0, 1, -1, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 1, 1, -1, ENDIANNESS_LITTLE>;
template class handler_entry_read_dispatch< 1, 1, -1, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 2, 1, -1, ENDIANNESS_LITTLE>;
@@ -120,6 +128,8 @@ template class handler_entry_read_dispatch< 7, 2, 0, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 8, 2, 0, ENDIANNESS_LITTLE>;
template class handler_entry_read_dispatch< 8, 2, 0, ENDIANNESS_BIG>;
+template class handler_entry_read_dispatch< 1, 2, -1, ENDIANNESS_LITTLE>;
+template class handler_entry_read_dispatch< 1, 2, -1, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 2, 2, -1, ENDIANNESS_LITTLE>;
template class handler_entry_read_dispatch< 2, 2, -1, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 3, 2, -1, ENDIANNESS_LITTLE>;
@@ -135,6 +145,10 @@ template class handler_entry_read_dispatch< 7, 2, -1, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 8, 2, -1, ENDIANNESS_LITTLE>;
template class handler_entry_read_dispatch< 8, 2, -1, ENDIANNESS_BIG>;
+template class handler_entry_read_dispatch< 0, 2, -2, ENDIANNESS_LITTLE>;
+template class handler_entry_read_dispatch< 0, 2, -2, ENDIANNESS_BIG>;
+template class handler_entry_read_dispatch< 1, 2, -2, ENDIANNESS_LITTLE>;
+template class handler_entry_read_dispatch< 1, 2, -2, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 2, 2, -2, ENDIANNESS_LITTLE>;
template class handler_entry_read_dispatch< 2, 2, -2, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 3, 2, -2, ENDIANNESS_LITTLE>;
@@ -163,6 +177,8 @@ template class handler_entry_read_dispatch< 7, 3, 0, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 8, 3, 0, ENDIANNESS_LITTLE>;
template class handler_entry_read_dispatch< 8, 3, 0, ENDIANNESS_BIG>;
+template class handler_entry_read_dispatch< 2, 3, -1, ENDIANNESS_LITTLE>;
+template class handler_entry_read_dispatch< 2, 3, -1, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 3, 3, -1, ENDIANNESS_LITTLE>;
template class handler_entry_read_dispatch< 3, 3, -1, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 4, 3, -1, ENDIANNESS_LITTLE>;
@@ -176,6 +192,10 @@ template class handler_entry_read_dispatch< 7, 3, -1, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 8, 3, -1, ENDIANNESS_LITTLE>;
template class handler_entry_read_dispatch< 8, 3, -1, ENDIANNESS_BIG>;
+template class handler_entry_read_dispatch< 1, 3, -2, ENDIANNESS_LITTLE>;
+template class handler_entry_read_dispatch< 1, 3, -2, ENDIANNESS_BIG>;
+template class handler_entry_read_dispatch< 2, 3, -2, ENDIANNESS_LITTLE>;
+template class handler_entry_read_dispatch< 2, 3, -2, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 3, 3, -2, ENDIANNESS_LITTLE>;
template class handler_entry_read_dispatch< 3, 3, -2, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 4, 3, -2, ENDIANNESS_LITTLE>;
@@ -189,6 +209,12 @@ template class handler_entry_read_dispatch< 7, 3, -2, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 8, 3, -2, ENDIANNESS_LITTLE>;
template class handler_entry_read_dispatch< 8, 3, -2, ENDIANNESS_BIG>;
+template class handler_entry_read_dispatch< 0, 3, -3, ENDIANNESS_LITTLE>;
+template class handler_entry_read_dispatch< 0, 3, -3, ENDIANNESS_BIG>;
+template class handler_entry_read_dispatch< 1, 3, -3, ENDIANNESS_LITTLE>;
+template class handler_entry_read_dispatch< 1, 3, -3, ENDIANNESS_BIG>;
+template class handler_entry_read_dispatch< 2, 3, -3, ENDIANNESS_LITTLE>;
+template class handler_entry_read_dispatch< 2, 3, -3, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 3, 3, -3, ENDIANNESS_LITTLE>;
template class handler_entry_read_dispatch< 3, 3, -3, ENDIANNESS_BIG>;
template class handler_entry_read_dispatch< 4, 3, -3, ENDIANNESS_LITTLE>;
diff --git a/src/emu/emumem_hedw.h b/src/emu/emumem_hedw.h
index 219b51d89f7..bb591e3bff8 100644
--- a/src/emu/emumem_hedw.h
+++ b/src/emu/emumem_hedw.h
@@ -3,7 +3,8 @@
// handler_entry_write_dispatch
-// dispatches an access among multiple handlers indexed on part of the address
+// dispatches an access among multiple handlers indexed on part of the
+// address and when appropriate a selected view
template<int HighBits, int Width, int AddrShift, endianness_t Endian> class handler_entry_write_dispatch : public handler_entry_write<Width, AddrShift, Endian>
{
@@ -13,6 +14,8 @@ public:
using mapping = typename inh::mapping;
handler_entry_write_dispatch(address_space *space, const handler_entry::range &init, handler_entry_write<Width, AddrShift, Endian> *handler);
+ handler_entry_write_dispatch(address_space *space, memory_view &view);
+ handler_entry_write_dispatch(handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian> *src);
~handler_entry_write_dispatch();
void write(offs_t offset, uX data, uX mem_mask) const override;
@@ -35,9 +38,13 @@ public:
void enumerate_references(handler_entry::reflist &refs) const override;
- virtual const handler_entry_write<Width, AddrShift, Endian> *const *get_dispatch() const override;
+ const handler_entry_write<Width, AddrShift, Endian> *const *get_dispatch() const override;
+ void select_a(int slot) override;
+ void select_u(int slot) override;
+ void init_handlers(offs_t start_entry, offs_t end_entry, u32 lowbits, handler_entry_write<Width, AddrShift, Endian> **dispatch, handler_entry::range *ranges) override;
+ handler_entry_write<Width, AddrShift, Endian> *dup() override;
-protected:
+private:
static constexpr int Level = emu::detail::handler_entry_dispatch_level(HighBits);
static constexpr u32 LowBits = emu::detail::handler_entry_dispatch_lowbits(HighBits, Width, AddrShift);
static constexpr u32 BITCOUNT = HighBits > LowBits ? HighBits - LowBits : 0;
@@ -47,10 +54,17 @@ protected:
static constexpr offs_t HIGHMASK = make_bitmask<offs_t>(HighBits) ^ LOWMASK;
static constexpr offs_t UPMASK = ~make_bitmask<offs_t>(HighBits);
- handler_entry_write<Width, AddrShift, Endian> *m_dispatch[COUNT];
- handler_entry::range m_ranges[COUNT];
+ memory_view *m_view;
+
+ std::vector<std::array<handler_entry_write<Width, AddrShift, Endian> *, COUNT>> m_dispatch_array;
+ std::vector<std::array<handler_entry::range, COUNT>> m_ranges_array;
+
+ handler_entry_write<Width, AddrShift, Endian> **m_a_dispatch;
+ handler_entry::range *m_a_ranges;
+
+ handler_entry_write<Width, AddrShift, Endian> **m_u_dispatch;
+ handler_entry::range *m_u_ranges;
-private:
void populate_nomirror_subdispatch(offs_t entry, offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_write<Width, AddrShift, Endian> *handler);
void populate_mirror_subdispatch(offs_t entry, offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, handler_entry_write<Width, AddrShift, Endian> *handler);
diff --git a/src/emu/emumem_hedw.ipp b/src/emu/emumem_hedw.ipp
index 3e12c702864..f63072b3bfb 100644
--- a/src/emu/emumem_hedw.ipp
+++ b/src/emu/emumem_hedw.ipp
@@ -12,70 +12,126 @@
template<int HighBits, int Width, int AddrShift, endianness_t Endian> const handler_entry_write<Width, AddrShift, Endian> *const *handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::get_dispatch() const
{
- return m_dispatch;
+ return m_a_dispatch;
}
-template<int HighBits, int Width, int AddrShift, endianness_t Endian> handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::handler_entry_write_dispatch(address_space *space, const handler_entry::range &init, handler_entry_write<Width, AddrShift, Endian> *handler) : handler_entry_write<Width, AddrShift, Endian>(space, handler_entry::F_DISPATCH)
+template<int HighBits, int Width, int AddrShift, endianness_t Endian> handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::handler_entry_write_dispatch(address_space *space, const handler_entry::range &init, handler_entry_write<Width, AddrShift, Endian> *handler) : handler_entry_write<Width, AddrShift, Endian>(space, handler_entry::F_DISPATCH), m_view(nullptr)
{
+ m_ranges_array.resize(1);
+ m_dispatch_array.resize(1);
+ m_a_ranges = m_ranges_array[0].data();
+ m_a_dispatch = m_dispatch_array[0].data();
+ m_u_ranges = m_ranges_array[0].data();
+ m_u_dispatch = m_dispatch_array[0].data();
+
if (!handler)
handler = space->get_unmap_w<Width, AddrShift, Endian>();
handler->ref(COUNT);
for(unsigned int i=0; i != COUNT; i++) {
- m_dispatch[i] = handler;
- m_ranges[i] = init;
+ m_u_dispatch[i] = handler;
+ m_u_ranges[i] = init;
+ }
+}
+
+template<int HighBits, int Width, int AddrShift, endianness_t Endian> handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::handler_entry_write_dispatch(address_space *space, memory_view &view) : handler_entry_write<Width, AddrShift, Endian>(space, handler_entry::F_VIEW), m_view(&view), m_a_dispatch(nullptr), m_a_ranges(nullptr), m_u_dispatch(nullptr), m_u_ranges(nullptr)
+{
+}
+
+
+template<int HighBits, int Width, int AddrShift, endianness_t Endian> handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::handler_entry_write_dispatch(handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian> *src) : handler_entry_write<Width, AddrShift, Endian>(src->m_space, handler_entry::F_DISPATCH), m_view(nullptr)
+{
+ m_ranges_array.resize(1);
+ m_dispatch_array.resize(1);
+ m_a_ranges = m_ranges_array[0].data();
+ m_a_dispatch = m_dispatch_array[0].data();
+ m_u_ranges = m_ranges_array[0].data();
+ m_u_dispatch = m_dispatch_array[0].data();
+
+ for(unsigned int i=0; i != COUNT; i++) {
+ m_u_dispatch[i] = src->m_u_dispatch[i];
+ m_u_ranges[i] = src->m_u_ranges[i];
}
}
+
template<int HighBits, int Width, int AddrShift, endianness_t Endian> handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::~handler_entry_write_dispatch()
{
- for(unsigned int i=0; i != COUNT; i++)
- m_dispatch[i]->unref();
+ for(auto &d : m_dispatch_array)
+ for(auto p : d)
+ if(p)
+ p->unref();
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::enumerate_references(handler_entry::reflist &refs) const
{
- for(unsigned int i=0; i != COUNT; i++)
- refs.add(m_dispatch[i]);
+ for(auto &d : m_dispatch_array)
+ for(auto p : d)
+ if(p)
+ refs.add(p);
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::dump_map(std::vector<memory_entry> &map) const
{
- offs_t cur = map.empty() ? 0 : map.back().end + 1;
- offs_t base = cur & UPMASK;
- do {
- offs_t entry = (cur >> LowBits) & BITMASK;
- if(m_dispatch[entry]->is_dispatch())
- m_dispatch[entry]->dump_map(map);
- else
- map.emplace_back(memory_entry{ m_ranges[entry].start, m_ranges[entry].end, m_dispatch[entry] });
- cur = map.back().end + 1;
- } while(cur && !((cur ^ base) & UPMASK));
+ if(m_view) {
+ for(u32 i = 0; i != m_dispatch_array.size(); i++) {
+ u32 j = map.size();
+ offs_t cur = map.empty() ? m_view->m_addrstart & HIGHMASK : map.back().end + 1;
+ offs_t end = m_view->m_addrend + 1;
+ do {
+ offs_t entry = (cur >> LowBits) & BITMASK;
+ if(m_dispatch_array[i][entry]->is_dispatch() || m_dispatch_array[i][entry]->is_view())
+ m_dispatch_array[i][entry]->dump_map(map);
+ else
+ map.emplace_back(memory_entry{ m_ranges_array[i][entry].start, m_ranges_array[i][entry].end, m_dispatch_array[i][entry] });
+ cur = map.back().end + 1;
+ } while(cur != end);
+ if(i == 0) {
+ for(u32 k = j; k != map.size(); k++)
+ map[k].context.emplace(map[k].context.begin(), memory_entry_context{ m_view, true, 0 });
+ } else {
+ int slot = m_view->id_to_slot(int(i)-1);
+ for(u32 k = j; k != map.size(); k++)
+ map[k].context.emplace(map[k].context.begin(), memory_entry_context{ m_view, false, slot });
+ }
+ }
+ } else {
+ offs_t cur = map.empty() ? 0 : map.back().end + 1;
+ offs_t base = cur & UPMASK;
+ do {
+ offs_t entry = (cur >> LowBits) & BITMASK;
+ if(m_a_dispatch[entry]->is_dispatch() || m_a_dispatch[entry]->is_view())
+ m_a_dispatch[entry]->dump_map(map);
+ else
+ map.emplace_back(memory_entry{ m_a_ranges[entry].start, m_a_ranges[entry].end, m_a_dispatch[entry] });
+ cur = map.back().end + 1;
+ } while(cur && !((cur ^ base) & UPMASK));
+ }
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::write(offs_t offset, uX data, uX mem_mask) const
{
- dispatch_write<Level, Width, AddrShift, Endian>(HIGHMASK, offset, data, mem_mask, m_dispatch);
+ dispatch_write<Level, Width, AddrShift, Endian>(HIGHMASK, offset, data, mem_mask, m_a_dispatch);
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void *handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::get_ptr(offs_t offset) const
{
- return m_dispatch[(offset & HIGHMASK) >> LowBits]->get_ptr(offset);
+ return m_a_dispatch[(offset & HIGHMASK) >> LowBits]->get_ptr(offset);
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> std::string handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::name() const
{
- return "dispatch";
+ return m_view ? "view" :"dispatch";
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::lookup(offs_t address, offs_t &start, offs_t &end, handler_entry_write<Width, AddrShift, Endian> *&handler) const
{
offs_t slot = (address >> LowBits) & BITMASK;
- auto h = m_dispatch[slot];
+ auto h = m_a_dispatch[slot];
if(h->is_dispatch())
h->lookup(address, start, end, handler);
else {
- start = m_ranges[slot].start;
- end = m_ranges[slot].end;
+ start = m_a_ranges[slot].start;
+ end = m_a_ranges[slot].end;
handler = h;
}
}
@@ -83,38 +139,38 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::range_cut_before(offs_t address, int start)
{
while(--start >= 0) {
- if(int(LowBits) > -AddrShift && m_dispatch[start]->is_dispatch()) {
- static_cast<handler_entry_write_dispatch<LowBits, Width, AddrShift, Endian> *>(m_dispatch[start])->range_cut_before(address);
+ if(int(LowBits) > -AddrShift && m_u_dispatch[start]->is_dispatch()) {
+ static_cast<handler_entry_write_dispatch<LowBits, Width, AddrShift, Endian> *>(m_u_dispatch[start])->range_cut_before(address);
break;
}
- if(m_ranges[start].end <= address)
+ if(m_u_ranges[start].end <= address)
break;
- m_ranges[start].end = address;
+ m_u_ranges[start].end = address;
}
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::range_cut_after(offs_t address, int start)
{
while(++start < COUNT) {
- if(int(LowBits) > -AddrShift && m_dispatch[start]->is_dispatch()) {
- static_cast<handler_entry_write_dispatch<LowBits, Width, AddrShift, Endian> *>(m_dispatch[start])->range_cut_after(address);
+ if(int(LowBits) > -AddrShift && m_u_dispatch[start]->is_dispatch()) {
+ static_cast<handler_entry_write_dispatch<LowBits, Width, AddrShift, Endian> *>(m_u_dispatch[start])->range_cut_after(address);
break;
}
- if(m_ranges[start].start >= address)
+ if(m_u_ranges[start].start >= address)
break;
- m_ranges[start].start = address;
+ m_u_ranges[start].start = address;
}
}
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::populate_nomirror_subdispatch(offs_t entry, offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_write<Width, AddrShift, Endian> *handler)
{
- auto cur = m_dispatch[entry];
+ auto cur = m_u_dispatch[entry];
if(cur->is_dispatch())
cur->populate_nomirror(start, end, ostart, oend, handler);
else {
- auto subdispatch = new handler_entry_write_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_ranges[entry], cur);
+ auto subdispatch = new handler_entry_write_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_u_ranges[entry], cur);
cur->unref();
- m_dispatch[entry] = subdispatch;
+ m_u_dispatch[entry] = subdispatch;
subdispatch->populate_nomirror(start, end, ostart, oend, handler);
}
}
@@ -127,18 +183,22 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
range_cut_after(oend+1, end_entry);
if(LowBits <= Width + AddrShift) {
+ if(handler->is_view())
+ handler->init_handlers(start_entry, end_entry, LowBits, m_u_dispatch, m_u_ranges);
handler->ref(end_entry - start_entry);
for(offs_t ent = start_entry; ent <= end_entry; ent++) {
- m_dispatch[ent]->unref();
- m_dispatch[ent] = handler;
- m_ranges[ent].set(ostart, oend);
+ m_u_dispatch[ent]->unref();
+ m_u_dispatch[ent] = handler;
+ m_u_ranges[ent].set(ostart, oend);
}
} else if(start_entry == end_entry) {
if(!(start & LOWMASK) && (end & LOWMASK) == LOWMASK) {
- m_dispatch[start_entry]->unref();
- m_dispatch[start_entry] = handler;
- m_ranges[start_entry].set(ostart, oend);
+ if(handler->is_view())
+ handler->init_handlers(start_entry, end_entry, LowBits, m_u_dispatch, m_u_ranges);
+ m_u_dispatch[start_entry]->unref();
+ m_u_dispatch[start_entry] = handler;
+ m_u_ranges[start_entry].set(ostart, oend);
} else
populate_nomirror_subdispatch(start_entry, start & LOWMASK, end & LOWMASK, ostart, oend, handler);
@@ -157,11 +217,13 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
}
if(start_entry <= end_entry) {
+ if(handler->is_view())
+ handler->init_handlers(start_entry, end_entry, LowBits, m_u_dispatch, m_u_ranges);
handler->ref(end_entry - start_entry);
for(offs_t ent = start_entry; ent <= end_entry; ent++) {
- m_dispatch[ent]->unref();
- m_dispatch[ent] = handler;
- m_ranges[ent].set(ostart, oend);
+ m_u_dispatch[ent]->unref();
+ m_u_dispatch[ent] = handler;
+ m_u_ranges[ent].set(ostart, oend);
}
}
}
@@ -169,13 +231,13 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::populate_mirror_subdispatch(offs_t entry, offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, handler_entry_write<Width, AddrShift, Endian> *handler)
{
- auto cur = m_dispatch[entry];
+ auto cur = m_u_dispatch[entry];
if(cur->is_dispatch())
cur->populate_mirror(start, end, ostart, oend, mirror, handler);
else {
- auto subdispatch = new handler_entry_write_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_ranges[entry], cur);
+ auto subdispatch = new handler_entry_write_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_u_ranges[entry], cur);
cur->unref();
- m_dispatch[entry] = subdispatch;
+ m_u_dispatch[entry] = subdispatch;
subdispatch->populate_mirror(start, end, ostart, oend, mirror, handler);
}
}
@@ -236,13 +298,13 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::populate_mismatched_nomirror_subdispatch(offs_t entry, 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)
{
- auto cur = m_dispatch[entry];
+ auto cur = m_u_dispatch[entry];
if(cur->is_dispatch())
cur->populate_mismatched_nomirror(start, end, ostart, oend, descriptor, rkey, mappings);
else {
- auto subdispatch = new handler_entry_write_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_ranges[entry], cur);
+ auto subdispatch = new handler_entry_write_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_u_ranges[entry], cur);
cur->unref();
- m_dispatch[entry] = subdispatch;
+ m_u_dispatch[entry] = subdispatch;
subdispatch->populate_mismatched_nomirror(start, end, ostart, oend, descriptor, rkey, mappings);
}
}
@@ -261,17 +323,17 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
rkey1 &= ~handler_entry::START;
if(ent != end_entry)
rkey1 &= ~handler_entry::END;
- mismatched_patch(descriptor, rkey1, mappings, m_dispatch[ent]);
- m_ranges[ent].intersect(ostart, oend);
+ mismatched_patch(descriptor, rkey1, mappings, m_u_dispatch[ent]);
+ m_u_ranges[ent].intersect(ostart, oend);
}
} else if(start_entry == end_entry) {
if(!(start & LOWMASK) && (end & LOWMASK) == LOWMASK) {
- if(m_dispatch[start_entry]->is_dispatch())
- m_dispatch[start_entry]->populate_mismatched_nomirror(start & LOWMASK, end & LOWMASK, ostart, oend, descriptor, rkey, mappings);
+ if(m_u_dispatch[start_entry]->is_dispatch())
+ m_u_dispatch[start_entry]->populate_mismatched_nomirror(start & LOWMASK, end & LOWMASK, ostart, oend, descriptor, rkey, mappings);
else {
- mismatched_patch(descriptor, rkey, mappings, m_dispatch[start_entry]);
- m_ranges[start_entry].intersect(ostart, oend);
+ mismatched_patch(descriptor, rkey, mappings, m_u_dispatch[start_entry]);
+ m_u_ranges[start_entry].intersect(ostart, oend);
}
} else
populate_mismatched_nomirror_subdispatch(start_entry, start & LOWMASK, end & LOWMASK, ostart, oend, descriptor, rkey, mappings);
@@ -295,11 +357,11 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
rkey1 &= ~handler_entry::START;
if(ent != end_entry)
rkey1 &= ~handler_entry::END;
- if(m_dispatch[ent]->is_dispatch())
- m_dispatch[ent]->populate_mismatched_nomirror(start & LOWMASK, end & LOWMASK, ostart, oend, descriptor, rkey1, mappings);
+ if(m_u_dispatch[ent]->is_dispatch())
+ m_u_dispatch[ent]->populate_mismatched_nomirror(start & LOWMASK, end & LOWMASK, ostart, oend, descriptor, rkey1, mappings);
else {
- mismatched_patch(descriptor, rkey1, mappings, m_dispatch[ent]);
- m_ranges[ent].intersect(ostart, oend);
+ mismatched_patch(descriptor, rkey1, mappings, m_u_dispatch[ent]);
+ m_u_ranges[ent].intersect(ostart, oend);
}
}
}
@@ -308,13 +370,13 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::populate_mismatched_mirror_subdispatch(offs_t entry, 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)
{
- auto cur = m_dispatch[entry];
+ auto cur = m_u_dispatch[entry];
if(cur->is_dispatch())
cur->populate_mismatched_mirror(start, end, ostart, oend, mirror, descriptor, mappings);
else {
- auto subdispatch = new handler_entry_write_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_ranges[entry], cur);
+ auto subdispatch = new handler_entry_write_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_u_ranges[entry], cur);
cur->unref();
- m_dispatch[entry] = subdispatch;
+ m_u_dispatch[entry] = subdispatch;
subdispatch->populate_mismatched_mirror(start, end, ostart, oend, mirror, descriptor, mappings);
}
}
@@ -367,13 +429,13 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::populate_passthrough_nomirror_subdispatch(offs_t entry, offs_t start, offs_t end, offs_t ostart, offs_t oend, handler_entry_write_passthrough<Width, AddrShift, Endian> *handler, std::vector<mapping> &mappings)
{
- auto cur = m_dispatch[entry];
+ auto cur = m_u_dispatch[entry];
if(cur->is_dispatch())
cur->populate_passthrough_nomirror(start, end, ostart, oend, handler, mappings);
else {
- auto subdispatch = new handler_entry_write_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_ranges[entry], cur);
+ auto subdispatch = new handler_entry_write_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_u_ranges[entry], cur);
cur->unref();
- m_dispatch[entry] = subdispatch;
+ m_u_dispatch[entry] = subdispatch;
subdispatch->populate_passthrough_nomirror(start, end, ostart, oend, handler, mappings);
}
}
@@ -387,17 +449,17 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
if(LowBits <= Width + AddrShift) {
for(offs_t ent = start_entry; ent <= end_entry; ent++) {
- passthrough_patch(handler, mappings, m_dispatch[ent]);
- m_ranges[ent].intersect(ostart, oend);
+ passthrough_patch(handler, mappings, m_u_dispatch[ent]);
+ m_u_ranges[ent].intersect(ostart, oend);
}
} else if(start_entry == end_entry) {
if(!(start & LOWMASK) && (end & LOWMASK) == LOWMASK) {
- if(m_dispatch[start_entry]->is_dispatch())
- m_dispatch[start_entry]->populate_passthrough_nomirror(start & LOWMASK, end & LOWMASK, ostart, oend, handler, mappings);
+ if(m_u_dispatch[start_entry]->is_dispatch())
+ m_u_dispatch[start_entry]->populate_passthrough_nomirror(start & LOWMASK, end & LOWMASK, ostart, oend, handler, mappings);
else {
- passthrough_patch(handler, mappings, m_dispatch[start_entry]);
- m_ranges[start_entry].intersect(ostart, oend);
+ passthrough_patch(handler, mappings, m_u_dispatch[start_entry]);
+ m_u_ranges[start_entry].intersect(ostart, oend);
}
} else
populate_passthrough_nomirror_subdispatch(start_entry, start & LOWMASK, end & LOWMASK, ostart, oend, handler, mappings);
@@ -414,11 +476,11 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
if(start_entry <= end_entry) {
for(offs_t ent = start_entry; ent <= end_entry; ent++) {
- if(m_dispatch[ent]->is_dispatch())
- m_dispatch[ent]->populate_passthrough_nomirror(start & LOWMASK, end & LOWMASK, ostart, oend, handler, mappings);
+ if(m_u_dispatch[ent]->is_dispatch())
+ m_u_dispatch[ent]->populate_passthrough_nomirror(start & LOWMASK, end & LOWMASK, ostart, oend, handler, mappings);
else {
- passthrough_patch(handler, mappings, m_dispatch[ent]);
- m_ranges[ent].intersect(ostart, oend);
+ passthrough_patch(handler, mappings, m_u_dispatch[ent]);
+ m_u_ranges[ent].intersect(ostart, oend);
}
}
}
@@ -427,13 +489,13 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::populate_passthrough_mirror_subdispatch(offs_t entry, 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)
{
- auto cur = m_dispatch[entry];
+ auto cur = m_u_dispatch[entry];
if(cur->is_dispatch())
cur->populate_passthrough_mirror(start, end, ostart, oend, mirror, handler, mappings);
else {
- auto subdispatch = new handler_entry_write_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_ranges[entry], cur);
+ auto subdispatch = new handler_entry_write_dispatch<LowBits, Width, AddrShift, Endian>(handler_entry::m_space, m_u_ranges[entry], cur);
cur->unref();
- m_dispatch[entry] = subdispatch;
+ m_u_dispatch[entry] = subdispatch;
subdispatch->populate_passthrough_mirror(start, end, ostart, oend, mirror, handler, mappings);
}
}
@@ -468,22 +530,108 @@ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handl
template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::detach(const std::unordered_set<handler_entry *> &handlers)
{
for(unsigned int i=0; i != COUNT; i++) {
- if(m_dispatch[i]->is_dispatch()) {
- m_dispatch[i]->detach(handlers);
+ if(m_u_dispatch[i]->is_dispatch()) {
+ m_u_dispatch[i]->detach(handlers);
continue;
}
- if(!m_dispatch[i]->is_passthrough())
+ if(!m_u_dispatch[i]->is_passthrough())
continue;
- auto np = static_cast<handler_entry_write_passthrough<Width, AddrShift, Endian> *>(m_dispatch[i]);
+ auto np = static_cast<handler_entry_write_passthrough<Width, AddrShift, Endian> *>(m_u_dispatch[i]);
if(handlers.find(np) != handlers.end()) {
- m_dispatch[i] = np->get_subhandler();
- m_dispatch[i]->ref();
+ m_u_dispatch[i] = np->get_subhandler();
+ m_u_dispatch[i]->ref();
np->unref();
} else
np->detach(handlers);
}
}
+
+template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::init_handlers(offs_t start_entry, offs_t end_entry, u32 lowbits, handler_entry_write<Width, AddrShift, Endian> **dispatch, handler_entry::range *ranges)
+{
+ if(!m_view)
+ fatalerror("init_handlers called on non-view handler_entry_write_dispatch.");
+ if(!m_dispatch_array.empty())
+ fatalerror("init_handlers called twice on handler_entry_write_dispatch.");
+
+ m_ranges_array.resize(1);
+ m_dispatch_array.resize(1);
+ m_a_ranges = m_ranges_array[0].data();
+ m_a_dispatch = m_dispatch_array[0].data();
+ m_u_ranges = m_ranges_array[0].data();
+ m_u_dispatch = m_dispatch_array[0].data();
+
+ auto filter = [s = m_view->m_addrstart, e = m_view->m_addrend] (handler_entry::range r) {
+ r.intersect(s, e);
+ return r;
+ };
+
+ if(lowbits != LowBits) {
+ u32 dt = lowbits - LowBits;
+ u32 ne = 1 << dt;
+ for(offs_t entry = start_entry; entry <= end_entry; entry++) {
+ m_u_dispatch[entry]->ref(ne);
+ u32 e0 = (entry << dt) & BITMASK;
+ for(offs_t e = 0; e != ne; e++) {
+ m_u_dispatch[e0 | e] = dispatch[entry];
+ m_u_ranges[e0 | e] = filter(ranges[entry]);
+ }
+ }
+
+ } else {
+ for(offs_t entry = start_entry; entry <= end_entry; entry++) {
+ m_u_dispatch[entry & BITMASK] = dispatch[entry];
+ m_u_ranges[entry & BITMASK] = filter(ranges[entry]);
+ dispatch[entry]->ref();
+ }
+ }
+}
+
+template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::select_a(int id)
+{
+ u32 i = id+1;
+ if(i >= m_dispatch_array.size())
+ fatalerror("out-of-range view selection.");
+
+ m_a_ranges = m_ranges_array[i].data();
+ m_a_dispatch = m_dispatch_array[i].data();
+}
+
+template<int HighBits, int Width, int AddrShift, endianness_t Endian> void handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::select_u(int id)
+{
+ u32 i = id+1;
+ if(i > m_dispatch_array.size())
+ fatalerror("out-of-range view update selection.");
+ else if(i == m_dispatch_array.size()) {
+ u32 aid = (std::array<handler_entry_write<Width, AddrShift, Endian> *, COUNT> *)(m_a_dispatch) - m_dispatch_array.data();
+
+ m_dispatch_array.resize(i+1);
+ m_ranges_array.resize(i+1);
+ m_a_ranges = m_ranges_array[aid].data();
+ m_a_dispatch = m_dispatch_array[aid].data();
+ m_u_ranges = m_ranges_array[i].data();
+ m_u_dispatch = m_dispatch_array[i].data();
+
+ for(u32 entry = 0; entry != COUNT; entry++) {
+ m_u_dispatch[entry] = m_dispatch_array[0][entry]->dup();
+ m_u_ranges[entry] = m_ranges_array[0][entry];
+ }
+
+ } else {
+ m_u_ranges = m_ranges_array[i].data();
+ m_u_dispatch = m_dispatch_array[i].data();
+ }
+}
+
+template<int HighBits, int Width, int AddrShift, endianness_t Endian> handler_entry_write<Width, AddrShift, Endian> *handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>::dup()
+{
+ if(m_view) {
+ handler_entry::ref();
+ return this;
+ }
+
+ return new handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>(this);
+}
diff --git a/src/emu/emumem_hedw0.cpp b/src/emu/emumem_hedw0.cpp
index 593a42d7417..67244fc3044 100644
--- a/src/emu/emumem_hedw0.cpp
+++ b/src/emu/emumem_hedw0.cpp
@@ -5,6 +5,8 @@
#include "emumem_hedw.ipp"
+template class handler_entry_write_dispatch< 0, 0, 1, ENDIANNESS_LITTLE>;
+template class handler_entry_write_dispatch< 0, 0, 1, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 1, 0, 1, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 1, 0, 1, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 2, 0, 1, ENDIANNESS_LITTLE>;
@@ -22,6 +24,8 @@ template class handler_entry_write_dispatch< 7, 0, 1, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 8, 0, 1, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 8, 0, 1, ENDIANNESS_BIG>;
+template class handler_entry_write_dispatch< 0, 0, 0, ENDIANNESS_LITTLE>;
+template class handler_entry_write_dispatch< 0, 0, 0, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 1, 0, 0, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 1, 0, 0, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 2, 0, 0, ENDIANNESS_LITTLE>;
@@ -39,6 +43,8 @@ template class handler_entry_write_dispatch< 7, 0, 0, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 8, 0, 0, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 8, 0, 0, ENDIANNESS_BIG>;
+template class handler_entry_write_dispatch< 0, 1, 3, ENDIANNESS_LITTLE>;
+template class handler_entry_write_dispatch< 0, 1, 3, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 1, 1, 3, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 1, 1, 3, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 2, 1, 3, ENDIANNESS_LITTLE>;
@@ -73,6 +79,8 @@ template class handler_entry_write_dispatch< 7, 1, 0, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 8, 1, 0, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 8, 1, 0, ENDIANNESS_BIG>;
+template class handler_entry_write_dispatch< 0, 1, -1, ENDIANNESS_LITTLE>;
+template class handler_entry_write_dispatch< 0, 1, -1, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 1, 1, -1, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 1, 1, -1, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 2, 1, -1, ENDIANNESS_LITTLE>;
@@ -90,6 +98,10 @@ template class handler_entry_write_dispatch< 7, 1, -1, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 8, 1, -1, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 8, 1, -1, ENDIANNESS_BIG>;
+template class handler_entry_write_dispatch< 0, 2, 3, ENDIANNESS_LITTLE>;
+template class handler_entry_write_dispatch< 0, 2, 3, ENDIANNESS_BIG>;
+template class handler_entry_write_dispatch< 1, 2, 3, ENDIANNESS_LITTLE>;
+template class handler_entry_write_dispatch< 1, 2, 3, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 2, 2, 3, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 2, 2, 3, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 3, 2, 3, ENDIANNESS_LITTLE>;
@@ -120,6 +132,8 @@ template class handler_entry_write_dispatch< 7, 2, 0, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 8, 2, 0, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 8, 2, 0, ENDIANNESS_BIG>;
+template class handler_entry_write_dispatch< 1, 2, -1, ENDIANNESS_LITTLE>;
+template class handler_entry_write_dispatch< 1, 2, -1, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 2, 2, -1, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 2, 2, -1, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 3, 2, -1, ENDIANNESS_LITTLE>;
@@ -135,6 +149,10 @@ template class handler_entry_write_dispatch< 7, 2, -1, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 8, 2, -1, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 8, 2, -1, ENDIANNESS_BIG>;
+template class handler_entry_write_dispatch< 0, 2, -2, ENDIANNESS_LITTLE>;
+template class handler_entry_write_dispatch< 0, 2, -2, ENDIANNESS_BIG>;
+template class handler_entry_write_dispatch< 1, 2, -2, ENDIANNESS_LITTLE>;
+template class handler_entry_write_dispatch< 1, 2, -2, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 2, 2, -2, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 2, 2, -2, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 3, 2, -2, ENDIANNESS_LITTLE>;
@@ -163,6 +181,8 @@ template class handler_entry_write_dispatch< 7, 3, 0, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 8, 3, 0, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 8, 3, 0, ENDIANNESS_BIG>;
+template class handler_entry_write_dispatch< 2, 3, -1, ENDIANNESS_LITTLE>;
+template class handler_entry_write_dispatch< 2, 3, -1, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 3, 3, -1, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 3, 3, -1, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 4, 3, -1, ENDIANNESS_LITTLE>;
@@ -176,6 +196,10 @@ template class handler_entry_write_dispatch< 7, 3, -1, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 8, 3, -1, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 8, 3, -1, ENDIANNESS_BIG>;
+template class handler_entry_write_dispatch< 1, 3, -2, ENDIANNESS_LITTLE>;
+template class handler_entry_write_dispatch< 1, 3, -2, ENDIANNESS_BIG>;
+template class handler_entry_write_dispatch< 2, 3, -2, ENDIANNESS_LITTLE>;
+template class handler_entry_write_dispatch< 2, 3, -2, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 3, 3, -2, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 3, 3, -2, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 4, 3, -2, ENDIANNESS_LITTLE>;
@@ -189,6 +213,12 @@ template class handler_entry_write_dispatch< 7, 3, -2, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 8, 3, -2, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 8, 3, -2, ENDIANNESS_BIG>;
+template class handler_entry_write_dispatch< 0, 3, -3, ENDIANNESS_LITTLE>;
+template class handler_entry_write_dispatch< 0, 3, -3, ENDIANNESS_BIG>;
+template class handler_entry_write_dispatch< 1, 3, -3, ENDIANNESS_LITTLE>;
+template class handler_entry_write_dispatch< 1, 3, -3, ENDIANNESS_BIG>;
+template class handler_entry_write_dispatch< 2, 3, -3, ENDIANNESS_LITTLE>;
+template class handler_entry_write_dispatch< 2, 3, -3, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 3, 3, -3, ENDIANNESS_LITTLE>;
template class handler_entry_write_dispatch< 3, 3, -3, ENDIANNESS_BIG>;
template class handler_entry_write_dispatch< 4, 3, -3, ENDIANNESS_LITTLE>;
diff --git a/src/emu/emumem_heu.cpp b/src/emu/emumem_heu.cpp
index e556a39bd31..aba5a28f9c2 100644
--- a/src/emu/emumem_heu.cpp
+++ b/src/emu/emumem_heu.cpp
@@ -36,12 +36,27 @@ template<int Width, int AddrShift, endianness_t Endian> handler_entry_read_units
std::sort(m_subunit_infos, m_subunit_infos + m_subunits, [](const subunit_info &a, const subunit_info &b) { return a.m_offset < b.m_offset; });
}
+template<int Width, int AddrShift, endianness_t Endian> handler_entry_read_units<Width, AddrShift, Endian>::handler_entry_read_units(const handler_entry_read_units *src) :
+ handler_entry_read<Width, AddrShift, Endian>(src->m_space, inh::F_UNITS),
+ m_subunits(src->m_subunits)
+{
+ for(u32 i=0; i != src->m_subunits; i++) {
+ m_subunit_infos[i] = src->m_subunit_infos[i];
+ m_subunit_infos[i].m_handler = static_cast<handler_entry_write<Width, AddrShift, Endian> *>(m_subunit_infos[i].m_handler)->dup();
+ }
+}
+
template<int Width, int AddrShift, endianness_t Endian> handler_entry_read_units<Width, AddrShift, Endian>::~handler_entry_read_units()
{
for(u32 i=0; i != m_subunits; i++)
m_subunit_infos[i].m_handler->unref();
}
+template<int Width, int AddrShift, endianness_t Endian> handler_entry_read<Width, AddrShift, Endian> *handler_entry_read_units<Width, AddrShift, Endian>::dup()
+{
+ return new handler_entry_read_units<Width, AddrShift, Endian>(this);
+}
+
template<int Width, int AddrShift, endianness_t Endian> void handler_entry_read_units<Width, AddrShift, Endian>::enumerate_references(handler_entry::reflist &refs) const
{
for(u32 i=0; i != m_subunits; i++)
@@ -155,12 +170,27 @@ template<int Width, int AddrShift, endianness_t Endian> handler_entry_write_unit
std::sort(m_subunit_infos, m_subunit_infos + m_subunits, [](const subunit_info &a, const subunit_info &b) { return a.m_offset < b.m_offset; });
}
+template<int Width, int AddrShift, endianness_t Endian> handler_entry_write_units<Width, AddrShift, Endian>::handler_entry_write_units(const handler_entry_write_units *src) :
+ handler_entry_write<Width, AddrShift, Endian>(src->m_space, inh::F_UNITS),
+ m_subunits(src->m_subunits)
+{
+ for(u32 i=0; i != src->m_subunits; i++) {
+ m_subunit_infos[i] = src->m_subunit_infos[i];
+ m_subunit_infos[i].m_handler = static_cast<handler_entry_write<Width, AddrShift, Endian> *>(m_subunit_infos[i].m_handler)->dup();
+ }
+}
+
template<int Width, int AddrShift, endianness_t Endian> handler_entry_write_units<Width, AddrShift, Endian>::~handler_entry_write_units()
{
for(u32 i=0; i != m_subunits; i++)
m_subunit_infos[i].m_handler->unref();
}
+template<int Width, int AddrShift, endianness_t Endian> handler_entry_write<Width, AddrShift, Endian> *handler_entry_write_units<Width, AddrShift, Endian>::dup()
+{
+ return new handler_entry_write_units<Width, AddrShift, Endian>(this);
+}
+
template<int Width, int AddrShift, endianness_t Endian> void handler_entry_write_units<Width, AddrShift, Endian>::enumerate_references(handler_entry::reflist &refs) const
{
for(u32 i=0; i != m_subunits; i++)
diff --git a/src/emu/emumem_heu.h b/src/emu/emumem_heu.h
index d084fddfe98..670d489d00a 100644
--- a/src/emu/emumem_heu.h
+++ b/src/emu/emumem_heu.h
@@ -13,6 +13,7 @@ public:
handler_entry_read_units(const memory_units_descriptor<Width, AddrShift, Endian> &descriptor, u8 ukey, address_space *space);
handler_entry_read_units(const memory_units_descriptor<Width, AddrShift, Endian> &descriptor, u8 ukey, const handler_entry_read_units *src);
+ handler_entry_read_units(const handler_entry_read_units *src);
~handler_entry_read_units();
uX read(offs_t offset, uX mem_mask) const override;
@@ -20,6 +21,7 @@ public:
std::string name() const override;
void enumerate_references(handler_entry::reflist &refs) const override;
+ handler_entry_read<Width, AddrShift, Endian> *dup() override;
private:
static constexpr u32 SUBUNIT_COUNT = 1 << Width;
@@ -54,6 +56,7 @@ public:
handler_entry_write_units(const memory_units_descriptor<Width, AddrShift, Endian> &descriptor, u8 ukey, address_space *space);
handler_entry_write_units(const memory_units_descriptor<Width, AddrShift, Endian> &descriptor, u8 ukey, const handler_entry_write_units<Width, AddrShift, Endian> *src);
+ handler_entry_write_units(const handler_entry_write_units *src);
~handler_entry_write_units();
void write(offs_t offset, uX data, uX mem_mask) const override;
@@ -61,6 +64,7 @@ public:
std::string name() const override;
void enumerate_references(handler_entry::reflist &refs) const override;
+ handler_entry_write<Width, AddrShift, Endian> *dup() override;
private:
static constexpr u32 SUBUNIT_COUNT = 1 << Width;
diff --git a/src/emu/emumem_mview.cpp b/src/emu/emumem_mview.cpp
new file mode 100644
index 00000000000..f4f92e1a7b8
--- /dev/null
+++ b/src/emu/emumem_mview.cpp
@@ -0,0 +1,995 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles,Olivier Galibert
+/***************************************************************************
+
+ emumem.cpp
+
+ Functions which handle device memory access.
+ Memory view specific functions
+
+***************************************************************************/
+
+#include "emu.h"
+#include <list>
+#include <map>
+#include "emuopts.h"
+#include "debug/debugcpu.h"
+
+#include "emumem_mud.h"
+#include "emumem_hea.h"
+#include "emumem_hem.h"
+#include "emumem_hedp.h"
+#include "emumem_heun.h"
+#include "emumem_heu.h"
+#include "emumem_hedr.h"
+#include "emumem_hedw.h"
+#include "emumem_hep.h"
+#include "emumem_het.h"
+
+#define VERBOSE 0
+
+#if VERBOSE
+template <typename Format, typename... Params> static void VPRINTF(Format &&fmt, Params &&...args)
+{
+ util::stream_format(std::cerr, std::forward<Format>(fmt), std::forward<Params>(args)...);
+}
+#else
+template <typename Format, typename... Params> static void VPRINTF(Format &&, Params &&...) {}
+#endif
+
+namespace {
+
+template <typename Delegate> struct handler_width;
+template <> struct handler_width<read8_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<read8m_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<read8s_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<read8sm_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<read8mo_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<read8smo_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<write8_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<write8m_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<write8s_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<write8sm_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<write8mo_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<write8smo_delegate> { static constexpr int value = 0; };
+template <> struct handler_width<read16_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<read16m_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<read16s_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<read16sm_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<read16mo_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<read16smo_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<write16_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<write16m_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<write16s_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<write16sm_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<write16mo_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<write16smo_delegate> { static constexpr int value = 1; };
+template <> struct handler_width<read32_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<read32m_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<read32s_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<read32sm_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<read32mo_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<read32smo_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<write32_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<write32m_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<write32s_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<write32sm_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<write32mo_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<write32smo_delegate> { static constexpr int value = 2; };
+template <> struct handler_width<read64_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<read64m_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<read64s_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<read64sm_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<read64mo_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<read64smo_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<write64_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<write64m_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<write64s_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<write64sm_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<write64mo_delegate> { static constexpr int value = 3; };
+template <> struct handler_width<write64smo_delegate> { static constexpr int value = 3; };
+} // anonymous namespace
+
+address_map_entry &memory_view::memory_view_entry::operator()(offs_t start, offs_t end)
+{
+ return (*m_map)(start, end);
+}
+
+template<int Level, int Width, int AddrShift, endianness_t Endian>
+class memory_view_entry_specific : public memory_view::memory_view_entry
+{
+ using uX = typename emu::detail::handler_entry_size<Width>::uX;
+ using NativeType = uX;
+
+ // constants describing the native size
+ static constexpr u32 NATIVE_BYTES = 1 << Width;
+ static constexpr u32 NATIVE_STEP = AddrShift >= 0 ? NATIVE_BYTES << iabs(AddrShift) : NATIVE_BYTES >> iabs(AddrShift);
+ static constexpr u32 NATIVE_MASK = NATIVE_STEP - 1;
+ static constexpr u32 NATIVE_BITS = 8 * NATIVE_BYTES;
+
+ static constexpr offs_t offset_to_byte(offs_t offset) { return AddrShift < 0 ? offset << iabs(AddrShift) : offset >> iabs(AddrShift); }
+
+public:
+ memory_view_entry_specific(const address_space_config &config, memory_manager &manager, memory_view &view, int id) : memory_view_entry(config, manager, view, id) {
+ }
+
+ virtual ~memory_view_entry_specific() = default;
+
+ handler_entry_read <Width, AddrShift, Endian> *r() { return static_cast<handler_entry_read <Width, AddrShift, Endian> *>(m_view.m_handler_read); }
+ handler_entry_write<Width, AddrShift, Endian> *w() { return static_cast<handler_entry_write<Width, AddrShift, Endian> *>(m_view.m_handler_write); }
+
+ void invalidate_caches(read_or_write readorwrite) { return m_view.m_space->invalidate_caches(readorwrite); }
+
+ virtual void populate_from_map(address_map *map = nullptr) override;
+
+ using address_space_installer::install_read_tap;
+ using address_space_installer::install_write_tap;
+ using address_space_installer::install_readwrite_tap;
+
+ 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, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) override;
+ 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, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph) override;
+ 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, uX &data, uX mem_mask)> tapr, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapw, memory_passthrough_handler *mph) override;
+
+ virtual void unmap_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, read_or_write readorwrite, bool quiet) override;
+ virtual void install_ram_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, read_or_write readorwrite, void *baseptr) override;
+ virtual void install_bank_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_bank *rbank, memory_bank *wbank) override;
+ virtual void install_view(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_view &view) override;
+ virtual void install_readwrite_port(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string rtag, std::string wtag) override;
+ virtual void install_device_delegate(offs_t addrstart, offs_t addrend, device_t &device, address_map_constructor &map, u64 unitmask, int cswidth) override;
+
+
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+ 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) override
+ { install_read_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler); }
+ 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) override
+ { install_write_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, whandler); }
+ 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) override
+ { install_readwrite_handler_impl(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, rhandler, whandler); }
+
+ template<typename READ>
+ void install_read_handler_impl(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, READ &handler_r)
+ {
+ try { handler_r.resolve(); }
+ catch (const binding_type_exception &) {
+ osd_printf_error("Binding error while installing read handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_r.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask);
+ throw;
+ }
+ install_read_handler_helper<handler_width<READ>::value>(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, handler_r);
+ }
+
+ template<typename WRITE>
+ void install_write_handler_impl(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, WRITE &handler_w)
+ {
+ try { handler_w.resolve(); }
+ catch (const binding_type_exception &) {
+ osd_printf_error("Binding error while installing write handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_w.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask);
+ throw;
+ }
+ install_write_handler_helper<handler_width<WRITE>::value>(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, handler_w);
+ }
+
+ template<typename READ, typename WRITE>
+ void install_readwrite_handler_impl(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, READ &handler_r, WRITE &handler_w)
+ {
+ static_assert(handler_width<READ>::value == handler_width<WRITE>::value, "handler widths do not match");
+ try { handler_r.resolve(); }
+ catch (const binding_type_exception &) {
+ osd_printf_error("Binding error while installing read handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_r.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask);
+ throw;
+ }
+ try { handler_w.resolve(); }
+ catch (const binding_type_exception &) {
+ osd_printf_error("Binding error while installing write handler %s for range 0x%X-0x%X mask 0x%X mirror 0x%X select 0x%X umask 0x%X\n", handler_w.name(), addrstart, addrend, addrmask, addrmirror, addrselect, unitmask);
+ throw;
+ }
+ install_readwrite_handler_helper<handler_width<READ>::value>(addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, handler_r, handler_w);
+ }
+
+ template<int AccessWidth, typename READ>
+ void install_read_handler_helper(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, const READ &handler_r)
+ {
+ if constexpr (Width < AccessWidth) {
+ fatalerror("install_read_handler: cannot install a %d-wide handler in a %d-wide bus", 8 << AccessWidth, 8 << Width);
+ } else {
+ VPRINTF("memory_view::install_read_handler(%*x-%*x mask=%*x mirror=%*x, space width=%d, handler width=%d, %s, %*x)\n",
+ m_addrchars, addrstart, m_addrchars, addrend,
+ m_addrchars, addrmask, m_addrchars, addrmirror,
+ 8 << Width, 8 << AccessWidth,
+ handler_r.name(), data_width() / 4, unitmask);
+
+ offs_t nstart, nend, nmask, nmirror;
+ u64 nunitmask;
+ int ncswidth;
+ check_optimize_all("install_read_handler", 8 << AccessWidth, addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, nstart, nend, nmask, nmirror, nunitmask, ncswidth);
+
+ if constexpr (Width == AccessWidth) {
+ auto hand_r = new handler_entry_read_delegate<Width, AddrShift, Endian, READ>(m_view.m_space, handler_r);
+ hand_r->set_address_info(nstart, nmask);
+ r()->populate(nstart, nend, nmirror, hand_r);
+ } else {
+ auto hand_r = new handler_entry_read_delegate<AccessWidth, -AccessWidth, Endian, READ>(m_view.m_space, handler_r);
+ memory_units_descriptor<Width, AddrShift, Endian> descriptor(AccessWidth, Endian, hand_r, nstart, nend, nmask, nunitmask, ncswidth);
+ hand_r->set_address_info(descriptor.get_handler_start(), descriptor.get_handler_mask());
+ r()->populate_mismatched(nstart, nend, nmirror, descriptor);
+ hand_r->unref();
+ }
+ invalidate_caches(read_or_write::READ);
+ }
+ }
+
+ template<int AccessWidth, typename WRITE>
+ void install_write_handler_helper(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth,
+ const WRITE &handler_w)
+ {
+ if constexpr (Width < AccessWidth) {
+ fatalerror("install_write_handler: cannot install a %d-wide handler in a %d-wide bus", 8 << AccessWidth, 8 << Width);
+ } else {
+ VPRINTF("memory_view::install_write_handler(%*x-%*x mask=%*x mirror=%*x, space width=%d, handler width=%d, %s, %*x)\n",
+ m_addrchars, addrstart, m_addrchars, addrend,
+ m_addrchars, addrmask, m_addrchars, addrmirror,
+ 8 << Width, 8 << AccessWidth,
+ handler_w.name(), data_width() / 4, unitmask);
+
+ offs_t nstart, nend, nmask, nmirror;
+ u64 nunitmask;
+ int ncswidth;
+ check_optimize_all("install_write_handler", 8 << AccessWidth, addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, nstart, nend, nmask, nmirror, nunitmask, ncswidth);
+
+ if constexpr (Width == AccessWidth) {
+ auto hand_w = new handler_entry_write_delegate<Width, AddrShift, Endian, WRITE>(m_view.m_space, handler_w);
+ hand_w->set_address_info(nstart, nmask);
+ w()->populate(nstart, nend, nmirror, hand_w);
+ } else {
+ auto hand_w = new handler_entry_write_delegate<AccessWidth, -AccessWidth, Endian, WRITE>(m_view.m_space, handler_w);
+ memory_units_descriptor<Width, AddrShift, Endian> descriptor(AccessWidth, Endian, hand_w, nstart, nend, nmask, nunitmask, ncswidth);
+ hand_w->set_address_info(descriptor.get_handler_start(), descriptor.get_handler_mask());
+ w()->populate_mismatched(nstart, nend, nmirror, descriptor);
+ hand_w->unref();
+ }
+ invalidate_caches(read_or_write::WRITE);
+ }
+ }
+
+ template<int AccessWidth, typename READ, typename WRITE>
+ void install_readwrite_handler_helper(offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth,
+ const READ &handler_r,
+ const WRITE &handler_w)
+ {
+ if constexpr (Width < AccessWidth) {
+ fatalerror("install_readwrite_handler: cannot install a %d-wide handler in a %d-wide bus", 8 << AccessWidth, 8 << Width);
+ } else {
+ VPRINTF("memory_view::install_readwrite_handler(%*x-%*x mask=%*x mirror=%*x, space width=%d, handler width=%d, %s, %s, %*x)\n",
+ m_addrchars, addrstart, m_addrchars, addrend,
+ m_addrchars, addrmask, m_addrchars, addrmirror,
+ 8 << Width, 8 << AccessWidth,
+ handler_r.name(), handler_w.name(), data_width() / 4, unitmask);
+
+ offs_t nstart, nend, nmask, nmirror;
+ u64 nunitmask;
+ int ncswidth;
+ check_optimize_all("install_readwrite_handler", 8 << AccessWidth, addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, nstart, nend, nmask, nmirror, nunitmask, ncswidth);
+
+ if constexpr (Width == AccessWidth) {
+ auto hand_r = new handler_entry_read_delegate <Width, AddrShift, Endian, READ>(m_view.m_space, handler_r);
+ hand_r->set_address_info(nstart, nmask);
+ r() ->populate(nstart, nend, nmirror, hand_r);
+
+ auto hand_w = new handler_entry_write_delegate<Width, AddrShift, Endian, WRITE>(m_view.m_space, handler_w);
+ hand_w->set_address_info(nstart, nmask);
+ w()->populate(nstart, nend, nmirror, hand_w);
+ } else {
+ auto hand_r = new handler_entry_read_delegate <AccessWidth, -AccessWidth, Endian, READ>(m_view.m_space, handler_r);
+ memory_units_descriptor<Width, AddrShift, Endian> descriptor(AccessWidth, Endian, hand_r, nstart, nend, nmask, nunitmask, ncswidth);
+ hand_r->set_address_info(descriptor.get_handler_start(), descriptor.get_handler_mask());
+ r() ->populate_mismatched(nstart, nend, nmirror, descriptor);
+ hand_r->unref();
+
+ auto hand_w = new handler_entry_write_delegate<AccessWidth, -AccessWidth, Endian, WRITE>(m_view.m_space, handler_w);
+ descriptor.set_subunit_handler(hand_w);
+ hand_w->set_address_info(descriptor.get_handler_start(), descriptor.get_handler_mask());
+ w()->populate_mismatched(nstart, nend, nmirror, descriptor);
+ hand_w->unref();
+ }
+ invalidate_caches(read_or_write::READWRITE);
+ }
+ }
+};
+
+namespace {
+ template<int Level, int Width, int AddrShift, endianness_t Endian> memory_view::memory_view_entry *mve_make_1(const address_space_config &config, memory_manager &manager, memory_view &view, int id) {
+ return new memory_view_entry_specific<Level, Width, AddrShift, Endian>(config, manager, view, id);
+ }
+
+ template<int Width, int AddrShift, endianness_t Endian> memory_view::memory_view_entry *mve_make_2(int Level, const address_space_config &config, memory_manager &manager, memory_view &view, int id) {
+ switch(Level) {
+ case 0: return mve_make_1<0, Width, AddrShift, Endian>(config, manager, view, id);
+ case 1: return mve_make_1<1, Width, AddrShift, Endian>(config, manager, view, id);
+ default: abort();
+ }
+ }
+
+ template<int Width, int AddrShift> memory_view::memory_view_entry *mve_make_3(int Level, endianness_t Endian, const address_space_config &config, memory_manager &manager, memory_view &view, int id) {
+ switch(Endian) {
+ case ENDIANNESS_LITTLE: return mve_make_2<Width, AddrShift, ENDIANNESS_LITTLE>(Level, config, manager, view, id);
+ case ENDIANNESS_BIG: return mve_make_2<Width, AddrShift, ENDIANNESS_BIG> (Level, config, manager, view, id);
+ default: abort();
+ }
+ }
+
+ memory_view::memory_view_entry *mve_make(int Level, int Width, int AddrShift, endianness_t Endian, const address_space_config &config, memory_manager &manager, memory_view &view, int id) {
+ switch (Width | (AddrShift + 4)) {
+ case 8|(4+1): return mve_make_3<0, 1>(Level, Endian, config, manager, view, id);
+ case 8|(4-0): return mve_make_3<0, 0>(Level, Endian, config, manager, view, id);
+ case 16|(4+3): return mve_make_3<1, 3>(Level, Endian, config, manager, view, id);
+ case 16|(4-0): return mve_make_3<1, 0>(Level, Endian, config, manager, view, id);
+ case 16|(4-1): return mve_make_3<1, -1>(Level, Endian, config, manager, view, id);
+ case 32|(4+3): return mve_make_3<2, 3>(Level, Endian, config, manager, view, id);
+ case 32|(4-0): return mve_make_3<2, 0>(Level, Endian, config, manager, view, id);
+ case 32|(4-1): return mve_make_3<2, -1>(Level, Endian, config, manager, view, id);
+ case 32|(4-2): return mve_make_3<2, -2>(Level, Endian, config, manager, view, id);
+ case 64|(4-0): return mve_make_3<3, 0>(Level, Endian, config, manager, view, id);
+ case 64|(4-1): return mve_make_3<3, -1>(Level, Endian, config, manager, view, id);
+ case 64|(4-2): return mve_make_3<3, -2>(Level, Endian, config, manager, view, id);
+ case 64|(4-3): return mve_make_3<3, -3>(Level, Endian, config, manager, view, id);
+ default: abort();
+ }
+ }
+}
+
+memory_view::memory_view_entry &memory_view::operator[](int slot)
+{
+ if (!m_config)
+ fatalerror("A view must be in a map or a space before it can be setup.");
+
+ auto i = m_entry_mapping.find(slot);
+ if (i == m_entry_mapping.end()) {
+ memory_view_entry *e;
+ int id = m_entries.size();
+ e = mve_make(emu::detail::handler_entry_dispatch_level(m_config->addr_width()), m_config->data_width(), m_config->addr_shift(), m_config->endianness(),
+ *m_config, m_device.machine().memory(), *this, id);
+ m_entries.resize(id+1);
+ m_entries[id].reset(e);
+ m_entry_mapping[slot] = id;
+ return *e;
+
+ } else
+ return *m_entries[i->second];
+}
+
+memory_view::memory_view_entry::memory_view_entry(const address_space_config &config, memory_manager &manager, memory_view &view, int id) : address_space_installer(config, manager), m_view(view), m_id(id)
+{
+ m_map = std::make_unique<address_map>(m_view);
+}
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> void memory_view_entry_specific<Level, Width, AddrShift, Endian>::populate_from_map(address_map *map)
+{
+ // no map specified, use the space-specific one
+ if (map == nullptr)
+ map = m_map.get();
+
+ memory_region *devregion = (m_view.m_space->spacenum() == 0) ? m_view.m_device.memregion(DEVICE_SELF) : nullptr;
+ u32 devregionsize = (devregion != nullptr) ? devregion->bytes() : 0;
+
+ // merge in the submaps
+ map->import_submaps(m_manager.machine(), m_view.m_device.owner() ? *m_view.m_device.owner() : m_view.m_device, data_width(), endianness(), addr_shift());
+
+ // make a pass over the address map, adjusting for the device and getting memory pointers
+ for (address_map_entry &entry : map->m_entrylist)
+ {
+ // computed adjusted addresses first
+ adjust_addresses(entry.m_addrstart, entry.m_addrend, entry.m_addrmask, entry.m_addrmirror);
+
+ // if we have a share entry, add it to our map
+ if (entry.m_share != nullptr)
+ {
+ // if we can't find it, add it to our map
+ std::string fulltag = entry.m_devbase.subtag(entry.m_share);
+ memory_share *share = m_manager.share_find(fulltag);
+ if (!share)
+ {
+ VPRINTF("Creating share '%s' of length 0x%X\n", fulltag, entry.m_addrend + 1 - entry.m_addrstart);
+ share = m_manager.share_alloc(m_view.m_device, fulltag, data_width(), address_to_byte(entry.m_addrend + 1 - entry.m_addrstart), endianness());
+ }
+ else
+ {
+ std::string result = share->compare(data_width(), address_to_byte(entry.m_addrend + 1 - entry.m_addrstart), endianness());
+ if (!result.empty())
+ fatalerror("%s\n", result);
+ }
+ entry.m_memory = share->ptr();
+ }
+
+ // if this is a ROM handler without a specified region and not shared, attach it to the implicit region
+ if (m_view.m_space->spacenum() == AS_PROGRAM && entry.m_read.m_type == AMH_ROM && entry.m_region == nullptr && entry.m_share == nullptr)
+ {
+ // make sure it fits within the memory region before doing so, however
+ if (entry.m_addrend < devregionsize)
+ {
+ entry.m_region = m_view.m_device.tag();
+ entry.m_rgnoffs = address_to_byte(entry.m_addrstart);
+ }
+ }
+
+ // validate adjusted addresses against implicit regions
+ if (entry.m_region != nullptr)
+ {
+ // determine full tag
+ std::string fulltag = entry.m_devbase.subtag(entry.m_region);
+
+ // find the region
+ memory_region *region = m_manager.machine().root_device().memregion(fulltag);
+ if (region == nullptr)
+ fatalerror("device '%s' %s view memory map entry %X-%X references nonexistent region \"%s\"\n", m_view.m_device.tag(), m_view.m_name, entry.m_addrstart, entry.m_addrend, entry.m_region);
+
+ // validate the region
+ if (entry.m_rgnoffs + m_config.addr2byte(entry.m_addrend - entry.m_addrstart + 1) > region->bytes())
+ fatalerror("device '%s' %s view memory map entry %X-%X extends beyond region \"%s\" size (%X)\n", m_view.m_device.tag(), m_view.m_name, entry.m_addrstart, entry.m_addrend, entry.m_region, region->bytes());
+
+ if (entry.m_share != nullptr)
+ fatalerror("device '%s' %s view memory map entry %X-%X has both .region() and .share()\n", m_view.m_device.tag(), m_view.m_name, entry.m_addrstart, entry.m_addrend);
+ }
+
+ // convert any region-relative entries to their memory pointers
+ if (entry.m_region != nullptr)
+ {
+ // determine full tag
+ std::string fulltag = entry.m_devbase.subtag(entry.m_region);
+
+ // set the memory address
+ entry.m_memory = m_manager.machine().root_device().memregion(fulltag)->base() + entry.m_rgnoffs;
+ }
+
+ // allocate anonymous ram when needed
+ if (!entry.m_memory && (entry.m_read.m_type == AMH_RAM || entry.m_write.m_type == AMH_RAM))
+ entry.m_memory = m_manager.anonymous_alloc(*m_view.m_space, address_to_byte(entry.m_addrend + 1 - entry.m_addrstart), m_config.data_width(), entry.m_addrstart, entry.m_addrend, key());
+ }
+
+ // Force the slot to exist, in case the map is empty
+ m_view.m_select_u(m_id);
+
+ // install the handlers, using the original, unadjusted memory map
+ for(const address_map_entry &entry : map->m_entrylist) {
+ // map both read and write halves
+ populate_map_entry(entry, read_or_write::READ);
+ populate_map_entry(entry, read_or_write::WRITE);
+ }
+}
+
+std::string memory_view::memory_view_entry::key() const
+{
+ std::string key = m_view.m_context;
+ if (m_id != -1)
+ key += util::string_format("%s[%d].", m_view.m_name, m_view.id_to_slot(m_id));
+ return key;
+}
+
+
+memory_view::memory_view(device_t &device, std::string name) : m_device(device), m_name(name), m_config(nullptr), m_addrstart(0), m_addrend(0), m_space(nullptr), m_handler_read(nullptr), m_handler_write(nullptr), m_cur_id(-1), m_cur_slot(-1)
+{
+}
+
+void memory_view::disable()
+{
+ m_cur_slot = -1;
+ m_cur_id = -1;
+ m_select_a(-1);
+}
+
+void memory_view::select(int slot)
+{
+ auto i = m_entry_mapping.find(slot);
+ if (i == m_entry_mapping.end())
+ fatalerror("memory_view %s: select of unknown slot %d", m_name, slot);
+
+ m_cur_slot = slot;
+ m_cur_id = i->second;
+ m_select_a(m_cur_id);
+}
+
+int memory_view::id_to_slot(int id) const
+{
+ for(const auto &p : m_entry_mapping)
+ if (p.second == id)
+ return p.first;
+ fatalerror("memory_view::id_to_slot on unknown id %d\n", id);
+}
+
+void memory_view::initialize_from_address_map(offs_t addrstart, offs_t addrend, const address_space_config &config)
+{
+ if (m_config)
+ fatalerror("A memory_view can be present in only one address map.");
+
+ m_config = &config;
+ m_addrstart = addrstart;
+ m_addrend = addrend;
+}
+
+namespace {
+ template<int HighBits, int Width, int AddrShift, endianness_t Endian> void h_make_1(address_space &space, memory_view &view, handler_entry *&r, handler_entry *&w, std::function<void (int)> &sa, std::function<void (int)> &su) {
+ auto rx = new handler_entry_read_dispatch <HighBits, Width, AddrShift, Endian>(&space, view);
+ auto wx = new handler_entry_write_dispatch<HighBits, Width, AddrShift, Endian>(&space, view);
+ r = rx;
+ w = wx;
+
+ sa = [rx, wx](int s) { rx->select_a(s); wx->select_a(s); };
+ su = [rx, wx](int s) { rx->select_u(s); wx->select_u(s); };
+ }
+
+ template<int Width, int AddrShift, endianness_t Endian> void h_make_2(int HighBits, address_space &space, memory_view &view, handler_entry *&r, handler_entry *&w, std::function<void (int)> &sa, std::function<void (int)> &su) {
+ switch(HighBits) {
+ case 0: h_make_1<std::max(0, Width), Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 1: h_make_1<std::max(1, Width), Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 2: h_make_1<std::max(2, Width), Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 3: h_make_1<std::max(3, Width), Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 4: h_make_1< 4, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 5: h_make_1< 5, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 6: h_make_1< 6, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 7: h_make_1< 7, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 8: h_make_1< 8, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 9: h_make_1< 9, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 10: h_make_1<10, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 11: h_make_1<11, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 12: h_make_1<12, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 13: h_make_1<13, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 14: h_make_1<14, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 15: h_make_1<15, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 16: h_make_1<16, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 17: h_make_1<17, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 18: h_make_1<18, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 19: h_make_1<19, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 20: h_make_1<20, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 21: h_make_1<21, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 22: h_make_1<22, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 23: h_make_1<23, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 24: h_make_1<24, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 25: h_make_1<25, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 26: h_make_1<26, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 27: h_make_1<27, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 28: h_make_1<28, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 29: h_make_1<29, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 30: h_make_1<20, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 31: h_make_1<31, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ case 32: h_make_1<32, Width, AddrShift, Endian>(space, view, r, w, sa, su); break;
+ default: abort();
+ }
+ }
+
+ template<int Width, int AddrShift> void h_make_3(int HighBits, endianness_t Endian, address_space &space, memory_view &view, handler_entry *&r, handler_entry *&w, std::function<void (int)> &sa, std::function<void (int)> &su) {
+ switch(Endian) {
+ case ENDIANNESS_LITTLE: h_make_2<Width, AddrShift, ENDIANNESS_LITTLE>(HighBits, space, view, r, w, sa, su); break;
+ case ENDIANNESS_BIG: h_make_2<Width, AddrShift, ENDIANNESS_BIG> (HighBits, space, view, r, w, sa, su); break;
+ default: abort();
+ }
+ }
+
+ void h_make(int HighBits, int Width, int AddrShift, endianness_t Endian, address_space &space, memory_view &view, handler_entry *&r, handler_entry *&w, std::function<void (int)> &sa, std::function<void (int)> &su) {
+ switch (Width | (AddrShift + 4)) {
+ case 8|(4+1): h_make_3<0, 1>(HighBits, Endian, space, view, r, w, sa, su); break;
+ case 8|(4-0): h_make_3<0, 0>(HighBits, Endian, space, view, r, w, sa, su); break;
+ case 16|(4+3): h_make_3<1, 3>(HighBits, Endian, space, view, r, w, sa, su); break;
+ case 16|(4-0): h_make_3<1, 0>(HighBits, Endian, space, view, r, w, sa, su); break;
+ case 16|(4-1): h_make_3<1, -1>(HighBits, Endian, space, view, r, w, sa, su); break;
+ case 32|(4+3): h_make_3<2, 3>(HighBits, Endian, space, view, r, w, sa, su); break;
+ case 32|(4-0): h_make_3<2, 0>(HighBits, Endian, space, view, r, w, sa, su); break;
+ case 32|(4-1): h_make_3<2, -1>(HighBits, Endian, space, view, r, w, sa, su); break;
+ case 32|(4-2): h_make_3<2, -2>(HighBits, Endian, space, view, r, w, sa, su); break;
+ case 64|(4-0): h_make_3<3, 0>(HighBits, Endian, space, view, r, w, sa, su); break;
+ case 64|(4-1): h_make_3<3, -1>(HighBits, Endian, space, view, r, w, sa, su); break;
+ case 64|(4-2): h_make_3<3, -2>(HighBits, Endian, space, view, r, w, sa, su); break;
+ case 64|(4-3): h_make_3<3, -3>(HighBits, Endian, space, view, r, w, sa, su); break;
+ default: abort();
+ }
+ }
+}
+
+std::pair<handler_entry *, handler_entry *> memory_view::make_handlers(address_space &space, offs_t addrstart, offs_t addrend)
+{
+ if (m_space != &space || m_addrstart != addrstart || m_addrend != addrend) {
+ if (m_space)
+ fatalerror("A memory_view can be installed only once.");
+
+ if (m_config) {
+ if (m_addrstart != addrstart || m_addrend != addrend)
+ fatalerror("A memory_view must be installed at its configuration address.");
+ } else {
+ m_config = &space.space_config();
+ m_addrstart = addrstart;
+ m_addrend = addrend;
+ }
+
+ m_space = &space;
+
+ offs_t span = addrstart ^ addrend;
+ u32 awidth = 0;
+ if (span) {
+ for(awidth = 1; awidth != 32; awidth++)
+ if ((1 << awidth) >= span)
+ break;
+ }
+
+ h_make(awidth, m_config->data_width(), m_config->addr_shift(), m_config->endianness(), space, *this, m_handler_read, m_handler_write, m_select_a, m_select_u);
+ }
+
+ return std::make_pair(m_handler_read, m_handler_write);
+}
+
+void memory_view::make_subdispatch(std::string context)
+{
+ m_context = context;
+ for(auto &e : m_entries)
+ e->populate_from_map();
+}
+
+void memory_view::memory_view_entry::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)
+{
+ check_optimize_mirror(function, addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
+ if (nstart < m_view.m_addrstart || (nend | nmirror) > m_view.m_addrend)
+ fatalerror("%s: The range %x-%x mirror %x, exceeds the view window boundaries %x-%x.\n", function, addrstart, addrend, addrmirror, m_view.m_addrstart, m_view.m_addrend);
+}
+
+void memory_view::memory_view_entry::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)
+{
+ check_optimize_all(function, width, addrstart, addrend, addrmask, addrmirror, addrselect, unitmask, cswidth, nstart, nend, nmask, nmirror, nunitmask, ncswidth);
+ if (nstart < m_view.m_addrstart || (nend | nmirror | addrselect) > m_view.m_addrend)
+ fatalerror("%s: The range %x-%x mirror %x select %x, exceeds the view window boundaries %x-%x.\n", function, addrstart, addrend, addrmirror, addrselect, m_view.m_addrstart, m_view.m_addrend);
+}
+
+void memory_view::memory_view_entry::check_range_address(const char *function, offs_t addrstart, offs_t addrend)
+{
+ check_address(function, addrstart, addrend);
+ if (addrstart < m_view.m_addrstart || addrend > m_view.m_addrend)
+ fatalerror("%s: The range %x-%x exceeds the view window boundaries %x-%x.\n", function, addrstart, addrend, m_view.m_addrstart, m_view.m_addrend);
+}
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> void memory_view_entry_specific<Level, Width, AddrShift, Endian>::install_ram_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, read_or_write readorwrite, void *baseptr)
+{
+ VPRINTF("memory_view::install_ram_generic(%s-%s mirror=%s, %s, %p)\n",
+ m_addrchars, addrstart, m_addrchars, addrend,
+ m_addrchars, addrmirror,
+ (readorwrite == read_or_write::READ) ? "read" : (readorwrite == read_or_write::WRITE) ? "write" : (readorwrite == read_or_write::READWRITE) ? "read/write" : "??",
+ baseptr);
+
+ offs_t nstart, nend, nmask, nmirror;
+ check_range_optimize_mirror("install_ram_generic", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
+
+ m_view.m_select_u(m_id);
+
+ // map for read
+ if (readorwrite == read_or_write::READ || readorwrite == read_or_write::READWRITE)
+ {
+ auto hand_r = new handler_entry_read_memory<Width, AddrShift, Endian>(m_view.m_space, baseptr);
+ hand_r->set_address_info(nstart, nmask);
+ r()->populate(nstart, nend, nmirror, hand_r);
+ }
+
+ // map for write
+ if (readorwrite == read_or_write::WRITE || readorwrite == read_or_write::READWRITE)
+ {
+ auto hand_w = new handler_entry_write_memory<Width, AddrShift, Endian>(m_view.m_space, baseptr);
+ hand_w->set_address_info(nstart, nmask);
+ w()->populate(nstart, nend, nmirror, hand_w);
+ }
+
+ invalidate_caches(readorwrite);
+}
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> void memory_view_entry_specific<Level, Width, AddrShift, Endian>::unmap_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, read_or_write readorwrite, bool quiet)
+{
+ VPRINTF("memory_view::unmap(%*x-%*x mirror=%*x, %s, %s)\n",
+ m_addrchars, addrstart, m_addrchars, addrend,
+ m_addrchars, addrmirror,
+ (readorwrite == read_or_write::READ) ? "read" : (readorwrite == read_or_write::WRITE) ? "write" : (readorwrite == read_or_write::READWRITE) ? "read/write" : "??",
+ quiet ? "quiet" : "normal");
+
+ offs_t nstart, nend, nmask, nmirror;
+ check_range_optimize_mirror("unmap_generic", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
+
+ m_view.m_select_u(m_id);
+
+ // read space
+ if (readorwrite == read_or_write::READ || readorwrite == read_or_write::READWRITE) {
+ auto handler = static_cast<handler_entry_read<Width, AddrShift, Endian> *>(quiet ? m_view.m_space->nop_r() : m_view.m_space->unmap_r());
+ handler->ref();
+ r()->populate(nstart, nend, nmirror, handler);
+ }
+
+ // write space
+ if (readorwrite == read_or_write::WRITE || readorwrite == read_or_write::READWRITE) {
+ auto handler = static_cast<handler_entry_write<Width, AddrShift, Endian> *>(quiet ? m_view.m_space->nop_w() : m_view.m_space->unmap_w());
+ handler->ref();
+ w()->populate(nstart, nend, nmirror, handler);
+ }
+
+ invalidate_caches(readorwrite);
+}
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> void memory_view_entry_specific<Level, Width, AddrShift, Endian>::install_view(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_view &view)
+{
+ offs_t nstart, nend, nmask, nmirror;
+ check_range_optimize_mirror("install_view", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
+
+ m_view.m_select_u(m_id);
+
+ auto handlers = view.make_handlers(*m_view.m_space, addrstart, addrend);
+ r()->populate(nstart, nend, nmirror, static_cast<handler_entry_read <Width, AddrShift, Endian> *>(handlers.first));
+ w()->populate(nstart, nend, nmirror, static_cast<handler_entry_write<Width, AddrShift, Endian> *>(handlers.second));
+ view.make_subdispatch(key()); // Must be called after populate
+}
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> memory_passthrough_handler *memory_view_entry_specific<Level, Width, AddrShift, Endian>::install_read_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph)
+{
+ offs_t nstart, nend, nmask, nmirror;
+ check_range_optimize_mirror("install_read_tap", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
+ if (!mph)
+ mph = m_view.m_space->make_mph();
+
+ m_view.m_select_u(m_id);
+
+ auto handler = new handler_entry_read_tap<Width, AddrShift, Endian>(m_view.m_space, *mph, name, tap);
+ r()->populate_passthrough(nstart, nend, nmirror, handler);
+ handler->unref();
+
+ invalidate_caches(read_or_write::READ);
+
+ return mph;
+}
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> memory_passthrough_handler *memory_view_entry_specific<Level, Width, AddrShift, Endian>::install_write_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tap, memory_passthrough_handler *mph)
+{
+ offs_t nstart, nend, nmask, nmirror;
+ check_range_optimize_mirror("install_write_tap", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
+ if (!mph)
+ mph = m_view.m_space->make_mph();
+
+ m_view.m_select_u(m_id);
+
+ auto handler = new handler_entry_write_tap<Width, AddrShift, Endian>(m_view.m_space, *mph, name, tap);
+ w()->populate_passthrough(nstart, nend, nmirror, handler);
+ handler->unref();
+
+ invalidate_caches(read_or_write::WRITE);
+
+ return mph;
+}
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> memory_passthrough_handler *memory_view_entry_specific<Level, Width, AddrShift, Endian>::install_readwrite_tap(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string name, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapr, std::function<void (offs_t offset, uX &data, uX mem_mask)> tapw, memory_passthrough_handler *mph)
+{
+ offs_t nstart, nend, nmask, nmirror;
+ check_range_optimize_mirror("install_readwrite_tap", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
+ if (!mph)
+ mph = m_view.m_space->make_mph();
+
+ m_view.m_select_u(m_id);
+
+ auto rhandler = new handler_entry_read_tap <Width, AddrShift, Endian>(m_view.m_space, *mph, name, tapr);
+ r() ->populate_passthrough(nstart, nend, nmirror, rhandler);
+ rhandler->unref();
+
+ auto whandler = new handler_entry_write_tap<Width, AddrShift, Endian>(m_view.m_space, *mph, name, tapw);
+ w()->populate_passthrough(nstart, nend, nmirror, whandler);
+ whandler->unref();
+
+ invalidate_caches(read_or_write::READWRITE);
+
+ return mph;
+}
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> void memory_view_entry_specific<Level, Width, AddrShift, Endian>::install_device_delegate(offs_t addrstart, offs_t addrend, device_t &device, address_map_constructor &delegate, u64 unitmask, int cswidth)
+{
+ check_range_address("install_device_delegate", addrstart, addrend);
+ address_map map(*m_view.m_space, addrstart, addrend, unitmask, cswidth, m_view.m_device, delegate);
+ map.import_submaps(m_manager.machine(), device, data_width(), endianness(), addr_shift());
+ populate_from_map(&map);
+}
+
+template<int Level, int Width, int AddrShift, endianness_t Endian> void memory_view_entry_specific<Level, Width, AddrShift, Endian>::install_readwrite_port(offs_t addrstart, offs_t addrend, offs_t addrmirror, std::string rtag, std::string wtag)
+{
+ VPRINTF("memory_view::install_readwrite_port(%*x-%*x mirror=%*x, read=\"%s\" / write=\"%s\")\n",
+ m_addrchars, addrstart, m_addrchars, addrend,
+ m_addrchars, addrmirror,
+ rtag.empty() ? "(none)" : rtag, wtag.empty() ? "(none)" : wtag);
+
+ offs_t nstart, nend, nmask, nmirror;
+ check_range_optimize_mirror("install_readwrite_port", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
+
+ m_view.m_select_u(m_id);
+
+ // read handler
+ if (rtag != "")
+ {
+ // find the port
+ ioport_port *port = m_view.m_device.owner()->ioport(rtag);
+ if (port == nullptr)
+ throw emu_fatalerror("Attempted to map non-existent port '%s' for read in space %s of device '%s'\n", rtag, m_view.m_name, m_view.m_device.tag());
+
+ // map the range and set the ioport
+ auto hand_r = new handler_entry_read_ioport<Width, AddrShift, Endian>(m_view.m_space, port);
+ r()->populate(nstart, nend, nmirror, hand_r);
+ }
+
+ if (wtag != "")
+ {
+ // find the port
+ ioport_port *port = m_view.m_device.owner()->ioport(wtag);
+ if (port == nullptr)
+ fatalerror("Attempted to map non-existent port '%s' for write in space %s of device '%s'\n", wtag, m_view.m_name, m_view.m_device.tag());
+
+ // map the range and set the ioport
+ auto hand_w = new handler_entry_write_ioport<Width, AddrShift, Endian>(m_view.m_space, port);
+ w()->populate(nstart, nend, nmirror, hand_w);
+ }
+
+ invalidate_caches(rtag != "" ? wtag != "" ? read_or_write::READWRITE : read_or_write::READ : read_or_write::WRITE);
+}
+template<int Level, int Width, int AddrShift, endianness_t Endian> void memory_view_entry_specific<Level, Width, AddrShift, Endian>::install_bank_generic(offs_t addrstart, offs_t addrend, offs_t addrmirror, memory_bank *rbank, memory_bank *wbank)
+{
+ VPRINTF("memory_view::install_readwrite_bank(%*x-%*x mirror=%*x, read=\"%s\" / write=\"%s\")\n",
+ m_addrchars, addrstart, m_addrchars, addrend,
+ m_addrchars, addrmirror,
+ (rbank != nullptr) ? rbank->tag() : "(none)", (wbank != nullptr) ? wbank->tag() : "(none)");
+
+ offs_t nstart, nend, nmask, nmirror;
+ check_range_optimize_mirror("install_bank_generic", addrstart, addrend, addrmirror, nstart, nend, nmask, nmirror);
+
+ m_view.m_select_u(m_id);
+
+ // map the read bank
+ if (rbank != nullptr)
+ {
+ auto hand_r = new handler_entry_read_memory_bank<Width, AddrShift, Endian>(m_view.m_space, *rbank);
+ hand_r->set_address_info(nstart, nmask);
+ r()->populate(nstart, nend, nmirror, hand_r);
+ }
+
+ // map the write bank
+ if (wbank != nullptr)
+ {
+ auto hand_w = new handler_entry_write_memory_bank<Width, AddrShift, Endian>(m_view.m_space, *wbank);
+ hand_w->set_address_info(nstart, nmask);
+ w()->populate(nstart, nend, nmirror, hand_w);
+ }
+
+ invalidate_caches(rbank ? wbank ? read_or_write::READWRITE : read_or_write::READ : read_or_write::WRITE);
+}