summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/emumem_hedr.ipp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/emumem_hedr.ipp')
-rw-r--r--src/emu/emumem_hedr.ipp169
1 files changed, 115 insertions, 54 deletions
diff --git a/src/emu/emumem_hedr.ipp b/src/emu/emumem_hedr.ipp
index 1f8b296a5b6..4cd0dfa8bf5 100644
--- a/src/emu/emumem_hedr.ipp
+++ b/src/emu/emumem_hedr.ipp
@@ -37,6 +37,19 @@ template<int HighBits, int Width, int AddrShift> handler_entry_read_dispatch<Hig
template<int HighBits, int Width, int AddrShift> handler_entry_read_dispatch<HighBits, Width, AddrShift>::handler_entry_read_dispatch(address_space *space, memory_view &view) : handler_entry_read<Width, AddrShift>(space, handler_entry::F_VIEW), m_view(&view), m_a_dispatch(nullptr), m_a_ranges(nullptr), m_u_dispatch(nullptr), m_u_ranges(nullptr)
{
+ m_ranges_array.resize(1);
+ m_dispatch_array.resize(1);
+ m_a_ranges = m_ranges_array[0].data();
+ m_a_dispatch = m_dispatch_array[0].data();
+ m_u_ranges = m_ranges_array[0].data();
+ m_u_dispatch = m_dispatch_array[0].data();
+
+ auto handler = space->get_unmap_r<Width, AddrShift>();
+ handler->ref(COUNT);
+ for(unsigned int i=0; i != COUNT; i++) {
+ m_u_dispatch[i] = handler;
+ m_u_ranges[i].set(0, 0);
+ }
}
template<int HighBits, int Width, int AddrShift> handler_entry_read_dispatch<HighBits, Width, AddrShift>::handler_entry_read_dispatch(handler_entry_read_dispatch<HighBits, Width, AddrShift> *src) : handler_entry_read<Width, AddrShift>(src->m_space, handler_entry::F_DISPATCH), m_view(nullptr)
@@ -71,6 +84,11 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatc
refs.add(p);
}
+template<int HighBits, int Width, int AddrShift> offs_t handler_entry_read_dispatch<HighBits, Width, AddrShift>::dispatch_entry(offs_t address) const
+{
+ return (address & HIGHMASK) >> LowBits;
+}
+
template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatch<HighBits, Width, AddrShift>::dump_map(std::vector<memory_entry> &map) const
{
if(m_view) {
@@ -184,8 +202,10 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatc
range_cut_after(oend+1, end_entry);
if constexpr(LowBits <= Width + AddrShift) {
- if(handler->is_view())
- handler->init_handlers(start_entry, end_entry, LowBits, m_u_dispatch, m_u_ranges);
+ if(handler->is_view()) {
+ int delta = dispatch_entry(ostart) - handler->dispatch_entry(ostart);
+ handler->init_handlers(start >> LowBits, end >> LowBits, LowBits, ostart, oend, m_u_dispatch + delta, m_u_ranges + delta);
+ }
handler->ref(end_entry - start_entry);
for(offs_t ent = start_entry; ent <= end_entry; ent++) {
m_u_dispatch[ent]->unref();
@@ -195,31 +215,37 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatc
} else if(start_entry == end_entry) {
if(!(start & LOWMASK) && (end & LOWMASK) == LOWMASK) {
- if(handler->is_view())
- handler->init_handlers(start_entry, end_entry, LowBits, m_u_dispatch, m_u_ranges);
+ if(handler->is_view()) {
+ int delta = dispatch_entry(ostart) - handler->dispatch_entry(ostart);
+ handler->init_handlers(start >> LowBits, end >> LowBits, LowBits, ostart, oend, m_u_dispatch + delta, m_u_ranges + delta);
+ }
m_u_dispatch[start_entry]->unref();
m_u_dispatch[start_entry] = handler;
m_u_ranges[start_entry].set(ostart, oend);
} else
- populate_nomirror_subdispatch(start_entry, start & LOWMASK, end & LOWMASK, ostart, oend, handler);
+ populate_nomirror_subdispatch(start_entry, start, end, ostart, oend, handler);
} else {
if(start & LOWMASK) {
- populate_nomirror_subdispatch(start_entry, start & LOWMASK, LOWMASK, ostart, oend, handler);
+ populate_nomirror_subdispatch(start_entry, start, start | LOWMASK, ostart, oend, handler);
start_entry++;
+ start = (start | LOWMASK) + 1;
if(start_entry <= end_entry)
handler->ref();
}
if((end & LOWMASK) != LOWMASK) {
- populate_nomirror_subdispatch(end_entry, 0, end & LOWMASK, ostart, oend, handler);
+ populate_nomirror_subdispatch(end_entry, end & ~LOWMASK, end, ostart, oend, handler);
end_entry--;
+ end = (end & ~LOWMASK) - 1;
if(start_entry <= end_entry)
handler->ref();
}
if(start_entry <= end_entry) {
- if(handler->is_view())
- handler->init_handlers(start_entry, end_entry, LowBits, m_u_dispatch, m_u_ranges);
+ if(handler->is_view()) {
+ int delta = dispatch_entry(ostart) - handler->dispatch_entry(ostart);
+ handler->init_handlers(start >> LowBits, end >> LowBits, LowBits, ostart, oend, m_u_dispatch + delta, m_u_ranges + delta);
+ }
handler->ref(end_entry - start_entry);
for(offs_t ent = start_entry; ent <= end_entry; ent++) {
m_u_dispatch[ent]->unref();
@@ -229,6 +255,7 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatc
}
}
}
+
template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatch<HighBits, Width, AddrShift>::populate_mirror_subdispatch(offs_t entry, offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, handler_entry_read<Width, AddrShift> *handler)
{
auto cur = m_u_dispatch[entry];
@@ -242,7 +269,6 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatc
}
}
-
template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatch<HighBits, Width, AddrShift>::populate_mirror(offs_t start, offs_t end, offs_t ostart, offs_t oend, offs_t mirror, handler_entry_read<Width, AddrShift> *handler)
{
offs_t hmirror = mirror & HIGHMASK;
@@ -253,12 +279,10 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatc
offs_t add = 1 + ~hmirror;
offs_t offset = 0;
offs_t base_entry = start >> LowBits;
- start &= LOWMASK;
- end &= LOWMASK;
do {
if(offset)
handler->ref();
- populate_mirror_subdispatch(base_entry | (offset >> LowBits), start, end, ostart | offset, oend | offset, lmirror, handler);
+ populate_mirror_subdispatch(base_entry | (offset >> LowBits), start | offset, end | offset, ostart | offset, oend | offset, lmirror, handler);
offset = (offset + add) & hmirror;
} while(offset);
} else {
@@ -331,26 +355,27 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatc
} else if(start_entry == end_entry) {
if(!(start & LOWMASK) && (end & LOWMASK) == LOWMASK) {
if(m_u_dispatch[start_entry]->is_dispatch())
- m_u_dispatch[start_entry]->populate_mismatched_nomirror(0, LOWMASK, ostart, oend, descriptor, rkey, mappings);
+ m_u_dispatch[start_entry]->populate_mismatched_nomirror(start, end, ostart, oend, descriptor, rkey, mappings);
else {
mismatched_patch(descriptor, rkey, mappings, m_u_dispatch[start_entry]);
m_u_ranges[start_entry].set(ostart, oend);
}
} else
- populate_mismatched_nomirror_subdispatch(start_entry, start & LOWMASK, end & LOWMASK, ostart, oend, descriptor, rkey, mappings);
+ populate_mismatched_nomirror_subdispatch(start_entry, start, end, ostart, oend, descriptor, rkey, mappings);
} else {
if(start & LOWMASK) {
- populate_mismatched_nomirror_subdispatch(start_entry, start & LOWMASK, LOWMASK, ostart, oend, descriptor, rkey & ~handler_entry::END, mappings);
+ populate_mismatched_nomirror_subdispatch(start_entry, start, start | LOWMASK, ostart, oend, descriptor, rkey & ~handler_entry::END, mappings);
start_entry++;
rkey &= ~handler_entry::START;
}
if((end & LOWMASK) != LOWMASK) {
- populate_mismatched_nomirror_subdispatch(end_entry, 0, end & LOWMASK, ostart, oend, descriptor, rkey & ~handler_entry::START, mappings);
+ populate_mismatched_nomirror_subdispatch(end_entry, end & ~LOWMASK, end, ostart, oend, descriptor, rkey & ~handler_entry::START, mappings);
end_entry--;
rkey &= ~handler_entry::END;
}
+ offs_t base = start & ~LOWMASK;
for(offs_t ent = start_entry; ent <= end_entry; ent++) {
u8 rkey1 = rkey;
if(ent != start_entry)
@@ -358,7 +383,7 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatc
if(ent != end_entry)
rkey1 &= ~handler_entry::END;
if(m_u_dispatch[ent]->is_dispatch())
- m_u_dispatch[ent]->populate_mismatched_nomirror(0, LOWMASK, ostart, oend, descriptor, rkey1, mappings);
+ m_u_dispatch[ent]->populate_mismatched_nomirror(base | (ent << LowBits), base | (ent << LowBits) | LOWMASK, ostart, oend, descriptor, rkey1, mappings);
else {
mismatched_patch(descriptor, rkey1, mappings, m_u_dispatch[ent]);
m_u_ranges[ent].set(ostart, oend);
@@ -390,8 +415,6 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatc
offs_t add = 1 + ~hmirror;
offs_t offset = 0;
offs_t base_entry = start >> LowBits;
- start &= LOWMASK;
- end &= LOWMASK;
do {
populate_mismatched_mirror_subdispatch(base_entry | (offset >> LowBits), start, end, ostart | offset, oend | offset, lmirror, descriptor, mappings);
offset = (offset + add) & hmirror;
@@ -455,27 +478,28 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatc
} else if(start_entry == end_entry) {
if(!(start & LOWMASK) && (end & LOWMASK) == LOWMASK) {
if(m_u_dispatch[start_entry]->is_dispatch())
- m_u_dispatch[start_entry]->populate_passthrough_nomirror(0, LOWMASK, ostart, oend, handler, mappings);
+ m_u_dispatch[start_entry]->populate_passthrough_nomirror(start, end, ostart, oend, handler, mappings);
else {
passthrough_patch(handler, mappings, m_u_dispatch[start_entry]);
m_u_ranges[start_entry].intersect(ostart, oend);
}
} else
- populate_passthrough_nomirror_subdispatch(start_entry, start & LOWMASK, end & LOWMASK, ostart, oend, handler, mappings);
+ populate_passthrough_nomirror_subdispatch(start_entry, start, end, ostart, oend, handler, mappings);
} else {
if(start & LOWMASK) {
- populate_passthrough_nomirror_subdispatch(start_entry, start & LOWMASK, LOWMASK, ostart, oend, handler, mappings);
+ populate_passthrough_nomirror_subdispatch(start_entry, start, start | LOWMASK, ostart, oend, handler, mappings);
start_entry++;
}
if((end & LOWMASK) != LOWMASK) {
- populate_passthrough_nomirror_subdispatch(end_entry, 0, end & LOWMASK, ostart, oend, handler, mappings);
+ populate_passthrough_nomirror_subdispatch(end_entry, end & ~LOWMASK, end, ostart, oend, handler, mappings);
end_entry--;
}
+ offs_t base = start & ~LOWMASK;
for(offs_t ent = start_entry; ent <= end_entry; ent++) {
if(m_u_dispatch[ent]->is_dispatch())
- m_u_dispatch[ent]->populate_passthrough_nomirror(0, LOWMASK, ostart, oend, handler, mappings);
+ m_u_dispatch[ent]->populate_passthrough_nomirror(base | (ent << LowBits), base | (ent << LowBits) | LOWMASK, ostart, oend, handler, mappings);
else {
passthrough_patch(handler, mappings, m_u_dispatch[ent]);
m_u_ranges[ent].intersect(ostart, oend);
@@ -507,10 +531,8 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatc
offs_t add = 1 + ~hmirror;
offs_t offset = 0;
offs_t base_entry = start >> LowBits;
- start &= LOWMASK;
- end &= LOWMASK;
do {
- populate_passthrough_mirror_subdispatch(base_entry | (offset >> LowBits), start, end, ostart | offset, oend | offset, lmirror, handler, mappings);
+ populate_passthrough_mirror_subdispatch(base_entry | (offset >> LowBits), start | offset, end | offset, ostart | offset, oend | offset, lmirror, handler, mappings);
offset = (offset + add) & hmirror;
} while(offset);
} else {
@@ -547,42 +569,81 @@ template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatc
}
}
-template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatch<HighBits, Width, AddrShift>::init_handlers(offs_t start_entry, offs_t end_entry, u32 lowbits, handler_entry_read<Width, AddrShift> **dispatch, handler_entry::range *ranges)
+template<int HighBits, int Width, int AddrShift> void handler_entry_read_dispatch<HighBits, Width, AddrShift>::init_handlers(offs_t start_entry, offs_t end_entry, u32 lowbits, offs_t ostart, offs_t oend, handler_entry_read<Width, AddrShift> **dispatch, handler_entry::range *ranges)
{
- if(!m_view)
- fatalerror("init_handlers called on non-view handler_entry_read_dispatch.");
- if(!m_dispatch_array.empty())
- fatalerror("init_handlers called twice on handler_entry_read_dispatch.");
+ if(lowbits < LowBits) {
+ offs_t entry = start_entry >> LowBits;
+ if(entry != (end_entry >> LowBits))
+ fatalerror("Recursive init_handlers spanning multiple entries.\n");
+ entry &= BITMASK;
+ handler_entry_read_dispatch<LowBits, Width, AddrShift> *subdispatch;
+ if(m_u_dispatch[entry]->flags() & handler_entry::F_DISPATCH)
+ subdispatch = static_cast<handler_entry_read_dispatch<LowBits, Width, AddrShift> *>(m_u_dispatch[entry]);
- m_ranges_array.resize(1);
- m_dispatch_array.resize(1);
- m_a_ranges = m_ranges_array[0].data();
- m_a_dispatch = m_dispatch_array[0].data();
- m_u_ranges = m_ranges_array[0].data();
- m_u_dispatch = m_dispatch_array[0].data();
+ else if(!(m_u_dispatch[entry]->flags() & handler_entry::F_UNMAP))
+ fatalerror("Collision on multiple init_handlers calls");
- auto filter = [s = m_view->m_addrstart, e = m_view->m_addrend] (handler_entry::range r) {
- r.intersect(s, e);
- return r;
- };
+ else {
+ m_u_dispatch[entry]->unref();
+ m_u_dispatch[entry] = subdispatch = new handler_entry_read_dispatch<LowBits, Width, AddrShift>(this->m_space, m_u_ranges[entry], nullptr);
+ }
+ int delta = dispatch_entry(ostart) - subdispatch->dispatch_entry(ostart);
+ subdispatch->init_handlers(start_entry, end_entry, lowbits, ostart, oend, dispatch + delta, ranges + delta);
- if(lowbits != LowBits) {
+ } else if(lowbits != LowBits) {
u32 dt = lowbits - LowBits;
u32 ne = 1 << dt;
- for(offs_t entry = start_entry; entry <= end_entry; entry++) {
- dispatch[entry]->ref(ne);
- u32 e0 = (entry << dt) & BITMASK;
- for(offs_t e = 0; e != ne; e++) {
- m_u_dispatch[e0 | e] = dispatch[entry];
- m_u_ranges[e0 | e] = filter(ranges[entry]);
+ if(m_view) {
+ auto filter = [s = m_view->m_addrstart, e = m_view->m_addrend] (handler_entry::range r) { r.intersect(s, e); return r; };
+
+ for(offs_t entry = start_entry; entry <= end_entry; entry++) {
+ dispatch[entry]->ref(ne);
+ u32 e0 = (entry << dt) & BITMASK;
+ for(offs_t e = 0; e != ne; e++) {
+ offs_t e1 = e0 | e;
+ if(!(m_u_dispatch[e1]->flags() & handler_entry::F_UNMAP))
+ fatalerror("Collision on multiple init_handlers calls");
+ m_u_dispatch[e1]->unref();
+ m_u_dispatch[e1] = dispatch[entry];
+ m_u_ranges[e1] = filter(ranges[entry]);
+ }
+ }
+ } else {
+ for(offs_t entry = start_entry; entry <= end_entry; entry++) {
+ dispatch[entry]->ref(ne);
+ u32 e0 = (entry << dt) & BITMASK;
+ for(offs_t e = 0; e != ne; e++) {
+ offs_t e1 = e0 | e;
+ if(!(m_u_dispatch[e1]->flags() & handler_entry::F_UNMAP))
+ fatalerror("Collision on multiple init_handlers calls");
+ m_u_dispatch[e1]->unref();
+ m_u_dispatch[e1] = dispatch[entry];
+ m_u_ranges[e1] = ranges[entry];
+ }
}
}
} else {
- for(offs_t entry = start_entry; entry <= end_entry; entry++) {
- m_u_dispatch[entry & BITMASK] = dispatch[entry];
- m_u_ranges[entry & BITMASK] = filter(ranges[entry]);
- dispatch[entry]->ref();
+ if(m_view) {
+ auto filter = [s = m_view->m_addrstart, e = m_view->m_addrend] (handler_entry::range r) { r.intersect(s, e); return r; };
+
+ for(offs_t entry = start_entry & BITMASK; entry <= (end_entry & BITMASK); entry++) {
+ if(!(m_u_dispatch[entry]->flags() & handler_entry::F_UNMAP))
+ fatalerror("Collision on multiple init_handlers calls");
+ m_u_dispatch[entry]->unref();
+ m_u_dispatch[entry] = dispatch[entry];
+ m_u_ranges[entry] = filter(ranges[entry]);
+ dispatch[entry]->ref();
+ }
+ } else {
+ for(offs_t entry = start_entry & BITMASK; entry <= (end_entry & BITMASK); entry++) {
+ if(!(m_u_dispatch[entry]->flags() & handler_entry::F_UNMAP))
+ fatalerror("Collision on multiple init_handlers calls");
+ m_u_dispatch[entry]->unref();
+ m_u_dispatch[entry] = dispatch[entry];
+ m_u_ranges[entry] = ranges[entry];
+ dispatch[entry]->ref();
+ }
}
}
}