summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
diff options
context:
space:
mode:
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
commit225a81600ada34edbd0fd0b1a1b8704f8a000c50 (patch)
tree7061c2b4437c86f86269728f573120da3c49bc57 /src/emu
parenta4489dcdb44ebf2b1654e7f6641fe17c029c1793 (diff)
emumem: Fix regions and shares on dynamically-installed device maps
Diffstat (limited to 'src/emu')
-rw-r--r--src/emu/emumem.h5
-rw-r--r--src/emu/emumem_aspace.cpp83
-rw-r--r--src/emu/emumem_mview.cpp55
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);
}