emumem: Handlers on different subunits of the same address with different address masks are now supported. [O. Galibert]

This commit is contained in:
Olivier Galibert 2016-06-17 19:00:03 +02:00
parent a903e4c59c
commit 402f0c86ab

View File

@ -309,6 +309,12 @@ public:
m_bytemask = bytemask; m_bytemask = bytemask;
} }
// Re-expand the bytemask after subunit fun
void expand_bytemask(offs_t previous_mask)
{
m_bytemask |= previous_mask;
}
// reconfigure the subunits on a base address change // reconfigure the subunits on a base address change
void reconfigure_subunits(offs_t bytestart); void reconfigure_subunits(offs_t bytestart);
@ -329,6 +335,7 @@ protected:
// Subunit description information // Subunit description information
struct subunit_info struct subunit_info
{ {
offs_t m_bytemask; // bytemask for this subunit
UINT32 m_mask; // mask (ff, ffff or ffffffff) UINT32 m_mask; // mask (ff, ffff or ffffffff)
INT32 m_offset; // offset to add to the address INT32 m_offset; // offset to add to the address
UINT32 m_multiplier; // multiplier to the pre-split address UINT32 m_multiplier; // multiplier to the pre-split address
@ -3090,7 +3097,7 @@ void address_table::setup_range_masked(offs_t addrstart, offs_t addrend, offs_t
m_space.m_direct->force_update(entry); m_space.m_direct->force_update(entry);
} }
// Ranges in range_partial must duplicated then partially changed // Ranges in range_partial must be duplicated then partially changed
if (!range_partial.empty()) if (!range_partial.empty())
{ {
for (std::map<UINT16, std::list<subrange> >::const_iterator i = range_partial.begin(); i != range_partial.end(); ++i) for (std::map<UINT16, std::list<subrange> >::const_iterator i = range_partial.begin(); i != range_partial.end(); ++i)
@ -3106,10 +3113,7 @@ void address_table::setup_range_masked(offs_t addrstart, offs_t addrend, offs_t
// Get the original handler // Get the original handler
handler_entry *base_entry = &handler(i->first); handler_entry *base_entry = &handler(i->first);
// Verify it is compatible enough with ours given what we can offs_t previous_bytemask = base_entry->bytemask();
// support.
if (base_entry->bytemask() != bytemask)
throw emu_fatalerror("Handlers on different subunits of the same address with different address masks are not supported.");
// Grab a new handler and copy it there // Grab a new handler and copy it there
UINT16 entry = get_free_handler(); UINT16 entry = get_free_handler();
@ -3126,6 +3130,8 @@ void address_table::setup_range_masked(offs_t addrstart, offs_t addrend, offs_t
for (const auto & elem : i->second) for (const auto & elem : i->second)
populate_range(elem.start, elem.end, entry); populate_range(elem.start, elem.end, entry);
curentry.expand_bytemask(previous_bytemask);
// Add it in the "to be setup" list // Add it in the "to be setup" list
entries.push_back(entry); entries.push_back(entry);
@ -4374,6 +4380,7 @@ void handler_entry::configure_subunits(UINT64 handlermask, int handlerbits, int
UINT32 shift = (unitnum^shift_xor_mask) * handlerbits; UINT32 shift = (unitnum^shift_xor_mask) * handlerbits;
if (((handlermask >> shift) & unitmask) != 0) if (((handlermask >> shift) & unitmask) != 0)
{ {
m_subunit_infos[m_subunits].m_bytemask = m_bytemask;
m_subunit_infos[m_subunits].m_mask = unitmask; m_subunit_infos[m_subunits].m_mask = unitmask;
m_subunit_infos[m_subunits].m_offset = cur_offset++; m_subunit_infos[m_subunits].m_offset = cur_offset++;
m_subunit_infos[m_subunits].m_size = handlerbits; m_subunit_infos[m_subunits].m_size = handlerbits;
@ -4462,11 +4469,12 @@ void handler_entry::description(char *buffer) const
{ {
if (i) if (i)
*buffer++ = ' '; *buffer++ = ' ';
buffer += sprintf (buffer, "%d:%d:%x:%d:%s", buffer += sprintf (buffer, "%d:%d:%x:%d:%x:%s",
m_subunit_infos[i].m_size, m_subunit_infos[i].m_size,
m_subunit_infos[i].m_shift, m_subunit_infos[i].m_shift,
m_subunit_infos[i].m_offset, m_subunit_infos[i].m_offset,
m_subunit_infos[i].m_multiplier, m_subunit_infos[i].m_multiplier,
m_subunit_infos[i].m_bytemask,
subunit_name(i)); subunit_name(i));
} }
} }
@ -4713,7 +4721,7 @@ UINT16 handler_entry_read::read_stub_16(address_space &space, offs_t offset, UIN
{ {
offs_t aoffset = offset * si.m_multiplier + si.m_offset; offs_t aoffset = offset * si.m_multiplier + si.m_offset;
UINT8 val; UINT8 val;
val = m_subread[index].r8(space, aoffset, submask); val = m_subread[index].r8(space, aoffset & si.m_bytemask, submask);
result |= val << si.m_shift; result |= val << si.m_shift;
} }
} }
@ -4740,10 +4748,10 @@ UINT32 handler_entry_read::read_stub_32(address_space &space, offs_t offset, UIN
switch (si.m_size) switch (si.m_size)
{ {
case 8: case 8:
val = m_subread[index].r8(space, aoffset, submask); val = m_subread[index].r8(space, aoffset & si.m_bytemask, submask);
break; break;
case 16: case 16:
val = m_subread[index].r16(space, aoffset, submask); val = m_subread[index].r16(space, aoffset & si.m_bytemask, submask);
break; break;
} }
result |= val << si.m_shift; result |= val << si.m_shift;
@ -4772,13 +4780,13 @@ UINT64 handler_entry_read::read_stub_64(address_space &space, offs_t offset, UIN
switch (si.m_size) switch (si.m_size)
{ {
case 8: case 8:
val = m_subread[index].r8(space, aoffset, submask); val = m_subread[index].r8(space, aoffset & si.m_bytemask, submask);
break; break;
case 16: case 16:
val = m_subread[index].r16(space, aoffset, submask); val = m_subread[index].r16(space, aoffset & si.m_bytemask, submask);
break; break;
case 32: case 32:
val = m_subread[index].r32(space, aoffset, submask); val = m_subread[index].r32(space, aoffset & si.m_bytemask, submask);
break; break;
} }
result |= UINT64(val) << si.m_shift; result |= UINT64(val) << si.m_shift;
@ -5006,7 +5014,7 @@ void handler_entry_write::write_stub_16(address_space &space, offs_t offset, UIN
{ {
offs_t aoffset = offset * si.m_multiplier + si.m_offset; offs_t aoffset = offset * si.m_multiplier + si.m_offset;
UINT8 adata = data >> si.m_shift; UINT8 adata = data >> si.m_shift;
m_subwrite[index].w8(space, aoffset, adata, submask); m_subwrite[index].w8(space, aoffset & si.m_bytemask, adata, submask);
} }
} }
} }
@ -5030,10 +5038,10 @@ void handler_entry_write::write_stub_32(address_space &space, offs_t offset, UIN
switch (si.m_size) switch (si.m_size)
{ {
case 8: case 8:
m_subwrite[index].w8(space, aoffset, adata, submask); m_subwrite[index].w8(space, aoffset & si.m_bytemask, adata, submask);
break; break;
case 16: case 16:
m_subwrite[index].w16(space, aoffset, adata, submask); m_subwrite[index].w16(space, aoffset & si.m_bytemask, adata, submask);
break; break;
} }
} }
@ -5059,13 +5067,13 @@ void handler_entry_write::write_stub_64(address_space &space, offs_t offset, UIN
switch (si.m_size) switch (si.m_size)
{ {
case 8: case 8:
m_subwrite[index].w8(space, aoffset, adata, submask); m_subwrite[index].w8(space, aoffset & si.m_bytemask, adata, submask);
break; break;
case 16: case 16:
m_subwrite[index].w16(space, aoffset, adata, submask); m_subwrite[index].w16(space, aoffset & si.m_bytemask, adata, submask);
break; break;
case 32: case 32:
m_subwrite[index].w32(space, aoffset, adata, submask); m_subwrite[index].w32(space, aoffset & si.m_bytemask, adata, submask);
break; break;
} }
} }