modernise drcuml somewhat (nw)

This commit is contained in:
Vas Crabb 2018-03-24 03:53:40 +11:00
parent a8633e35a4
commit 1e1e8eb034
6 changed files with 282 additions and 279 deletions

View File

@ -32,13 +32,14 @@
***************************************************************************/ ***************************************************************************/
#include "emu.h" #include "emu.h"
#include "emuopts.h"
#include "drcuml.h" #include "drcuml.h"
#include "emuopts.h"
#include "drcbec.h" #include "drcbec.h"
#include "drcbex86.h" #include "drcbex86.h"
#include "drcbex64.h" #include "drcbex64.h"
using namespace uml; #include <fstream>
@ -66,11 +67,11 @@ typedef NATIVE_DRC drcbe_native;
// structure describing back-end validation test // structure describing back-end validation test
struct bevalidate_test struct bevalidate_test
{ {
opcode_t opcode; uml::opcode_t opcode;
uint8_t size; u8 size;
uint8_t iflags; u8 iflags;
uint8_t flags; u8 flags;
uint64_t param[4]; u64 param[4];
}; };
@ -84,11 +85,12 @@ struct bevalidate_test
//------------------------------------------------- //-------------------------------------------------
drcbe_interface::drcbe_interface(drcuml_state &drcuml, drc_cache &cache, device_t &device) drcbe_interface::drcbe_interface(drcuml_state &drcuml, drc_cache &cache, device_t &device)
: m_drcuml(drcuml), : m_drcuml(drcuml)
m_cache(cache), , m_cache(cache)
m_device(device), , m_device(device)
m_state(*(drcuml_machine_state *)cache.alloc_near(sizeof(m_state))), , m_space()
m_accessors(nullptr) , m_state(*reinterpret_cast<drcuml_machine_state *>(cache.alloc_near(sizeof(m_state))))
, m_accessors(nullptr)
{ {
// reset the machine state // reset the machine state
memset(&m_state, 0, sizeof(m_state)); memset(&m_state, 0, sizeof(m_state));
@ -97,12 +99,13 @@ drcbe_interface::drcbe_interface(drcuml_state &drcuml, drc_cache &cache, device_
device_memory_interface *memory; device_memory_interface *memory;
if (device.interface(memory)) if (device.interface(memory))
{ {
int count = memory->max_space_count(); int const count = memory->max_space_count();
m_accessors = ((data_accessors *)cache.alloc_near(sizeof(*m_accessors) * count)); m_accessors = reinterpret_cast<data_accessors *>(cache.alloc_near(sizeof(*m_accessors) * count));
memset(m_accessors, 0, sizeof(*m_accessors) * count); memset(m_accessors, 0, sizeof(*m_accessors) * count);
m_space.resize(count, nullptr); m_space.resize(count, nullptr);
for (int spacenum = 0; spacenum < count; ++spacenum) for (int spacenum = 0; spacenum < count; ++spacenum)
{
if (memory->has_space(spacenum)) if (memory->has_space(spacenum))
{ {
m_space[spacenum] = &memory->space(spacenum); m_space[spacenum] = &memory->space(spacenum);
@ -110,6 +113,7 @@ drcbe_interface::drcbe_interface(drcuml_state &drcuml, drc_cache &cache, device_
} }
} }
} }
}
//------------------------------------------------- //-------------------------------------------------
@ -130,21 +134,19 @@ drcbe_interface::~drcbe_interface()
// drcuml_state - constructor // drcuml_state - constructor
//------------------------------------------------- //-------------------------------------------------
drcuml_state::drcuml_state(device_t &device, drc_cache &cache, uint32_t flags, int modes, int addrbits, int ignorebits) drcuml_state::drcuml_state(device_t &device, drc_cache &cache, u32 flags, int modes, int addrbits, int ignorebits)
: m_device(device), : m_device(device)
m_cache(cache), , m_cache(cache)
m_drcbe_interface(device.machine().options().drc_use_c() ? , m_beintf(device.machine().options().drc_use_c()
std::unique_ptr<drcbe_interface>{ std::make_unique<drcbe_c>(*this, device, cache, flags, modes, addrbits, ignorebits) } : ? std::unique_ptr<drcbe_interface>{ new drcbe_c(*this, device, cache, flags, modes, addrbits, ignorebits) }
std::unique_ptr<drcbe_interface>{ std::make_unique<drcbe_native>(*this, device, cache, flags, modes, addrbits, ignorebits) }), : std::unique_ptr<drcbe_interface>{ new drcbe_native(*this, device, cache, flags, modes, addrbits, ignorebits) })
m_beintf(*m_drcbe_interface.get()), , m_umllog(device.machine().options().drc_log_uml()
m_umllog(nullptr) ? 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() drcuml_state::~drcuml_state()
{ {
// close any files
if (m_umllog != nullptr)
fclose(m_umllog);
} }
@ -174,14 +173,15 @@ void drcuml_state::reset()
m_cache.flush(); m_cache.flush();
// reset all handle code pointers // reset all handle code pointers
for (code_handle *handle = m_handlelist.first(); handle != nullptr; handle = handle->next()) for (uml::code_handle &handle : m_handlelist)
*handle->m_code = nullptr; *handle.codeptr_addr() = nullptr;
// call the backend to reset // call the backend to reset
m_beintf.reset(); m_beintf->reset();
// do a one-time validation if requested // do a one-time validation if requested
/* if (VALIDATE_BACKEND) #if 0
if (VALIDATE_BACKEND)
{ {
static bool validated = false; static bool validated = false;
if (!validated) if (!validated)
@ -189,7 +189,8 @@ void drcuml_state::reset()
validated = true; validated = true;
validate_backend(this); validate_backend(this);
} }
}*/ }
#endif
} }
catch (drcuml_block::abort_compilation &) catch (drcuml_block::abort_compilation &)
{ {
@ -205,14 +206,16 @@ void drcuml_state::reset()
drcuml_block *drcuml_state::begin_block(uint32_t maxinst) drcuml_block *drcuml_state::begin_block(uint32_t maxinst)
{ {
// find an inactive block that matches our qualifications // find an inactive block that matches our qualifications
drcuml_block *bestblock = nullptr; drcuml_block *bestblock(nullptr);
for (drcuml_block *block = m_blocklist.first(); block != nullptr; block = block->next()) for (drcuml_block &block : m_blocklist)
if (!block->inuse() && block->maxinst() >= maxinst && (bestblock == nullptr || block->maxinst() < bestblock->maxinst())) {
bestblock = block; if (!block.inuse() && (block.maxinst() >= maxinst) && (!bestblock || (block.maxinst() < bestblock->maxinst())))
bestblock = &block;
}
// if we failed to find one, allocate a new one // if we failed to find one, allocate a new one
if (bestblock == nullptr) if (!bestblock)
bestblock = &m_blocklist.append(*global_alloc(drcuml_block(*this, maxinst * 3/2))); bestblock = &*m_blocklist.emplace(m_blocklist.end(), *this, maxinst * 3 / 2);
// start the block // start the block
bestblock->begin(); bestblock->begin();
@ -224,10 +227,10 @@ drcuml_block *drcuml_state::begin_block(uint32_t maxinst)
// handle_alloc - allocate a new handle // 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 // 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 // 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,22 +251,21 @@ void drcuml_state::symbol_add(void *base, uint32_t length, const char *name)
// found // 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<drccodeptr>(base));
// simple linear search // simple linear search
for (symbol *cursym = m_symlist.first(); cursym != nullptr; cursym = cursym->next()) for (symbol const &cursym : m_symlist)
if (search >= cursym->m_base && search < cursym->m_base + cursym->m_length)
{ {
// if no offset pointer, only match perfectly // if no offset pointer, only match perfectly
if (offset == nullptr && search != cursym->m_base) if (cursym.includes(search) && (offset || (cursym.base() == search)))
continue; {
// return the offset and name // return the offset and name
if (offset != nullptr) if (offset)
*offset = search - cursym->m_base; *offset = search - cursym.base();
return cursym->m_name.c_str(); return cursym.name().c_str();
}
} }
// not found; return nullptr // not found; 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 // if generated
//------------------------------------------------- //-------------------------------------------------
void drcuml_state::log_printf(const char *format, ...) void drcuml_state::log_vprintf(util::format_argument_pack<std::ostream> const &args)
{ {
// if we have a file, print to it // if we have a file, print to it
if (m_umllog != nullptr) if (m_umllog)
{ {
va_list va; util::stream_format(*m_umllog, args);
m_umllog->flush();
// do the printf
va_start(va, format);
vfprintf(m_umllog, format, va);
va_end(va);
fflush(m_umllog);
} }
} }
@ -301,13 +298,12 @@ void drcuml_state::log_printf(const char *format, ...)
// drcuml_block - constructor // drcuml_block - constructor
//------------------------------------------------- //-------------------------------------------------
drcuml_block::drcuml_block(drcuml_state &drcuml, uint32_t maxinst) drcuml_block::drcuml_block(drcuml_state &drcuml, u32 maxinst)
: m_drcuml(drcuml), : m_drcuml(drcuml)
m_next(nullptr), , m_nextinst(0)
m_nextinst(0), , m_maxinst(maxinst * 3/2)
m_maxinst(maxinst * 3/2), , m_inst(m_maxinst)
m_inst(m_maxinst), , m_inuse(false)
m_inuse(false)
{ {
} }
@ -380,7 +376,7 @@ void drcuml_block::abort()
uml::instruction &drcuml_block::append() uml::instruction &drcuml_block::append()
{ {
// get a pointer to the next instruction // 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) if (m_nextinst > m_maxinst)
fatalerror("Overran maxinst in drcuml_block_append\n"); fatalerror("Overran maxinst in drcuml_block_append\n");
@ -395,39 +391,39 @@ uml::instruction &drcuml_block::append()
void drcuml_block::optimize() void drcuml_block::optimize()
{ {
uint32_t mapvar[MAPVAR_COUNT] = { 0 }; u32 mapvar[uml::MAPVAR_COUNT] = { 0 };
// iterate over instructions // iterate over instructions
for (int instnum = 0; instnum < m_nextinst; instnum++) 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 // first compute what flags we need
uint8_t accumflags = 0; u8 accumflags(0);
uint8_t remainingflags = inst.output_flags(); u8 remainingflags(inst.output_flags());
// scan ahead until we run out of possible remaining flags // scan ahead until we run out of possible remaining flags
for (int scannum = instnum + 1; remainingflags != 0 && scannum < m_nextinst; scannum++) for (int scannum = instnum + 1; remainingflags != 0 && scannum < m_nextinst; scannum++)
{ {
// any input flags are required // any input flags are required
const instruction &scan = m_inst[scannum]; uml::instruction const &scan(m_inst[scannum]);
accumflags |= scan.input_flags(); accumflags |= scan.input_flags();
// if the scanahead instruction is unconditional, assume his flags are modified // 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(); remainingflags &= ~scan.modified_flags();
} }
inst.set_flags(accumflags); inst.set_flags(accumflags);
// track mapvars // track mapvars
if (inst.opcode() == OP_MAPVAR) if (inst.opcode() == uml::OP_MAPVAR)
mapvar[inst.param(0).mapvar() - MAPVAR_M0] = inst.param(1).immediate(); mapvar[inst.param(0).mapvar() - uml::MAPVAR_M0] = inst.param(1).immediate();
// convert all mapvar parameters to immediates // 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++) for (int pnum = 0; pnum < inst.numparams(); pnum++)
if (inst.param(pnum).is_mapvar()) 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 // now that flags are correct, simplify the instruction
inst.simplify(); inst.simplify();
@ -445,41 +441,43 @@ void drcuml_block::disassemble()
std::string comment; std::string comment;
// iterate over instructions and output // iterate over instructions and output
int firstcomment = -1; int firstcomment(-1);
for (int instnum = 0; instnum < m_nextinst; instnum++) for (int instnum = 0; instnum < m_nextinst; instnum++)
{ {
const instruction &inst = m_inst[instnum]; uml::instruction const &inst(m_inst[instnum]);
bool flushcomments = false; bool flushcomments(false);
// remember comments and mapvars for later // 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) if (firstcomment == -1)
firstcomment = instnum; firstcomment = instnum;
} }
// print labels, handles, and hashes left justified // print labels, handles, and hashes left justified
else if (inst.opcode() == OP_LABEL) else if (inst.opcode() == uml::OP_LABEL)
m_drcuml.log_printf("$%X:\n", uint32_t(inst.param(0).label())); m_drcuml.log_printf("$%X:\n", u32(inst.param(0).label()));
else if (inst.opcode() == OP_HANDLE) else if (inst.opcode() == uml::OP_HANDLE)
m_drcuml.log_printf("%s:\n", inst.param(0).handle().string()); m_drcuml.log_printf("%s:\n", inst.param(0).handle().string());
else if (inst.opcode() == OP_HASH) else if (inst.opcode() == uml::OP_HASH)
m_drcuml.log_printf("(%X,%X):\n", uint32_t(inst.param(0).immediate()), uint32_t(inst.param(1).immediate())); m_drcuml.log_printf("(%X,%X):\n", u32(inst.param(0).immediate()), u32(inst.param(1).immediate()));
// indent everything else with a tab // indent everything else with a tab
else 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 // include the first accumulated comment with this line
if (firstcomment != -1) 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++; firstcomment++;
flushcomments = true; flushcomments = true;
} }
else else
m_drcuml.log_printf("\t%s\n", dasm.c_str()); {
m_drcuml.log_printf("\t%s\n", dasm);
}
} }
// flush any comments pending // flush any comments pending
@ -487,8 +485,8 @@ void drcuml_block::disassemble()
{ {
while (firstcomment <= instnum) while (firstcomment <= instnum)
{ {
const char *text = get_comment_text(m_inst[firstcomment++], comment); char const *const text(get_comment_text(m_inst[firstcomment++], comment));
if (text != nullptr) if (text)
m_drcuml.log_printf("\t%50s; %s\n", "", text); m_drcuml.log_printf("\t%50s; %s\n", "", text);
} }
firstcomment = -1; firstcomment = -1;
@ -504,21 +502,25 @@ void drcuml_block::disassemble()
// associated with a comment or mapvar // 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)
{
if (inst.opcode() == uml::OP_COMMENT)
{ {
// comments return their strings // comments return their strings
if (inst.opcode() == OP_COMMENT)
return comment.assign(inst.param(0).string()).c_str(); return comment.assign(inst.param(0).string()).c_str();
}
else if (inst.opcode() == uml::OP_MAPVAR)
{
// mapvars comment about their values // mapvars comment about their values
else if (inst.opcode() == OP_MAPVAR) { comment = string_format("m%d = $%X", int(inst.param(0).mapvar() - uml::MAPVAR_M0), u32(inst.param(1).immediate()));
comment = string_format("m%d = $%X", (int)inst.param(0).mapvar() - MAPVAR_M0, (uint32_t)inst.param(1).immediate());
return comment.c_str(); return comment.c_str();
} }
else
{
// everything else is nullptr // everything else is nullptr
return nullptr; return nullptr;
} }
}
@ -549,12 +551,12 @@ inline uint8_t effective_test_psize(const opcode_info &opinfo, int pnum, int ins
return instsize; return instsize;
} }
#define TEST_ENTRY_2(op, size, p1, p2, flags) { OP_##op, size, 0, flags, { U64(p1), U64(p2) } }, #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_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_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_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_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_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[] = 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) static void validate_backend(drcuml_state *drcuml)
{ {
code_handle *handles[3]; uml::code_handle *handles[3];
int tnum; int tnum;
// allocate handles for the code // 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 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()]; const opcode_info *opinfo = opcode_info_table[test->opcode()];
drcuml_ptype ptype; drcuml_ptype ptype;
@ -812,7 +814,7 @@ static void bevalidate_iterate_over_params(drcuml_state *drcuml, code_handle **h
all supported flag masks 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()]; const opcode_info *opinfo = opcode_info_table[test->opcode()];
uint8_t flagmask = opinfo->outflags; uint8_t flagmask = opinfo->outflags;
@ -831,7 +833,7 @@ static void bevalidate_iterate_over_flags(drcuml_state *drcuml, code_handle **ha
results 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)]; parameter params[ARRAY_LENGTH(test->param)];
drcuml_machine_state istate, fstate; 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) if (opinfo->param[pnum].output & PIO_OUT)
{ {
int psize = effective_test_psize(opinfo, pnum, test->size, test->param); 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; uint64_t result = 0;
// fetch the result from the parameters // fetch the result from the parameters

View File

@ -7,15 +7,19 @@
Universal machine language for dynamic recompiling CPU cores. Universal machine language for dynamic recompiling CPU cores.
***************************************************************************/ ***************************************************************************/
#ifndef MAME_CPU_DRCUML_H
#define MAME_CPU_DRCUML_H
#pragma once #pragma once
#ifndef MAME_DEVICES_CPU_DRCUML_H
#define MAME_DEVICES_CPU_DRCUML_H
#include "drccache.h" #include "drccache.h"
#include "uml.h" #include "uml.h"
#include <iostream>
#include <list>
#include <memory>
#include <vector>
//************************************************************************** //**************************************************************************
// CONSTANTS // CONSTANTS
@ -37,11 +41,11 @@ class drcuml_state;
union drcuml_ireg union drcuml_ireg
{ {
#ifdef LSB_FIRST #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 #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 #endif
uint64_t d; // 64-bit full register u64 d; // 64-bit full register
}; };
@ -62,34 +66,33 @@ struct drcuml_machine_state
{ {
drcuml_ireg r[uml::REG_I_COUNT]; // integer registers drcuml_ireg r[uml::REG_I_COUNT]; // integer registers
drcuml_freg f[uml::REG_F_COUNT]; // floating-point registers drcuml_freg f[uml::REG_F_COUNT]; // floating-point registers
uint32_t exp; // exception parameter register u32 exp; // exception parameter register
uint8_t fmod; // fmod (floating-point mode) register u8 fmod; // fmod (floating-point mode) register
uint8_t flags; // flags state u8 flags; // flags state
}; };
// hints and information about the back-end // hints and information about the back-end
struct drcbe_info struct drcbe_info
{ {
uint8_t direct_iregs; // number of direct-mapped integer registers u8 direct_iregs; // number of direct-mapped integer registers
uint8_t direct_fregs; // number of direct-mapped floating point registers u8 direct_fregs; // number of direct-mapped floating point registers
}; };
// a drcuml_block describes a basic block of instructions // a drcuml_block describes a basic block of instructions
class drcuml_block class drcuml_block
{ {
friend class simple_list<drcuml_block>;
public: public:
// construction/destruction // 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(); ~drcuml_block();
// getters // getters
drcuml_block *next() const { return m_next; }
bool inuse() const { return m_inuse; } bool inuse() const { return m_inuse; }
uint32_t maxinst() const { return m_maxinst; } u32 maxinst() const { return m_maxinst; }
// code generation // code generation
void begin(); void begin();
@ -111,13 +114,12 @@ private:
// internal helpers // internal helpers
void optimize(); void optimize();
void disassemble(); 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 // internal state
drcuml_state & m_drcuml; // pointer back to the owning UML drcuml_state & m_drcuml; // pointer back to the owning UML
drcuml_block * m_next; // pointer to next block u32 m_nextinst; // next instruction to fill in the cache
uint32_t m_nextinst; // next instruction to fill in the cache u32 m_maxinst; // maximum number of instructions
uint32_t m_maxinst; // maximum number of instructions
std::vector<uml::instruction> m_inst; // pointer to the instruction list std::vector<uml::instruction> m_inst; // pointer to the instruction list
bool m_inuse; // this block is in use bool m_inuse; // this block is in use
}; };
@ -127,19 +129,21 @@ private:
class drcbe_interface class drcbe_interface
{ {
public: public:
// construction/destruction // allow deleting through base pointer
drcbe_interface(drcuml_state &drcuml, drc_cache &cache, device_t &device);
virtual ~drcbe_interface(); virtual ~drcbe_interface();
// required overrides // required overrides
virtual void reset() = 0; virtual void reset() = 0;
virtual int execute(uml::code_handle &entry) = 0; virtual int execute(uml::code_handle &entry) = 0;
virtual void generate(drcuml_block &block, const uml::instruction *instlist, uint32_t numinst) = 0; virtual void generate(drcuml_block &block, uml::instruction const *instlist, u32 numinst) = 0;
virtual bool hash_exists(uint32_t mode, uint32_t pc) = 0; virtual bool hash_exists(u32 mode, u32 pc) = 0;
virtual void get_info(drcbe_info &info) = 0; virtual void get_info(drcbe_info &info) = 0;
virtual bool logging() const { return false; } virtual bool logging() const { return false; }
protected: protected:
// base constructor
drcbe_interface(drcuml_state &drcuml, drc_cache &cache, device_t &device);
// internal state // internal state
drcuml_state & m_drcuml; // pointer back to our owner drcuml_state & m_drcuml; // pointer back to our owner
drc_cache & m_cache; // pointer to the cache drc_cache & m_cache; // pointer to the cache
@ -155,7 +159,7 @@ class drcuml_state
{ {
public: public:
// construction/destruction // 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(); ~drcuml_state();
// getters // getters
@ -164,64 +168,66 @@ public:
// reset the state // reset the state
void reset(); 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 // code generation
drcuml_block *begin_block(uint32_t maxinst); drcuml_block *begin_block(u32 maxinst);
// back-end interface // back-end interface
void get_backend_info(drcbe_info &info) { m_beintf.get_info(info); } 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); } bool hash_exists(u32 mode, u32 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 generate(drcuml_block &block, uml::instruction *instructions, u32 count) { m_beintf->generate(block, instructions, count); }
// handle management // handle management
uml::code_handle *handle_alloc(const char *name); uml::code_handle *handle_alloc(char const *name);
// symbol management // symbol management
void symbol_add(void *base, uint32_t length, const char *name); void symbol_add(void *base, u32 length, char const *name);
const char *symbol_find(void *base, uint32_t *offset = nullptr); char const *symbol_find(void *base, u32 *offset = nullptr);
// logging // logging
bool logging() const { return (m_umllog != nullptr); } bool logging() const { return bool(m_umllog); }
void log_printf(const char *format, ...) ATTR_PRINTF(2,3); template <typename Format, typename... Params>
void log_flush() { if (logging()) fflush(m_umllog); } void log_printf(Format &&fmt, Params &&...args)
bool logging_native() const { return m_beintf.logging(); } {
log_vprintf(util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...));
}
void log_vprintf(util::format_argument_pack<std::ostream> const &args);
void log_flush() { if (logging()) m_umllog->flush(); }
bool logging_native() const { return m_beintf->logging(); }
private: private:
// symbol class // symbol class
class symbol class symbol
{ {
friend class drcuml_state;
friend class simple_list<symbol>;
// construction/destruction
symbol(void *base, uint32_t length, const char *name)
: m_next(nullptr),
m_base(drccodeptr(base)),
m_length(length),
m_name(name) { }
public: public:
// construction/destruction
symbol(void *base, u32 length, char const *name)
: m_base(reinterpret_cast<drccodeptr>(base))
, m_length(length)
, m_name(name)
{ }
// getters // 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: private:
// internal state // internal state
symbol * m_next; // link to the next symbol
drccodeptr m_base; // base of the symbol drccodeptr m_base; // base of the symbol
uint32_t m_length; // length of the region covered u32 m_length; // length of the region covered
std::string m_name; // name of the symbol std::string m_name; // name of the symbol
}; };
// internal state // internal state
device_t & m_device; // CPU device we are associated with device_t & m_device; // CPU device we are associated with
drc_cache & m_cache; // pointer to the codegen cache drc_cache & m_cache; // pointer to the codegen cache
std::unique_ptr<drcbe_interface> m_drcbe_interface; std::unique_ptr<drcbe_interface> const m_beintf; // backend interface pointer
drcbe_interface & m_beintf; // backend interface pointer std::unique_ptr<std::ostream> const m_umllog; // handle to the UML logfile
FILE * m_umllog; // handle to the UML logfile std::list<drcuml_block> m_blocklist; // list of active blocks
simple_list<drcuml_block> m_blocklist; // list of active blocks std::list<uml::code_handle> m_handlelist; // list of active handles
simple_list<uml::code_handle> m_handlelist; // list of active handles std::list<symbol> m_symlist; // list of symbols
simple_list<symbol> m_symlist; // list of symbols
}; };
@ -239,11 +245,11 @@ template <typename Format, typename... Params>
inline void drcuml_block::append_comment(Format &&fmt, Params &&... args) inline void drcuml_block::append_comment(Format &&fmt, Params &&... args)
{ {
// do the printf // do the printf
std::string temp(util::string_format(std::forward<Format>(fmt), std::forward<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 // allocate space in the cache to hold the comment
char *comment = (char *)m_drcuml.cache().alloc_temporary(temp.length() + 1); char *const comment = reinterpret_cast<char *>(m_drcuml.cache().alloc_temporary(temp.length() + 1));
if (comment != nullptr) if (comment)
{ {
strcpy(comment, temp.c_str()); 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

View File

@ -668,8 +668,8 @@ protected:
bool generate_instruction_3f(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); 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); void log_add_disasm_comment(drcuml_block *block, uint32_t pc, uint32_t op);
const char *log_desc_flags_to_string(uint32_t flags); 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_register_list(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_opcode_desc(const opcode_desc *desclist, int indent);
}; };

View File

@ -389,7 +389,7 @@ void ppc_device::code_compile_block(uint8_t mode, offs_t pc)
/* get a description of this sequence */ /* get a description of this sequence */
desclist = m_drcfe->describe_code(pc); desclist = m_drcfe->describe_code(pc);
if (m_drcuml->logging() || m_drcuml->logging_native()) if (m_drcuml->logging() || m_drcuml->logging_native())
log_opcode_desc(m_drcuml.get(), desclist, 0); log_opcode_desc(desclist, 0);
bool succeeded = false; bool succeeded = false;
while (!succeeded) while (!succeeded)
@ -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 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" }; static const char *const crtext[4] = { "lt", "gt", "eq", "so" };
int count = 0; 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) if (reglist[0] == 0 && reglist[1] == 0 && reglist[2] == 0 && reglist[3] == 0)
return; return;
drcuml->log_printf("[%s:", string); m_drcuml->log_printf("[%s:", string);
for (regnum = 0; regnum < 32; regnum++) for (regnum = 0; regnum < 32; regnum++)
if (reglist[0] & frontend::REGFLAG_R(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))) if (regnostarlist != nullptr && !(regnostarlist[0] & frontend::REGFLAG_R(regnum)))
drcuml->log_printf("*"); m_drcuml->log_printf("*");
} }
for (regnum = 0; regnum < 32; regnum++) for (regnum = 0; regnum < 32; regnum++)
if (reglist[1] & frontend::REGFLAG_FR(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))) if (regnostarlist != nullptr && !(regnostarlist[1] & frontend::REGFLAG_FR(regnum)))
drcuml->log_printf("*"); m_drcuml->log_printf("*");
} }
for (regnum = 0; regnum < 8; regnum++) 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))) 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))) if (regnostarlist != nullptr && !(regnostarlist[2] & frontend::REGFLAG_CR(regnum)))
drcuml->log_printf("*"); m_drcuml->log_printf("*");
} }
else else
{ {
for (crnum = 0; crnum < 4; crnum++) for (crnum = 0; crnum < 4; crnum++)
if (reglist[2] & frontend::REGFLAG_CR_BIT(regnum * 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))) 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) 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)) if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_XER_CA))
drcuml->log_printf("*"); m_drcuml->log_printf("*");
} }
if (reglist[3] & frontend::REGFLAG_XER_OV) 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)) if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_XER_OV))
drcuml->log_printf("*"); m_drcuml->log_printf("*");
} }
if (reglist[3] & frontend::REGFLAG_XER_SO) 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)) if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_XER_SO))
drcuml->log_printf("*"); m_drcuml->log_printf("*");
} }
if (reglist[3] & frontend::REGFLAG_XER_COUNT) 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)) if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_XER_COUNT))
drcuml->log_printf("*"); m_drcuml->log_printf("*");
} }
if (reglist[3] & frontend::REGFLAG_CTR) 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)) if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_CTR))
drcuml->log_printf("*"); m_drcuml->log_printf("*");
} }
if (reglist[3] & frontend::REGFLAG_LR) 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)) if (regnostarlist != nullptr && !(regnostarlist[3] & frontend::REGFLAG_LR))
drcuml->log_printf("*"); m_drcuml->log_printf("*");
} }
for (regnum = 0; regnum < 8; regnum++) for (regnum = 0; regnum < 8; regnum++)
if (reglist[3] & frontend::REGFLAG_FPSCR(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))) 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 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; util::ovectorstream buffer;
/* open the file, creating it if necessary */ /* open the file, creating it if necessary */
if (indent == 0) 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 */ /* output each descriptor */
for ( ; desclist != nullptr; desclist = desclist->next()) 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); buffer.seekp(0);
/* disassemble the current instruction and output it to the log */ /* 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) if (desclist->flags & OPFLAG_VIRTUAL_NOOP)
buffer << "<virtual nop>"; buffer << "<virtual nop>";
@ -3966,19 +3966,19 @@ void ppc_device::log_opcode_desc(drcuml_state *drcuml, const opcode_desc *descli
buffer << "???"; buffer << "???";
buffer.put('\0'); 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 */ /* output register states */
log_register_list(drcuml, "use", desclist->regin, nullptr); log_register_list("use", desclist->regin, nullptr);
log_register_list(drcuml, "mod", desclist->regout, desclist->regreq); log_register_list("mod", desclist->regout, desclist->regreq);
drcuml->log_printf("\n"); m_drcuml->log_printf("\n");
/* if we have a delay slot, output it recursively */ /* if we have a delay slot, output it recursively */
if (desclist->delay.first() != nullptr) 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 */ /* at the end of a sequence add a dividing line */
if (desclist->flags & OPFLAG_END_SEQUENCE) if (desclist->flags & OPFLAG_END_SEQUENCE)
drcuml->log_printf("-----\n"); m_drcuml->log_printf("-----\n");
} }
} }

View File

@ -257,10 +257,10 @@ inline u64 rol64(u64 source, u8 count)
uml::code_handle::code_handle(drcuml_state &drcuml, const char *name) uml::code_handle::code_handle(drcuml_state &drcuml, const char *name)
: m_code(reinterpret_cast<drccodeptr *>(drcuml.cache().alloc_near(sizeof(drccodeptr)))) : m_code(reinterpret_cast<drccodeptr *>(drcuml.cache().alloc_near(sizeof(drccodeptr))))
, m_string(name) , m_string(name)
, m_next(nullptr)
, m_drcuml(drcuml) , 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(); throw std::bad_alloc();
*m_code = nullptr; *m_code = nullptr;
} }

View File

@ -230,15 +230,11 @@ namespace uml
// class describing a global code handle // class describing a global code handle
class code_handle class code_handle
{ {
friend class ::drcuml_state; public:
friend class ::simple_list<code_handle>;
// construction/destruction // construction/destruction
code_handle(drcuml_state &drcuml, const char *name); code_handle(drcuml_state &drcuml, const char *name);
public:
// getters // getters
code_handle *next() const { return m_next; }
drccodeptr codeptr() const { return *m_code; } drccodeptr codeptr() const { return *m_code; }
drccodeptr *codeptr_addr() { return m_code; } drccodeptr *codeptr_addr() { return m_code; }
char const *string() const { return m_string.c_str(); } char const *string() const { return m_string.c_str(); }
@ -250,7 +246,6 @@ namespace uml
// internal state // internal state
drccodeptr * m_code; // pointer in the cache to the associated code drccodeptr * m_code; // pointer in the cache to the associated code
std::string m_string; // pointer to string attached to handle 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 drcuml_state & m_drcuml; // pointer to owning object
}; };