summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--docs/source/commandline/commandline-all.rst27
-rw-r--r--docs/source/commandline/commandline-index.rst1
-rw-r--r--src/devices/cpu/drcbearm64.cpp2
-rw-r--r--src/devices/cpu/drcbeut.cpp22
-rw-r--r--src/devices/cpu/drcbex64.cpp4
-rw-r--r--src/devices/cpu/drccache.cpp196
-rw-r--r--src/devices/cpu/drccache.h127
-rw-r--r--src/devices/cpu/drcuml.cpp2
-rw-r--r--src/devices/cpu/drcuml.h2
-rw-r--r--src/devices/cpu/dsp16/dsp16.cpp9
-rw-r--r--src/devices/cpu/dsp16/dsp16.h3
-rw-r--r--src/devices/cpu/dsp16/dsp16core.h7
-rw-r--r--src/devices/cpu/dspp/dspp.cpp23
-rw-r--r--src/devices/cpu/dspp/dspp.h7
-rw-r--r--src/devices/cpu/dspp/dsppdrc.cpp114
-rw-r--r--src/devices/cpu/e132xs/e132xs.cpp124
-rw-r--r--src/devices/cpu/e132xs/e132xs.h2
-rw-r--r--src/devices/cpu/mb86235/mb86235.cpp8
-rw-r--r--src/devices/cpu/mb86235/mb86235.h2
-rw-r--r--src/devices/cpu/mips/mips3.cpp13
-rw-r--r--src/devices/cpu/mips/mips3.h37
-rw-r--r--src/devices/cpu/mips/mips3com.cpp121
-rw-r--r--src/devices/cpu/mips/mips3com.h26
-rw-r--r--src/devices/cpu/powerpc/ppc.h3
-rw-r--r--src/devices/cpu/powerpc/ppccom.cpp7
-rw-r--r--src/devices/cpu/sh/sh.cpp27
-rw-r--r--src/devices/cpu/sh/sh.h20
-rw-r--r--src/devices/cpu/sharc/sharc.cpp8
-rw-r--r--src/devices/cpu/uml.cpp2
-rw-r--r--src/devices/cpu/unsp/unsp.cpp97
-rw-r--r--src/devices/cpu/unsp/unsp.h65
-rw-r--r--src/devices/sound/swp30.cpp4
-rw-r--r--src/emu/emuopts.cpp3
-rw-r--r--src/emu/emuopts.h2
34 files changed, 689 insertions, 428 deletions
diff --git a/docs/source/commandline/commandline-all.rst b/docs/source/commandline/commandline-all.rst
index ac3220aeb16..208cc9810d0 100644
--- a/docs/source/commandline/commandline-all.rst
+++ b/docs/source/commandline/commandline-all.rst
@@ -3923,7 +3923,9 @@ Core Misc Options
**-[no]drc**
- Enable DRC (dynamic recompiler) CPU core if available for maximum speed.
+ Enable DRC (dynamic recompiler) CPU cores if available. Turn this option
+ off to use interpreter CPU cores if available. This option does not affect
+ CPUs that only support one core type.
The default is ON (**-drc**).
@@ -3932,18 +3934,37 @@ Core Misc Options
mame ironfort -nodrc
+.. _mame-commandline-drcrwx:
+
+**\-[no]drc_rwx**
+
+ Allow DRC CPU cores to use memory that is simultaneously writable and
+ executable if supported. Turning this option off may decrease performance.
+ This option only affects DRC CPU cores, and has no effect in configurations
+ that do not allow memory to be simultaneously writable and executable (e.g.
+ recent versions of macOS and NetBSD).
+
+ The default is ON (**-drc_rwx**).
+
+ Example:
+ .. code-block:: bash
+
+ mame fiveside -nodrc_rwx
+
.. _mame-commandline-drcusec:
**\-[no]drc_use_c**
- Force DRC to use the C code backend.
+ Force DRC CPU cores to use the portable C code back-end when a native
+ back-end is available. This option only affects DRC CPU cores, and has no
+ effect if a native DRC back-end is not available.
The default is OFF (**-nodrc_use_c**).
Example:
.. code-block:: bash
- mame ironfort -drc_use_c
+ mame vamphalf -drc_use_c
.. _mame-commandline-drcloguml:
diff --git a/docs/source/commandline/commandline-index.rst b/docs/source/commandline/commandline-index.rst
index 8d3ee9f516a..07808ee4445 100644
--- a/docs/source/commandline/commandline-index.rst
+++ b/docs/source/commandline/commandline-index.rst
@@ -318,6 +318,7 @@ Core Misc Options
~~~~~~~~~~~~~~~~~
| :ref:`[no]drc <mame-commandline-drc>`
+| :ref:`[no]drc_rwx <mame-commandline-drcrwx>`
| :ref:`[no]drc_use_c <mame-commandline-drcusec>`
| :ref:`[no]drc_log_uml <mame-commandline-drcloguml>`
| :ref:`[no]drc_log_native <mame-commandline-drclognative>`
diff --git a/src/devices/cpu/drcbearm64.cpp b/src/devices/cpu/drcbearm64.cpp
index 7795a73a12c..0958614f19a 100644
--- a/src/devices/cpu/drcbearm64.cpp
+++ b/src/devices/cpu/drcbearm64.cpp
@@ -1549,7 +1549,7 @@ drcbe_arm64::drcbe_arm64(drcuml_state &drcuml, device_t &device, drc_cache &cach
, m_nocode(nullptr)
, m_endofblock(nullptr)
, m_baseptr(cache.near() + 0x100)
- , m_near(*(near_state *)cache.alloc_near(sizeof(m_near)))
+ , m_near(*cache.alloc_near<near_state>())
{
// create the log
if (device.machine().options().drc_log_native())
diff --git a/src/devices/cpu/drcbeut.cpp b/src/devices/cpu/drcbeut.cpp
index 23526e1a8aa..66513c9dc29 100644
--- a/src/devices/cpu/drcbeut.cpp
+++ b/src/devices/cpu/drcbeut.cpp
@@ -43,7 +43,7 @@ drc_hash_table::drc_hash_table(drc_cache &cache, uint32_t modes, uint8_t addrbit
m_l2shift(ignorebits),
m_l1mask((1 << m_l1bits) - 1),
m_l2mask((1 << m_l2bits) - 1),
- m_base(reinterpret_cast<drccodeptr ***>(cache.alloc(modes * sizeof(**m_base)))),
+ m_base(reinterpret_cast<drccodeptr ***>(cache.alloc(modes * sizeof(**m_base), std::align_val_t(alignof(drccodeptr *))))),
m_emptyl1(nullptr),
m_emptyl2(nullptr)
{
@@ -59,8 +59,8 @@ drc_hash_table::drc_hash_table(drc_cache &cache, uint32_t modes, uint8_t addrbit
bool drc_hash_table::reset()
{
// allocate an empty l2 hash table
- m_emptyl2 = (drccodeptr *)m_cache.alloc_temporary(sizeof(drccodeptr) << m_l2bits);
- if (m_emptyl2 == nullptr)
+ m_emptyl2 = reinterpret_cast<drccodeptr *>(m_cache.alloc_temporary(sizeof(drccodeptr) << m_l2bits, std::align_val_t(alignof(drccodeptr))));
+ if (!m_emptyl2)
return false;
// populate it with pointers to the recompile_exit code
@@ -68,8 +68,8 @@ bool drc_hash_table::reset()
m_emptyl2[entry] = m_nocodeptr;
// allocate an empty l1 hash table
- m_emptyl1 = (drccodeptr **)m_cache.alloc_temporary(sizeof(drccodeptr *) << m_l1bits);
- if (m_emptyl1 == nullptr)
+ m_emptyl1 = reinterpret_cast<drccodeptr **>(m_cache.alloc_temporary(sizeof(drccodeptr *) << m_l1bits, std::align_val_t(alignof(drccodeptr *))));
+ if (!m_emptyl1)
return false;
// populate it with pointers to the empty l2 table
@@ -166,10 +166,10 @@ bool drc_hash_table::set_codeptr(uint32_t mode, uint32_t pc, drccodeptr code)
assert(mode < m_modes);
if (m_base[mode] == m_emptyl1)
{
- drccodeptr **newtable = (drccodeptr **)m_cache.alloc_temporary(sizeof(drccodeptr *) << m_l1bits);
- if (newtable == nullptr)
+ drccodeptr **newtable = (drccodeptr **)m_cache.alloc_temporary(sizeof(drccodeptr *) << m_l1bits, std::align_val_t(alignof(drccodeptr *)));
+ if (!newtable)
return false;
- memcpy(newtable, m_emptyl1, sizeof(drccodeptr *) << m_l1bits);
+ std::copy_n(m_emptyl1, 1U << m_l1bits, newtable);
m_base[mode] = newtable;
}
@@ -177,10 +177,10 @@ bool drc_hash_table::set_codeptr(uint32_t mode, uint32_t pc, drccodeptr code)
uint32_t l1 = (pc >> m_l1shift) & m_l1mask;
if (m_base[mode][l1] == m_emptyl2)
{
- drccodeptr *newtable = (drccodeptr *)m_cache.alloc_temporary(sizeof(drccodeptr) << m_l2bits);
- if (newtable == nullptr)
+ drccodeptr *newtable = (drccodeptr *)m_cache.alloc_temporary(sizeof(drccodeptr) << m_l2bits, std::align_val_t(alignof(drccodeptr)));
+ if (!newtable)
return false;
- memcpy(newtable, m_emptyl2, sizeof(drccodeptr) << m_l2bits);
+ std::copy_n(m_emptyl2, 1U << m_l2bits, newtable);
m_base[mode][l1] = newtable;
}
diff --git a/src/devices/cpu/drcbex64.cpp b/src/devices/cpu/drcbex64.cpp
index b916919aa91..953da55b247 100644
--- a/src/devices/cpu/drcbex64.cpp
+++ b/src/devices/cpu/drcbex64.cpp
@@ -1014,14 +1014,14 @@ drcbe_x64::drcbe_x64(drcuml_state &drcuml, device_t &device, drc_cache &cache, u
, m_log_asmjit(nullptr)
, m_lzcnt(false)
, m_bmi(false)
- , m_absmask32((u32 *)cache.alloc_near(16*2 + 15))
+ , m_absmask32((u32 *)cache.alloc_near(16*2 + 15, std::align_val_t(alignof(u32))))
, m_absmask64(nullptr)
, m_rbpvalue(cache.near() + 0x80)
, m_entry(nullptr)
, m_exit(nullptr)
, m_nocode(nullptr)
, m_endofblock(nullptr)
- , m_near(*(near_state *)cache.alloc_near(sizeof(m_near)))
+ , m_near(*cache.alloc_near<near_state>())
{
// check for optional CPU features
const auto &x86_features = CpuInfo::host().features().x86();
diff --git a/src/devices/cpu/drccache.cpp b/src/devices/cpu/drccache.cpp
index edee380a61f..6b68af8b6b6 100644
--- a/src/devices/cpu/drccache.cpp
+++ b/src/devices/cpu/drccache.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- drccache.c
+ drccache.cpp
Universal dynamic recompiler cache management.
@@ -12,16 +12,19 @@
#include "drccache.h"
#include <algorithm>
+#include <numeric>
namespace {
-template <typename T, typename U> constexpr T *ALIGN_PTR_UP(T *p, U align)
+template <typename T, typename U>
+constexpr T *ALIGN_PTR_UP(T *p, U align)
{
return reinterpret_cast<T *>((uintptr_t(p) + (align - 1)) & ~uintptr_t(align - 1));
}
-template <typename T, typename U> constexpr T *ALIGN_PTR_DOWN(T *p, U align)
+template <typename T, typename U>
+constexpr T *ALIGN_PTR_DOWN(T *p, U align)
{
return reinterpret_cast<T *>(uintptr_t(p) & ~uintptr_t(align - 1));
}
@@ -35,40 +38,111 @@ template <typename T, typename U> constexpr T *ALIGN_PTR_DOWN(T *p, U align)
//**************************************************************************
//-------------------------------------------------
-// drc_cache - constructor
+// construction/destruction
//-------------------------------------------------
-drc_cache::drc_cache(size_t bytes) :
- m_cache({ NEAR_CACHE_SIZE, bytes - NEAR_CACHE_SIZE }, osd::virtual_memory_allocation::READ_WRITE_EXECUTE),
- m_near(reinterpret_cast<drccodeptr>(m_cache.get())),
- m_neartop(m_near),
- m_base(ALIGN_PTR_UP(m_near + NEAR_CACHE_SIZE, m_cache.page_size())),
- m_top(m_base),
- m_limit(m_near + m_cache.size()),
- m_end(m_limit),
- m_codegen(nullptr),
- m_size(m_cache.size()),
- m_executable(false),
- m_rwx(false)
+drc_cache::drc_cache(std::size_t bytes) noexcept
+ : m_near(nullptr)
+ , m_neartop(nullptr)
+ , m_base(nullptr)
+ , m_top(nullptr)
+ , m_limit(nullptr)
+ , m_end(nullptr)
+ , m_codegen(nullptr)
+ , m_size(bytes)
+ , m_executable(false)
+ , m_rwx(false)
+ , m_max_temporary(0)
+ , m_flush_count(0)
+#if defined(MAME_DEBUG)
+ , m_near_allocated(0)
+ , m_near_oversize(0)
+ , m_near_freed(0)
+ , m_near_reused(0)
+ , m_cache_allocated(0)
+ , m_cache_oversize(0)
+ , m_cache_freed(0)
+ , m_cache_reused(0)
+#endif
{
- // alignment and page size must be powers of two, cache must be page-aligned
- assert(!(CACHE_ALIGNMENT & (CACHE_ALIGNMENT - 1)));
- assert(!(m_cache.page_size() & (m_cache.page_size() - 1)));
- assert(!(uintptr_t(m_near) & (m_cache.page_size() - 1)));
- assert(m_cache.page_size() >= CACHE_ALIGNMENT);
+ // alignment must be power of two
+ static_assert(!(CACHE_ALIGNMENT & (CACHE_ALIGNMENT - 1)));
std::fill(std::begin(m_free), std::end(m_free), nullptr);
std::fill(std::begin(m_nearfree), std::end(m_nearfree), nullptr);
+}
+
+drc_cache::~drc_cache()
+{
+ if (m_cache)
+ {
+ try
+ {
+ osd_printf_verbose("drc_cache: Statistics:\nFlush count %u, near cache use %u, permanent cache use %u/%u, maximum temporary cache use %u\n",
+ m_flush_count,
+ m_neartop - m_near,
+ m_size - (m_end - m_near),
+ m_size - (m_limit - m_near),
+ m_max_temporary);
+#if defined(MAME_DEBUG)
+ osd_printf_verbose("Near cache allocated %u (%u oversize), freed %u reused %u\nPermanent cache allocated %u (%u oversize), freed %u reused %u\n",
+ m_near_allocated,
+ m_near_oversize,
+ m_near_freed,
+ m_near_reused,
+ m_cache_allocated,
+ m_cache_oversize,
+ m_cache_freed,
+ m_cache_reused);
+#endif
+ }
+ catch (...)
+ {
+ // ignore exceptions dumping statistics
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// setup
+//-------------------------------------------------
+
+void drc_cache::set_size(std::size_t bytes)
+{
+ if (m_cache)
+ throw emu_fatalerror("drc_cache: Cannot reconfigure size after allocating");
+
+ if (bytes < NEAR_CACHE_SIZE)
+ throw emu_fatalerror("drc_cache: Requested size %u is smaller than near cache size %u", bytes, NEAR_CACHE_SIZE);
- if (!m_cache)
+ m_size = bytes;
+}
+
+void drc_cache::allocate_cache(bool rwx)
+{
+ if (m_cache)
+ throw emu_fatalerror("drc_cache: Cannot reallocate cache");
+
+ m_cache.emplace({ NEAR_CACHE_SIZE, m_size - NEAR_CACHE_SIZE }, osd::virtual_memory_allocation::READ_WRITE_EXECUTE);
+ m_near = reinterpret_cast<drccodeptr>(m_cache->get());
+ m_neartop = m_near;
+ m_base = ALIGN_PTR_UP(m_near + NEAR_CACHE_SIZE, m_cache->page_size());
+ m_top = m_base;
+ m_limit = m_near + m_cache->size();
+ m_end = m_limit;
+ m_size = m_cache->size();
+ m_rwx = false;
+
+ if (!*m_cache)
{
throw emu_fatalerror("drc_cache: Error allocating virtual memory");
}
- else if (!m_cache.set_access(0, m_size, osd::virtual_memory_allocation::READ_WRITE))
+ else if (!m_cache->set_access(0, m_size, osd::virtual_memory_allocation::READ_WRITE))
{
throw emu_fatalerror("drc_cache: Error marking cache read/write");
}
- else if (m_cache.set_access(m_base - m_near, m_end - m_base, osd::virtual_memory_allocation::READ_WRITE_EXECUTE))
+ else if (rwx && m_cache->set_access(m_base - m_near, m_end - m_base, osd::virtual_memory_allocation::READ_WRITE_EXECUTE))
{
osd_printf_verbose("drc_cache: RWX pages supported\n");
m_rwx = true;
@@ -78,19 +152,14 @@ drc_cache::drc_cache(size_t bytes) :
osd_printf_verbose("drc_cache: Using W^X mode\n");
m_rwx = false;
}
-}
-
-
-//-------------------------------------------------
-// ~drc_cache - destructor
-//-------------------------------------------------
-drc_cache::~drc_cache()
-{
+ // page size must be power of two, cache must be page-aligned
+ assert(!(m_cache->page_size() & (m_cache->page_size() - 1)));
+ assert(!(uintptr_t(m_near) & (m_cache->page_size() - 1)));
+ assert(m_cache->page_size() >= CACHE_ALIGNMENT);
}
-
//-------------------------------------------------
// flush - flush the cache contents
//-------------------------------------------------
@@ -101,6 +170,8 @@ void drc_cache::flush()
assert(!m_codegen);
// just reset the top back to the base and re-seed
+ m_max_temporary = std::max<std::size_t>(m_max_temporary, m_top - m_base);
+ ++m_flush_count;
m_top = m_base;
codegen_init();
}
@@ -111,9 +182,13 @@ void drc_cache::flush()
// cache
//-------------------------------------------------
-void *drc_cache::alloc(size_t bytes)
+void *drc_cache::alloc(std::size_t bytes, std::align_val_t align) noexcept
{
- assert(bytes > 0);
+ assert(bytes);
+ assert(std::size_t(align));
+
+ if (UNEXPECTED((std::size_t(align) > CACHE_ALIGNMENT) || (CACHE_ALIGNMENT % std::size_t(align))))
+ osd_printf_error("drc_cache: Requested alignment %u not satisfied by cache alignment %u\n", std::size_t(align), CACHE_ALIGNMENT);
// pick first from the free list
if (bytes < MAX_PERMANENT_ALLOC)
@@ -122,6 +197,10 @@ void *drc_cache::alloc(size_t bytes)
free_link *const link = *linkptr;
if (link)
{
+#if defined(MAME_DEBUG)
+ ++m_cache_allocated;
+ ++m_cache_reused;
+#endif
*linkptr = link->m_next;
return link;
}
@@ -129,11 +208,16 @@ void *drc_cache::alloc(size_t bytes)
// if no space, we just fail
drccodeptr const ptr = ALIGN_PTR_DOWN(m_end - bytes, CACHE_ALIGNMENT);
- drccodeptr const limit = ALIGN_PTR_DOWN(ptr, m_cache.page_size());
+ drccodeptr const limit = ALIGN_PTR_DOWN(ptr, m_cache->page_size());
if (m_top > limit)
return nullptr;
// otherwise update the end of the cache
+#if defined(MAME_DEBUG)
+ ++m_cache_allocated;
+ if (bytes >= MAX_PERMANENT_ALLOC)
+ ++m_cache_oversize;
+#endif
m_limit = limit;
m_end = ptr;
return ptr;
@@ -145,9 +229,13 @@ void *drc_cache::alloc(size_t bytes)
// the near part of the cache
//-------------------------------------------------
-void *drc_cache::alloc_near(size_t bytes)
+void *drc_cache::alloc_near(std::size_t bytes, std::align_val_t align) noexcept
{
- assert(bytes > 0);
+ assert(bytes);
+ assert(std::size_t(align));
+
+ if (UNEXPECTED(((std::size_t(align) > CACHE_ALIGNMENT) || (CACHE_ALIGNMENT % std::size_t(align)))))
+ osd_printf_error("drc_cache: Requested alignment %u not satisfied by cache alignment %u\n", std::size_t(align), CACHE_ALIGNMENT);
// pick first from the free list
if (bytes < MAX_PERMANENT_ALLOC)
@@ -156,6 +244,10 @@ void *drc_cache::alloc_near(size_t bytes)
free_link *const link = *linkptr;
if (link)
{
+#if defined(MAME_DEBUG)
+ ++m_near_allocated;
+ ++m_near_reused;
+#endif
*linkptr = link->m_next;
return link;
}
@@ -167,6 +259,11 @@ void *drc_cache::alloc_near(size_t bytes)
return nullptr;
// otherwise update the top of the near part of the cache
+#if defined(MAME_DEBUG)
+ ++m_near_allocated;
+ if (bytes >= MAX_PERMANENT_ALLOC)
+ ++m_near_oversize;
+#endif
m_neartop = ptr + bytes;
return ptr;
}
@@ -177,11 +274,14 @@ void *drc_cache::alloc_near(size_t bytes)
// from the cache
//-------------------------------------------------
-void *drc_cache::alloc_temporary(size_t bytes)
+void *drc_cache::alloc_temporary(std::size_t bytes, std::align_val_t align) noexcept
{
// can't allocate in the middle of codegen
assert(!m_codegen);
+ assert(bytes);
+ assert(std::size_t(align));
+
// if no space, we just fail
drccodeptr const ptr = m_top;
if ((ptr + bytes) > m_limit)
@@ -189,7 +289,7 @@ void *drc_cache::alloc_temporary(size_t bytes)
// otherwise, update the cache top
codegen_init();
- m_top = ALIGN_PTR_UP(ptr + bytes, CACHE_ALIGNMENT);
+ m_top = ALIGN_PTR_UP(ptr + bytes, std::lcm(std::size_t(align), CACHE_ALIGNMENT));
return ptr;
}
@@ -199,7 +299,7 @@ void *drc_cache::alloc_temporary(size_t bytes)
// the cache
//-------------------------------------------------
-void drc_cache::dealloc(void *memory, size_t bytes)
+void drc_cache::dealloc(void *memory, std::size_t bytes) noexcept
{
drccodeptr const mem = reinterpret_cast<drccodeptr>(memory);
assert(bytes < MAX_PERMANENT_ALLOC);
@@ -207,6 +307,9 @@ void drc_cache::dealloc(void *memory, size_t bytes)
// determine which free list to add to
free_link **const linkptr = &((mem < m_base) ? m_nearfree : m_free)[(bytes + CACHE_ALIGNMENT - 1) / CACHE_ALIGNMENT];
+#if defined(MAME_DEBUG)
+ ++((mem < m_base) ? m_near_freed : m_cache_freed);
+#endif
// link is into the free list for our size
free_link *const link = reinterpret_cast<free_link *>(memory);
@@ -215,23 +318,23 @@ void drc_cache::dealloc(void *memory, size_t bytes)
}
-void drc_cache::codegen_init()
+void drc_cache::codegen_init() noexcept
{
if (m_executable)
{
if (!m_rwx)
- m_cache.set_access(0, m_size, osd::virtual_memory_allocation::READ_WRITE);
+ m_cache->set_access(0, m_size, osd::virtual_memory_allocation::READ_WRITE);
m_executable = false;
}
}
-void drc_cache::codegen_complete()
+void drc_cache::codegen_complete() noexcept
{
if (!m_executable)
{
if (!m_rwx)
- m_cache.set_access(m_base - m_near, ALIGN_PTR_UP(m_top, m_cache.page_size()) - m_base, osd::virtual_memory_allocation::READ_EXECUTE);
+ m_cache->set_access(m_base - m_near, ALIGN_PTR_UP(m_top, m_cache->page_size()) - m_base, osd::virtual_memory_allocation::READ_EXECUTE);
m_executable = true;
}
}
@@ -241,7 +344,7 @@ void drc_cache::codegen_complete()
// begin_codegen - begin code generation
//-------------------------------------------------
-drccodeptr *drc_cache::begin_codegen(uint32_t reserve_bytes)
+drccodeptr *drc_cache::begin_codegen(uint32_t reserve_bytes) noexcept
{
// can't restart in the middle of codegen
assert(!m_codegen);
@@ -252,7 +355,6 @@ drccodeptr *drc_cache::begin_codegen(uint32_t reserve_bytes)
return nullptr;
// otherwise, return a pointer to the cache top
- codegen_init();
m_codegen = m_top;
return &m_top;
}
diff --git a/src/devices/cpu/drccache.h b/src/devices/cpu/drccache.h
index 01adaafd981..f207f7b4040 100644
--- a/src/devices/cpu/drccache.h
+++ b/src/devices/cpu/drccache.h
@@ -14,6 +14,12 @@
#include "modules/lib/osdlib.h"
+#include <algorithm>
+#include <cstdlib>
+#include <list>
+#include <optional>
+#include <utility>
+
//**************************************************************************
// MACROS
@@ -37,14 +43,17 @@ typedef uint8_t *drccodeptr;
typedef delegate<void (drccodeptr *, void *, void *)> drc_oob_delegate;
-// drc_cache
class drc_cache
{
public:
// construction/destruction
- drc_cache(size_t bytes);
+ drc_cache(std::size_t bytes) noexcept;
~drc_cache();
+ // setup
+ void set_size(std::size_t bytes) ATTR_COLD;
+ void allocate_cache(bool rwx) ATTR_COLD;
+
// getters
drccodeptr near() const { return m_near; }
drccodeptr base() const { return m_base; }
@@ -55,64 +64,118 @@ public:
bool contains_near_pointer(const void *ptr) const { return ((const drccodeptr)ptr >= m_near && (const drccodeptr)ptr < m_neartop); }
bool generating_code() const { return (m_codegen != nullptr); }
- // memory management
+ // cache memory allocation
void flush();
- void *alloc(size_t bytes);
- void *alloc_near(size_t bytes);
- void *alloc_temporary(size_t bytes);
- void dealloc(void *memory, size_t bytes);
+ void *alloc(std::size_t bytes, std::align_val_t align) noexcept;
+ void *alloc_near(std::size_t bytes, std::align_val_t align) noexcept;
+ void *alloc_temporary(std::size_t bytes, std::align_val_t align) noexcept;
+ void dealloc(void *memory, std::size_t bytes) noexcept;
+
+ template <typename T, typename... Params>
+ T *alloc(Params &&... args)
+ {
+ auto const result = reinterpret_cast<T *>(alloc(sizeof(T), std::align_val_t(alignof(T))));
+ if (result)
+ {
+ try
+ {
+ new (result) T(std::forward<Params>(args)...);
+ }
+ catch (...)
+ {
+ dealloc(result, sizeof(T));
+ throw;
+ }
+ }
+ return result;
+ }
+
+ template <typename T, typename... Params>
+ T *alloc_near(Params &&... args)
+ {
+ auto const result = reinterpret_cast<T *>(alloc_near(sizeof(T), std::align_val_t(alignof(T))));
+ if (result)
+ {
+ try
+ {
+ new (result) T(std::forward<Params>(args)...);
+ }
+ catch (...)
+ {
+ dealloc(result, sizeof(T));
+ throw;
+ }
+ }
+ return result;
+ }
// codegen helpers
- void codegen_init();
- void codegen_complete();
- drccodeptr *begin_codegen(uint32_t reserve_bytes);
+ void codegen_init() noexcept;
+ void codegen_complete() noexcept;
+ drccodeptr *begin_codegen(uint32_t reserve_bytes) noexcept;
drccodeptr end_codegen();
void request_oob_codegen(drc_oob_delegate &&callback, void *param1 = nullptr, void *param2 = nullptr);
private:
// largest block of code that can be generated at once
- static constexpr size_t CODEGEN_MAX_BYTES = 131072;
+ static constexpr std::size_t CODEGEN_MAX_BYTES = 128 * 1024;
// minimum alignment, in bytes (must be power of 2)
- static constexpr size_t CACHE_ALIGNMENT = alignof(std::max_align_t);
+ static constexpr std::size_t CACHE_ALIGNMENT = std::max<std::size_t>(alignof(std::max_align_t), 8);
// largest permanent allocation we allow
- static constexpr size_t MAX_PERMANENT_ALLOC = 1024;
+ static constexpr std::size_t MAX_PERMANENT_ALLOC = 1024;
// size of "near" area at the base of the cache
- static constexpr size_t NEAR_CACHE_SIZE = 131072;
-
- osd::virtual_memory_allocation m_cache;
+ static constexpr std::size_t NEAR_CACHE_SIZE = 128 * 1024;
- // core parameters
- drccodeptr const m_near; // pointer to the near part of the cache
- drccodeptr m_neartop; // unallocated area of near cache
- drccodeptr const m_base; // end of near cache
- drccodeptr m_top; // end of temporary allocations and code
- drccodeptr m_limit; // limit for temporary allocations and code (page-aligned)
- drccodeptr m_end; // first allocated byte in cache
- drccodeptr m_codegen; // start of current generated code block
- size_t const m_size; // size of the cache in bytes
- bool m_executable; // whether cached code is currently executable
- bool m_rwx; // whether pages can be simultaneously writable and executable
-
- // oob management
struct oob_handler
{
drc_oob_delegate m_callback; // callback function
void * m_param1; // 1st pointer parameter
void * m_param2; // 2nd pointer parameter
};
- std::list<oob_handler> m_oob_list; // list of active oob handlers
- std::list<oob_handler> m_oob_free; // list of recyclable oob handlers
- // free lists
+ std::optional<osd::virtual_memory_allocation> m_cache;
+
struct free_link
{
free_link * m_next; // pointer to the next guy
};
+
+ // core parameters
+ drccodeptr m_near; // pointer to the near part of the cache
+ drccodeptr m_neartop; // unallocated area of near cache
+ drccodeptr m_base; // end of near cache
+ drccodeptr m_top; // end of temporary allocations and code
+ drccodeptr m_limit; // limit for temporary allocations and code (page-aligned)
+ drccodeptr m_end; // first allocated byte in cache
+ drccodeptr m_codegen; // start of current generated code block
+ std::size_t m_size; // size of the cache in bytes
+ bool m_executable; // whether cached code is currently executable
+ bool m_rwx; // whether pages can be simultaneously writable and executable
+
+ // oob management
+ std::list<oob_handler> m_oob_list; // list of active oob handlers
+ std::list<oob_handler> m_oob_free; // list of recyclable oob handlers
+
+ // free lists
free_link * m_free[MAX_PERMANENT_ALLOC / CACHE_ALIGNMENT];
free_link * m_nearfree[MAX_PERMANENT_ALLOC / CACHE_ALIGNMENT];
+
+ // stats
+ std::size_t m_max_temporary;
+ uint32_t m_flush_count;
+#if defined(MAME_DEBUG)
+ uint32_t m_near_allocated;
+ uint32_t m_near_oversize;
+ uint32_t m_near_freed;
+ uint32_t m_near_reused;
+ uint32_t m_cache_allocated;
+ uint32_t m_cache_oversize;
+ uint32_t m_cache_freed;
+ uint32_t m_cache_reused;
+#endif
};
#endif // MAME_CPU_DRCCACHE_H
diff --git a/src/devices/cpu/drcuml.cpp b/src/devices/cpu/drcuml.cpp
index a0ccfa7b349..dbf7d3a026e 100644
--- a/src/devices/cpu/drcuml.cpp
+++ b/src/devices/cpu/drcuml.cpp
@@ -89,7 +89,7 @@ drcbe_interface::drcbe_interface(drcuml_state &drcuml, drc_cache &cache, device_
, m_cache(cache)
, m_device(device)
, m_space()
- , m_state(*reinterpret_cast<drcuml_machine_state *>(cache.alloc_near(sizeof(m_state))))
+ , m_state(*cache.alloc_near<drcuml_machine_state>())
{
// reset the machine state
memset(&m_state, 0, sizeof(m_state));
diff --git a/src/devices/cpu/drcuml.h b/src/devices/cpu/drcuml.h
index acc864a5201..21190720b72 100644
--- a/src/devices/cpu/drcuml.h
+++ b/src/devices/cpu/drcuml.h
@@ -247,7 +247,7 @@ inline void drcuml_block::append_comment(Format &&fmt, Params &&... args)
std::string const temp(util::string_format(std::forward<Format>(fmt), std::forward<Params>(args)...));
// allocate space in the cache to hold the comment
- char *const comment = reinterpret_cast<char *>(m_drcuml.cache().alloc_temporary(temp.length() + 1));
+ char *const comment = reinterpret_cast<char *>(m_drcuml.cache().alloc_temporary(temp.length() + 1, std::align_val_t(alignof(char))));
if (comment)
{
strcpy(comment, temp.c_str());
diff --git a/src/devices/cpu/dsp16/dsp16.cpp b/src/devices/cpu/dsp16/dsp16.cpp
index 288c52d1fe8..4a7c287d52a 100644
--- a/src/devices/cpu/dsp16/dsp16.cpp
+++ b/src/devices/cpu/dsp16/dsp16.cpp
@@ -77,9 +77,12 @@
#include "emu.h"
#include "dsp16.h"
+
#include "dsp16core.ipp"
#include "dsp16rc.h"
+#include "emuopts.h"
+
#include <functional>
#include <limits>
@@ -184,7 +187,7 @@ dsp16_device_base::dsp16_device_base(
{ "exm", ENDIANNESS_BIG, 16, 16, -1 } }
, m_yaau_bits(yaau_bits)
, m_workram(*this, "workram"), m_spaces{ nullptr, nullptr, nullptr }, m_workram_mask(0U)
- , m_drc_cache(CACHE_SIZE), m_core(nullptr, [] (core_state *core) { core->~core_state(); }), m_recompiler()
+ , m_drc_cache(CACHE_SIZE), m_core(), m_recompiler()
, m_cache_mode(cache::NONE), m_phase(phase::PURGE), m_int_enable{ 0U, 0U }, m_flags(FLAGS_NONE), m_cache_ptr(0U), m_cache_limit(0U), m_cache_iterations(0U)
, m_exm_in(1U), m_int_in(CLEAR_LINE), m_iack_out(1U)
, m_ick_in(1U), m_ild_in(CLEAR_LINE), m_do_out(1U), m_ock_in(1U), m_old_in(CLEAR_LINE), m_ose_out(1U)
@@ -202,8 +205,8 @@ dsp16_device_base::dsp16_device_base(
void dsp16_device_base::device_start()
{
- m_core.reset(reinterpret_cast<core_state *>(m_drc_cache.alloc_near(sizeof(core_state))));
- new (m_core.get()) core_state(m_yaau_bits);
+ m_drc_cache.allocate_cache(mconfig().options().drc_rwx());
+ m_core.reset(m_drc_cache.alloc_near<core_state>(m_yaau_bits));
set_icountptr(m_core->icount);
m_spaces[AS_PROGRAM] = &space(AS_PROGRAM);
diff --git a/src/devices/cpu/dsp16/dsp16.h b/src/devices/cpu/dsp16/dsp16.h
index f513e3fdceb..f969f14e851 100644
--- a/src/devices/cpu/dsp16/dsp16.h
+++ b/src/devices/cpu/dsp16/dsp16.h
@@ -175,7 +175,8 @@ private:
class core_state;
class frontend;
class recompiler;
- using core_state_ptr = std::unique_ptr<core_state, void (*)(core_state *)>;
+ struct core_destructer { void operator()(core_state *obj) const noexcept; };
+ using core_state_ptr = std::unique_ptr<core_state, core_destructer>;
using recompiler_ptr = std::unique_ptr<recompiler>;
// internal address maps
diff --git a/src/devices/cpu/dsp16/dsp16core.h b/src/devices/cpu/dsp16/dsp16core.h
index 80c2d60d08c..1ae09bd46f7 100644
--- a/src/devices/cpu/dsp16/dsp16core.h
+++ b/src/devices/cpu/dsp16/dsp16core.h
@@ -114,4 +114,11 @@ private:
u64 dau_set_psw_flags(s64 d);
};
+
+inline void dsp16_device::core_destructer::operator()(core_state *obj) const noexcept
+{
+ if (obj)
+ obj->~core_state();
+}
+
#endif // MAME_CPU_DSP16_DSP16CORE_H
diff --git a/src/devices/cpu/dspp/dspp.cpp b/src/devices/cpu/dspp/dspp.cpp
index 1e889a32bec..b42e1960212 100644
--- a/src/devices/cpu/dspp/dspp.cpp
+++ b/src/devices/cpu/dspp/dspp.cpp
@@ -11,8 +11,11 @@
#include "emu.h"
#include "dspp.h"
-#include "dsppfe.h"
+
#include "dsppdasm.h"
+#include "dsppfe.h"
+
+#include "emuopts.h"
//**************************************************************************
@@ -142,13 +145,21 @@ void dspp_device::device_start()
{
m_isdrc = false;//allow_drc();
- m_core = (dspp_internal_state *)m_cache.alloc_near(sizeof(dspp_internal_state));
- memset(m_core, 0, sizeof(dspp_internal_state));
+ if (m_isdrc)
+ {
+ m_cache.allocate_cache(mconfig().options().drc_rwx());
+ m_core = m_cache.alloc_near<dspp_internal_state>();
- uint32_t flags = 0;
- m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, flags, 1, 16, 0);
+ uint32_t flags = 0;
+ m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, flags, 1, 16, 0);
- m_drcfe = std::make_unique<dspp_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE);
+ m_drcfe = std::make_unique<dspp_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE);
+ }
+ else
+ {
+ m_core = &m_local_core;
+ }
+ memset(m_core, 0, sizeof(dspp_internal_state));
// Get our address spaces
space(AS_PROGRAM).cache(m_code_cache);
diff --git a/src/devices/cpu/dspp/dspp.h b/src/devices/cpu/dspp/dspp.h
index 13dc682b01f..ac73416953a 100644
--- a/src/devices/cpu/dspp/dspp.h
+++ b/src/devices/cpu/dspp/dspp.h
@@ -15,7 +15,6 @@
#include "cpu/drcfe.h"
#include "cpu/drcuml.h"
-#include "cpu/drcumlsh.h"
//**************************************************************************
@@ -243,7 +242,9 @@ private:
// External control registers
uint32_t m_dspx_control;
- } * m_core;
+ };
+ dspp_internal_state* m_core;
+ dspp_internal_state m_local_core; // for non-DRC mode
// DMA
struct fifo_dma
@@ -319,7 +320,7 @@ private:
};
public: // TODO
- void alloc_handle(drcuml_state *drcuml, uml::code_handle **handleptr, const char *name);
+ void alloc_handle(uml::code_handle **handleptr, const char *name);
void load_fast_iregs(drcuml_block &block);
void save_fast_iregs(drcuml_block &block);
// void arm7_drc_init();
diff --git a/src/devices/cpu/dspp/dsppdrc.cpp b/src/devices/cpu/dspp/dsppdrc.cpp
index a010133cce9..4992c0acf6d 100644
--- a/src/devices/cpu/dspp/dsppdrc.cpp
+++ b/src/devices/cpu/dspp/dsppdrc.cpp
@@ -9,9 +9,9 @@
#include "emu.h"
#include "dspp.h"
+
#include "dsppfe.h"
-#include "cpu/drcfe.h"
-#include "cpu/drcuml.h"
+
#include "cpu/drcumlsh.h"
using namespace uml;
@@ -29,10 +29,10 @@ using namespace uml;
#define EXECUTE_UNMAPPED_CODE 2
#define EXECUTE_RESET_CACHE 3
-inline void dspp_device::alloc_handle(drcuml_state *drcuml, code_handle **handleptr, const char *name)
+inline void dspp_device::alloc_handle(code_handle **handleptr, const char *name)
{
if (*handleptr == nullptr)
- *handleptr = drcuml->handle_alloc(name);
+ *handleptr = m_drcuml->handle_alloc(name);
}
static inline uint32_t epc(const opcode_desc *desc)
@@ -132,7 +132,7 @@ void dspp_device::static_generate_memory_accessor(bool iswrite, const char *name
drcuml_block &block = m_drcuml->begin_block(10);
// add a global entry for this
- alloc_handle(m_drcuml.get(), &handleptr, name);
+ alloc_handle(&handleptr, name);
UML_HANDLE(block, *handleptr); // handle *handleptr
if (iswrite)
@@ -152,7 +152,6 @@ void dspp_device::static_generate_memory_accessor(bool iswrite, const char *name
void dspp_device::execute_run_drc()
{
- drcuml_state *drcuml = m_drcuml.get();
int execute_result;
if (m_cache_dirty)
@@ -162,7 +161,7 @@ void dspp_device::execute_run_drc()
do
{
- execute_result = drcuml->execute(*m_entry);
+ execute_result = m_drcuml->execute(*m_entry);
/* if we need to recompile, do it */
if (execute_result == EXECUTE_MISSING_CODE)
@@ -182,7 +181,6 @@ void dspp_device::execute_run_drc()
void dspp_device::compile_block(offs_t pc)
{
- drcuml_state *drcuml = m_drcuml.get();
compiler_state compiler = { 0 };
const opcode_desc *seqhead, *seqlast;
int override = false;
@@ -198,7 +196,7 @@ void dspp_device::compile_block(offs_t pc)
try
{
/* start the block */
- drcuml_block &block = drcuml->begin_block(32768);
+ drcuml_block &block = m_drcuml->begin_block(32768);
/* loop until we get through all instruction sequences */
for (seqhead = desclist; seqhead != nullptr; seqhead = seqlast->next())
@@ -207,7 +205,7 @@ void dspp_device::compile_block(offs_t pc)
uint32_t nextpc;
/* add a code log entry */
- if (drcuml->logging())
+ if (m_drcuml->logging())
block.append_comment("-------------------------");
/* determine the last instruction in this sequence */
@@ -217,7 +215,7 @@ void dspp_device::compile_block(offs_t pc)
assert(seqlast != nullptr);
/* if we don't have a hash for this mode/pc, or if we are overriding all, add one */
- if (override || !drcuml->hash_exists(0, seqhead->pc))
+ if (override || !m_drcuml->hash_exists(0, seqhead->pc))
UML_HASH(block, 0, seqhead->pc); // hash mode,pc
/* if we already have a hash, and this is the first sequence, assume that we */
@@ -352,8 +350,8 @@ void dspp_device::static_generate_entry_point()
drcuml_block &block = m_drcuml->begin_block(20);
/* forward references */
- alloc_handle(m_drcuml.get(), &m_nocode, "nocode");
- alloc_handle(m_drcuml.get(), &m_entry, "entry");
+ alloc_handle(&m_nocode, "nocode");
+ alloc_handle(&m_entry, "entry");
UML_HANDLE(block, *m_entry); // handle entry
//load_fast_iregs(block); // <load fastregs>
@@ -370,7 +368,7 @@ void dspp_device::static_generate_nocode_handler()
drcuml_block &block = m_drcuml->begin_block(10);
/* generate a hash jump via the current mode and PC */
- alloc_handle(m_drcuml.get(), &m_nocode, "nocode");
+ alloc_handle(&m_nocode, "nocode");
UML_HANDLE(block, *m_nocode); // handle nocode
UML_GETEXP(block, I0); // getexp i0
@@ -387,7 +385,7 @@ void dspp_device::static_generate_out_of_cycles()
drcuml_block &block = m_drcuml->begin_block(10);
/* generate a hash jump via the current mode and PC */
- alloc_handle(m_drcuml.get(), &m_out_of_cycles, "out_of_cycles");
+ alloc_handle(&m_out_of_cycles, "out_of_cycles");
UML_HANDLE(block, *m_out_of_cycles); // handle out_of_cycles
UML_GETEXP(block, I0); // getexp i0
UML_MOV(block, mem(&m_core->m_pc), I0); // mov <pc>,i0
@@ -450,7 +448,7 @@ void dspp_device::generate_opcode(drcuml_block &block, compiler_state *compiler,
UML_SUB(block, mem(&m_core->m_tclock), mem(&m_core->m_tclock), 1);
UML_CALLC(block, cfunc_update_fifo_dma, this);
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("generate_opcode: %04x", op);
code_label skip = compiler->labelnum++;
@@ -489,7 +487,7 @@ void dspp_device::generate_opcode(drcuml_block &block, compiler_state *compiler,
void dspp_device::generate_set_rbase(drcuml_block &block, compiler_state *compiler, uint32_t base, uint32_t addr)
{
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("set_rbase");
switch (base)
{
@@ -518,7 +516,7 @@ void dspp_device::generate_super_special(drcuml_block &block, compiler_state *co
{
case 1: // BAC
{
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("BAC");
UML_SHR(block, mem(&m_core->m_jmpdest), mem(&m_core->m_acc), 4); // m_core->m_pc = m_core->m_acc >> 4;
generate_branch(block, compiler, desc);
@@ -526,7 +524,7 @@ void dspp_device::generate_super_special(drcuml_block &block, compiler_state *co
}
case 4: // RTS
{
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("RTS");
// m_core->m_pc = m_core->m_stack[--m_core->m_stack_ptr];
UML_SUB(block, mem(&m_core->m_stack_ptr), mem(&m_core->m_stack_ptr), 1);
@@ -537,7 +535,7 @@ void dspp_device::generate_super_special(drcuml_block &block, compiler_state *co
case 5: // OP_MASK
{
// TODO
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("OP_MASK");
break;
}
@@ -545,7 +543,7 @@ void dspp_device::generate_super_special(drcuml_block &block, compiler_state *co
case 7: // SLEEP
{
// TODO: How does sleep work?
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("SLEEP");
UML_SUB(block, mem(&m_core->m_pc), mem(&m_core->m_pc), 1); // --m_core->m_pc;
UML_MOV(block, mem(&m_core->m_flag_sleep), 1); // m_core->m_flag_sleep = 1;
@@ -573,7 +571,7 @@ void dspp_device::generate_special_opcode(drcuml_block &block, compiler_state *c
}
case 1: // JUMP
{
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("JUMP");
UML_MOV(block, mem(&m_core->m_jmpdest), op & 0x3ff);
@@ -582,7 +580,7 @@ void dspp_device::generate_special_opcode(drcuml_block &block, compiler_state *c
}
case 2: // JSR
{
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("JSR");
UML_STORE(block, (void *)m_core->m_stack, mem(&m_core->m_stack_ptr), mem(&m_core->m_pc), SIZE_DWORD, SCALE_x4);
UML_ADD(block, mem(&m_core->m_stack_ptr), mem(&m_core->m_stack_ptr), 1);
@@ -593,13 +591,13 @@ void dspp_device::generate_special_opcode(drcuml_block &block, compiler_state *c
case 3: // BFM
{
// TODO
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("BFM");
break;
}
case 4: // MOVEREG
{
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("MOVEREG");
const uint32_t regdi = op & 0x3f;
generate_translate_reg(block, regdi & 0xf);
@@ -624,14 +622,14 @@ void dspp_device::generate_special_opcode(drcuml_block &block, compiler_state *c
}
case 5: // RBASE
{
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("RBASE");
generate_set_rbase(block, compiler, (op & 3) << 2, op & 0x3fc);
break;
}
case 6: // MOVED
{
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("MOVED");
generate_parse_operands(block, compiler, desc, 1);
generate_read_next_operand(block, compiler, desc);
@@ -642,7 +640,7 @@ void dspp_device::generate_special_opcode(drcuml_block &block, compiler_state *c
}
case 7: // MOVEI
{
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("MOVEI");
generate_parse_operands(block, compiler, desc, 1);
UML_MOV(block, I1, op & 0x3ff);
@@ -690,7 +688,7 @@ void dspp_device::generate_branch_opcode(drcuml_block &block, compiler_state *co
{
uint16_t op = desc->opptr.w[0];
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("branch_opcode");
uint32_t mode = (op >> 13) & 3;
@@ -741,24 +739,24 @@ void dspp_device::generate_complex_branch_opcode(drcuml_block &block, compiler_s
switch ((op >> 10) & 7)
{
case 0: // BLT
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("BLT");
UML_XOR(block, I0, mem(&m_core->m_flag_neg), mem(&m_core->m_flag_over)); // branch = (n && !v) || (!n && v);
break;
case 1: // BLE
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("BLE");
UML_XOR(block, I0, mem(&m_core->m_flag_neg), mem(&m_core->m_flag_over));
UML_OR(block, I0, I0, mem(&m_core->m_flag_zero)); // branch = ((n && !v) || (!n && v)) || z;
break;
case 2: // BGE
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("BGE");
UML_XOR(block, I0, mem(&m_core->m_flag_neg), mem(&m_core->m_flag_over));
UML_SUB(block, I0, 1, I0); // branch = ((n && v) || (!n && !v));
break;
case 3: // BGT
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("BGT");
UML_AND(block, I0, mem(&m_core->m_flag_neg), mem(&m_core->m_flag_over));
UML_SUB(block, I0, 1, I0);
@@ -766,24 +764,24 @@ void dspp_device::generate_complex_branch_opcode(drcuml_block &block, compiler_s
UML_AND(block, I0, I0, I1); // branch = ((n && v) || (!n && !v)) && !z;
break;
case 4: // BHI
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("BHI");
UML_SUB(block, I0, 1, mem(&m_core->m_flag_zero));
UML_AND(block, I0, I0, mem(&m_core->m_flag_carry)); // branch = c && !z;
break;
case 5: // BLS
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("BLS");
UML_SUB(block, I0, 1, mem(&m_core->m_flag_carry));
UML_OR(block, I0, I0, mem(&m_core->m_flag_zero)); // branch = !c || z;
break;
case 6: // BXS
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("BXS");
UML_MOV(block, I0, mem(&m_core->m_flag_exact)); // branch = x;
break;
case 7: // BXC
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("BXC");
UML_SUB(block, I0, 1, mem(&m_core->m_flag_exact)); // branch = !x;
break;
@@ -800,7 +798,7 @@ void dspp_device::generate_complex_branch_opcode(drcuml_block &block, compiler_s
void dspp_device::generate_translate_reg(drcuml_block &block, uint16_t reg)
{
const uint32_t base = (reg >> 2) & 3;
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("translate_reg");
UML_MOV(block, I1, mem(&m_core->m_rbase[base]));
UML_ADD(block, I1, I1, reg - (reg & ~3));
@@ -813,7 +811,7 @@ void dspp_device::generate_parse_operands(drcuml_block &block, compiler_state *c
uint32_t operand = 0;
uint32_t numregs = 0;
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("parse_operands");
for (uint32_t i = 0; i < MAX_OPERANDS; ++i)
@@ -934,7 +932,7 @@ void dspp_device::generate_read_next_operand(drcuml_block &block, compiler_state
//uint16_t op = (uint16_t)desc->opptr.w[0];
code_label no_load;
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("read_next_operand");
UML_LOAD(block, I0, (void *)&m_core->m_operands[0].value, mem(&m_core->m_opidx), SIZE_DWORD, SCALE_x8);
//if (op == 0x46a0)
@@ -965,7 +963,7 @@ void dspp_device::generate_read_next_operand(drcuml_block &block, compiler_state
void dspp_device::generate_write_next_operand(drcuml_block &block, compiler_state *compiler)
{
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("write_next_operand");
// int32_t addr = m_core->m_operands[m_core->m_opidx].addr;
UML_LOAD(block, I1, (void *)&m_core->m_operands[0].addr, mem(&m_core->m_opidx), SIZE_DWORD, SCALE_x8);
@@ -986,7 +984,7 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
uint32_t alu_op = (op >> 4) & 0xf;
uint32_t barrel_code = op & 0xf;
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("arithmetic_opcode");
// Check for operand overflow
@@ -1066,7 +1064,7 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
switch (alu_op)
{
case 0: // _TRA
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("_TRA");
UML_MOV(block, I0, I2); // alu_res = alu_a;
UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
@@ -1074,7 +1072,7 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
break;
case 1: // _NEG
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("_NEG");
UML_SUB(block, I0, 0, I3); // alu_res = -alu_b;
UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
@@ -1082,7 +1080,7 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
break;
case 2: // _+
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("_+");
UML_ADD(block, I0, I2, I3); // alu_res = alu_a + alu_b;
@@ -1103,7 +1101,7 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
break;
case 3: // _+C
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("_+C");
UML_SHL(block, I3, mem(&m_core->m_flag_carry), 4);
UML_ADD(block, I0, I2, I3); // alu_res = alu_a + (m_core->m_flag_carry << 4);
@@ -1117,7 +1115,7 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
break;
case 4: // _-
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("_-");
UML_SUB(block, I0, I2, I3); // alu_res = alu_a - alu_b;
@@ -1139,7 +1137,7 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
break;
case 5: // _-B
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("_-B");
UML_SHL(block, I3, mem(&m_core->m_flag_carry), 4);
UML_SUB(block, I0, I2, I3); // alu_res = alu_a - (m_core->m_flag_carry << 4);
@@ -1153,7 +1151,7 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
break;
case 6: // _++
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("_++");
UML_ADD(block, I0, I2, 1); // alu_res = alu_a + 1;
@@ -1167,7 +1165,7 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
break;
case 7: // _--
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("_--");
UML_SUB(block, I0, I2, 1); // alu_res = alu_a - 1;
@@ -1181,7 +1179,7 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
break;
case 8: // _TRL
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("_TRL");
UML_MOV(block, I0, I2); // alu_res = alu_a;
UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
@@ -1189,7 +1187,7 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
break;
case 9: // _NOT
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("_NOT");
UML_XOR(block, I0, I2, 0xffffffff); // alu_res = ~alu_a;
UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
@@ -1197,7 +1195,7 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
break;
case 10: // _AND
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("_AND");
UML_AND(block, I0, I2, I3); // alu_res = alu_a & alu_b;
UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
@@ -1205,7 +1203,7 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
break;
case 11: // _NAND
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("_NAND");
UML_AND(block, I0, I2, I3);
UML_XOR(block, I0, I0, 0xffffffff); // alu_res = ~(alu_a & alu_b);
@@ -1214,7 +1212,7 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
break;
case 12: // _OR
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("_OR");
UML_OR(block, I0, I2, I3); // alu_res = alu_a | alu_b;
UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
@@ -1222,7 +1220,7 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
break;
case 13: // _NOR
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("_NOR");
UML_OR(block, I0, I2, I3);
UML_XOR(block, I0, I0, 0xffffffff); // alu_res = ~(alu_a | alu_b);
@@ -1231,7 +1229,7 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
break;
case 14: // _XOR
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("_XOR");
UML_XOR(block, I0, I2, I3); // alu_res = alu_a ^ alu_b;
UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
@@ -1239,7 +1237,7 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
break;
case 15: // _XNOR
- if (m_drcuml.get()->logging())
+ if (m_drcuml->logging())
block.append_comment("_XNOR");
UML_XOR(block, I0, I2, I3);
UML_XOR(block, I0, I0, 0xffffffff); // alu_res = ~(alu_a ^ alu_b);
diff --git a/src/devices/cpu/e132xs/e132xs.cpp b/src/devices/cpu/e132xs/e132xs.cpp
index 157a4fe1f9a..cd4c6e948e9 100644
--- a/src/devices/cpu/e132xs/e132xs.cpp
+++ b/src/devices/cpu/e132xs/e132xs.cpp
@@ -95,6 +95,8 @@
#include "32xsdefs.h"
+#include "emuopts.h"
+
#include <algorithm>
//#define VERBOSE 1
@@ -158,7 +160,7 @@ hyperstone_device::hyperstone_device(
: cpu_device(mconfig, type, tag, owner, clock)
, m_program_config("program", ENDIANNESS_BIG, prg_data_width, 32, 0, internal_map)
, m_io_config("io", ENDIANNESS_BIG, io_data_width, io_addr_bits, (io_data_width == 16) ? -1 : -2)
- , m_cache(CACHE_SIZE + sizeof(hyperstone_device))
+ , m_cache(CACHE_SIZE + sizeof(internal_hyperstone_state))
, m_drcuml(nullptr)
, m_drcfe(nullptr)
, m_drcoptions(0)
@@ -1464,10 +1466,17 @@ void hyperstone_device::check_interrupts()
void hyperstone_device::device_start()
{
- m_core = (internal_hyperstone_state *)m_cache.alloc_near(sizeof(internal_hyperstone_state));
- memset(m_core, 0, sizeof(internal_hyperstone_state));
-
m_enable_drc = allow_drc();
+ if (m_enable_drc)
+ {
+ m_cache.allocate_cache(mconfig().options().drc_rwx());
+ m_core = m_cache.alloc_near<internal_hyperstone_state>();
+ }
+ else
+ {
+ m_core = &m_local_core;
+ }
+ memset(m_core, 0, sizeof(internal_hyperstone_state));
#if E132XS_LOG_DRC_REGS || E132XS_LOG_INTERPRETER_REGS
if (m_enable_drc)
@@ -1553,66 +1562,69 @@ void hyperstone_device::device_start()
m_core->fl_lut[i] = (i ? i : 16);
}
- const uint32_t umlflags = 0;
- m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, umlflags, 4, 32, 1);
-
- // add UML symbols
- m_drcuml->symbol_add(&m_core->global_regs[PC_REGISTER], sizeof(m_core->global_regs[PC_REGISTER]), "pc");
- m_drcuml->symbol_add(&m_core->global_regs[SR_REGISTER], sizeof(m_core->global_regs[SR_REGISTER]), "sr");
- m_drcuml->symbol_add(&m_core->global_regs[FER_REGISTER], sizeof(m_core->global_regs[FER_REGISTER]), "fer");
- m_drcuml->symbol_add(&m_core->global_regs[SP_REGISTER], sizeof(m_core->global_regs[SP_REGISTER]), "sp");
- m_drcuml->symbol_add(&m_core->global_regs[UB_REGISTER], sizeof(m_core->global_regs[UB_REGISTER]), "ub");
- m_drcuml->symbol_add(&m_core->trap_entry, sizeof(m_core->trap_entry), "trap_entry");
- m_drcuml->symbol_add(&m_core->delay_pc, sizeof(m_core->delay_pc), "delay_pc");
- m_drcuml->symbol_add(&m_core->delay_slot, sizeof(m_core->delay_slot), "delay_slot");
- m_drcuml->symbol_add(&m_core->delay_slot_taken, sizeof(m_core->delay_slot_taken), "delay_slot_taken");
- m_drcuml->symbol_add(&m_core->intblock, sizeof(m_core->intblock), "intblock");
- m_drcuml->symbol_add(&m_core->powerdown, sizeof(m_core->powerdown), "powerdown");
- m_drcuml->symbol_add(&m_core->arg0, sizeof(m_core->arg0), "arg0");
- m_drcuml->symbol_add(&m_core->arg1, sizeof(m_core->arg1), "arg1");
- m_drcuml->symbol_add(&m_core->icount, sizeof(m_core->icount), "icount");
-
- char buf[4];
- buf[3] = '\0';
- buf[0] = 'g';
- for (int i = 0; i < 32; i++)
- {
- if (9 < i)
- {
- buf[1] = '0' + (i / 10);
- buf[2] = '0' + (i % 10);
- }
- else
- {
- buf[1] = '0' + i;
- buf[2] = '\0';
- }
- m_drcuml->symbol_add(&m_core->global_regs[i], sizeof(uint32_t), buf);
- }
- buf[0] = 'l';
- for (int i = 0; i < 64; i++)
+ if (m_enable_drc)
{
- if (9 < i)
+ const uint32_t umlflags = 0;
+ m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, umlflags, 4, 32, 1);
+
+ // add UML symbols
+ m_drcuml->symbol_add(&m_core->global_regs[PC_REGISTER], sizeof(m_core->global_regs[PC_REGISTER]), "pc");
+ m_drcuml->symbol_add(&m_core->global_regs[SR_REGISTER], sizeof(m_core->global_regs[SR_REGISTER]), "sr");
+ m_drcuml->symbol_add(&m_core->global_regs[FER_REGISTER], sizeof(m_core->global_regs[FER_REGISTER]), "fer");
+ m_drcuml->symbol_add(&m_core->global_regs[SP_REGISTER], sizeof(m_core->global_regs[SP_REGISTER]), "sp");
+ m_drcuml->symbol_add(&m_core->global_regs[UB_REGISTER], sizeof(m_core->global_regs[UB_REGISTER]), "ub");
+ m_drcuml->symbol_add(&m_core->trap_entry, sizeof(m_core->trap_entry), "trap_entry");
+ m_drcuml->symbol_add(&m_core->delay_pc, sizeof(m_core->delay_pc), "delay_pc");
+ m_drcuml->symbol_add(&m_core->delay_slot, sizeof(m_core->delay_slot), "delay_slot");
+ m_drcuml->symbol_add(&m_core->delay_slot_taken, sizeof(m_core->delay_slot_taken), "delay_slot_taken");
+ m_drcuml->symbol_add(&m_core->intblock, sizeof(m_core->intblock), "intblock");
+ m_drcuml->symbol_add(&m_core->powerdown, sizeof(m_core->powerdown), "powerdown");
+ m_drcuml->symbol_add(&m_core->arg0, sizeof(m_core->arg0), "arg0");
+ m_drcuml->symbol_add(&m_core->arg1, sizeof(m_core->arg1), "arg1");
+ m_drcuml->symbol_add(&m_core->icount, sizeof(m_core->icount), "icount");
+
+ char buf[4];
+ buf[3] = '\0';
+ buf[0] = 'g';
+ for (int i = 0; i < 32; i++)
{
- buf[1] = '0' + (i / 10);
- buf[2] = '0' + (i % 10);
+ if (9 < i)
+ {
+ buf[1] = '0' + (i / 10);
+ buf[2] = '0' + (i % 10);
+ }
+ else
+ {
+ buf[1] = '0' + i;
+ buf[2] = '\0';
+ }
+ m_drcuml->symbol_add(&m_core->global_regs[i], sizeof(uint32_t), buf);
}
- else
+ buf[0] = 'l';
+ for (int i = 0; i < 64; i++)
{
- buf[1] = '0' + i;
- buf[2] = '\0';
+ if (9 < i)
+ {
+ buf[1] = '0' + (i / 10);
+ buf[2] = '0' + (i % 10);
+ }
+ else
+ {
+ buf[1] = '0' + i;
+ buf[2] = '\0';
+ }
+ m_drcuml->symbol_add(&m_core->local_regs[i], sizeof(uint32_t), buf);
}
- m_drcuml->symbol_add(&m_core->local_regs[i], sizeof(uint32_t), buf);
- }
- m_drcuml->symbol_add(&m_core->arg0, sizeof(uint32_t), "arg0");
- m_drcuml->symbol_add(&m_core->arg1, sizeof(uint32_t), "arg1");
+ m_drcuml->symbol_add(&m_core->arg0, sizeof(uint32_t), "arg0");
+ m_drcuml->symbol_add(&m_core->arg1, sizeof(uint32_t), "arg1");
- /* initialize the front-end helper */
- m_drcfe = std::make_unique<e132xs_frontend>(*this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, m_single_instruction_mode ? 1 : COMPILE_MAX_SEQUENCE);
+ /* initialize the front-end helper */
+ m_drcfe = std::make_unique<e132xs_frontend>(*this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, m_single_instruction_mode ? 1 : COMPILE_MAX_SEQUENCE);
- /* mark the cache dirty so it is updated on next execute */
- m_cache_dirty = true;
+ /* mark the cache dirty so it is updated on next execute */
+ m_cache_dirty = true;
+ }
// register our state for the debugger
state_add(STATE_GENPC, "GENPC", m_core->global_regs[0]).noshow();
diff --git a/src/devices/cpu/e132xs/e132xs.h b/src/devices/cpu/e132xs/e132xs.h
index dfe1eeb991c..79e5e45b604 100644
--- a/src/devices/cpu/e132xs/e132xs.h
+++ b/src/devices/cpu/e132xs/e132xs.h
@@ -467,6 +467,8 @@ private:
uml::code_handle *m_io_write32;
uml::code_handle *m_exception;
+ internal_hyperstone_state m_local_core; // for non-DRC mode
+
uint32_t m_debug_local_regs[16];
bool m_enable_drc;
diff --git a/src/devices/cpu/mb86235/mb86235.cpp b/src/devices/cpu/mb86235/mb86235.cpp
index b9ceda72515..6a7dfac3c45 100644
--- a/src/devices/cpu/mb86235/mb86235.cpp
+++ b/src/devices/cpu/mb86235/mb86235.cpp
@@ -14,8 +14,11 @@
#include "emu.h"
#include "mb86235.h"
-#include "mb86235fe.h"
+
#include "mb86235d.h"
+#include "mb86235fe.h"
+
+#include "emuopts.h"
#define ENABLE_DRC 0
@@ -89,7 +92,8 @@ void mb86235_device::device_start()
space(AS_BUSA).specific(m_dataa);
space(AS_BUSB).specific(m_datab);
- m_core = (mb86235_internal_state *)m_cache.alloc_near(sizeof(mb86235_internal_state));
+ m_cache.allocate_cache(mconfig().options().drc_rwx());
+ m_core = m_cache.alloc_near<mb86235_internal_state>();
memset(m_core, 0, sizeof(mb86235_internal_state));
diff --git a/src/devices/cpu/mb86235/mb86235.h b/src/devices/cpu/mb86235/mb86235.h
index 59597b875e6..e3a660f1987 100644
--- a/src/devices/cpu/mb86235/mb86235.h
+++ b/src/devices/cpu/mb86235/mb86235.h
@@ -13,8 +13,10 @@
#include "cpu/drcfe.h"
#include "cpu/drcuml.h"
+
#include "machine/gen_fifo.h"
+
class mb86235_frontend;
class mb86235_device : public cpu_device
diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp
index 060c5acfc2f..a56f19a3b21 100644
--- a/src/devices/cpu/mips/mips3.cpp
+++ b/src/devices/cpu/mips/mips3.cpp
@@ -10,9 +10,13 @@
#include "emu.h"
#include "mips3.h"
+
#include "mips3com.h"
#include "mips3dsm.h"
#include "ps2vu.h"
+
+#include "emuopts.h"
+
#include <cmath>
#define ENABLE_OVERFLOWS (0)
@@ -387,18 +391,19 @@ void r5900_device::check_irqs()
void mips3_device::device_start()
{
m_isdrc = allow_drc();
+ m_drc_cache.allocate_cache(mconfig().options().drc_rwx());
/* allocate the implementation-specific state from the full cache */
- m_core = (internal_mips3_state *)m_drc_cache.alloc_near(sizeof(internal_mips3_state));
- m_icache = (uint8_t *)m_drc_cache.alloc_near(c_dcache_size);
- m_dcache = (uint8_t *)m_drc_cache.alloc_near(c_icache_size);
+ m_core = m_drc_cache.alloc_near<internal_mips3_state>();
+ m_icache = (uint8_t *)m_drc_cache.alloc_near(c_dcache_size, std::align_val_t(alignof(uint64_t)));
+ m_dcache = (uint8_t *)m_drc_cache.alloc_near(c_icache_size, std::align_val_t(alignof(uint64_t)));
/* initialize based on the config */
memset(m_core, 0, sizeof(internal_mips3_state));
m_cpu_clock = clock();
m_program = &space(AS_PROGRAM);
- if(m_program->endianness() == ENDIANNESS_LITTLE)
+ if (m_program->endianness() == ENDIANNESS_LITTLE)
{
if (m_data_bits == 32)
{
diff --git a/src/devices/cpu/mips/mips3.h b/src/devices/cpu/mips/mips3.h
index 73105cb0ad3..181df0e9a47 100644
--- a/src/devices/cpu/mips/mips3.h
+++ b/src/devices/cpu/mips/mips3.h
@@ -15,11 +15,13 @@ MIPS III/IV emulator.
#pragma once
-#include "divtlb.h"
#include "cpu/drcfe.h"
#include "cpu/drcuml.h"
#include "ps2vu.h"
+#include "divtlb.h"
+
+
DECLARE_DEVICE_TYPE(R4000BE, r4000be_device)
DECLARE_DEVICE_TYPE(R4000LE, r4000le_device)
DECLARE_DEVICE_TYPE(R4400BE, r4400be_device)
@@ -235,9 +237,6 @@ enum {
MIPS3_R31H,
};
-#define MIPS3_MAX_FASTRAM 3
-#define MIPS3_MAX_HOTSPOTS 16
-
/* COP1 CCR register */
#define COP1_FCR31 (m_core->ccr[1][31])
@@ -258,21 +257,12 @@ INTERRUPT CONSTANTS
STRUCTURES
***************************************************************************/
-/* MIPS3 TLB entry */
-struct mips3_tlb_entry {
- uint64_t page_mask;
- uint64_t entry_hi;
- uint64_t entry_lo[2];
-};
-
-#define MIPS3_MAX_TLB_ENTRIES 48
-
class mips3_frontend;
class mips3_device : public cpu_device, public device_vtlb_interface {
+protected:
friend class mips3_frontend;
-protected:
/* MIPS flavors */
enum mips3_flavor {
/* MIPS III variants */
@@ -294,10 +284,27 @@ protected:
MIPS3_TYPE_RM7000
};
+ static inline constexpr unsigned MIPS3_MAX_FASTRAM = 3;
+ static inline constexpr unsigned MIPS3_MAX_HOTSPOTS = 16;
+
+ static inline constexpr unsigned MIPS3_MAX_TLB_ENTRIES = 48;
+
+ // MIPS3 TLB entry
+ struct mips3_tlb_entry {
+ bool matches_asid(uint8_t asid) const noexcept;
+ bool is_global() const noexcept;
+ void log_half(int tlbindex, int which) const;
+
+ uint64_t page_mask;
+ uint64_t entry_hi;
+ uint64_t entry_lo[2];
+ };
+
public:
// construction/destruction
mips3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, mips3_flavor flavor, endianness_t endiannes, uint32_t data_bits);
+ void set_drc_cache_size(size_t bytes) { m_drc_cache.set_size(bytes); }
void set_icache_size(size_t icache_size) { c_icache_size = icache_size; }
void set_dcache_size(size_t dcache_size) { c_dcache_size = dcache_size; }
void set_secondary_cache_line_size(uint8_t secondary_cache_line_size) { c_secondary_cache_line_size = secondary_cache_line_size; }
@@ -312,7 +319,7 @@ public:
void mips3drc_add_hotspot(offs_t pc, uint32_t opcode, uint32_t cycles);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void device_stop() override ATTR_COLD;
diff --git a/src/devices/cpu/mips/mips3com.cpp b/src/devices/cpu/mips/mips3com.cpp
index 2a9a933ef87..405eb61fb87 100644
--- a/src/devices/cpu/mips/mips3com.cpp
+++ b/src/devices/cpu/mips/mips3com.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- mips3com.c
+ mips3com.cpp
Common MIPS III/IV definitions and functions
@@ -13,40 +13,6 @@
#include "ps2vu.h"
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-static void tlb_entry_log_half(mips3_tlb_entry *entry, int tlbindex, int which);
-
-
-
-/***************************************************************************
- INLINE FUNCTIONS
-***************************************************************************/
-
-/*-------------------------------------------------
- tlb_entry_matches_asid - true if the given
- TLB entry matches the provided ASID
--------------------------------------------------*/
-
-static inline bool tlb_entry_matches_asid(const mips3_tlb_entry *entry, uint8_t asid)
-{
- return (entry->entry_hi & 0xff) == asid;
-}
-
-
-/*-------------------------------------------------
- tlb_entry_is_global - true if the given
- TLB entry is global
--------------------------------------------------*/
-
-static inline bool tlb_entry_is_global(const mips3_tlb_entry *entry)
-{
- return (entry->entry_lo[0] & entry->entry_lo[1] & TLB_GLOBAL);
-}
-
-
void mips3_device::execute_set_input(int inputnum, int state)
{
if (inputnum >= MIPS3_IRQ0 && inputnum <= MIPS3_IRQ5)
@@ -98,7 +64,7 @@ void mips3_device::mips3com_asid_changed()
/* iterate over all non-global TLB entries and remap them */
for (tlbindex = 0; tlbindex < m_tlbentries; tlbindex++)
- if (!tlb_entry_is_global(&m_tlb[tlbindex]))
+ if (!m_tlb[tlbindex].is_global())
tlb_map_entry(tlbindex);
}
@@ -114,13 +80,13 @@ void mips3_device::mips3com_tlbr()
/* only handle entries within the TLB */
if (tlbindex < m_tlbentries)
{
- mips3_tlb_entry *entry = &m_tlb[tlbindex];
+ const mips3_tlb_entry &entry = m_tlb[tlbindex];
/* copy data from the TLB entry into the COP0 registers */
- m_core->cpr[0][COP0_PageMask] = entry->page_mask;
- m_core->cpr[0][COP0_EntryHi] = entry->entry_hi;
- m_core->cpr[0][COP0_EntryLo0] = entry->entry_lo[0];
- m_core->cpr[0][COP0_EntryLo1] = entry->entry_lo[1];
+ m_core->cpr[0][COP0_PageMask] = entry.page_mask;
+ m_core->cpr[0][COP0_EntryHi] = entry.entry_hi;
+ m_core->cpr[0][COP0_EntryLo0] = entry.entry_lo[0];
+ m_core->cpr[0][COP0_EntryLo1] = entry.entry_lo[1];
}
}
@@ -178,14 +144,14 @@ void mips3_device::mips3com_tlbp()
/* iterate over TLB entries */
for (tlbindex = 0; tlbindex < m_tlbentries; tlbindex++)
{
- mips3_tlb_entry *entry = &m_tlb[tlbindex];
- uint64_t mask = ~((entry->page_mask >> 13) & 0xfff) << 13;
+ const mips3_tlb_entry &entry = m_tlb[tlbindex];
+ const uint64_t mask = ~((entry.page_mask >> 13) & 0xfff) << 13;
/* if the relevant bits of EntryHi match the relevant bits of the TLB */
- if ((entry->entry_hi & mask) == (m_core->cpr[0][COP0_EntryHi] & mask))
+ if ((entry.entry_hi & mask) == (m_core->cpr[0][COP0_EntryHi] & mask))
/* and if we are either global or matching the current ASID, then stop */
- if ((entry->entry_hi & 0xff) == (m_core->cpr[0][COP0_EntryHi] & 0xff) || ((entry->entry_lo[0] & entry->entry_lo[1]) & TLB_GLOBAL))
+ if ((entry.entry_hi & 0xff) == (m_core->cpr[0][COP0_EntryHi] & 0xff) || ((entry.entry_lo[0] & entry.entry_lo[1]) & TLB_GLOBAL))
break;
}
@@ -380,12 +346,12 @@ uint32_t mips3_device::compute_fpu_prid_register()
void mips3_device::tlb_map_entry(int tlbindex)
{
int current_asid = m_core->cpr[0][COP0_EntryHi] & 0xff;
- mips3_tlb_entry *entry = &m_tlb[tlbindex];
+ const mips3_tlb_entry &entry = m_tlb[tlbindex];
uint32_t count, vpn;
int which;
/* the ASID doesn't match the current ASID, and if the page isn't global, unmap it from the TLB */
- if (!tlb_entry_matches_asid(entry, current_asid) && !tlb_entry_is_global(entry))
+ if (!entry.matches_asid(current_asid) && !entry.is_global())
{
vtlb_load(2 * tlbindex + 0, 0, 0, 0);
vtlb_load(2 * tlbindex + 1, 0, 0, 0);
@@ -393,7 +359,7 @@ void mips3_device::tlb_map_entry(int tlbindex)
}
/* extract the VPN index; ignore if the virtual address is beyond 32 bits */
- vpn = ((entry->entry_hi >> 13) & 0x07ffffff) << 1;
+ vpn = ((entry.entry_hi >> 13) & 0x07ffffff) << 1;
if (vpn >= (1 << (MIPS3_MAX_PADDR_SHIFT - MIPS3_MIN_PAGE_SHIFT)))
{
vtlb_load(2 * tlbindex + 0, 0, 0, 0);
@@ -403,16 +369,16 @@ void mips3_device::tlb_map_entry(int tlbindex)
/* get the number of pages from the page mask */
/* R5900: if the S bit is set in EntryLo, it is the scratchpad, and is always 4 pages. */
- if ((entry->entry_lo[0] & 0x80000000) && m_flavor == MIPS3_TYPE_R5900)
+ if ((entry.entry_lo[0] & 0x80000000) && m_flavor == MIPS3_TYPE_R5900)
count = 4;
else
- count = ((entry->page_mask >> 13) & 0x00fff) + 1;
+ count = ((entry.page_mask >> 13) & 0x00fff) + 1;
/* loop over both the even and odd pages */
for (which = 0; which < 2; which++)
{
uint32_t effvpn = vpn + count * which;
- uint64_t lo = entry->entry_lo[which];
+ uint64_t lo = entry.entry_lo[which];
uint32_t pfn;
uint32_t flags = 0;
@@ -452,19 +418,19 @@ void mips3_device::tlb_write_common(int tlbindex)
/* only handle entries within the TLB */
if (tlbindex < m_tlbentries)
{
- mips3_tlb_entry *entry = &m_tlb[tlbindex];
+ mips3_tlb_entry &entry = m_tlb[tlbindex];
/* fill in the new TLB entry from the COP0 registers */
- entry->page_mask = m_core->cpr[0][COP0_PageMask];
- entry->entry_hi = m_core->cpr[0][COP0_EntryHi] & ~(entry->page_mask & u64(0x0000000001ffe000U));
- entry->entry_lo[0] = m_core->cpr[0][COP0_EntryLo0];
- entry->entry_lo[1] = m_core->cpr[0][COP0_EntryLo1];
+ entry.page_mask = m_core->cpr[0][COP0_PageMask];
+ entry.entry_hi = m_core->cpr[0][COP0_EntryHi] & ~(entry.page_mask & u64(0x0000000001ffe000U));
+ entry.entry_lo[0] = m_core->cpr[0][COP0_EntryLo0];
+ entry.entry_lo[1] = m_core->cpr[0][COP0_EntryLo1];
/* remap this TLB entry */
tlb_map_entry(tlbindex);
/* log the two halves once they are in */
- tlb_entry_log_half(entry, tlbindex, 0);
- tlb_entry_log_half(entry, tlbindex, 1);
+ entry.log_half(tlbindex, 0);
+ entry.log_half(tlbindex, 1);
}
}
@@ -474,25 +440,24 @@ void mips3_device::tlb_write_common(int tlbindex)
entry
-------------------------------------------------*/
-static void tlb_entry_log_half(mips3_tlb_entry *entry, int tlbindex, int which)
-{
-if (PRINTF_TLB)
+void mips3_device::mips3_tlb_entry::log_half(int tlbindex, int which) const
{
- uint64_t hi = entry->entry_hi;
- uint64_t lo = entry->entry_lo[which];
- uint32_t vpn = (((hi >> 13) & 0x07ffffff) << 1);
- uint32_t asid = hi & 0xff;
- uint32_t r = (hi >> 62) & 3;
- uint32_t pfn = (lo >> 6) & 0x00ffffff;
- uint32_t c = (lo >> 3) & 7;
- uint32_t pagesize = (((entry->page_mask >> 13) & 0xfff) + 1) << MIPS3_MIN_PAGE_SHIFT;
- uint64_t vaddr = (uint64_t)vpn * MIPS3_MIN_PAGE_SIZE;
- uint64_t paddr = (uint64_t)pfn * MIPS3_MIN_PAGE_SIZE;
-
- vaddr += pagesize * which;
-
- printf("index=%08X pagesize=%08X vaddr=%08X%08X paddr=%08X%08X asid=%02X r=%X c=%X dvg=%c%c%c\n",
- tlbindex, pagesize, (uint32_t)(vaddr >> 32), (uint32_t)vaddr, (uint32_t)(paddr >> 32), (uint32_t)paddr,
- asid, r, c, (lo & 4) ? 'd' : '.', (lo & 2) ? 'v' : '.', (lo & 1) ? 'g' : '.');
-}
+ if (PRINTF_TLB)
+ {
+ const uint64_t hi = entry_hi;
+ const uint64_t lo = entry_lo[which];
+ const uint32_t vpn = (((hi >> 13) & 0x07ffffff) << 1);
+ const uint32_t asid = hi & 0xff;
+ const uint32_t r = (hi >> 62) & 3;
+ const uint32_t pfn = (lo >> 6) & 0x00ffffff;
+ const uint32_t c = (lo >> 3) & 7;
+ const uint32_t pagesize = (((page_mask >> 13) & 0xfff) + 1) << MIPS3_MIN_PAGE_SHIFT;
+ const uint64_t vaddr = ((uint64_t)vpn * MIPS3_MIN_PAGE_SIZE) + (pagesize * which);
+ const uint64_t paddr = (uint64_t)pfn * MIPS3_MIN_PAGE_SIZE;
+
+ util::stream_format(std::cout,
+ "index=%08X pagesize=%08X vaddr=%016X paddr=%016X asid=%02X r=%X c=%X dvg=%c%c%c\n",
+ tlbindex, pagesize, vaddr, paddr,
+ asid, r, c, (lo & 4) ? 'd' : '.', (lo & 2) ? 'v' : '.', (lo & 1) ? 'g' : '.');
+ }
}
diff --git a/src/devices/cpu/mips/mips3com.h b/src/devices/cpu/mips/mips3com.h
index 8976f42575f..e92aba0d9e7 100644
--- a/src/devices/cpu/mips/mips3com.h
+++ b/src/devices/cpu/mips/mips3com.h
@@ -200,4 +200,30 @@
#define CACHE_TYPE ((op >> 16) & 3)
#define CACHE_OP ((op >> 18) & 7)
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ tlb_entry_matches_asid - true if the given
+ TLB entry matches the provided ASID
+-------------------------------------------------*/
+
+inline bool mips3_device::mips3_tlb_entry::matches_asid(uint8_t asid) const noexcept
+{
+ return (entry_hi & 0xff) == asid;
+}
+
+
+/*-------------------------------------------------
+ tlb_entry_is_global - true if the given
+ TLB entry is global
+-------------------------------------------------*/
+
+inline bool mips3_device::mips3_tlb_entry::is_global() const noexcept
+{
+ return (entry_lo[0] & entry_lo[1] & TLB_GLOBAL);
+}
+
#endif // MAME_CPU_MIPS_MIPS3COM_H
diff --git a/src/devices/cpu/powerpc/ppc.h b/src/devices/cpu/powerpc/ppc.h
index ce715b59dc1..08aedd46741 100644
--- a/src/devices/cpu/powerpc/ppc.h
+++ b/src/devices/cpu/powerpc/ppc.h
@@ -229,6 +229,7 @@ public:
void ppc_set_dcstore_callback(write32sm_delegate callback);
+ void set_drc_cache_size(size_t bytes) { m_cache.set_size(bytes); }
void ppcdrc_set_options(uint32_t options);
void ppcdrc_add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base);
void ppcdrc_add_hotspot(offs_t pc, uint32_t opcode, uint32_t cycles);
@@ -259,7 +260,7 @@ public:
void ppccom_get_dsisr();
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void device_stop() override ATTR_COLD;
diff --git a/src/devices/cpu/powerpc/ppccom.cpp b/src/devices/cpu/powerpc/ppccom.cpp
index 4e76a3efbb2..60e06ed9b27 100644
--- a/src/devices/cpu/powerpc/ppccom.cpp
+++ b/src/devices/cpu/powerpc/ppccom.cpp
@@ -10,9 +10,13 @@
#include "emu.h"
#include "ppccom.h"
+
#include "ppcfe.h"
#include "ppc_dasm.h"
+#include "emuopts.h"
+
+
/***************************************************************************
DEBUGGING
***************************************************************************/
@@ -596,7 +600,8 @@ static inline int sign_double(double x)
void ppc_device::device_start()
{
/* allocate the core from the near cache */
- m_core = (internal_ppc_state *)m_cache.alloc_near(sizeof(internal_ppc_state));
+ m_cache.allocate_cache(mconfig().options().drc_rwx());
+ m_core = m_cache.alloc_near<internal_ppc_state>();
memset(m_core, 0, sizeof(internal_ppc_state));
m_entry = nullptr;
diff --git a/src/devices/cpu/sh/sh.cpp b/src/devices/cpu/sh/sh.cpp
index 08054e047fe..4c1d987f639 100644
--- a/src/devices/cpu/sh/sh.cpp
+++ b/src/devices/cpu/sh/sh.cpp
@@ -3,13 +3,38 @@
#include "emu.h"
#include "sh.h"
+
#include "sh_dasm.h"
+
#include "cpu/drcumlsh.h"
+#include "emuopts.h"
+
+
+sh_common_execution::sh_common_execution(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness, address_map_constructor internal)
+ : cpu_device(mconfig, type, tag, owner, clock)
+ , m_sh2_state(nullptr)
+ , m_cache(CACHE_SIZE + sizeof(internal_sh2_state))
+ , m_drcuml(nullptr)
+ , m_drcoptions(0)
+ , m_entry(nullptr)
+ , m_read8(nullptr)
+ , m_write8(nullptr)
+ , m_read16(nullptr)
+ , m_write16(nullptr)
+ , m_read32(nullptr)
+ , m_write32(nullptr)
+ , m_interrupt(nullptr)
+ , m_nocode(nullptr)
+ , m_out_of_cycles(nullptr)
+{
+}
+
void sh_common_execution::device_start()
{
/* allocate the implementation-specific state from the full cache */
- m_sh2_state = (internal_sh2_state *)m_cache.alloc_near(sizeof(internal_sh2_state));
+ m_cache.allocate_cache(mconfig().options().drc_rwx());
+ m_sh2_state = m_cache.alloc_near<internal_sh2_state>();
save_item(NAME(m_sh2_state->pc));
save_item(NAME(m_sh2_state->sr));
diff --git a/src/devices/cpu/sh/sh.h b/src/devices/cpu/sh/sh.h
index 9980fa87709..44023ac096e 100644
--- a/src/devices/cpu/sh/sh.h
+++ b/src/devices/cpu/sh/sh.h
@@ -101,24 +101,6 @@ class sh_common_execution : public cpu_device
{
public:
- sh_common_execution(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness, address_map_constructor internal)
- : cpu_device(mconfig, type, tag, owner, clock)
- , m_sh2_state(nullptr)
- , m_cache(CACHE_SIZE + sizeof(internal_sh2_state))
- , m_drcuml(nullptr)
- , m_drcoptions(0)
- , m_entry(nullptr)
- , m_read8(nullptr)
- , m_write8(nullptr)
- , m_read16(nullptr)
- , m_write16(nullptr)
- , m_read32(nullptr)
- , m_write32(nullptr)
- , m_interrupt(nullptr)
- , m_nocode(nullptr)
- , m_out_of_cycles(nullptr)
- { }
-
// Data that needs to be stored close to the generated DRC code
struct internal_sh2_state
{
@@ -204,6 +186,8 @@ protected:
EXECUTE_RESET_CACHE = 3
};
+ sh_common_execution(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness, address_map_constructor internal);
+
void ADD(uint32_t m, uint32_t n);
void ADDI(uint32_t i, uint32_t n);
void ADDC(uint32_t m, uint32_t n);
diff --git a/src/devices/cpu/sharc/sharc.cpp b/src/devices/cpu/sharc/sharc.cpp
index f03dd5bbfc4..439f10b42d4 100644
--- a/src/devices/cpu/sharc/sharc.cpp
+++ b/src/devices/cpu/sharc/sharc.cpp
@@ -7,8 +7,11 @@
#include "emu.h"
#include "sharc.h"
-#include "sharcfe.h"
+
#include "sharcdsm.h"
+#include "sharcfe.h"
+
+#include "emuopts.h"
#define DISABLE_FAST_REGISTERS 1
@@ -474,7 +477,8 @@ void adsp21062_device::external_dma_write(uint32_t address, uint64_t data)
void adsp21062_device::device_start()
{
- m_core = (sharc_internal_state *)m_cache.alloc_near(sizeof(sharc_internal_state));
+ m_cache.allocate_cache(mconfig().options().drc_rwx());
+ m_core = m_cache.alloc_near<sharc_internal_state>();
memset(m_core, 0, sizeof(sharc_internal_state));
m_program = &space(AS_PROGRAM);
diff --git a/src/devices/cpu/uml.cpp b/src/devices/cpu/uml.cpp
index 0beb9a7a00e..85496960686 100644
--- a/src/devices/cpu/uml.cpp
+++ b/src/devices/cpu/uml.cpp
@@ -236,7 +236,7 @@ opcode_info const instruction::s_opcode_info_table[OP_MAX] =
//-------------------------------------------------
uml::code_handle::code_handle(drcuml_state &drcuml, const char *name)
- : m_code(reinterpret_cast<drccodeptr *>(drcuml.cache().alloc_near(sizeof(drccodeptr))))
+ : m_code(drcuml.cache().alloc_near<drccodeptr>())
, m_string(name)
, m_drcuml(drcuml)
{
diff --git a/src/devices/cpu/unsp/unsp.cpp b/src/devices/cpu/unsp/unsp.cpp
index 6a815b7f441..5f580c8ce28 100644
--- a/src/devices/cpu/unsp/unsp.cpp
+++ b/src/devices/cpu/unsp/unsp.cpp
@@ -18,16 +18,18 @@
#include "emu.h"
#include "unsp.h"
-#include "unspfe.h"
#include "unspdasm.h"
+#include "unspfe.h"
+
+#include "emuopts.h"
#include <climits>
DEFINE_DEVICE_TYPE(UNSP, unsp_device, "unsp", "SunPlus u'nSP (ISA 1.0)")
// 1.1 is just 1.0 with better CPI?
DEFINE_DEVICE_TYPE(UNSP_11, unsp_11_device, "unsp_11", "SunPlus u'nSP (ISA 1.1)")
- // it's possible that most unSP systems we emulate are 1.2, but are not using 99% of the additional features / instructions over 1.0 (only enable_irq and enable_fiq are meant to be 1.2 specific and used, but that could be a research error)
+ // it's possible that most μ'nSP systems we emulate are 1.2, but are not using 99% of the additional features / instructions over 1.0 (only enable_irq and enable_fiq are meant to be 1.2 specific and used, but that could be a research error)
DEFINE_DEVICE_TYPE(UNSP_12, unsp_12_device, "unsp_12", "SunPlus u'nSP (ISA 1.2)")
// found on GCM394 die (based on use of 2 extended push/pop opcodes in the smartfp irq), has extra instructions
DEFINE_DEVICE_TYPE(UNSP_20, unsp_20_device, "unsp_20", "SunPlus u'nSP (ISA 2.0)")
@@ -43,9 +45,9 @@ unsp_device::unsp_device(const machine_config &mconfig, device_type type, const
#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
, m_log_ops(0)
#endif
- , m_drccache(CACHE_SIZE + sizeof(unsp_device))
- , m_drcuml(nullptr)
- , m_drcfe(nullptr)
+ , m_drccache(CACHE_SIZE + sizeof(internal_unsp_state))
+ , m_drcuml()
+ , m_drcfe()
, m_drcoptions(0)
, m_cache_dirty(0)
, m_entry(nullptr)
@@ -190,16 +192,24 @@ void unsp_device::unimplemented_opcode(uint16_t op, uint16_t ximm, uint16_t ximm
void unsp_device::device_start()
{
-
- m_core = (internal_unsp_state *)m_drccache.alloc_near(sizeof(internal_unsp_state));
- memset(m_core, 0, sizeof(internal_unsp_state));
-
#if ENABLE_UNSP_DRC
m_enable_drc = allow_drc() && (m_iso < 12);
#else
m_enable_drc = false;
#endif
+ if (m_enable_drc)
+ {
+ m_drccache.allocate_cache(mconfig().options().drc_rwx());
+ m_core = m_drccache.alloc_near<internal_unsp_state>();
+ }
+ else
+ {
+ m_core = &m_local_core;
+ }
+ memset(m_core, 0, sizeof(internal_unsp_state));
+
+
#if UNSP_LOG_REGS
if (m_enable_drc)
m_log_file = fopen("unsp_drc.bin", "wb");
@@ -212,34 +222,37 @@ void unsp_device::device_start()
space(AS_PROGRAM).cache(m_cache);
space(AS_PROGRAM).specific(m_program);
- uint32_t umlflags = 0;
- m_drcuml = std::make_unique<drcuml_state>(*this, m_drccache, umlflags, 1, 23, 0);
-
- // add UML symbols-
- m_drcuml->symbol_add(&m_core->m_r[REG_SP], sizeof(uint32_t), "SP");
- m_drcuml->symbol_add(&m_core->m_r[REG_R1], sizeof(uint32_t), "R1");
- m_drcuml->symbol_add(&m_core->m_r[REG_R2], sizeof(uint32_t), "R2");
- m_drcuml->symbol_add(&m_core->m_r[REG_R3], sizeof(uint32_t), "R3");
- m_drcuml->symbol_add(&m_core->m_r[REG_R4], sizeof(uint32_t), "R4");
- m_drcuml->symbol_add(&m_core->m_r[REG_BP], sizeof(uint32_t), "BP");
- m_drcuml->symbol_add(&m_core->m_r[REG_SR], sizeof(uint32_t), "SR");
- m_drcuml->symbol_add(&m_core->m_r[REG_PC], sizeof(uint32_t), "PC");
- m_drcuml->symbol_add(&m_core->m_enable_irq, sizeof(uint32_t), "IRQE");
- m_drcuml->symbol_add(&m_core->m_enable_fiq, sizeof(uint32_t), "FIQE");
- m_drcuml->symbol_add(&m_core->m_fir_move, sizeof(uint32_t), "FIR_MOV");
- m_drcuml->symbol_add(&m_core->m_sb, sizeof(uint32_t), "SB");
- m_drcuml->symbol_add(&m_core->m_aq, sizeof(uint32_t), "AQ");
- m_drcuml->symbol_add(&m_core->m_fra, sizeof(uint32_t), "FRA");
- m_drcuml->symbol_add(&m_core->m_bnk, sizeof(uint32_t), "BNK");
- m_drcuml->symbol_add(&m_core->m_ine, sizeof(uint32_t), "INE");
- m_drcuml->symbol_add(&m_core->m_pri, sizeof(uint32_t), "PRI");
- m_drcuml->symbol_add(&m_core->m_icount, sizeof(m_core->m_icount), "icount");
-
- /* initialize the front-end helper */
- m_drcfe = std::make_unique<unsp_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE);
-
- /* mark the cache dirty so it is updated on next execute */
- m_cache_dirty = true;
+ if (m_enable_drc)
+ {
+ uint32_t umlflags = 0;
+ m_drcuml = std::make_unique<drcuml_state>(*this, m_drccache, umlflags, 1, 23, 0);
+
+ // add UML symbols-
+ m_drcuml->symbol_add(&m_core->m_r[REG_SP], sizeof(uint32_t), "SP");
+ m_drcuml->symbol_add(&m_core->m_r[REG_R1], sizeof(uint32_t), "R1");
+ m_drcuml->symbol_add(&m_core->m_r[REG_R2], sizeof(uint32_t), "R2");
+ m_drcuml->symbol_add(&m_core->m_r[REG_R3], sizeof(uint32_t), "R3");
+ m_drcuml->symbol_add(&m_core->m_r[REG_R4], sizeof(uint32_t), "R4");
+ m_drcuml->symbol_add(&m_core->m_r[REG_BP], sizeof(uint32_t), "BP");
+ m_drcuml->symbol_add(&m_core->m_r[REG_SR], sizeof(uint32_t), "SR");
+ m_drcuml->symbol_add(&m_core->m_r[REG_PC], sizeof(uint32_t), "PC");
+ m_drcuml->symbol_add(&m_core->m_enable_irq, sizeof(uint32_t), "IRQE");
+ m_drcuml->symbol_add(&m_core->m_enable_fiq, sizeof(uint32_t), "FIQE");
+ m_drcuml->symbol_add(&m_core->m_fir_move, sizeof(uint32_t), "FIR_MOV");
+ m_drcuml->symbol_add(&m_core->m_sb, sizeof(uint32_t), "SB");
+ m_drcuml->symbol_add(&m_core->m_aq, sizeof(uint32_t), "AQ");
+ m_drcuml->symbol_add(&m_core->m_fra, sizeof(uint32_t), "FRA");
+ m_drcuml->symbol_add(&m_core->m_bnk, sizeof(uint32_t), "BNK");
+ m_drcuml->symbol_add(&m_core->m_ine, sizeof(uint32_t), "INE");
+ m_drcuml->symbol_add(&m_core->m_pri, sizeof(uint32_t), "PRI");
+ m_drcuml->symbol_add(&m_core->m_icount, sizeof(m_core->m_icount), "icount");
+
+ /* initialize the front-end helper */
+ m_drcfe = std::make_unique<unsp_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE);
+
+ /* mark the cache dirty so it is updated on next execute */
+ m_cache_dirty = true;
+ }
// register our state for the debugger
state_add(STATE_GENFLAGS, "GENFLAGS", m_core->m_r[REG_SR]).callimport().callexport().formatstr("%4s").noshow();
@@ -339,14 +352,8 @@ void unsp_20_device::device_reset()
void unsp_device::device_stop()
{
- if (m_drcfe != nullptr)
- {
- m_drcfe = nullptr;
- }
- if (m_drcuml != nullptr)
- {
- m_drcuml = nullptr;
- }
+ m_drcfe.reset();
+ m_drcuml.reset();
#if UNSP_LOG_REGS
fclose(m_log_file);
#endif
diff --git a/src/devices/cpu/unsp/unsp.h b/src/devices/cpu/unsp/unsp.h
index b7b72a3cf5a..05d8871cb76 100644
--- a/src/devices/cpu/unsp/unsp.h
+++ b/src/devices/cpu/unsp/unsp.h
@@ -121,35 +121,6 @@ public:
void cfunc_muls();
protected:
- unsp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal);
-
- // device-level overrides
- virtual void device_start() override ATTR_COLD;
- virtual void device_reset() override ATTR_COLD;
- virtual void device_stop() override ATTR_COLD;
-
- // device_execute_interface overrides
- virtual uint32_t execute_min_cycles() const noexcept override { return 5; }
- virtual uint32_t execute_max_cycles() const noexcept override { return 5; }
- virtual void execute_run() override;
- virtual void execute_set_input(int inputnum, int state) override;
-
- // device_memory_interface overrides
- virtual space_config_vector memory_space_config() const override;
-
- // device_state_interface overrides
- virtual void state_import(const device_state_entry& entry) override;
- virtual void state_export(const device_state_entry& entry) override;
- virtual void state_string_export(const device_state_entry& entry, std::string& str) const override;
-
- // device_disasm_interface overrides
- virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
-
- // HACK: IRQ line state can only be modified directly by hardware on-board the SPG SoC itself.
- // Therefore, to avoid an unnecessary scheduler sync when the derived spg2xx_device sets or
- // clears an interrupt line, we provide this direct accessor.
- void set_state_unsynced(int inputnum, int state);
-
enum : uint32_t
{
REG_SP = 0,
@@ -206,10 +177,35 @@ protected:
int m_icount;
};
- /* core state */
- internal_unsp_state* m_core;
+ unsp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal);
+
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_stop() override ATTR_COLD;
+
+ // device_execute_interface overrides
+ virtual uint32_t execute_min_cycles() const noexcept override { return 5; }
+ virtual uint32_t execute_max_cycles() const noexcept override { return 5; }
+ virtual void execute_run() override;
+ virtual void execute_set_input(int inputnum, int state) override;
+
+ // device_memory_interface overrides
+ virtual space_config_vector memory_space_config() const override;
+
+ // device_state_interface overrides
+ virtual void state_import(const device_state_entry& entry) override;
+ virtual void state_export(const device_state_entry& entry) override;
+ virtual void state_string_export(const device_state_entry& entry, std::string& str) const override;
+
+ // device_disasm_interface overrides
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+ // HACK: IRQ line state can only be modified directly by hardware on-board the SPG SoC itself.
+ // Therefore, to avoid an unnecessary scheduler sync when the derived spg2xx_device sets or
+ // clears an interrupt line, we provide this direct accessor.
+ void set_state_unsynced(int inputnum, int state);
-protected:
uint16_t read16(uint32_t address) { return m_program.read_word(address); }
void write16(uint32_t address, uint16_t data)
@@ -245,6 +241,9 @@ protected:
void unimplemented_opcode(uint16_t op, uint16_t ximm, uint16_t ximm_2);
virtual bool op_is_divq(const uint16_t op) { return false; }
+ /* core state */
+ internal_unsp_state* m_core;
+
int m_iso;
static char const *const regs[];
@@ -286,7 +285,6 @@ private:
void execute_one(const uint16_t op);
-
address_space_config m_program_config;
memory_access<23, 1, -1, ENDIANNESS_BIG>::cache m_cache;
memory_access<23, 1, -1, ENDIANNESS_BIG>::specific m_program;
@@ -319,6 +317,7 @@ private:
bool m_enable_drc;
uint16_t m_vectorbase;
+ internal_unsp_state m_local_core; // for non-DRC mode
void execute_run_drc();
void flush_drc_cache();
diff --git a/src/devices/sound/swp30.cpp b/src/devices/sound/swp30.cpp
index 4939af3cebd..bb0ad7f6011 100644
--- a/src/devices/sound/swp30.cpp
+++ b/src/devices/sound/swp30.cpp
@@ -9,6 +9,7 @@
#include "cpu/drcumlsh.h"
#include "debugger.h"
+#include "emuopts.h"
#include <algorithm>
#include <sstream>
@@ -1718,7 +1719,8 @@ void swp30_device::device_start()
m_wave->cache(m_wave_cache);
m_reverb->cache(m_reverb_cache);
- m_meg = static_cast<meg_state *>(m_drccache.alloc_near(sizeof(meg_state)));
+ m_drccache.allocate_cache(mconfig().options().drc_rwx());
+ m_meg = m_drccache.alloc_near<meg_state>();
m_meg->m_swp = this;
m_meg->reset();
diff --git a/src/emu/emuopts.cpp b/src/emu/emuopts.cpp
index ae188b6fd03..1e82325e266 100644
--- a/src/emu/emuopts.cpp
+++ b/src/emu/emuopts.cpp
@@ -197,7 +197,8 @@ const options_entry emu_options::s_option_entries[] =
// misc options
{ nullptr, nullptr, core_options::option_type::HEADER, "CORE MISC OPTIONS" },
- { OPTION_DRC, "1", core_options::option_type::BOOLEAN, "enable DRC CPU core if available" },
+ { OPTION_DRC, "1", core_options::option_type::BOOLEAN, "enable DRC CPU cores if available" },
+ { OPTION_DRC_RWX, "1", core_options::option_type::BOOLEAN, "allow DRC to use writable executable pages if supported" },
{ OPTION_DRC_USE_C, "0", core_options::option_type::BOOLEAN, "force DRC to use C backend" },
{ OPTION_DRC_LOG_UML, "0", core_options::option_type::BOOLEAN, "write DRC UML disassembly log" },
{ OPTION_DRC_LOG_NATIVE, "0", core_options::option_type::BOOLEAN, "write DRC native disassembly log" },
diff --git a/src/emu/emuopts.h b/src/emu/emuopts.h
index 3940baf70f8..8755678b0e5 100644
--- a/src/emu/emuopts.h
+++ b/src/emu/emuopts.h
@@ -161,6 +161,7 @@
// core misc options
#define OPTION_DRC "drc"
+#define OPTION_DRC_RWX "drc_rwx"
#define OPTION_DRC_USE_C "drc_use_c"
#define OPTION_DRC_LOG_UML "drc_log_uml"
#define OPTION_DRC_LOG_NATIVE "drc_log_native"
@@ -444,6 +445,7 @@ public:
// core misc options
bool drc() const { return bool_value(OPTION_DRC); }
+ bool drc_rwx() const { return bool_value(OPTION_DRC_RWX); }
bool drc_use_c() const { return bool_value(OPTION_DRC_USE_C); }
bool drc_log_uml() const { return bool_value(OPTION_DRC_LOG_UML); }
bool drc_log_native() const { return bool_value(OPTION_DRC_LOG_NATIVE); }