// license:BSD-3-Clause // copyright-holders:Aaron Giles /*************************************************************************** drcbeut.h Utility functions for dynamic recompiling backends. ***************************************************************************/ #pragma once #ifndef __DRCBEUT_H__ #define __DRCBEUT_H__ #include "drcuml.h" //************************************************************************** // TYPE DEFINITIONS //************************************************************************** // ======================> drc_hash_table // common hash table management class drc_hash_table { public: // construction/destruction drc_hash_table(drc_cache &cache, UINT32 modes, UINT8 addrbits, UINT8 ignorebits); // getters drccodeptr ***base() const { return m_base; } UINT8 l1bits() const { return m_l1bits; } UINT8 l2bits() const { return m_l2bits; } UINT8 l1shift() const { return m_l1shift; } UINT8 l2shift() const { return m_l2shift; } offs_t l1mask() const { return m_l1mask; } offs_t l2mask() const { return m_l2mask; } bool is_mode_populated(UINT32 mode) const { return m_base[mode] != m_emptyl1; } // set up and configuration bool reset(); void set_default_codeptr(drccodeptr code); // block begin/end void block_begin(drcuml_block &block, const uml::instruction *instlist, UINT32 numinst); void block_end(drcuml_block &block); // code pointer access bool set_codeptr(UINT32 mode, UINT32 pc, drccodeptr code); drccodeptr get_codeptr(UINT32 mode, UINT32 pc) { assert(mode < m_modes); return m_base[mode][(pc >> m_l1shift) & m_l1mask][(pc >> m_l2shift) & m_l2mask]; } bool code_exists(UINT32 mode, UINT32 pc) { return get_codeptr(mode, pc) != m_nocodeptr; } private: // internal state drc_cache & m_cache; // cache where allocations come from UINT32 m_modes; // number of modes supported drccodeptr m_nocodeptr; // pointer to code which will handle missing entries UINT8 m_l1bits; // bits worth of entries in l1 hash tables UINT8 m_l2bits; // bits worth of entries in l2 hash tables UINT8 m_l1shift; // shift to apply to the PC to get the l1 hash entry UINT8 m_l2shift; // shift to apply to the PC to get the l2 hash entry offs_t m_l1mask; // mask to apply after shifting offs_t m_l2mask; // mask to apply after shifting drccodeptr *** m_base; // pointer to the l1 table for each mode drccodeptr ** m_emptyl1; // pointer to empty l1 hash table drccodeptr * m_emptyl2; // pointer to empty l2 hash table }; // ======================> drc_map_variables // common map variable management class drc_map_variables { public: // construction/destruction drc_map_variables(drc_cache &cache, UINT64 uniquevalue); ~drc_map_variables(); // block begin/end void block_begin(drcuml_block &block); void block_end(drcuml_block &block); // get/set values void set_value(drccodeptr codebase, UINT32 mapvar, UINT32 newvalue); UINT32 get_value(drccodeptr codebase, UINT32 mapvar) const; UINT32 get_last_value(UINT32 mapvar); // static accessors to be called directly by generated code static UINT32 static_get_value(drc_map_variables &map, drccodeptr codebase, UINT32 mapvar); private: // internal state drc_cache & m_cache; // pointer to the cache UINT64 m_uniquevalue; // unique value used to find the table UINT32 m_mapvalue[uml::MAPVAR_END - uml::MAPVAR_M0]; // array of current values // list of entries struct map_entry { map_entry *next() const { return m_next; } map_entry * m_next; // pointer to next map entry drccodeptr m_codeptr; // pointer to the relevant code UINT32 m_mapvar; // map variable id UINT32 m_newval; // value of the variable starting at codeptr }; simple_list m_entry_list; // list of entries }; // ======================> drc_label_list typedef delegate drc_label_fixup_delegate; // structure holding a live list of labels class drc_label_list { public: // construction/destruction drc_label_list(drc_cache &cache); ~drc_label_list(); // block begin/end void block_begin(drcuml_block &block); void block_end(drcuml_block &block); // get/set values drccodeptr get_codeptr(uml::code_label label, drc_label_fixup_delegate fixup, void *param); void set_codeptr(uml::code_label label, drccodeptr codeptr); private: struct label_entry { label_entry *next() const { return m_next; } label_entry * m_next; // pointer to next label uml::code_label m_label; // the label specified drccodeptr m_codeptr; // pointer to the relevant code }; struct label_fixup { label_fixup *next() const { return m_next; } label_fixup * m_next; // pointer to the next oob label_entry * m_label; // the label in question drc_label_fixup_delegate m_callback; // callback }; // internal helpers void reset(bool fatal_on_leftovers); label_entry *find_or_allocate(uml::code_label label); void oob_callback(drccodeptr *codeptr, void *param1, void *param2); // internal state drc_cache & m_cache; // pointer to the cache simple_list m_list; // head of the live list simple_list m_fixup_list; // list of pending oob fixups drc_oob_delegate m_oob_callback_delegate; // pre-computed delegate }; #endif /* __DRCBEUT_H__ */