diff options
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); } |
