diff options
author | Olivier Galibert <galibert@pobox.com> | 2021-02-16 19:19:58 +0100 |
---|---|---|
committer | Olivier Galibert <galibert@pobox.com> | 2021-02-16 21:55:12 +0100 |
commit | 225a81600ada34edbd0fd0b1a1b8704f8a000c50 (patch) | |
tree | 7061c2b4437c86f86269728f573120da3c49bc57 /src/emu | |
parent | a4489dcdb44ebf2b1654e7f6641fe17c029c1793 (diff) |
emumem: Fix regions and shares on dynamically-installed device maps
Diffstat (limited to 'src/emu')
-rw-r--r-- | src/emu/emumem.h | 5 | ||||
-rw-r--r-- | src/emu/emumem_aspace.cpp | 83 | ||||
-rw-r--r-- | src/emu/emumem_mview.cpp | 55 |
3 files changed, 105 insertions, 38 deletions
diff --git a/src/emu/emumem.h b/src/emu/emumem.h index 662db2ad77d..aeeef578500 100644 --- a/src/emu/emumem.h +++ b/src/emu/emumem.h @@ -1649,6 +1649,7 @@ public: // setup void prepare_map(); + void prepare_device_map(address_map &map); void populate_from_map(address_map *map = nullptr); 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); } @@ -1664,6 +1665,8 @@ protected: virtual std::pair<void *, void *> get_cache_info() = 0; virtual std::pair<const void *, const void *> get_specific_info() = 0; + void prepare_map_generic(address_map &map, bool allow_alloc); + // private state device_t & m_device; // reference to the owning device std::unique_ptr<address_map> m_map; // original memory map @@ -1832,6 +1835,8 @@ public: int m_id; memory_view_entry(const address_space_config &config, memory_manager &manager, memory_view &view, int id); + void prepare_map_generic(address_map &map, bool allow_alloc); + void prepare_device_map(address_map &map); void check_range_optimize_all(const char *function, int width, offs_t addrstart, offs_t addrend, offs_t addrmask, offs_t addrmirror, offs_t addrselect, u64 unitmask, int cswidth, offs_t &nstart, offs_t &nend, offs_t &nmask, offs_t &nmirror, u64 &nunitmask, int &ncswidth); void check_range_optimize_mirror(const char *function, offs_t addrstart, offs_t addrend, offs_t addrmirror, offs_t &nstart, offs_t &nend, offs_t &nmask, offs_t &nmirror); diff --git a/src/emu/emumem_aspace.cpp b/src/emu/emumem_aspace.cpp index f9029b9422f..fb1351ff453 100644 --- a/src/emu/emumem_aspace.cpp +++ b/src/emu/emumem_aspace.cpp @@ -771,34 +771,18 @@ address_space::~address_space() //------------------------------------------------- -// prepare_map - allocate the address map and -// walk through it to find implicit memory regions -// and identify shared regions +// prepare_map_generic - walk through an address +// map to find implicit memory regions and +// identify shared regions //------------------------------------------------- -void address_space::prepare_map() +void address_space::prepare_map_generic(address_map &map, bool allow_alloc) { 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) + 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); @@ -806,11 +790,13 @@ void address_space::prepare_map() // 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 + // if we can't find it, add it to our map if we're allowed to std::string fulltag = entry.m_devbase.subtag(entry.m_share); memory_share *share = m_manager.share_find(fulltag); if (!share) { + if (!allow_alloc) + fatalerror("Trying to create share '%s' too late\n", fulltag); 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()); } @@ -865,8 +851,60 @@ void address_space::prepare_map() // allocate anonymous ram when needed if (!entry.m_memory && (entry.m_read.m_type == AMH_RAM || entry.m_write.m_type == AMH_RAM)) + { + if (!allow_alloc) + fatalerror("Trying to create memory in range %X-%X too late\n", entry.m_addrstart, entry.m_addrend); + 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); + } + } +} + + +//------------------------------------------------- +// prepare_map - allocate the address map and +// walk through it to find implicit memory regions +// and identify shared regions +//------------------------------------------------- + +void address_space::prepare_map() +{ + // 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; } + + prepare_map_generic(*m_map, true); +} + +//------------------------------------------------- +// prepare_device_map - check and walk through a +// device-provided to to dynamically install to +// find implicit memory regions and identify +// shared regions +//------------------------------------------------- + +void address_space::prepare_device_map(address_map &map) +{ + // device maps are not supposed to set global parameters + if (map.m_unmapval) + fatalerror("Device maps should not set the unmap value\n"); + + if (map.m_globalmask && map.m_globalmask != m_addrmask) + fatalerror("Device maps should not set the global mask\n"); + + prepare_map_generic(map, false); } @@ -1059,6 +1097,7 @@ template<int Level, int Width, int AddrShift, endianness_t Endian> void address_ 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()); + prepare_device_map(map); populate_from_map(&map); } diff --git a/src/emu/emumem_mview.cpp b/src/emu/emumem_mview.cpp index 653a37bcf1a..4f704d969a9 100644 --- a/src/emu/emumem_mview.cpp +++ b/src/emu/emumem_mview.cpp @@ -503,20 +503,13 @@ memory_view::memory_view_entry::memory_view_entry(const address_space_config &co 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) +void memory_view::memory_view_entry::prepare_map_generic(address_map &map, bool allow_alloc) { - // 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) + 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); @@ -524,17 +517,19 @@ template<int Level, int Width, int AddrShift, endianness_t Endian> void memory_v // 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 + // if we can't find it, add it to our map if we're allowed to std::string fulltag = entry.m_devbase.subtag(entry.m_share); memory_share *share = m_manager.share_find(fulltag); if (!share) { + if (!allow_alloc) + fatalerror("Trying to create share '%s' too late\n", fulltag); 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()); + share = m_manager.share_alloc(m_view.m_device, fulltag, m_config.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()); + 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); } @@ -561,14 +556,14 @@ template<int Level, int Width, int AddrShift, endianness_t Endian> void memory_v // 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); + fatalerror("device '%s' %s space memory map entry %X-%X references nonexistent region \"%s\"\n", m_view.m_device.tag(), m_view.m_space->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()); + fatalerror("device '%s' %s space memory map entry %X-%X extends beyond region \"%s\" size (%X)\n", m_view.m_device.tag(), m_view.m_space->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); + fatalerror("device '%s' %s space memory map entry %X-%X has both .region() and .share()\n", m_view.m_device.tag(), m_view.m_space->name(), entry.m_addrstart, entry.m_addrend); } // convert any region-relative entries to their memory pointers @@ -583,8 +578,35 @@ template<int Level, int Width, int AddrShift, endianness_t Endian> void memory_v // 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()); + { + if (!allow_alloc) + fatalerror("Trying to create memory in range %X-%X too late\n", entry.m_addrstart, entry.m_addrend); + + 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); + } } +} + +void memory_view::memory_view_entry::prepare_device_map(address_map &map) +{ + // device maps are not supposed to set global parameters + if (map.m_unmapval) + fatalerror("Device maps should not set the unmap value\n"); + + if (map.m_globalmask && map.m_globalmask != m_view.m_space->addrmask()) + fatalerror("Device maps should not set the global mask\n"); + + prepare_map_generic(map, false); +} + + +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(); + + prepare_map_generic(*map, true); // Force the slot to exist, in case the map is empty r()->select_u(m_id); @@ -928,6 +950,7 @@ template<int Level, int Width, int AddrShift, endianness_t Endian> void memory_v 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()); + prepare_device_map(map); populate_from_map(&map); } |