summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/divtlb.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/divtlb.cpp')
-rw-r--r--src/emu/divtlb.cpp403
1 files changed, 217 insertions, 186 deletions
diff --git a/src/emu/divtlb.cpp b/src/emu/divtlb.cpp
index 4c9a9a2f311..01be30919cb 100644
--- a/src/emu/divtlb.cpp
+++ b/src/emu/divtlb.cpp
@@ -2,309 +2,340 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- vtlb.c
+ divtlb.c
- Generic virtual TLB implementation.
+ Device generic virtual TLB interface.
***************************************************************************/
#include "emu.h"
-#include "vtlb.h"
+#include "divtlb.h"
+#include "validity.h"
-/***************************************************************************
- DEBUGGING
-***************************************************************************/
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
#define PRINTF_TLB (0)
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
+//**************************************************************************
+// DEVICE VTLB INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_vtlb_interface - constructor
+//-------------------------------------------------
-/* VTLB state */
-struct vtlb_state
+device_vtlb_interface::device_vtlb_interface(const machine_config &mconfig, device_t &device, address_spacenum space)
+ : device_interface(device, "vtlb"),
+ m_space(space),
+ m_dynamic(0),
+ m_fixed(0),
+ m_dynindex(0),
+ m_pageshift(0),
+ m_addrwidth(0)
{
- cpu_device * cpudevice; /* CPU device */
- address_spacenum space; /* address space */
- int dynamic; /* number of dynamic entries */
- int fixed; /* number of fixed entries */
- int dynindex; /* index of next dynamic entry */
- int pageshift; /* bits to shift to get page index */
- int addrwidth; /* logical address bus width */
- std::vector<offs_t> live; /* array of live entries by table index */
- std::vector<int> fixedpages; /* number of pages each fixed entry covers */
- std::vector<vtlb_entry> table; /* table of entries by address */
-};
+}
+//-------------------------------------------------
+// device_vtlb_interface - destructor
+//-------------------------------------------------
+
+device_vtlb_interface::~device_vtlb_interface()
+{
+}
+
+
+//-------------------------------------------------
+// interface_validity_check - validation for a
+// device after the configuration has been
+// constructed
+//-------------------------------------------------
+
+void device_vtlb_interface::interface_validity_check(validity_checker &valid) const
+{
+ const device_memory_interface *intf;
+ if (!device().interface(intf))
+ osd_printf_error("Device does not have memory interface\n");
+ else
+ {
+ // validate CPU information
+ const address_space_config *spaceconfig = intf->space_config(m_space);
+ if (spaceconfig == nullptr)
+ osd_printf_error("No memory address space configuration found for space %d\n", m_space);
+ else if ((1 << spaceconfig->m_page_shift) <= VTLB_FLAGS_MASK || spaceconfig->m_logaddr_width <= spaceconfig->m_page_shift)
+ osd_printf_error("Invalid page shift %d for VTLB\n", spaceconfig->m_page_shift);
+ }
+}
-/***************************************************************************
- INITIALIZATION/TEARDOWN
-***************************************************************************/
-/*-------------------------------------------------
- vtlb_alloc - allocate a new VTLB for the
- given CPU
--------------------------------------------------*/
+//-------------------------------------------------
+// interface_pre_start - work to be done prior to
+// actually starting a device
+//-------------------------------------------------
-vtlb_state *vtlb_alloc(device_t *cpu, address_spacenum space, int fixed_entries, int dynamic_entries)
+void device_vtlb_interface::interface_pre_start()
{
- vtlb_state *vtlb;
-
- /* allocate memory for the core structure */
- vtlb = auto_alloc_clear(cpu->machine(), <vtlb_state>());
-
- /* fill in CPU information */
- vtlb->cpudevice = downcast<cpu_device *>(cpu);
- vtlb->space = space;
- vtlb->dynamic = dynamic_entries;
- vtlb->fixed = fixed_entries;
- const address_space_config *spaceconfig = device_get_space_config(*cpu, space);
- assert(spaceconfig != nullptr);
- vtlb->pageshift = spaceconfig->m_page_shift;
- vtlb->addrwidth = spaceconfig->m_logaddr_width;
-
- /* validate CPU information */
- assert((1 << vtlb->pageshift) > VTLB_FLAGS_MASK);
- assert(vtlb->addrwidth > vtlb->pageshift);
-
- /* allocate the entry array */
- vtlb->live.resize(fixed_entries + dynamic_entries);
- memset(&vtlb->live[0], 0, vtlb->live.size()*sizeof(vtlb->live[0]));
- cpu->save_item(NAME(vtlb->live));
-
- /* allocate the lookup table */
- vtlb->table.resize((size_t) 1 << (vtlb->addrwidth - vtlb->pageshift));
- memset(&vtlb->table[0], 0, vtlb->table.size()*sizeof(vtlb->table[0]));
- cpu->save_item(NAME(vtlb->table));
-
- /* allocate the fixed page count array */
- if (fixed_entries > 0)
+ // fill in CPU information
+ const address_space_config *spaceconfig = device().memory().space_config(m_space);
+ m_pageshift = spaceconfig->m_page_shift;
+ m_addrwidth = spaceconfig->m_logaddr_width;
+
+ // allocate the entry array
+ m_live.resize(m_fixed + m_dynamic);
+ memset(&m_live[0], 0, m_live.size()*sizeof(m_live[0]));
+
+ // allocate the lookup table
+ m_table.resize((size_t) 1 << (m_addrwidth - m_pageshift));
+ memset(&m_table[0], 0, m_table.size()*sizeof(m_table[0]));
+
+ // allocate the fixed page count array
+ if (m_fixed > 0)
{
- vtlb->fixedpages.resize(fixed_entries);
- memset(&vtlb->fixedpages[0], 0, fixed_entries*sizeof(vtlb->fixedpages[0]));
- cpu->save_item(NAME(vtlb->fixedpages));
+ m_fixedpages.resize(m_fixed);
+ memset(&m_fixedpages[0], 0, m_fixed*sizeof(m_fixedpages[0]));
}
- return vtlb;
}
-/*-------------------------------------------------
- vtlb_free - free an allocated VTLB
--------------------------------------------------*/
+//-------------------------------------------------
+// interface_post_start - work to be done after
+// actually starting a device
+//-------------------------------------------------
-void vtlb_free(vtlb_state *vtlb)
+void device_vtlb_interface::interface_post_start()
{
- auto_free(vtlb->cpudevice->machine(), vtlb);
+ device().save_item(NAME(m_live));
+ device().save_item(NAME(m_table));
+ if (m_fixed > 0)
+ device().save_item(NAME(m_fixedpages));
}
+//-------------------------------------------------
+// interface_pre_reset - work to be done prior to
+// actually resetting a device
+//-------------------------------------------------
-/***************************************************************************
- FILLING
-***************************************************************************/
+void device_vtlb_interface::interface_pre_reset()
+{
+ vtlb_flush_dynamic();
+}
-/*-------------------------------------------------
- vtlb_fill - rcalled by the CPU core in
- response to an unmapped access
--------------------------------------------------*/
-int vtlb_fill(vtlb_state *vtlb, offs_t address, int intention)
+//**************************************************************************
+// FILLING
+//**************************************************************************
+
+//-------------------------------------------------
+// vtlb_fill - called by the CPU core in
+// response to an unmapped access
+//-------------------------------------------------
+
+int device_vtlb_interface::vtlb_fill(offs_t address, int intention)
{
- offs_t tableindex = address >> vtlb->pageshift;
- vtlb_entry entry = vtlb->table[tableindex];
+ offs_t tableindex = address >> m_pageshift;
+ vtlb_entry entry = m_table[tableindex];
offs_t taddress;
- if (PRINTF_TLB)
- printf("vtlb_fill: %08X(%X) ... ", address, intention);
+#if PRINTF_TLB
+ osd_printf_debug("vtlb_fill: %08X(%X) ... ", address, intention);
+#endif
- /* should not be called here if the entry is in the table already */
+ // should not be called here if the entry is in the table already
// assert((entry & (1 << intention)) == 0);
- /* if we have no dynamic entries, we always fail */
- if (vtlb->dynamic == 0)
+ // if we have no dynamic entries, we always fail
+ if (m_dynamic == 0)
{
- if (PRINTF_TLB)
- printf("failed: no dynamic entries\n");
+#if PRINTF_TLB
+ osd_printf_debug("failed: no dynamic entries\n");
+#endif
return FALSE;
}
- /* ask the CPU core to translate for us */
+ // ask the CPU core to translate for us
taddress = address;
- if (!vtlb->cpudevice->translate(vtlb->space, intention, taddress))
+ if (!device().memory().translate(m_space, intention, taddress))
{
- if (PRINTF_TLB)
- printf("failed: no translation\n");
+#if PRINTF_TLB
+ osd_printf_debug("failed: no translation\n");
+#endif
return FALSE;
}
- /* if this is the first successful translation for this address, allocate a new entry */
+ // if this is the first successful translation for this address, allocate a new entry
if ((entry & VTLB_FLAGS_MASK) == 0)
{
- int liveindex = vtlb->dynindex++ % vtlb->dynamic;
+ int liveindex = m_dynindex++ % m_dynamic;
- /* if an entry already exists at this index, free it */
- if (vtlb->live[liveindex] != 0)
- vtlb->table[vtlb->live[liveindex] - 1] = 0;
+ // if an entry already exists at this index, free it
+ if (m_live[liveindex] != 0)
+ m_table[m_live[liveindex] - 1] = 0;
- /* claim this new entry */
- vtlb->live[liveindex] = tableindex + 1;
+ // claim this new entry
+ m_live[liveindex] = tableindex + 1;
- /* form a new blank entry */
- entry = (taddress >> vtlb->pageshift) << vtlb->pageshift;
+ // form a new blank entry
+ entry = (taddress >> m_pageshift) << m_pageshift;
entry |= VTLB_FLAG_VALID;
- if (PRINTF_TLB)
- printf("success (%08X), new entry\n", taddress);
+#if PRINTF_TLB
+ osd_printf_debug("success (%08X), new entry\n", taddress);
+#endif
}
- /* otherwise, ensure that different intentions do not produce different addresses */
+ // otherwise, ensure that different intentions do not produce different addresses
else
{
- assert((entry >> vtlb->pageshift) == (taddress >> vtlb->pageshift));
+ assert((entry >> m_pageshift) == (taddress >> m_pageshift));
assert(entry & VTLB_FLAG_VALID);
- if (PRINTF_TLB)
- printf("success (%08X), existing entry\n", taddress);
+#if PRINTF_TLB
+ osd_printf_debug("success (%08X), existing entry\n", taddress);
+#endif
}
- /* add the intention to the list of valid intentions and store */
+ // add the intention to the list of valid intentions and store
entry |= 1 << (intention & (TRANSLATE_TYPE_MASK | TRANSLATE_USER_MASK));
- vtlb->table[tableindex] = entry;
+ m_table[tableindex] = entry;
return TRUE;
}
-/*-------------------------------------------------
- vtlb_load - load a fixed VTLB entry
--------------------------------------------------*/
+//-------------------------------------------------
+// vtlb_load - load a fixed VTLB entry
+//-------------------------------------------------
-void vtlb_load(vtlb_state *vtlb, int entrynum, int numpages, offs_t address, vtlb_entry value)
+void device_vtlb_interface::vtlb_load(int entrynum, int numpages, offs_t address, vtlb_entry value)
{
- offs_t tableindex = address >> vtlb->pageshift;
- int liveindex = vtlb->dynamic + entrynum;
+ offs_t tableindex = address >> m_pageshift;
+ int liveindex = m_dynamic + entrynum;
int pagenum;
- /* must be in range */
- assert(entrynum >= 0 && entrynum < vtlb->fixed);
+ // must be in range
+ assert(entrynum >= 0 && entrynum < m_fixed);
- if (PRINTF_TLB)
- printf("vtlb_load %d for %d pages at %08X == %08X\n", entrynum, numpages, address, value);
+#if PRINTF_TLB
+ osd_printf_debug("vtlb_load %d for %d pages at %08X == %08X\n", entrynum, numpages, address, value);
+#endif
- /* if an entry already exists at this index, free it */
- if (vtlb->live[liveindex] != 0)
+ // if an entry already exists at this index, free it
+ if (m_live[liveindex] != 0)
{
- int pagecount = vtlb->fixedpages[entrynum];
- int oldtableindex = vtlb->live[liveindex] - 1;
+ int pagecount = m_fixedpages[entrynum];
+ int oldtableindex = m_live[liveindex] - 1;
for (pagenum = 0; pagenum < pagecount; pagenum++)
- vtlb->table[oldtableindex + pagenum] = 0;
+ m_table[oldtableindex + pagenum] = 0;
}
- /* claim this new entry */
- vtlb->live[liveindex] = tableindex + 1;
+ // claim this new entry
+ m_live[liveindex] = tableindex + 1;
- /* store the raw value, making sure the "fixed" flag is set */
+ // store the raw value, making sure the "fixed" flag is set
value |= VTLB_FLAG_FIXED;
- vtlb->fixedpages[entrynum] = numpages;
+ m_fixedpages[entrynum] = numpages;
for (pagenum = 0; pagenum < numpages; pagenum++)
- vtlb->table[tableindex + pagenum] = value + (pagenum << vtlb->pageshift);
+ m_table[tableindex + pagenum] = value + (pagenum << m_pageshift);
}
-/*-------------------------------------------------
- vtlb_dynload - load a dynamic VTLB entry
--------------------------------------------------*/
+//-------------------------------------------------
+// vtlb_dynload - load a dynamic VTLB entry
+//-------------------------------------------------
-void vtlb_dynload(vtlb_state *vtlb, UINT32 index, offs_t address, vtlb_entry value)
+void device_vtlb_interface::vtlb_dynload(UINT32 index, offs_t address, vtlb_entry value)
{
- vtlb_entry entry = vtlb->table[index];
+ vtlb_entry entry = m_table[index];
- if (vtlb->dynamic == 0)
+ if (m_dynamic == 0)
{
- if (PRINTF_TLB)
- printf("failed: no dynamic entries\n");
+#if PRINTF_TLB
+ osd_printf_debug("failed: no dynamic entries\n");
+#endif
return;
}
- int liveindex = vtlb->dynindex++ % vtlb->dynamic;
- /* is entry already live? */
+ int liveindex = m_dynindex++ % m_dynamic;
+ // is entry already live?
if (!(entry & VTLB_FLAG_VALID))
{
- /* if an entry already exists at this index, free it */
- if (vtlb->live[liveindex] != 0)
- vtlb->table[vtlb->live[liveindex] - 1] = 0;
+ // if an entry already exists at this index, free it
+ if (m_live[liveindex] != 0)
+ m_table[m_live[liveindex] - 1] = 0;
- /* claim this new entry */
- vtlb->live[liveindex] = index + 1;
+ // claim this new entry
+ m_live[liveindex] = index + 1;
}
- /* form a new blank entry */
- entry = (address >> vtlb->pageshift) << vtlb->pageshift;
+ // form a new blank entry
+ entry = (address >> m_pageshift) << m_pageshift;
entry |= VTLB_FLAG_VALID | value;
- if (PRINTF_TLB)
- printf("success (%08X), new entry\n", address);
-
- vtlb->table[index] = entry;
+#if PRINTF_TLB
+ osd_printf_debug("success (%08X), new entry\n", address);
+#endif
+ m_table[index] = entry;
}
-/***************************************************************************
- FLUSHING
-***************************************************************************/
+//**************************************************************************
+// FLUSHING
+//**************************************************************************
-/*-------------------------------------------------
- vtlb_flush_dynamic - flush all knowledge
- from the dynamic part of the VTLB
--------------------------------------------------*/
+//-------------------------------------------------
+// vtlb_flush_dynamic - flush all knowledge
+// from the dynamic part of the VTLB
+//-------------------------------------------------
-void vtlb_flush_dynamic(vtlb_state *vtlb)
+void device_vtlb_interface::vtlb_flush_dynamic()
{
- int liveindex;
-
- if (PRINTF_TLB)
- printf("vtlb_flush_dynamic\n");
+#if PRINTF_TLB
+ osd_printf_debug("vtlb_flush_dynamic\n");
+#endif
- /* loop over live entries and release them from the table */
- for (liveindex = 0; liveindex < vtlb->dynamic; liveindex++)
- if (vtlb->live[liveindex] != 0)
+ // loop over live entries and release them from the table
+ for (int liveindex = 0; liveindex < m_dynamic; liveindex++)
+ if (m_live[liveindex] != 0)
{
- offs_t tableindex = vtlb->live[liveindex] - 1;
- vtlb->table[tableindex] = 0;
- vtlb->live[liveindex] = 0;
+ offs_t tableindex = m_live[liveindex] - 1;
+ m_table[tableindex] = 0;
+ m_live[liveindex] = 0;
}
}
-/*-------------------------------------------------
- vtlb_flush_address - flush knowledge of a
- particular address from the VTLB
--------------------------------------------------*/
+//-------------------------------------------------
+// vtlb_flush_address - flush knowledge of a
+// particular address from the VTLB
+//-------------------------------------------------
-void vtlb_flush_address(vtlb_state *vtlb, offs_t address)
+void device_vtlb_interface::vtlb_flush_address(offs_t address)
{
- offs_t tableindex = address >> vtlb->pageshift;
+ offs_t tableindex = address >> m_pageshift;
- if (PRINTF_TLB)
- printf("vtlb_flush_address %08X\n", address);
+#if PRINTF_TLB
+ osd_printf_debug("vtlb_flush_address %08X\n", address);
+#endif
- /* free the entry in the table; for speed, we leave the entry in the live array */
- vtlb->table[tableindex] = 0;
+ // free the entry in the table; for speed, we leave the entry in the live array
+ m_table[tableindex] = 0;
}
-/***************************************************************************
- ACCESSORS
-***************************************************************************/
+//**************************************************************************
+// ACCESSORS
+//**************************************************************************
-/*-------------------------------------------------
- vtlb_table - return a pointer to the base of
- the linear VTLB lookup table
--------------------------------------------------*/
+//-------------------------------------------------
+// vtlb_table - return a pointer to the base of
+// the linear VTLB lookup table
+//-------------------------------------------------
-const vtlb_entry *vtlb_table(vtlb_state *vtlb)
+const vtlb_entry *device_vtlb_interface::vtlb_table() const
{
- return &vtlb->table[0];
+ return &m_table[0];
}