// license:BSD-3-Clause // copyright-holders:Aaron Giles /*************************************************************************** drccache.h Universal dynamic recompiler cache management. ***************************************************************************/ #ifndef MAME_CPU_DRCCACHE_H #define MAME_CPU_DRCCACHE_H #pragma once #include "modules/lib/osdlib.h" //************************************************************************** // MACROS //************************************************************************** // ensure that a given pointer is within the cache boundaries #define assert_in_cache(c,p) assert((c).contains_pointer(p)) #define assert_in_near_cache(c,p) assert((c).contains_near_pointer(p)) //************************************************************************** // TYPE DEFINITIONS //************************************************************************** // generic code pointer typedef uint8_t *drccodeptr; // helper template for oob codegen typedef delegate drc_oob_delegate; // drc_cache class drc_cache { public: // construction/destruction drc_cache(size_t bytes); ~drc_cache(); // getters drccodeptr near() const { return m_near; } drccodeptr base() const { return m_base; } drccodeptr top() const { return m_top; } // pointer checking bool contains_pointer(const void *ptr) const { return ((const drccodeptr)ptr >= m_near && (const drccodeptr)ptr < m_near + m_size); } 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 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); // codegen helpers void codegen_init(); void codegen_complete(); drccodeptr *begin_codegen(uint32_t reserve_bytes); 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; // minimum alignment, in bytes (must be power of 2) static constexpr size_t CACHE_ALIGNMENT = alignof(std::max_align_t); // largest permanent allocation we allow static constexpr 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; // 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 m_oob_list; // list of active oob handlers std::list m_oob_free; // list of recyclable oob handlers // free lists struct free_link { free_link * m_next; // pointer to the next guy }; free_link * m_free[MAX_PERMANENT_ALLOC / CACHE_ALIGNMENT]; free_link * m_nearfree[MAX_PERMANENT_ALLOC / CACHE_ALIGNMENT]; }; #endif // MAME_CPU_DRCCACHE_H