Make submaps work with address-shifted spaces (nw)

Note that submaps are now assumed to use an address shift of 0. It is possible, though unlikely, for this to cause some breakage.
This commit is contained in:
AJR 2019-06-09 19:14:19 -04:00
parent a610524c5f
commit c84a6b2530
3 changed files with 43 additions and 10 deletions

View File

@ -835,7 +835,7 @@ address_map_entry &address_map::operator()(offs_t start, offs_t end)
// import_submaps - propagate in the device submaps
//-------------------------------------------------
void address_map::import_submaps(running_machine &machine, device_t &owner, int data_width, endianness_t endian)
void address_map::import_submaps(running_machine &machine, device_t &owner, int data_width, endianness_t endian, int addr_shift)
{
address_map_entry *prev = nullptr;
address_map_entry *entry = m_entrylist.first();
@ -857,7 +857,7 @@ void address_map::import_submaps(running_machine &machine, device_t &owner, int
address_map submap(*mapdevice, entry);
// Recursively import if needed
submap.import_submaps(machine, *mapdevice, data_width, endian);
submap.import_submaps(machine, *mapdevice, data_width, endian, addr_shift);
offs_t max_end = entry->m_addrend - entry->m_addrstart;
@ -867,6 +867,24 @@ void address_map::import_submaps(running_machine &machine, device_t &owner, int
while (submap.m_entrylist.count())
{
address_map_entry *subentry = submap.m_entrylist.detach_head();
if (addr_shift > 0)
{
subentry->m_addrstart <<= addr_shift;
subentry->m_addrend = ((subentry->m_addrend + 1) << addr_shift) - 1;
subentry->m_addrmirror <<= addr_shift;
subentry->m_addrmask <<= addr_shift;
subentry->m_addrselect <<= addr_shift;
}
else if (addr_shift < 0)
{
subentry->m_addrstart >>= -addr_shift;
subentry->m_addrend >>= -addr_shift;
subentry->m_addrmirror >>= -addr_shift;
subentry->m_addrmask >>= -addr_shift;
subentry->m_addrselect >>= -addr_shift;
}
if (subentry->m_addrend > max_end)
subentry->m_addrend = max_end;
@ -895,6 +913,10 @@ void address_map::import_submaps(running_machine &machine, device_t &owner, int
if ((entry->m_mask >> i) & 1)
ratio ++;
ratio = data_width / ratio;
if (addr_shift > 0)
ratio <<= addr_shift;
else if (addr_shift < 0)
max_end = ((max_end + 1) << -addr_shift) - 1;
max_end = (max_end + 1) / ratio - 1;
// Then merge the contents taking the ratio into account
@ -933,11 +955,22 @@ void address_map::import_submaps(running_machine &machine, device_t &owner, int
if (subentry->m_addrend > max_end)
subentry->m_addrend = max_end;
subentry->m_addrstart = subentry->m_addrstart * ratio + entry->m_addrstart;
subentry->m_addrend = (subentry->m_addrend + 1) * ratio - 1 + entry->m_addrstart;
subentry->m_addrmirror = (subentry->m_addrmirror / ratio) | entry->m_addrmirror;
subentry->m_addrmask = (subentry->m_addrmask / ratio) | entry->m_addrmask;
subentry->m_addrselect = (subentry->m_addrselect / ratio) | entry->m_addrselect;
if (addr_shift < 0)
{
subentry->m_addrstart = ((subentry->m_addrstart * ratio) >> -addr_shift) + entry->m_addrstart;
subentry->m_addrend = (((subentry->m_addrend + 1) * ratio - 1) >> -addr_shift) + entry->m_addrstart;
subentry->m_addrmirror = ((subentry->m_addrmirror / ratio) << -addr_shift) | entry->m_addrmirror;
subentry->m_addrmask = ((subentry->m_addrmask / ratio) << -addr_shift) | entry->m_addrmask;
subentry->m_addrselect = ((subentry->m_addrselect / ratio) << -addr_shift) | entry->m_addrselect;
}
else
{
subentry->m_addrstart = subentry->m_addrstart * ratio + entry->m_addrstart;
subentry->m_addrend = (subentry->m_addrend + 1) * ratio - 1 + entry->m_addrstart;
subentry->m_addrmirror = (subentry->m_addrmirror / ratio) | entry->m_addrmirror;
subentry->m_addrmask = (subentry->m_addrmask / ratio) | entry->m_addrmask;
subentry->m_addrselect = (subentry->m_addrselect / ratio) | entry->m_addrselect;
}
if (subentry->m_addrstart > entry->m_addrend)
{

View File

@ -480,7 +480,7 @@ public:
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);
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;
};

View File

@ -1235,7 +1235,7 @@ void address_space::prepare_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());
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;
@ -1859,7 +1859,7 @@ template<int Width, int AddrShift, endianness_t Endian> void address_space_speci
{
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());
map.import_submaps(m_manager.machine(), device, data_width(), endianness(), addr_shift());
populate_from_map(&map);
}