From 1e1e8eb034358f200a61561feeafe422cd9321a1 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Sat, 24 Mar 2018 03:53:40 +1100 Subject: modernise drcuml somewhat (nw) --- src/devices/cpu/drcuml.cpp | 256 +++++++++++++++++++------------------ src/devices/cpu/drcuml.h | 160 ++++++++++++----------- src/devices/cpu/powerpc/ppc.h | 4 +- src/devices/cpu/powerpc/ppcdrc.cpp | 128 +++++++++---------- src/devices/cpu/uml.cpp | 4 +- src/devices/cpu/uml.h | 7 +- 6 files changed, 281 insertions(+), 278 deletions(-) diff --git a/src/devices/cpu/drcuml.cpp b/src/devices/cpu/drcuml.cpp index 6bc65ef8c3e..dcf8196dfe6 100644 --- a/src/devices/cpu/drcuml.cpp +++ b/src/devices/cpu/drcuml.cpp @@ -32,13 +32,14 @@ ***************************************************************************/ #include "emu.h" -#include "emuopts.h" #include "drcuml.h" + +#include "emuopts.h" #include "drcbec.h" #include "drcbex86.h" #include "drcbex64.h" -using namespace uml; +#include @@ -66,11 +67,11 @@ typedef NATIVE_DRC drcbe_native; // structure describing back-end validation test struct bevalidate_test { - opcode_t opcode; - uint8_t size; - uint8_t iflags; - uint8_t flags; - uint64_t param[4]; + uml::opcode_t opcode; + u8 size; + u8 iflags; + u8 flags; + u64 param[4]; }; @@ -84,11 +85,12 @@ struct bevalidate_test //------------------------------------------------- drcbe_interface::drcbe_interface(drcuml_state &drcuml, drc_cache &cache, device_t &device) - : m_drcuml(drcuml), - m_cache(cache), - m_device(device), - m_state(*(drcuml_machine_state *)cache.alloc_near(sizeof(m_state))), - m_accessors(nullptr) + : m_drcuml(drcuml) + , m_cache(cache) + , m_device(device) + , m_space() + , m_state(*reinterpret_cast(cache.alloc_near(sizeof(m_state)))) + , m_accessors(nullptr) { // reset the machine state memset(&m_state, 0, sizeof(m_state)); @@ -97,17 +99,19 @@ drcbe_interface::drcbe_interface(drcuml_state &drcuml, drc_cache &cache, device_ device_memory_interface *memory; if (device.interface(memory)) { - int count = memory->max_space_count(); - m_accessors = ((data_accessors *)cache.alloc_near(sizeof(*m_accessors) * count)); + int const count = memory->max_space_count(); + m_accessors = reinterpret_cast(cache.alloc_near(sizeof(*m_accessors) * count)); memset(m_accessors, 0, sizeof(*m_accessors) * count); m_space.resize(count, nullptr); for (int spacenum = 0; spacenum < count; ++spacenum) + { if (memory->has_space(spacenum)) { m_space[spacenum] = &memory->space(spacenum); m_space[spacenum]->accessors(m_accessors[spacenum]); } + } } } @@ -130,21 +134,19 @@ drcbe_interface::~drcbe_interface() // drcuml_state - constructor //------------------------------------------------- -drcuml_state::drcuml_state(device_t &device, drc_cache &cache, uint32_t flags, int modes, int addrbits, int ignorebits) - : m_device(device), - m_cache(cache), - m_drcbe_interface(device.machine().options().drc_use_c() ? - std::unique_ptr{ std::make_unique(*this, device, cache, flags, modes, addrbits, ignorebits) } : - std::unique_ptr{ std::make_unique(*this, device, cache, flags, modes, addrbits, ignorebits) }), - m_beintf(*m_drcbe_interface.get()), - m_umllog(nullptr) +drcuml_state::drcuml_state(device_t &device, drc_cache &cache, u32 flags, int modes, int addrbits, int ignorebits) + : m_device(device) + , m_cache(cache) + , m_beintf(device.machine().options().drc_use_c() + ? std::unique_ptr{ new drcbe_c(*this, device, cache, flags, modes, addrbits, ignorebits) } + : std::unique_ptr{ new drcbe_native(*this, device, cache, flags, modes, addrbits, ignorebits) }) + , m_umllog(device.machine().options().drc_log_uml() + ? new std::ofstream(util::string_format("drcuml_%s.asm", device.shortname())) + : nullptr) + , m_blocklist() + , m_handlelist() + , m_symlist() { - // if we're to log, create the logfile - if (device.machine().options().drc_log_uml()) - { - std::string filename = std::string("drcuml_").append(m_device.shortname()).append(".asm"); - m_umllog = fopen(filename.c_str(), "w"); - } } @@ -154,9 +156,6 @@ drcuml_state::drcuml_state(device_t &device, drc_cache &cache, uint32_t flags, i drcuml_state::~drcuml_state() { - // close any files - if (m_umllog != nullptr) - fclose(m_umllog); } @@ -174,22 +173,24 @@ void drcuml_state::reset() m_cache.flush(); // reset all handle code pointers - for (code_handle *handle = m_handlelist.first(); handle != nullptr; handle = handle->next()) - *handle->m_code = nullptr; + for (uml::code_handle &handle : m_handlelist) + *handle.codeptr_addr() = nullptr; // call the backend to reset - m_beintf.reset(); + m_beintf->reset(); // do a one-time validation if requested -/* if (VALIDATE_BACKEND) - { - static bool validated = false; - if (!validated) - { - validated = true; - validate_backend(this); - } - }*/ +#if 0 + if (VALIDATE_BACKEND) + { + static bool validated = false; + if (!validated) + { + validated = true; + validate_backend(this); + } + } +#endif } catch (drcuml_block::abort_compilation &) { @@ -205,14 +206,16 @@ void drcuml_state::reset() drcuml_block *drcuml_state::begin_block(uint32_t maxinst) { // find an inactive block that matches our qualifications - drcuml_block *bestblock = nullptr; - for (drcuml_block *block = m_blocklist.first(); block != nullptr; block = block->next()) - if (!block->inuse() && block->maxinst() >= maxinst && (bestblock == nullptr || block->maxinst() < bestblock->maxinst())) - bestblock = block; + drcuml_block *bestblock(nullptr); + for (drcuml_block &block : m_blocklist) + { + if (!block.inuse() && (block.maxinst() >= maxinst) && (!bestblock || (block.maxinst() < bestblock->maxinst()))) + bestblock = █ + } // if we failed to find one, allocate a new one - if (bestblock == nullptr) - bestblock = &m_blocklist.append(*global_alloc(drcuml_block(*this, maxinst * 3/2))); + if (!bestblock) + bestblock = &*m_blocklist.emplace(m_blocklist.end(), *this, maxinst * 3 / 2); // start the block bestblock->begin(); @@ -224,10 +227,10 @@ drcuml_block *drcuml_state::begin_block(uint32_t maxinst) // handle_alloc - allocate a new handle //------------------------------------------------- -code_handle *drcuml_state::handle_alloc(const char *name) +uml::code_handle *drcuml_state::handle_alloc(char const *name) { // allocate the handle, add it to our list, and return it - return &m_handlelist.append(*global_alloc(code_handle(*this, name))); + return &*m_handlelist.emplace(m_handlelist.end(), *this, name); } @@ -236,9 +239,9 @@ code_handle *drcuml_state::handle_alloc(const char *name) // symbol table //------------------------------------------------- -void drcuml_state::symbol_add(void *base, uint32_t length, const char *name) +void drcuml_state::symbol_add(void *base, u32 length, char const *name) { - m_symlist.append(*global_alloc(symbol(base, length, name))); + m_symlist.emplace_back(base, length, name); } @@ -248,23 +251,22 @@ void drcuml_state::symbol_add(void *base, uint32_t length, const char *name) // found //------------------------------------------------- -const char *drcuml_state::symbol_find(void *base, uint32_t *offset) +const char *drcuml_state::symbol_find(void *base, u32 *offset) { - drccodeptr search = drccodeptr(base); + drccodeptr const search(reinterpret_cast(base)); // simple linear search - for (symbol *cursym = m_symlist.first(); cursym != nullptr; cursym = cursym->next()) - if (search >= cursym->m_base && search < cursym->m_base + cursym->m_length) + for (symbol const &cursym : m_symlist) + { + // if no offset pointer, only match perfectly + if (cursym.includes(search) && (offset || (cursym.base() == search))) { - // if no offset pointer, only match perfectly - if (offset == nullptr && search != cursym->m_base) - continue; - // return the offset and name - if (offset != nullptr) - *offset = search - cursym->m_base; - return cursym->m_name.c_str(); + if (offset) + *offset = search - cursym.base(); + return cursym.name().c_str(); } + } // not found; return nullptr return nullptr; @@ -272,22 +274,17 @@ const char *drcuml_state::symbol_find(void *base, uint32_t *offset) //------------------------------------------------- -// log_printf - directly printf to the UML log +// log_vprintf - directly printf to the UML log // if generated //------------------------------------------------- -void drcuml_state::log_printf(const char *format, ...) +void drcuml_state::log_vprintf(util::format_argument_pack const &args) { // if we have a file, print to it - if (m_umllog != nullptr) + if (m_umllog) { - va_list va; - - // do the printf - va_start(va, format); - vfprintf(m_umllog, format, va); - va_end(va); - fflush(m_umllog); + util::stream_format(*m_umllog, args); + m_umllog->flush(); } } @@ -301,13 +298,12 @@ void drcuml_state::log_printf(const char *format, ...) // drcuml_block - constructor //------------------------------------------------- -drcuml_block::drcuml_block(drcuml_state &drcuml, uint32_t maxinst) - : m_drcuml(drcuml), - m_next(nullptr), - m_nextinst(0), - m_maxinst(maxinst * 3/2), - m_inst(m_maxinst), - m_inuse(false) +drcuml_block::drcuml_block(drcuml_state &drcuml, u32 maxinst) + : m_drcuml(drcuml) + , m_nextinst(0) + , m_maxinst(maxinst * 3/2) + , m_inst(m_maxinst) + , m_inuse(false) { } @@ -380,7 +376,7 @@ void drcuml_block::abort() uml::instruction &drcuml_block::append() { // get a pointer to the next instruction - instruction &curinst = m_inst[m_nextinst++]; + uml::instruction &curinst(m_inst[m_nextinst++]); if (m_nextinst > m_maxinst) fatalerror("Overran maxinst in drcuml_block_append\n"); @@ -395,39 +391,39 @@ uml::instruction &drcuml_block::append() void drcuml_block::optimize() { - uint32_t mapvar[MAPVAR_COUNT] = { 0 }; + u32 mapvar[uml::MAPVAR_COUNT] = { 0 }; // iterate over instructions for (int instnum = 0; instnum < m_nextinst; instnum++) { - instruction &inst = m_inst[instnum]; + uml::instruction &inst(m_inst[instnum]); // first compute what flags we need - uint8_t accumflags = 0; - uint8_t remainingflags = inst.output_flags(); + u8 accumflags(0); + u8 remainingflags(inst.output_flags()); // scan ahead until we run out of possible remaining flags for (int scannum = instnum + 1; remainingflags != 0 && scannum < m_nextinst; scannum++) { // any input flags are required - const instruction &scan = m_inst[scannum]; + uml::instruction const &scan(m_inst[scannum]); accumflags |= scan.input_flags(); // if the scanahead instruction is unconditional, assume his flags are modified - if (scan.condition() == COND_ALWAYS) + if (scan.condition() == uml::COND_ALWAYS) remainingflags &= ~scan.modified_flags(); } inst.set_flags(accumflags); // track mapvars - if (inst.opcode() == OP_MAPVAR) - mapvar[inst.param(0).mapvar() - MAPVAR_M0] = inst.param(1).immediate(); + if (inst.opcode() == uml::OP_MAPVAR) + mapvar[inst.param(0).mapvar() - uml::MAPVAR_M0] = inst.param(1).immediate(); // convert all mapvar parameters to immediates - else if (inst.opcode() != OP_RECOVER) + else if (inst.opcode() != uml::OP_RECOVER) for (int pnum = 0; pnum < inst.numparams(); pnum++) if (inst.param(pnum).is_mapvar()) - inst.set_mapvar(pnum, mapvar[inst.param(pnum).mapvar() - MAPVAR_M0]); + inst.set_mapvar(pnum, mapvar[inst.param(pnum).mapvar() - uml::MAPVAR_M0]); // now that flags are correct, simplify the instruction inst.simplify(); @@ -445,41 +441,43 @@ void drcuml_block::disassemble() std::string comment; // iterate over instructions and output - int firstcomment = -1; + int firstcomment(-1); for (int instnum = 0; instnum < m_nextinst; instnum++) { - const instruction &inst = m_inst[instnum]; - bool flushcomments = false; + uml::instruction const &inst(m_inst[instnum]); + bool flushcomments(false); // remember comments and mapvars for later - if (inst.opcode() == OP_COMMENT || inst.opcode() == OP_MAPVAR) + if (inst.opcode() == uml::OP_COMMENT || inst.opcode() == uml::OP_MAPVAR) { if (firstcomment == -1) firstcomment = instnum; } // print labels, handles, and hashes left justified - else if (inst.opcode() == OP_LABEL) - m_drcuml.log_printf("$%X:\n", uint32_t(inst.param(0).label())); - else if (inst.opcode() == OP_HANDLE) + else if (inst.opcode() == uml::OP_LABEL) + m_drcuml.log_printf("$%X:\n", u32(inst.param(0).label())); + else if (inst.opcode() == uml::OP_HANDLE) m_drcuml.log_printf("%s:\n", inst.param(0).handle().string()); - else if (inst.opcode() == OP_HASH) - m_drcuml.log_printf("(%X,%X):\n", uint32_t(inst.param(0).immediate()), uint32_t(inst.param(1).immediate())); + else if (inst.opcode() == uml::OP_HASH) + m_drcuml.log_printf("(%X,%X):\n", u32(inst.param(0).immediate()), u32(inst.param(1).immediate())); // indent everything else with a tab else { - std::string dasm = m_inst[instnum].disasm(&m_drcuml); + std::string const dasm(m_inst[instnum].disasm(&m_drcuml)); // include the first accumulated comment with this line if (firstcomment != -1) { - m_drcuml.log_printf("\t%-50.50s; %s\n", dasm.c_str(), get_comment_text(m_inst[firstcomment], comment)); + m_drcuml.log_printf("\t%-50.50s; %s\n", dasm, get_comment_text(m_inst[firstcomment], comment)); firstcomment++; flushcomments = true; } else - m_drcuml.log_printf("\t%s\n", dasm.c_str()); + { + m_drcuml.log_printf("\t%s\n", dasm); + } } // flush any comments pending @@ -487,8 +485,8 @@ void drcuml_block::disassemble() { while (firstcomment <= instnum) { - const char *text = get_comment_text(m_inst[firstcomment++], comment); - if (text != nullptr) + char const *const text(get_comment_text(m_inst[firstcomment++], comment)); + if (text) m_drcuml.log_printf("\t%50s; %s\n", "", text); } firstcomment = -1; @@ -504,20 +502,24 @@ void drcuml_block::disassemble() // associated with a comment or mapvar //------------------------------------------------- -const char *drcuml_block::get_comment_text(const instruction &inst, std::string &comment) +char const *drcuml_block::get_comment_text(uml::instruction const &inst, std::string &comment) { - // comments return their strings - if (inst.opcode() == OP_COMMENT) + if (inst.opcode() == uml::OP_COMMENT) + { + // comments return their strings return comment.assign(inst.param(0).string()).c_str(); - - // mapvars comment about their values - else if (inst.opcode() == OP_MAPVAR) { - comment = string_format("m%d = $%X", (int)inst.param(0).mapvar() - MAPVAR_M0, (uint32_t)inst.param(1).immediate()); + } + else if (inst.opcode() == uml::OP_MAPVAR) + { + // mapvars comment about their values + comment = string_format("m%d = $%X", int(inst.param(0).mapvar() - uml::MAPVAR_M0), u32(inst.param(1).immediate())); return comment.c_str(); } - - // everything else is nullptr - return nullptr; + else + { + // everything else is nullptr + return nullptr; + } } @@ -549,12 +551,12 @@ inline uint8_t effective_test_psize(const opcode_info &opinfo, int pnum, int ins return instsize; } -#define TEST_ENTRY_2(op, size, p1, p2, flags) { OP_##op, size, 0, flags, { U64(p1), U64(p2) } }, -#define TEST_ENTRY_2F(op, size, p1, p2, iflags, flags) { OP_##op, size, iflags, flags, { U64(p1), U64(p2) } }, -#define TEST_ENTRY_3(op, size, p1, p2, p3, flags) { OP_##op, size, 0, flags, { U64(p1), U64(p2), U64(p3) } }, -#define TEST_ENTRY_3F(op, size, p1, p2, p3, iflags, flags) { OP_##op, size, iflags, flags, { U64(p1), U64(p2), U64(p3) } }, -#define TEST_ENTRY_4(op, size, p1, p2, p3, p4, flags) { OP_##op, size, 0, flags, { U64(p1), U64(p2), U64(p3), U64(p4) } }, -#define TEST_ENTRY_4F(op, size, p1, p2, p3, p4, iflags, flags) { OP_##op, size, iflags, flags, { U64(p1), U64(p2), U64(p3), U64(p4) } }, +#define TEST_ENTRY_2(op, size, p1, p2, flags) { OP_##op, size, 0, flags, { u64(p1), u64(p2) } }, +#define TEST_ENTRY_2F(op, size, p1, p2, iflags, flags) { OP_##op, size, iflags, flags, { u64(p1), u64(p2) } }, +#define TEST_ENTRY_3(op, size, p1, p2, p3, flags) { OP_##op, size, 0, flags, { u64(p1), u64(p2), u64(p3) } }, +#define TEST_ENTRY_3F(op, size, p1, p2, p3, iflags, flags) { OP_##op, size, iflags, flags, { u64(p1), u64(p2), u64(p3) } }, +#define TEST_ENTRY_4(op, size, p1, p2, p3, p4, flags) { OP_##op, size, 0, flags, { u64(p1), u64(p2), u64(p3), u64(p4) } }, +#define TEST_ENTRY_4F(op, size, p1, p2, p3, p4, iflags, flags) { OP_##op, size, iflags, flags, { u64(p1), u64(p2), u64(p3), u64(p4) } }, static const bevalidate_test bevalidate_test_list[] = { @@ -689,7 +691,7 @@ static const bevalidate_test bevalidate_test_list[] = static void validate_backend(drcuml_state *drcuml) { - code_handle *handles[3]; + uml::code_handle *handles[3]; int tnum; // allocate handles for the code @@ -739,7 +741,7 @@ static void validate_backend(drcuml_state *drcuml) or else move on to iterate over the flags -------------------------------------------------*/ -static void bevalidate_iterate_over_params(drcuml_state *drcuml, code_handle **handles, const bevalidate_test *test, parameter *paramlist, int pnum) +static void bevalidate_iterate_over_params(drcuml_state *drcuml, uml::code_handle **handles, const bevalidate_test *test, parameter *paramlist, int pnum) { const opcode_info *opinfo = opcode_info_table[test->opcode()]; drcuml_ptype ptype; @@ -812,7 +814,7 @@ static void bevalidate_iterate_over_params(drcuml_state *drcuml, code_handle **h all supported flag masks -------------------------------------------------*/ -static void bevalidate_iterate_over_flags(drcuml_state *drcuml, code_handle **handles, const bevalidate_test *test, parameter *paramlist) +static void bevalidate_iterate_over_flags(drcuml_state *drcuml, uml::code_handle **handles, const bevalidate_test *test, parameter *paramlist) { const opcode_info *opinfo = opcode_info_table[test->opcode()]; uint8_t flagmask = opinfo->outflags; @@ -831,7 +833,7 @@ static void bevalidate_iterate_over_flags(drcuml_state *drcuml, code_handle **ha results -------------------------------------------------*/ -static void bevalidate_execute(drcuml_state *drcuml, code_handle **handles, const bevalidate_test *test, const parameter *paramlist, uint8_t flagmask) +static void bevalidate_execute(drcuml_state *drcuml, uml::code_handle **handles, const bevalidate_test *test, const parameter *paramlist, uint8_t flagmask) { parameter params[ARRAY_LENGTH(test->param)]; drcuml_machine_state istate, fstate; @@ -1045,7 +1047,7 @@ static int bevalidate_verify_state(drcuml_state *drcuml, const drcuml_machine_st if (opinfo->param[pnum].output & PIO_OUT) { int psize = effective_test_psize(opinfo, pnum, test->size, test->param); - uint64_t mask = U64(0xffffffffffffffff) >> (64 - 8 * psize); + uint64_t mask = u64(0xffffffffffffffff) >> (64 - 8 * psize); uint64_t result = 0; // fetch the result from the parameters diff --git a/src/devices/cpu/drcuml.h b/src/devices/cpu/drcuml.h index ce808595e57..75dcadadc23 100644 --- a/src/devices/cpu/drcuml.h +++ b/src/devices/cpu/drcuml.h @@ -7,15 +7,19 @@ Universal machine language for dynamic recompiling CPU cores. ***************************************************************************/ +#ifndef MAME_CPU_DRCUML_H +#define MAME_CPU_DRCUML_H #pragma once -#ifndef MAME_DEVICES_CPU_DRCUML_H -#define MAME_DEVICES_CPU_DRCUML_H - #include "drccache.h" #include "uml.h" +#include +#include +#include +#include + //************************************************************************** // CONSTANTS @@ -37,11 +41,11 @@ class drcuml_state; union drcuml_ireg { #ifdef LSB_FIRST - struct { uint32_t l,h; } w; // 32-bit low, high parts of the register + struct { u32 l, h; } w; // 32-bit low, high parts of the register #else - struct { uint32_t h,l; } w; // 32-bit low, high parts of the register + struct { u32 h, l; } w; // 32-bit low, high parts of the register #endif - uint64_t d; // 64-bit full register + u64 d; // 64-bit full register }; @@ -49,47 +53,46 @@ union drcuml_ireg union drcuml_freg { #ifdef LSB_FIRST - struct { float l,h; } s; // 32-bit low, high parts of the register + struct { float l, h; } s; // 32-bit low, high parts of the register #else - struct { float h,l; } s; // 32-bit low, high parts of the register + struct { float h, l; } s; // 32-bit low, high parts of the register #endif - double d; // 64-bit full register + double d; // 64-bit full register }; // the collected machine state of a system struct drcuml_machine_state { - drcuml_ireg r[uml::REG_I_COUNT]; // integer registers - drcuml_freg f[uml::REG_F_COUNT]; // floating-point registers - uint32_t exp; // exception parameter register - uint8_t fmod; // fmod (floating-point mode) register - uint8_t flags; // flags state + drcuml_ireg r[uml::REG_I_COUNT]; // integer registers + drcuml_freg f[uml::REG_F_COUNT]; // floating-point registers + u32 exp; // exception parameter register + u8 fmod; // fmod (floating-point mode) register + u8 flags; // flags state }; // hints and information about the back-end struct drcbe_info { - uint8_t direct_iregs; // number of direct-mapped integer registers - uint8_t direct_fregs; // number of direct-mapped floating point registers + u8 direct_iregs; // number of direct-mapped integer registers + u8 direct_fregs; // number of direct-mapped floating point registers }; // a drcuml_block describes a basic block of instructions class drcuml_block { - friend class simple_list; - public: // construction/destruction - drcuml_block(drcuml_state &drcuml, uint32_t maxinst); + drcuml_block(drcuml_state &drcuml, u32 maxinst); + drcuml_block(drcuml_block const &) = delete; + drcuml_block &operator=(drcuml_block const &) = delete; ~drcuml_block(); // getters - drcuml_block *next() const { return m_next; } bool inuse() const { return m_inuse; } - uint32_t maxinst() const { return m_maxinst; } + u32 maxinst() const { return m_maxinst; } // code generation void begin(); @@ -111,15 +114,14 @@ private: // internal helpers void optimize(); void disassemble(); - const char *get_comment_text(const uml::instruction &inst, std::string &comment); + char const *get_comment_text(uml::instruction const &inst, std::string &comment); // internal state - drcuml_state & m_drcuml; // pointer back to the owning UML - drcuml_block * m_next; // pointer to next block - uint32_t m_nextinst; // next instruction to fill in the cache - uint32_t m_maxinst; // maximum number of instructions - std::vector m_inst; // pointer to the instruction list - bool m_inuse; // this block is in use + drcuml_state & m_drcuml; // pointer back to the owning UML + u32 m_nextinst; // next instruction to fill in the cache + u32 m_maxinst; // maximum number of instructions + std::vector m_inst; // pointer to the instruction list + bool m_inuse; // this block is in use }; @@ -127,26 +129,28 @@ private: class drcbe_interface { public: - // construction/destruction - drcbe_interface(drcuml_state &drcuml, drc_cache &cache, device_t &device); + // allow deleting through base pointer virtual ~drcbe_interface(); // required overrides virtual void reset() = 0; virtual int execute(uml::code_handle &entry) = 0; - virtual void generate(drcuml_block &block, const uml::instruction *instlist, uint32_t numinst) = 0; - virtual bool hash_exists(uint32_t mode, uint32_t pc) = 0; + virtual void generate(drcuml_block &block, uml::instruction const *instlist, u32 numinst) = 0; + virtual bool hash_exists(u32 mode, u32 pc) = 0; virtual void get_info(drcbe_info &info) = 0; virtual bool logging() const { return false; } protected: + // base constructor + drcbe_interface(drcuml_state &drcuml, drc_cache &cache, device_t &device); + // internal state - drcuml_state & m_drcuml; // pointer back to our owner - drc_cache & m_cache; // pointer to the cache - device_t & m_device; // CPU device we are associated with - std::vector m_space; // pointers to CPU's address space - drcuml_machine_state & m_state; // state of the machine (in near cache) - data_accessors * m_accessors; // memory accessors (in near cache) + drcuml_state & m_drcuml; // pointer back to our owner + drc_cache & m_cache; // pointer to the cache + device_t & m_device; // CPU device we are associated with + std::vector m_space; // pointers to CPU's address space + drcuml_machine_state & m_state; // state of the machine (in near cache) + data_accessors * m_accessors; // memory accessors (in near cache) }; @@ -155,7 +159,7 @@ class drcuml_state { public: // construction/destruction - drcuml_state(device_t &device, drc_cache &cache, uint32_t flags, int modes, int addrbits, int ignorebits); + drcuml_state(device_t &device, drc_cache &cache, u32 flags, int modes, int addrbits, int ignorebits); ~drcuml_state(); // getters @@ -164,64 +168,66 @@ public: // reset the state void reset(); - int execute(uml::code_handle &entry) { return m_beintf.execute(entry); } + int execute(uml::code_handle &entry) { return m_beintf->execute(entry); } // code generation - drcuml_block *begin_block(uint32_t maxinst); + drcuml_block *begin_block(u32 maxinst); // back-end interface - void get_backend_info(drcbe_info &info) { m_beintf.get_info(info); } - bool hash_exists(uint32_t mode, uint32_t pc) { return m_beintf.hash_exists(mode, pc); } - void generate(drcuml_block &block, uml::instruction *instructions, uint32_t count) { m_beintf.generate(block, instructions, count); } + void get_backend_info(drcbe_info &info) { m_beintf->get_info(info); } + bool hash_exists(u32 mode, u32 pc) { return m_beintf->hash_exists(mode, pc); } + void generate(drcuml_block &block, uml::instruction *instructions, u32 count) { m_beintf->generate(block, instructions, count); } // handle management - uml::code_handle *handle_alloc(const char *name); + uml::code_handle *handle_alloc(char const *name); // symbol management - void symbol_add(void *base, uint32_t length, const char *name); - const char *symbol_find(void *base, uint32_t *offset = nullptr); + void symbol_add(void *base, u32 length, char const *name); + char const *symbol_find(void *base, u32 *offset = nullptr); // logging - bool logging() const { return (m_umllog != nullptr); } - void log_printf(const char *format, ...) ATTR_PRINTF(2,3); - void log_flush() { if (logging()) fflush(m_umllog); } - bool logging_native() const { return m_beintf.logging(); } + bool logging() const { return bool(m_umllog); } + template + void log_printf(Format &&fmt, Params &&...args) + { + log_vprintf(util::make_format_argument_pack(std::forward(fmt), std::forward(args)...)); + } + void log_vprintf(util::format_argument_pack const &args); + void log_flush() { if (logging()) m_umllog->flush(); } + bool logging_native() const { return m_beintf->logging(); } private: // symbol class class symbol { - friend class drcuml_state; - friend class simple_list; - + public: // construction/destruction - symbol(void *base, uint32_t length, const char *name) - : m_next(nullptr), - m_base(drccodeptr(base)), - m_length(length), - m_name(name) { } + symbol(void *base, u32 length, char const *name) + : m_base(reinterpret_cast(base)) + , m_length(length) + , m_name(name) + { } - public: // getters - symbol *next() const { return m_next; } + bool includes(drccodeptr search) const { return (m_base <= search) && ((m_base + m_length) > search); } + drccodeptr base() const { return m_base; } + std::string const &name() const { return m_name; } private: // internal state - symbol * m_next; // link to the next symbol - drccodeptr m_base; // base of the symbol - uint32_t m_length; // length of the region covered - std::string m_name; // name of the symbol + drccodeptr m_base; // base of the symbol + u32 m_length; // length of the region covered + std::string m_name; // name of the symbol }; // internal state - device_t & m_device; // CPU device we are associated with - drc_cache & m_cache; // pointer to the codegen cache - std::unique_ptr m_drcbe_interface; - drcbe_interface & m_beintf; // backend interface pointer - FILE * m_umllog; // handle to the UML logfile - simple_list m_blocklist; // list of active blocks - simple_list m_handlelist; // list of active handles - simple_list m_symlist; // list of symbols + device_t & m_device; // CPU device we are associated with + drc_cache & m_cache; // pointer to the codegen cache + std::unique_ptr const m_beintf; // backend interface pointer + std::unique_ptr const m_umllog; // handle to the UML logfile + std::list m_blocklist; // list of active blocks + std::list m_handlelist; // list of active handles + std::list m_symlist; // list of symbols }; @@ -239,11 +245,11 @@ template inline void drcuml_block::append_comment(Format &&fmt, Params &&... args) { // do the printf - std::string temp(util::string_format(std::forward(fmt), std::forward(args)...)); + std::string const temp(util::string_format(std::forward(fmt), std::forward(args)...)); // allocate space in the cache to hold the comment - char *comment = (char *)m_drcuml.cache().alloc_temporary(temp.length() + 1); - if (comment != nullptr) + char *const comment = reinterpret_cast(m_drcuml.cache().alloc_temporary(temp.length() + 1)); + if (comment) { strcpy(comment, temp.c_str()); @@ -253,4 +259,4 @@ inline void drcuml_block::append_comment(Format &&fmt, Params &&... args) } -#endif /* MAME_DEVICES_CPU_DRCUML_H */ +#endif // MAME_CPU_DRCUML_H diff --git a/src/devices/cpu/powerpc/ppc.h b/src/devices/cpu/powerpc/ppc.h index 7c75237e834..cc4fd03006e 100644 --- a/src/devices/cpu/powerpc/ppc.h +++ b/src/devices/cpu/powerpc/ppc.h @@ -668,8 +668,8 @@ protected: bool generate_instruction_3f(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); void log_add_disasm_comment(drcuml_block *block, uint32_t pc, uint32_t op); const char *log_desc_flags_to_string(uint32_t flags); - void log_register_list(drcuml_state *drcuml, const char *string, const uint32_t *reglist, const uint32_t *regnostarlist); - void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent); + void log_register_list(const char *string, const uint32_t *reglist, const uint32_t *regnostarlist); + void log_opcode_desc(const opcode_desc *desclist, int indent); }; diff --git a/src/devices/cpu/powerpc/ppcdrc.cpp b/src/devices/cpu/powerpc/ppcdrc.cpp index 6b158fd6110..d3d1dd794e8 100644 --- a/src/devices/cpu/powerpc/ppcdrc.cpp +++ b/src/devices/cpu/powerpc/ppcdrc.cpp @@ -389,7 +389,7 @@ void ppc_device::code_compile_block(uint8_t mode, offs_t pc) /* get a description of this sequence */ desclist = m_drcfe->describe_code(pc); if (m_drcuml->logging() || m_drcuml->logging_native()) - log_opcode_desc(m_drcuml.get(), desclist, 0); + log_opcode_desc(desclist, 0); bool succeeded = false; while (!succeeded) @@ -670,29 +670,29 @@ void ppc_device::static_generate_entry_point() alloc_handle(m_drcuml.get(), &m_exception_norecover[EXCEPTION_EI], "exception_ei_norecover"); alloc_handle(m_drcuml.get(), &m_entry, "entry"); - UML_HANDLE(block, *m_entry); // handle entry + UML_HANDLE(block, *m_entry); // handle entry /* reset the FPU mode */ UML_AND(block, I0, FPSCR32, 3); // and i0,fpscr,3 - UML_LOAD(block, I0, &m_fpmode[0], I0, SIZE_BYTE, SCALE_x1); // load i0,fpmode,i0,byte - UML_SETFMOD(block, I0); // setfmod i0 + UML_LOAD(block, I0, &m_fpmode[0], I0, SIZE_BYTE, SCALE_x1); // load i0,fpmode,i0,byte + UML_SETFMOD(block, I0); // setfmod i0 /* load fast integer registers */ - load_fast_iregs(block); // + load_fast_iregs(block); // load_fast_fregs(block); /* check for interrupts */ - UML_TEST(block, mem(&m_core->irq_pending), ~0); // test [irq_pending],0 - UML_JMPc(block, COND_Z, skip); // jmp skip,Z - UML_TEST(block, MSR32, MSR_EE); // test msr,MSR_EE - UML_JMPc(block, COND_Z, skip); // jmp skip,Z - UML_MOV(block, I0, mem(&m_core->pc)); // mov i0,pc + UML_TEST(block, mem(&m_core->irq_pending), ~0); // test [irq_pending],0 + UML_JMPc(block, COND_Z, skip); // jmp skip,Z + UML_TEST(block, MSR32, MSR_EE); // test msr,MSR_EE + UML_JMPc(block, COND_Z, skip); // jmp skip,Z + UML_MOV(block, I0, mem(&m_core->pc)); // mov i0,pc UML_MOV(block, I1, 0); // mov i1,0 - UML_CALLH(block, *m_exception_norecover[EXCEPTION_EI]); // callh exception_norecover - UML_LABEL(block, skip); // skip: + UML_CALLH(block, *m_exception_norecover[EXCEPTION_EI]); // callh exception_norecover + UML_LABEL(block, skip); // skip: /* generate a hash jump via the current mode and PC */ - UML_HASHJMP(block, mem(&m_core->mode), mem(&m_core->pc), *m_nocode); // hashjmp ,,nocode + UML_HASHJMP(block, mem(&m_core->mode), mem(&m_core->pc), *m_nocode); // hashjmp ,,nocode block->end(); } @@ -768,25 +768,25 @@ void ppc_device::static_generate_tlb_mismatch() /* generate a hash jump via the current mode and PC */ alloc_handle(m_drcuml.get(), &m_tlb_mismatch, "tlb_mismatch"); - UML_HANDLE(block, *m_tlb_mismatch); // handle tlb_mismatch - UML_RECOVER(block, I0, MAPVAR_PC); // recover i0,PC + UML_HANDLE(block, *m_tlb_mismatch); // handle tlb_mismatch + UML_RECOVER(block, I0, MAPVAR_PC); // recover i0,PC UML_SHR(block, I1, I0, 12); // shr i1,i0,12 - UML_LOAD(block, I2, (void *)vtlb_table(), I1, SIZE_DWORD, SCALE_x4); // load i2,[vtlb],i1,dword - UML_MOV(block, mem(&m_core->param0), I0); // mov [param0],i0 - UML_MOV(block, mem(&m_core->param1), TRANSLATE_FETCH); // mov [param1],TRANSLATE_FETCH - UML_CALLC(block, (c_function)cfunc_ppccom_tlb_fill, this); // callc tlbfill,ppc - UML_LOAD(block, I1, (void *)vtlb_table(), I1, SIZE_DWORD, SCALE_x4); // load i1,[vtlb],i1,dword - UML_TEST(block, I1, VTLB_FETCH_ALLOWED); // test i1,VTLB_FETCH_ALLOWED - UML_JMPc(block, COND_Z, isi = label++); // jmp isi,z - UML_CMP(block, I2, 0); // cmp i2,0 - UML_JMPc(block, COND_NZ, exit = label++); // jmp exit,nz - UML_HASHJMP(block, mem(&m_core->mode), I0, *m_nocode); // hashjmp ,i0,nocode - UML_LABEL(block, exit); // exit: - UML_MOV(block, mem(&m_core->pc), I0); // mov ,i0 - save_fast_iregs(block); // + UML_LOAD(block, I2, (void *)vtlb_table(), I1, SIZE_DWORD, SCALE_x4); // load i2,[vtlb],i1,dword + UML_MOV(block, mem(&m_core->param0), I0); // mov [param0],i0 + UML_MOV(block, mem(&m_core->param1), TRANSLATE_FETCH); // mov [param1],TRANSLATE_FETCH + UML_CALLC(block, (c_function)cfunc_ppccom_tlb_fill, this); // callc tlbfill,ppc + UML_LOAD(block, I1, (void *)vtlb_table(), I1, SIZE_DWORD, SCALE_x4); // load i1,[vtlb],i1,dword + UML_TEST(block, I1, VTLB_FETCH_ALLOWED); // test i1,VTLB_FETCH_ALLOWED + UML_JMPc(block, COND_Z, isi = label++); // jmp isi,z + UML_CMP(block, I2, 0); // cmp i2,0 + UML_JMPc(block, COND_NZ, exit = label++); // jmp exit,nz + UML_HASHJMP(block, mem(&m_core->mode), I0, *m_nocode); // hashjmp ,i0,nocode + UML_LABEL(block, exit); // exit: + UML_MOV(block, mem(&m_core->pc), I0); // mov ,i0 + save_fast_iregs(block); // save_fast_fregs(block); - UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE - UML_LABEL(block, isi); // isi: + UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE + UML_LABEL(block, isi); // isi: if (!(m_cap & PPCCAP_603_MMU)) { // DAR gets the address, DSISR gets the 'reason' flags @@ -3837,7 +3837,7 @@ const char *ppc_device::log_desc_flags_to_string(uint32_t flags) log_register_list - log a list of GPR registers -------------------------------------------------*/ -void ppc_device::log_register_list(drcuml_state *drcuml, const char *string, const uint32_t *reglist, const uint32_t *regnostarlist) +void ppc_device::log_register_list(const char *string, const uint32_t *reglist, const uint32_t *regnostarlist) { static const char *const crtext[4] = { "lt", "gt", "eq", "so" }; int count = 0; @@ -3848,22 +3848,22 @@ void ppc_device::log_register_list(drcuml_state *drcuml, const char *string, con if (reglist[0] == 0 && reglist[1] == 0 && reglist[2] == 0 && reglist[3] == 0) return; - drcuml->log_printf("[%s:", string); + m_drcuml->log_printf("[%s:", string); for (regnum = 0; regnum < 32; regnum++) if (reglist[0] & frontend::REGFLAG_R(regnum)) { - drcuml->log_printf("%sr%d", (count++ == 0) ? "" : ",", regnum); + m_drcuml->log_printf("%sr%d", (count++ == 0) ? "" : ",", regnum); if (regnostarlist != nullptr && !(regnostarlist[0] & frontend::REGFLAG_R(regnum))) - drcuml->log_printf("*"); + m_drcuml->log_printf("*"); } for (regnum = 0; regnum < 32; regnum++) if (reglist[1] & frontend::REGFLAG_FR(regnum)) { - drcuml->log_printf("%sfr%d", (count++ == 0) ? "" : ",", regnum); + m_drcuml->log_printf("%sfr%d", (count++ == 0) ? "" : ",", regnum); if (regnostarlist != nullptr && !(regnostarlist[1] & frontend::REGFLAG_FR(regnum))) - drcuml->log_printf("*"); + m_drcuml->log_printf("*"); } for (regnum = 0; regnum < 8; regnum++) @@ -3871,68 +3871,68 @@ void ppc_device::log_register_list(drcuml_state *drcuml, const char *string, con { if ((reglist[2] & frontend::REGFLAG_CR(regnum)) == frontend::REGFLAG_CR(regnum) && (regnostarlist == nullptr || (regnostarlist[2] & frontend::REGFLAG_CR(regnum)) == frontend::REGFLAG_CR(regnum))) { - drcuml->log_printf("%scr%d", (count++ == 0) ? "" : ",", regnum); + m_drcuml->log_printf("%scr%d", (count++ == 0) ? "" : ",", regnum); if (regnostarlist != nullptr && !(regnostarlist[2] & frontend::REGFLAG_CR(regnum))) - drcuml->log_printf("*"); + m_drcuml->log_printf("*"); } else { for (crnum = 0; crnum < 4; crnum++) if (reglist[2] & frontend::REGFLAG_CR_BIT(regnum * 4 + crnum)) { - drcuml->log_printf("%scr%d[%s]", (count++ == 0) ? "" : ",", regnum, crtext[crnum]); + m_drcuml->log_printf("%scr%d[%s]", (count++ == 0) ? "" : ",", regnum, crtext[crnum]); if (regnostarlist != nullptr && !(regnostarlist[2] & frontend::REGFLAG_CR_BIT(regnum * 4 + crnum))) - drcuml->log_printf("*"); + m_drcuml->log_printf("*"); } } } if (reglist[3] & frontend::REGFLAG_XER_CA) { - drcuml->log_printf("%sxer_ca", (count++ == 0) ? "" : ","); + m_drcuml->log_printf("%sxer_ca", (count++ == 0) ? "" : ","); if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_XER_CA)) - drcuml->log_printf("*"); + m_drcuml->log_printf("*"); } if (reglist[3] & frontend::REGFLAG_XER_OV) { - drcuml->log_printf("%sxer_ov", (count++ == 0) ? "" : ","); + m_drcuml->log_printf("%sxer_ov", (count++ == 0) ? "" : ","); if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_XER_OV)) - drcuml->log_printf("*"); + m_drcuml->log_printf("*"); } if (reglist[3] & frontend::REGFLAG_XER_SO) { - drcuml->log_printf("%sxer_so", (count++ == 0) ? "" : ","); + m_drcuml->log_printf("%sxer_so", (count++ == 0) ? "" : ","); if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_XER_SO)) - drcuml->log_printf("*"); + m_drcuml->log_printf("*"); } if (reglist[3] & frontend::REGFLAG_XER_COUNT) { - drcuml->log_printf("%sxer_count", (count++ == 0) ? "" : ","); + m_drcuml->log_printf("%sxer_count", (count++ == 0) ? "" : ","); if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_XER_COUNT)) - drcuml->log_printf("*"); + m_drcuml->log_printf("*"); } if (reglist[3] & frontend::REGFLAG_CTR) { - drcuml->log_printf("%sctr", (count++ == 0) ? "" : ","); + m_drcuml->log_printf("%sctr", (count++ == 0) ? "" : ","); if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_CTR)) - drcuml->log_printf("*"); + m_drcuml->log_printf("*"); } if (reglist[3] & frontend::REGFLAG_LR) { - drcuml->log_printf("%slr", (count++ == 0) ? "" : ","); + m_drcuml->log_printf("%slr", (count++ == 0) ? "" : ","); if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_LR)) - drcuml->log_printf("*"); + m_drcuml->log_printf("*"); } for (regnum = 0; regnum < 8; regnum++) if (reglist[3] & frontend::REGFLAG_FPSCR(regnum)) { - drcuml->log_printf("%sfpscr%d", (count++ == 0) ? "" : ",", regnum); + m_drcuml->log_printf("%sfpscr%d", (count++ == 0) ? "" : ",", regnum); if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_FPSCR(regnum))) - drcuml->log_printf("*"); + m_drcuml->log_printf("*"); } - drcuml->log_printf("] "); + m_drcuml->log_printf("] "); } @@ -3940,13 +3940,13 @@ void ppc_device::log_register_list(drcuml_state *drcuml, const char *string, con log_opcode_desc - log a list of descriptions -------------------------------------------------*/ -void ppc_device::log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent) +void ppc_device::log_opcode_desc(const opcode_desc *desclist, int indent) { util::ovectorstream buffer; /* open the file, creating it if necessary */ if (indent == 0) - drcuml->log_printf("\nDescriptor list @ %08X\n", desclist->pc); + m_drcuml->log_printf("\nDescriptor list @ %08X\n", desclist->pc); /* output each descriptor */ for ( ; desclist != nullptr; desclist = desclist->next()) @@ -3955,7 +3955,7 @@ void ppc_device::log_opcode_desc(drcuml_state *drcuml, const opcode_desc *descli buffer.seekp(0); /* disassemble the current instruction and output it to the log */ - if (drcuml->logging() || drcuml->logging_native()) + if (m_drcuml->logging() || m_drcuml->logging_native()) { if (desclist->flags & OPFLAG_VIRTUAL_NOOP) buffer << ""; @@ -3966,19 +3966,19 @@ void ppc_device::log_opcode_desc(drcuml_state *drcuml, const opcode_desc *descli buffer << "???"; buffer.put('\0'); - drcuml->log_printf("%08X [%08X] t:%08X f:%s: %-30s", desclist->pc, desclist->physpc, desclist->targetpc, log_desc_flags_to_string(desclist->flags), &buffer.vec()[0]); + m_drcuml->log_printf("%08X [%08X] t:%08X f:%s: %-30s", desclist->pc, desclist->physpc, desclist->targetpc, log_desc_flags_to_string(desclist->flags), &buffer.vec()[0]); /* output register states */ - log_register_list(drcuml, "use", desclist->regin, nullptr); - log_register_list(drcuml, "mod", desclist->regout, desclist->regreq); - drcuml->log_printf("\n"); + log_register_list("use", desclist->regin, nullptr); + log_register_list("mod", desclist->regout, desclist->regreq); + m_drcuml->log_printf("\n"); /* if we have a delay slot, output it recursively */ if (desclist->delay.first() != nullptr) - log_opcode_desc(drcuml, desclist->delay.first(), indent + 1); + log_opcode_desc(desclist->delay.first(), indent + 1); /* at the end of a sequence add a dividing line */ if (desclist->flags & OPFLAG_END_SEQUENCE) - drcuml->log_printf("-----\n"); + m_drcuml->log_printf("-----\n"); } } diff --git a/src/devices/cpu/uml.cpp b/src/devices/cpu/uml.cpp index 6555eff161d..a26f3a92038 100644 --- a/src/devices/cpu/uml.cpp +++ b/src/devices/cpu/uml.cpp @@ -257,10 +257,10 @@ inline u64 rol64(u64 source, u8 count) uml::code_handle::code_handle(drcuml_state &drcuml, const char *name) : m_code(reinterpret_cast(drcuml.cache().alloc_near(sizeof(drccodeptr)))) , m_string(name) - , m_next(nullptr) , m_drcuml(drcuml) { - if (m_code == nullptr) + (void)m_drcuml; // without this, non-debug builds fail because the asserts are preprocessed out + if (!m_code) throw std::bad_alloc(); *m_code = nullptr; } diff --git a/src/devices/cpu/uml.h b/src/devices/cpu/uml.h index f9bae7b7d0b..a035b17a932 100644 --- a/src/devices/cpu/uml.h +++ b/src/devices/cpu/uml.h @@ -230,15 +230,11 @@ namespace uml // class describing a global code handle class code_handle { - friend class ::drcuml_state; - friend class ::simple_list; - + public: // construction/destruction code_handle(drcuml_state &drcuml, const char *name); - public: // getters - code_handle *next() const { return m_next; } drccodeptr codeptr() const { return *m_code; } drccodeptr *codeptr_addr() { return m_code; } char const *string() const { return m_string.c_str(); } @@ -250,7 +246,6 @@ namespace uml // internal state drccodeptr * m_code; // pointer in the cache to the associated code std::string m_string; // pointer to string attached to handle - code_handle * m_next; // link to next handle in the list drcuml_state & m_drcuml; // pointer to owning object }; -- cgit v1.2.3