summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/addrmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/addrmap.c')
-rw-r--r--trunk/src/emu/addrmap.c950
1 files changed, 950 insertions, 0 deletions
diff --git a/trunk/src/emu/addrmap.c b/trunk/src/emu/addrmap.c
new file mode 100644
index 00000000000..631bf544267
--- /dev/null
+++ b/trunk/src/emu/addrmap.c
@@ -0,0 +1,950 @@
+/***************************************************************************
+
+ addrmap.c
+
+ Macros and helper functions for handling address map definitions.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include "emu.h"
+
+
+//**************************************************************************
+// ADDRESS MAP ENTRY
+//**************************************************************************
+
+//-------------------------------------------------
+// address_map_entry - constructor
+//-------------------------------------------------
+
+address_map_entry::address_map_entry(address_map &map, offs_t start, offs_t end)
+ : m_next(NULL),
+ m_map(map),
+ m_addrstart((map.m_globalmask == 0) ? start : start & map.m_globalmask),
+ m_addrend((map.m_globalmask == 0) ? end : end & map.m_globalmask),
+ m_addrmirror(0),
+ m_addrmask(0),
+ m_share(NULL),
+ m_baseptr(NULL),
+ m_sizeptr(NULL),
+ m_baseptroffs_plus1(0),
+ m_sizeptroffs_plus1(0),
+ m_region(NULL),
+ m_rgnoffs(0),
+ m_rspace8(NULL),
+ m_rspace16(NULL),
+ m_rspace32(NULL),
+ m_rspace64(NULL),
+ m_rdevice8(NULL),
+ m_rdevice16(NULL),
+ m_rdevice32(NULL),
+ m_rdevice64(NULL),
+ m_wspace8(NULL),
+ m_wspace16(NULL),
+ m_wspace32(NULL),
+ m_wspace64(NULL),
+ m_wdevice8(NULL),
+ m_wdevice16(NULL),
+ m_wdevice32(NULL),
+ m_wdevice64(NULL),
+ m_memory(NULL),
+ m_bytestart(0),
+ m_byteend(0),
+ m_bytemirror(0),
+ m_bytemask(0)
+{
+}
+
+
+//-------------------------------------------------
+// set_mask - set the mask value
+//-------------------------------------------------
+
+void address_map_entry::set_mask(offs_t _mask)
+{
+ m_addrmask = _mask;
+ if (m_map.m_globalmask != 0)
+ m_addrmask &= m_map.m_globalmask;
+}
+
+
+//-------------------------------------------------
+// set_read_port - set up a handler for reading
+// an I/O port
+//-------------------------------------------------
+
+void address_map_entry::set_read_port(const device_t &device, const char *tag)
+{
+ m_read.m_type = AMH_PORT;
+ device.subtag(m_read.m_tag, tag);
+}
+
+
+//-------------------------------------------------
+// set_write_port - set up a handler for writing
+// an I/O port
+//-------------------------------------------------
+
+void address_map_entry::set_write_port(const device_t &device, const char *tag)
+{
+ m_write.m_type = AMH_PORT;
+ device.subtag(m_write.m_tag, tag);
+}
+
+
+//-------------------------------------------------
+// set_readwrite_port - set up a handler for
+// reading and writing an I/O port
+//-------------------------------------------------
+
+void address_map_entry::set_readwrite_port(const device_t &device, const char *tag)
+{
+ m_read.m_type = AMH_PORT;
+ device.subtag(m_read.m_tag, tag);
+ m_write.m_type = AMH_PORT;
+ device.subtag(m_write.m_tag, tag);
+}
+
+
+//-------------------------------------------------
+// set_read_bank - set up a handler for reading
+// from a memory bank
+//-------------------------------------------------
+
+void address_map_entry::set_read_bank(const device_t &device, const char *tag)
+{
+ m_read.m_type = AMH_BANK;
+ device.subtag(m_read.m_tag, tag);
+}
+
+
+//-------------------------------------------------
+// set_write_bank - set up a handler for writing
+// to a memory bank
+//-------------------------------------------------
+
+void address_map_entry::set_write_bank(const device_t &device, const char *tag)
+{
+ m_write.m_type = AMH_BANK;
+ device.subtag(m_write.m_tag, tag);
+}
+
+
+//-------------------------------------------------
+// set_readwrite_bank - set up a handler for
+// reading and writing to a memory bank
+//-------------------------------------------------
+
+void address_map_entry::set_readwrite_bank(const device_t &device, const char *tag)
+{
+ m_read.m_type = AMH_BANK;
+ device.subtag(m_read.m_tag, tag);
+ m_write.m_type = AMH_BANK;
+ device.subtag(m_write.m_tag, tag);
+}
+
+
+//-------------------------------------------------
+// set_submap - set up a handler for
+// retrieve a submap from a device
+//-------------------------------------------------
+
+void address_map_entry::set_submap(const device_t &device, const char *tag, address_map_delegate func, int bits, UINT64 mask)
+{
+ if(!bits)
+ bits = m_map.m_databits;
+
+ assert(unitmask_is_appropriate(bits, mask, func.name()));
+
+ m_read.m_type = AMH_DEVICE_SUBMAP;
+ device.subtag(m_read.m_tag, tag);
+ m_read.m_mask = mask;
+ m_write.m_type = AMH_DEVICE_SUBMAP;
+ device.subtag(m_write.m_tag, tag);
+ m_write.m_mask = mask;
+ m_submap_delegate = func;
+ m_submap_bits = bits;
+}
+
+
+//-------------------------------------------------
+// internal_set_handler - handler setters for
+// 8-bit read/write handlers
+//-------------------------------------------------
+
+void address_map_entry::internal_set_handler(read8_space_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(8, unitmask, string));
+ m_read.m_type = AMH_LEGACY_SPACE_HANDLER;
+ m_read.m_bits = 8;
+ m_read.m_mask = unitmask;
+ m_read.m_name = string;
+ m_rspace8 = func;
+}
+
+
+void address_map_entry::internal_set_handler(write8_space_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(8, unitmask, string));
+ m_write.m_type = AMH_LEGACY_SPACE_HANDLER;
+ m_write.m_bits = 8;
+ m_write.m_mask = unitmask;
+ m_write.m_name = string;
+ m_wspace8 = func;
+}
+
+
+void address_map_entry::internal_set_handler(read8_space_func rfunc, const char *rstring, write8_space_func wfunc, const char *wstring, UINT64 unitmask)
+{
+ internal_set_handler(rfunc, rstring, unitmask);
+ internal_set_handler(wfunc, wstring, unitmask);
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read8_device_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(8, unitmask, string));
+ m_read.m_type = AMH_LEGACY_DEVICE_HANDLER;
+ m_read.m_bits = 8;
+ m_read.m_mask = unitmask;
+ m_read.m_name = string;
+ device.subtag(m_read.m_tag, tag);
+ m_rdevice8 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, write8_device_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(8, unitmask, string));
+ m_write.m_type = AMH_LEGACY_DEVICE_HANDLER;
+ m_write.m_bits = 8;
+ m_write.m_mask = unitmask;
+ m_write.m_name = string;
+ device.subtag(m_write.m_tag, tag);
+ m_wdevice8 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read8_device_func rfunc, const char *rstring, write8_device_func wfunc, const char *wstring, UINT64 unitmask)
+{
+ internal_set_handler(device, tag, rfunc, rstring, unitmask);
+ internal_set_handler(device, tag, wfunc, wstring, unitmask);
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read8_delegate func, UINT64 unitmask)
+{
+ assert(!func.isnull());
+ assert(unitmask_is_appropriate(8, unitmask, func.name()));
+ m_read.m_type = AMH_DEVICE_DELEGATE;
+ m_read.m_bits = 8;
+ m_read.m_mask = unitmask;
+ m_read.m_name = func.name();
+ device.subtag(m_read.m_tag, tag);
+ m_rproto8 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, write8_delegate func, UINT64 unitmask)
+{
+ assert(!func.isnull());
+ assert(unitmask_is_appropriate(8, unitmask, func.name()));
+ m_write.m_type = AMH_DEVICE_DELEGATE;
+ m_write.m_bits = 8;
+ m_write.m_mask = unitmask;
+ m_write.m_name = func.name();
+ device.subtag(m_write.m_tag, tag);
+ m_wproto8 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read8_delegate rfunc, write8_delegate wfunc, UINT64 unitmask)
+{
+ internal_set_handler(device, tag, rfunc, unitmask);
+ internal_set_handler(device, tag, wfunc, unitmask);
+}
+
+
+//-------------------------------------------------
+// internal_set_handler - handler setters for
+// 16-bit read/write handlers
+//-------------------------------------------------
+
+void address_map_entry::internal_set_handler(read16_space_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(16, unitmask, string));
+ m_read.m_type = AMH_LEGACY_SPACE_HANDLER;
+ m_read.m_bits = 16;
+ m_read.m_mask = unitmask;
+ m_read.m_name = string;
+ m_rspace16 = func;
+}
+
+
+void address_map_entry::internal_set_handler(write16_space_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(16, unitmask, string));
+ m_write.m_type = AMH_LEGACY_SPACE_HANDLER;
+ m_write.m_bits = 16;
+ m_write.m_mask = unitmask;
+ m_write.m_name = string;
+ m_wspace16 = func;
+}
+
+
+void address_map_entry::internal_set_handler(read16_space_func rfunc, const char *rstring, write16_space_func wfunc, const char *wstring, UINT64 unitmask)
+{
+ internal_set_handler(rfunc, rstring, unitmask);
+ internal_set_handler(wfunc, wstring, unitmask);
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read16_device_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(16, unitmask, string));
+ m_read.m_type = AMH_LEGACY_DEVICE_HANDLER;
+ m_read.m_bits = 16;
+ m_read.m_mask = unitmask;
+ m_read.m_name = string;
+ device.subtag(m_read.m_tag, tag);
+ m_rdevice16 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, write16_device_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(16, unitmask, string));
+ m_write.m_type = AMH_LEGACY_DEVICE_HANDLER;
+ m_write.m_bits = 16;
+ m_write.m_mask = unitmask;
+ m_write.m_name = string;
+ device.subtag(m_write.m_tag, tag);
+ m_wdevice16 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read16_device_func rfunc, const char *rstring, write16_device_func wfunc, const char *wstring, UINT64 unitmask)
+{
+ internal_set_handler(device, tag, rfunc, rstring, unitmask);
+ internal_set_handler(device, tag, wfunc, wstring, unitmask);
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read16_delegate func, UINT64 unitmask)
+{
+ assert(!func.isnull());
+ assert(unitmask_is_appropriate(16, unitmask, func.name()));
+ m_read.m_type = AMH_DEVICE_DELEGATE;
+ m_read.m_bits = 16;
+ m_read.m_mask = unitmask;
+ m_read.m_name = func.name();
+ device.subtag(m_read.m_tag, tag);
+ m_rproto16 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, write16_delegate func, UINT64 unitmask)
+{
+ assert(!func.isnull());
+ assert(unitmask_is_appropriate(16, unitmask, func.name()));
+ m_write.m_type = AMH_DEVICE_DELEGATE;
+ m_write.m_bits = 16;
+ m_write.m_mask = unitmask;
+ m_write.m_name = func.name();
+ device.subtag(m_write.m_tag, tag);
+ m_wproto16 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read16_delegate rfunc, write16_delegate wfunc, UINT64 unitmask)
+{
+ internal_set_handler(device, tag, rfunc, unitmask);
+ internal_set_handler(device, tag, wfunc, unitmask);
+}
+
+
+//-------------------------------------------------
+// internal_set_handler - handler setters for
+// 32-bit read/write handlers
+//-------------------------------------------------
+
+void address_map_entry::internal_set_handler(read32_space_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(32, unitmask, string));
+ m_read.m_type = AMH_LEGACY_SPACE_HANDLER;
+ m_read.m_bits = 32;
+ m_read.m_mask = unitmask;
+ m_read.m_name = string;
+ m_rspace32 = func;
+}
+
+
+void address_map_entry::internal_set_handler(write32_space_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(32, unitmask, string));
+ m_write.m_type = AMH_LEGACY_SPACE_HANDLER;
+ m_write.m_bits = 32;
+ m_write.m_mask = unitmask;
+ m_write.m_name = string;
+ m_wspace32 = func;
+}
+
+
+void address_map_entry::internal_set_handler(read32_space_func rfunc, const char *rstring, write32_space_func wfunc, const char *wstring, UINT64 unitmask)
+{
+ internal_set_handler(rfunc, rstring, unitmask);
+ internal_set_handler(wfunc, wstring, unitmask);
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read32_device_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(32, unitmask, string));
+ m_read.m_type = AMH_LEGACY_DEVICE_HANDLER;
+ m_read.m_bits = 32;
+ m_read.m_mask = unitmask;
+ m_read.m_name = string;
+ device.subtag(m_read.m_tag, tag);
+ m_rdevice32 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, write32_device_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(32, unitmask, string));
+ m_write.m_type = AMH_LEGACY_DEVICE_HANDLER;
+ m_write.m_bits = 32;
+ m_write.m_mask = unitmask;
+ m_write.m_name = string;
+ device.subtag(m_write.m_tag, tag);
+ m_wdevice32 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read32_device_func rfunc, const char *rstring, write32_device_func wfunc, const char *wstring, UINT64 unitmask)
+{
+ internal_set_handler(device, tag, rfunc, rstring, unitmask);
+ internal_set_handler(device, tag, wfunc, wstring, unitmask);
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read32_delegate func, UINT64 unitmask)
+{
+ assert(!func.isnull());
+ assert(unitmask_is_appropriate(32, unitmask, func.name()));
+ m_read.m_type = AMH_DEVICE_DELEGATE;
+ m_read.m_bits = 32;
+ m_read.m_mask = unitmask;
+ m_read.m_name = func.name();
+ device.subtag(m_read.m_tag, tag);
+ m_rproto32 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, write32_delegate func, UINT64 unitmask)
+{
+ assert(!func.isnull());
+ assert(unitmask_is_appropriate(32, unitmask, func.name()));
+ m_write.m_type = AMH_DEVICE_DELEGATE;
+ m_write.m_bits = 32;
+ m_write.m_mask = unitmask;
+ m_write.m_name = func.name();
+ device.subtag(m_write.m_tag, tag);
+ m_wproto32 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read32_delegate rfunc, write32_delegate wfunc, UINT64 unitmask)
+{
+ internal_set_handler(device, tag, rfunc, unitmask);
+ internal_set_handler(device, tag, wfunc, unitmask);
+}
+
+
+//-------------------------------------------------
+// internal_set_handler - handler setters for
+// 64-bit read/write handlers
+//-------------------------------------------------
+
+void address_map_entry::internal_set_handler(read64_space_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(64, unitmask, string));
+ m_read.m_type = AMH_LEGACY_SPACE_HANDLER;
+ m_read.m_bits = 64;
+ m_read.m_mask = 0;
+ m_read.m_name = string;
+ m_rspace64 = func;
+}
+
+
+void address_map_entry::internal_set_handler(write64_space_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(64, unitmask, string));
+ m_write.m_type = AMH_LEGACY_SPACE_HANDLER;
+ m_write.m_bits = 64;
+ m_write.m_mask = 0;
+ m_write.m_name = string;
+ m_wspace64 = func;
+}
+
+
+void address_map_entry::internal_set_handler(read64_space_func rfunc, const char *rstring, write64_space_func wfunc, const char *wstring, UINT64 unitmask)
+{
+ internal_set_handler(rfunc, rstring, unitmask);
+ internal_set_handler(wfunc, wstring, unitmask);
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read64_device_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(64, unitmask, string));
+ m_read.m_type = AMH_LEGACY_DEVICE_HANDLER;
+ m_read.m_bits = 64;
+ m_read.m_mask = 0;
+ m_read.m_name = string;
+ device.subtag(m_read.m_tag, tag);
+ m_rdevice64 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, write64_device_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(64, unitmask, string));
+ m_write.m_type = AMH_LEGACY_DEVICE_HANDLER;
+ m_write.m_bits = 64;
+ m_write.m_mask = 0;
+ m_write.m_name = string;
+ device.subtag(m_write.m_tag, tag);
+ m_wdevice64 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read64_device_func rfunc, const char *rstring, write64_device_func wfunc, const char *wstring, UINT64 unitmask)
+{
+ internal_set_handler(device, tag, rfunc, rstring, unitmask);
+ internal_set_handler(device, tag, wfunc, wstring, unitmask);
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read64_delegate func, UINT64 unitmask)
+{
+ assert(!func.isnull());
+ assert(unitmask_is_appropriate(64, unitmask, func.name()));
+ m_read.m_type = AMH_DEVICE_DELEGATE;
+ m_read.m_bits = 64;
+ m_read.m_mask = 0;
+ m_read.m_name = func.name();
+ device.subtag(m_read.m_tag, tag);
+ m_rproto64 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, write64_delegate func, UINT64 unitmask)
+{
+ assert(!func.isnull());
+ assert(unitmask_is_appropriate(64, unitmask, func.name()));
+ m_write.m_type = AMH_DEVICE_DELEGATE;
+ m_write.m_bits = 64;
+ m_write.m_mask = 0;
+ m_write.m_name = func.name();
+ device.subtag(m_write.m_tag, tag);
+ m_wproto64 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read64_delegate rfunc, write64_delegate wfunc, UINT64 unitmask)
+{
+ internal_set_handler(device, tag, rfunc, unitmask);
+ internal_set_handler(device, tag, wfunc, unitmask);
+}
+
+
+//-------------------------------------------------
+// unitmask_is_appropriate - verify that the
+// provided unitmask is valid and expected
+//-------------------------------------------------
+
+bool address_map_entry::unitmask_is_appropriate(UINT8 width, UINT64 unitmask, const char *string)
+{
+ // if no mask, this must match the default width of the map
+ if (unitmask == 0)
+ {
+ if (m_map.m_databits != width)
+ throw emu_fatalerror("Handler %s is a %d-bit handler but was specified in a %d-bit address map", string, width, m_map.m_databits);
+ return true;
+ }
+
+ // if we have a mask, we must be smaller than the default width of the map
+ if (m_map.m_databits <= width)
+ throw emu_fatalerror("Handler %s is a %d-bit handler and is too wide to be used in a %d-bit address map", string, width, m_map.m_databits);
+
+ // the mask must represent whole units of width
+ UINT32 basemask = (width == 8) ? 0xff : (width == 16) ? 0xffff : 0xffffffff;
+ UINT64 singlemask = basemask;
+ while (singlemask != 0)
+ {
+ if ((unitmask & singlemask) != 0 && (unitmask & singlemask) != singlemask)
+ throw emu_fatalerror("Handler %s specified a mask of %08X%08X; needs to be in even chunks of %X", string, (UINT32)(unitmask >> 32), (UINT32)unitmask, basemask);
+ singlemask <<= width;
+ }
+ return true;
+}
+
+
+
+//**************************************************************************
+// WIDTH-SPECIFIC ADDRESS MAP ENTRY CONSTRUCTORS
+//**************************************************************************
+
+//-------------------------------------------------
+// address_map_entry8 - constructor
+//-------------------------------------------------
+
+address_map_entry8::address_map_entry8(address_map &map, offs_t start, offs_t end)
+ : address_map_entry(map, start, end)
+{
+}
+
+
+//-------------------------------------------------
+// address_map_entry16 - constructor
+//-------------------------------------------------
+
+address_map_entry16::address_map_entry16(address_map &map, offs_t start, offs_t end)
+ : address_map_entry(map, start, end)
+{
+}
+
+
+//-------------------------------------------------
+// address_map_entry32 - constructor
+//-------------------------------------------------
+
+address_map_entry32::address_map_entry32(address_map &map, offs_t start, offs_t end)
+ : address_map_entry(map, start, end)
+{
+}
+
+
+//-------------------------------------------------
+// address_map_entry64 - constructor
+//-------------------------------------------------
+
+address_map_entry64::address_map_entry64(address_map &map, offs_t start, offs_t end)
+ : address_map_entry(map, start, end)
+{
+}
+
+
+
+//**************************************************************************
+// ADDRESS MAP
+//**************************************************************************
+
+//-------------------------------------------------
+// address_map - constructor
+//-------------------------------------------------
+
+address_map::address_map(const device_t &device, address_spacenum spacenum)
+ : m_spacenum(spacenum),
+ m_databits(0xff),
+ m_unmapval(0),
+ m_globalmask(0)
+{
+ // get our memory interface
+ const device_memory_interface *memintf;
+ if (!device.interface(memintf))
+ throw emu_fatalerror("No memory interface defined for device '%s'\n", device.tag());
+
+ // and then the configuration for the current address space
+ const address_space_config *spaceconfig = memintf->space_config(spacenum);
+ if (!device.interface(memintf))
+ throw emu_fatalerror("No memory address space configuration found for device '%s', space %d\n", device.tag(), spacenum);
+
+ // append the internal device map (first so it takes priority) */
+ if (spaceconfig->m_internal_map != NULL)
+ (*spaceconfig->m_internal_map)(*this, device);
+
+ // construct the standard map */
+ if (memintf->address_map(spacenum) != NULL)
+ (*memintf->address_map(spacenum))(*this, *device.owner());
+
+ // append the default device map (last so it can be overridden) */
+ if (spaceconfig->m_default_map != NULL)
+ (*spaceconfig->m_default_map)(*this, device);
+}
+
+
+
+//-------------------------------------------------
+// address_map - constructor in the submap case
+//-------------------------------------------------
+
+address_map::address_map(const device_t &device, address_map_entry *entry)
+ : m_spacenum(AS_PROGRAM),
+ m_databits(0xff),
+ m_unmapval(0),
+ m_globalmask(0)
+{
+ // Retrieve the submap
+ entry->m_submap_delegate.late_bind(const_cast<device_t &>(device));
+ entry->m_submap_delegate(*this, device);
+}
+
+
+//-------------------------------------------------
+// ~address_map - destructor
+//-------------------------------------------------
+
+address_map::~address_map()
+{
+}
+
+
+//-------------------------------------------------
+// configure - either configure the space and
+// databits, or verify they match previously-set
+// values
+//-------------------------------------------------
+
+void address_map::configure(address_spacenum spacenum, UINT8 databits)
+{
+ assert(m_spacenum == spacenum);
+ if (m_databits == 0xff)
+ m_databits = databits;
+ else
+ assert(m_databits == databits);
+}
+
+
+//-------------------------------------------------
+// append - append an entry to the end of the
+// list
+//-------------------------------------------------
+
+void address_map::set_global_mask(offs_t mask)
+{
+// if (m_entrylist != NULL)
+// throw emu_fatalerror("AM_GLOBALMASK must be specified before any entries");
+ m_globalmask = mask;
+}
+
+
+
+//-------------------------------------------------
+// add - add a new entry of the appropriate type
+//-------------------------------------------------
+
+address_map_entry8 *address_map::add(offs_t start, offs_t end, address_map_entry8 *ptr)
+{
+ ptr = global_alloc(address_map_entry8(*this, start, end));
+ m_entrylist.append(*ptr);
+ return ptr;
+}
+
+
+address_map_entry16 *address_map::add(offs_t start, offs_t end, address_map_entry16 *ptr)
+{
+ ptr = global_alloc(address_map_entry16(*this, start, end));
+ m_entrylist.append(*ptr);
+ return ptr;
+}
+
+
+address_map_entry32 *address_map::add(offs_t start, offs_t end, address_map_entry32 *ptr)
+{
+ ptr = global_alloc(address_map_entry32(*this, start, end));
+ m_entrylist.append(*ptr);
+ return ptr;
+}
+
+
+address_map_entry64 *address_map::add(offs_t start, offs_t end, address_map_entry64 *ptr)
+{
+ ptr = global_alloc(address_map_entry64(*this, start, end));
+ m_entrylist.append(*ptr);
+ return ptr;
+}
+
+
+//-------------------------------------------------
+// uplift_submaps - propagate in the device submaps
+//-------------------------------------------------
+
+void address_map::uplift_submaps(running_machine &machine, device_t &device, endianness_t endian)
+{
+ address_map_entry *prev = 0;
+ address_map_entry *entry = m_entrylist.first();
+ while (entry)
+ {
+ if (entry->m_read.m_type == AMH_DEVICE_SUBMAP)
+ {
+ const char *tag = entry->m_read.m_tag;
+ device_t *mapdevice = machine.device(tag);
+ if (mapdevice == NULL)
+ throw emu_fatalerror("Attempted to submap a non-existent device '%s' in space %d of device '%s'\n", tag, m_spacenum, device.tag());
+ // Grab the submap
+ address_map submap(*mapdevice, entry);
+
+ // Recursively uplift it if needed
+ submap.uplift_submaps(machine, *mapdevice, endian);
+
+ // Compute the unit repartition characteristics
+ int entry_bits = entry->m_submap_bits;
+ if (!entry_bits)
+ entry_bits = m_databits;
+
+ if (submap.m_databits != entry_bits)
+ throw emu_fatalerror("AM_DEVICE wants a %d bits large address map and got a %d bits large one instead.\n", entry_bits, submap.m_databits);
+
+ int entry_bytes = entry_bits / 8;
+ int databytes = m_databits / 8;
+
+ offs_t mirror_address_mask = (databytes - 1) & ~(entry_bytes - 1);
+
+ UINT64 entry_mask = (2ULL << (entry_bits-1)) - 1;
+
+ int slot_offset[8];
+ int slot_count = 0;
+ int max_slot_count = m_databits / entry_bits;
+ int slot_xor_mask = endian == ENDIANNESS_LITTLE ? 0 : max_slot_count - 1;
+
+ UINT64 global_mask = entry->m_read.m_mask;
+ // zero means all
+ if (!global_mask)
+ global_mask = ~global_mask;
+
+ // mask consistency has already been checked in
+ // unitmask_is_appropriate, so one bit is enough
+ for (int slot=0; slot < max_slot_count; slot++)
+ if (global_mask & (1ULL << (slot * entry_bits)))
+ slot_offset[slot_count++] = (slot ^ slot_xor_mask) * entry_bits;
+
+ // Merge in all the map contents in order
+ while (submap.m_entrylist.count())
+ {
+ address_map_entry *subentry = submap.m_entrylist.detach_head();
+
+ // Remap start and end
+
+ int start_offset = subentry->m_addrstart / entry_bytes;
+ int start_slot = start_offset % slot_count;
+ subentry->m_addrstart = entry->m_addrstart + (start_offset / slot_count) * databytes;
+
+ // Drop the entry if it ends up outside the range
+ if (subentry->m_addrstart > entry->m_addrend)
+ {
+ global_free(subentry);
+ continue;
+ }
+
+ int end_offset = subentry->m_addrend / entry_bytes;
+ int end_slot = end_offset % slot_count;
+ subentry->m_addrend = entry->m_addrstart + (end_offset / slot_count) * databytes + databytes - 1;
+
+ // Clip the entry to the end of the range
+ if (subentry->m_addrend > entry->m_addrend)
+ subentry->m_addrend = entry->m_addrend;
+
+ // Detect special unhandled case (range straddling
+ // slots, requiring splitting in multiple entries and
+ // unimplemented offset-add subunit handler)
+ if (subentry->m_addrstart + databytes - 1 != subentry->m_addrend &&
+ (start_slot != 0 || end_slot != slot_count - 1))
+ throw emu_fatalerror("uplift_submaps unhandled case: range straddling slots.\n");
+
+ if (entry->m_addrmask || subentry->m_addrmask)
+ throw emu_fatalerror("uplift_submaps unhandled case: address masks.\n");
+
+ if (subentry->m_addrmirror & mirror_address_mask)
+ throw emu_fatalerror("uplift_submaps unhandled case: address mirror bit within subentry.\n");
+
+ subentry->m_addrmirror |= entry->m_addrmirror;
+
+ // Twiddle the unitmask on the data accessors that need it
+ for (int data_entry = 0; data_entry < 2; data_entry++)
+ {
+ map_handler_data &mdata = data_entry ? subentry->m_write : subentry->m_read;
+
+ if (mdata.m_type == AMH_NONE)
+ continue;
+
+ if (mdata.m_type != AMH_DEVICE_DELEGATE)
+ throw emu_fatalerror("Only normal read/write methods are accepted in device submaps.\n");
+
+ if (mdata.m_bits == 0 && entry_bits != m_databits)
+ mdata.m_bits = entry_bits;
+
+ UINT64 mask = 0;
+ if (entry_bits != m_databits)
+ {
+ UINT64 unitmask = mdata.m_mask ? mdata.m_mask : entry_mask;
+ for (int slot = start_slot; slot <= end_slot; slot++)
+ mask |= unitmask << slot_offset[slot];
+ }
+ mdata.m_mask = mask;
+ }
+
+ // Insert the entry in the map
+ m_entrylist.insert_after(*subentry, prev);
+ prev = subentry;
+ }
+
+ address_map_entry *to_delete = entry;
+ entry = entry->next();
+ m_entrylist.remove(*to_delete);
+ }
+ else
+ {
+ prev = entry;
+ entry = entry->next();
+ }
+ }
+}