From 323eb04ded6efbf03ff4355512201a0df0d443a7 Mon Sep 17 00:00:00 2001 From: AJR Date: Sat, 25 Mar 2017 17:35:45 -0400 Subject: Memory unit masking and address mirroring fixes (nw) - Fix a bug which effectively treated AM_MIRROR as AM_SELECT when applied to a single-address range mirrored into a contiguous block. The automatic expansion of zero address masks now only applies to those stemming from (default) configuration, not from optimization. (This allows the assertion in latch8_device to be reinstated.) - Fix a bug where AM_SELECT applied to narrow-width handlers with a submaximal number of subunits would select the wrong address bits or none at all. (This allows rpunch_gga_w to be WRITE8 as intended.) - Add more stringent appropriateness checking of unit masks for narrow-width handlers. --- src/devices/machine/latch8.cpp | 3 +-- src/emu/addrmap.cpp | 26 +++++++++++++++++++++++++- src/emu/emumem.cpp | 13 ++++++------- src/mame/drivers/rpunch.cpp | 2 +- src/mame/includes/rpunch.h | 2 +- src/mame/video/rpunch.cpp | 5 ++--- 6 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/devices/machine/latch8.cpp b/src/devices/machine/latch8.cpp index ca6d2c9f789..3c12ea10129 100644 --- a/src/devices/machine/latch8.cpp +++ b/src/devices/machine/latch8.cpp @@ -40,8 +40,7 @@ READ8_MEMBER( latch8_device::read ) { uint8_t res; - // FIXME: AM_MIRROR(0xff) doesn't work properly - //assert(offset == 0); + assert(offset == 0); res = m_value; if (m_has_read) diff --git a/src/emu/addrmap.cpp b/src/emu/addrmap.cpp index 5b12f139026..d6e0290e4f0 100644 --- a/src/emu/addrmap.cpp +++ b/src/emu/addrmap.cpp @@ -288,15 +288,39 @@ bool address_map_entry::unitmask_is_appropriate(u8 width, u64 unitmask, const ch 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); + // if map is narrower than 64 bits, check the mask width as well + if (m_map.m_databits < 64 && (unitmask >> m_map.m_databits) != 0) + throw emu_fatalerror("Handler %s specified a mask of %08X%08X, too wide to be used in a %d-bit address map", string, (u32)(unitmask >> 32), (u32)unitmask, m_map.m_databits); + // the mask must represent whole units of width u32 basemask = (width == 8) ? 0xff : (width == 16) ? 0xffff : 0xffffffff; u64 singlemask = basemask; + int count = 0; while (singlemask != 0) { - if ((unitmask & singlemask) != 0 && (unitmask & singlemask) != singlemask) + if ((unitmask & singlemask) == singlemask) + count++; + else if ((unitmask & singlemask) != 0) throw emu_fatalerror("Handler %s specified a mask of %08X%08X; needs to be in even chunks of %X", string, (u32)(unitmask >> 32), (u32)unitmask, basemask); singlemask <<= width; } + + // subunit count must be a power of 2 + if (count != 1 && count != 2 && count != 4 && count != 8) + throw emu_fatalerror("Handler %s specifies %d subunits with a mask of %08X%08X; needs to be a power of 2", string, count, (u32)(unitmask >> 32), (u32)unitmask); + + // the mask must be symmetrical + u64 unitmask_bh = unitmask >> 8 & 0x00ff00ff00ff00ffU; + u64 unitmask_bl = unitmask & 0x00ff00ff00ff00ffU; + u64 unitmask_wh = unitmask >> 16 & 0x0000ffff0000ffffU; + u64 unitmask_wl = unitmask & 0x0000ffff0000ffffU; + u64 unitmask_dh = unitmask >> 32 & 0x00000000ffffffffU; + u64 unitmask_dl = unitmask & 0x00000000ffffffffU; + if ((unitmask_bh != 0 && unitmask_bl != 0 && unitmask_bh != unitmask_bl) + || (unitmask_wh != 0 && unitmask_wl != 0 && unitmask_wh != unitmask_wl) + || (unitmask_dh != 0 && unitmask_dl != 0 && unitmask_dh != unitmask_dl)) + throw emu_fatalerror("Handler %s specified an asymmetrical mask of %08X%08X", string, (u32)(unitmask >> 32), (u32)unitmask); + return true; } diff --git a/src/emu/emumem.cpp b/src/emu/emumem.cpp index 723d705914a..432115400ed 100644 --- a/src/emu/emumem.cpp +++ b/src/emu/emumem.cpp @@ -1853,10 +1853,7 @@ void address_space::allocate(std::vector> &space_ inline void address_space::adjust_addresses(offs_t &start, offs_t &end, offs_t &mask, offs_t &mirror) { // adjust start/end/mask values - if (mask == 0) - mask = m_addrmask & ~mirror; - else - mask &= m_addrmask; + mask &= m_addrmask; start &= ~mirror & m_addrmask; end &= ~mirror & m_addrmask; @@ -2027,7 +2024,7 @@ void address_space::prepare_map() entry.m_bytestart = entry.m_addrstart; entry.m_byteend = entry.m_addrend; entry.m_bytemirror = entry.m_addrmirror; - entry.m_bytemask = entry.m_addrmask; + entry.m_bytemask = entry.m_addrmask ? entry.m_addrmask : ~entry.m_addrmirror; adjust_addresses(entry.m_bytestart, entry.m_byteend, entry.m_bytemask, entry.m_bytemirror); // if we have a share entry, add it to our map @@ -2857,7 +2854,7 @@ memory_bank &address_space::bank_find_or_allocate(const char *tag, offs_t addrst // adjust the addresses, handling mirrors and such offs_t bytemirror = addrmirror; offs_t bytestart = addrstart; - offs_t bytemask = 0; + offs_t bytemask = ~addrmirror; offs_t byteend = addrend; adjust_addresses(bytestart, byteend, bytemask, bytemirror); @@ -4380,6 +4377,8 @@ void handler_entry::configure_subunits(u64 handlermask, int handlerbits, int &st if ((scanmask & unitmask) != 0) count++; } + assert(count != 0); + assert(maxunits % count == 0); // fill in the shifts int cur_offset = 0; @@ -4389,7 +4388,7 @@ void handler_entry::configure_subunits(u64 handlermask, int handlerbits, int &st u32 shift = (unitnum^shift_xor_mask) * handlerbits; if (((handlermask >> shift) & unitmask) != 0) { - m_subunit_infos[m_subunits].m_bytemask = m_bytemask; + m_subunit_infos[m_subunits].m_bytemask = m_bytemask / (maxunits / count); m_subunit_infos[m_subunits].m_mask = unitmask; m_subunit_infos[m_subunits].m_offset = cur_offset++; m_subunit_infos[m_subunits].m_size = handlerbits; diff --git a/src/mame/drivers/rpunch.cpp b/src/mame/drivers/rpunch.cpp index 1a4a79320c4..81c7feeb113 100644 --- a/src/mame/drivers/rpunch.cpp +++ b/src/mame/drivers/rpunch.cpp @@ -247,7 +247,7 @@ static ADDRESS_MAP_START( main_map, AS_PROGRAM, 16, rpunch_state ) AM_RANGE(0x080000, 0x083fff) AM_RAM_WRITE(rpunch_videoram_w) AM_SHARE("videoram") AM_RANGE(0x0a0000, 0x0a07ff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette") AM_RANGE(0x0c0000, 0x0c0007) AM_WRITE(rpunch_scrollreg_w) - AM_RANGE(0x0c0008, 0x0c0009) AM_SELECT(0x20) AM_WRITE(rpunch_gga_w) + AM_RANGE(0x0c0008, 0x0c0009) AM_SELECT(0x20) AM_WRITE8(rpunch_gga_w, 0x00ff) AM_RANGE(0x0c000c, 0x0c000d) AM_WRITE(rpunch_videoreg_w) AM_RANGE(0x0c000e, 0x0c000f) AM_WRITE(sound_command_w) AM_RANGE(0x0c0010, 0x0c0013) AM_WRITE(rpunch_ins_w) diff --git a/src/mame/includes/rpunch.h b/src/mame/includes/rpunch.h index a6c08a36abf..20b88d8887e 100644 --- a/src/mame/includes/rpunch.h +++ b/src/mame/includes/rpunch.h @@ -50,7 +50,7 @@ public: DECLARE_WRITE16_MEMBER(rpunch_videoram_w); DECLARE_WRITE16_MEMBER(rpunch_videoreg_w); DECLARE_WRITE16_MEMBER(rpunch_scrollreg_w); - DECLARE_WRITE16_MEMBER(rpunch_gga_w); + DECLARE_WRITE8_MEMBER(rpunch_gga_w); DECLARE_WRITE8_MEMBER(rpunch_gga_data_w); DECLARE_WRITE16_MEMBER(rpunch_ins_w); DECLARE_CUSTOM_INPUT_MEMBER(hi_bits_r); diff --git a/src/mame/video/rpunch.cpp b/src/mame/video/rpunch.cpp index 2d24bd59733..b3a072db267 100644 --- a/src/mame/video/rpunch.cpp +++ b/src/mame/video/rpunch.cpp @@ -152,10 +152,9 @@ WRITE16_MEMBER(rpunch_state::rpunch_scrollreg_w) } -WRITE16_MEMBER(rpunch_state::rpunch_gga_w) +WRITE8_MEMBER(rpunch_state::rpunch_gga_w) { - if (ACCESSING_BITS_0_7) - m_gga->write(space, offset >> 4, data & 0xff); + m_gga->write(space, offset >> 4, data & 0xff); } -- cgit v1.2.3