mirror of
https://github.com/holub/mame
synced 2025-05-19 20:29:09 +03:00
C++-ified the DRC backend utility helpers.
This commit is contained in:
parent
ed94203e79
commit
159e684763
@ -217,9 +217,9 @@ struct _drcbe_state
|
|||||||
drcuml_state * drcuml; /* pointer back to our owner */
|
drcuml_state * drcuml; /* pointer back to our owner */
|
||||||
drc_cache * cache; /* pointer to the cache */
|
drc_cache * cache; /* pointer to the cache */
|
||||||
drcuml_machine_state state; /* state of the machine */
|
drcuml_machine_state state; /* state of the machine */
|
||||||
drchash_state * hash; /* hash table state */
|
drc_hash_table * hash; /* hash table state */
|
||||||
drcmap_state * map; /* code map */
|
drc_map_variables * map; /* code map */
|
||||||
drclabel_list * labels; /* label list */
|
drc_label_list * labels; /* label list */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -358,19 +358,13 @@ static drcbe_state *drcbec_alloc(drcuml_state *drcuml, drc_cache *cache, device_
|
|||||||
drcbe->cache = cache;
|
drcbe->cache = cache;
|
||||||
|
|
||||||
/* allocate hash tables */
|
/* allocate hash tables */
|
||||||
drcbe->hash = drchash_alloc(cache, modes, addrbits, ignorebits);
|
drcbe->hash = auto_alloc(device->machine, drc_hash_table(*cache, modes, addrbits, ignorebits));
|
||||||
if (drcbe->hash == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* allocate code map */
|
/* allocate code map */
|
||||||
drcbe->map = drcmap_alloc(cache, 0);
|
drcbe->map = auto_alloc(device->machine, drc_map_variables(*cache, 0));
|
||||||
if (drcbe->map == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* allocate a label tracker */
|
/* allocate a label tracker */
|
||||||
drcbe->labels = drclabel_list_alloc(cache);
|
drcbe->labels = auto_alloc(device->machine, drc_label_list(*cache));
|
||||||
if (drcbe->labels == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return drcbe;
|
return drcbe;
|
||||||
}
|
}
|
||||||
@ -392,8 +386,8 @@ static void drcbec_free(drcbe_state *drcbe)
|
|||||||
static void drcbec_reset(drcbe_state *drcbe)
|
static void drcbec_reset(drcbe_state *drcbe)
|
||||||
{
|
{
|
||||||
/* reset our hash tables */
|
/* reset our hash tables */
|
||||||
drchash_reset(drcbe->hash);
|
drcbe->hash->reset();
|
||||||
drchash_set_default_codeptr(drcbe->hash, NULL);
|
drcbe->hash->set_default_codeptr(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -409,9 +403,9 @@ static void drcbec_generate(drcbe_state *drcbe, drcuml_block *block, const drcum
|
|||||||
int inum;
|
int inum;
|
||||||
|
|
||||||
/* tell all of our utility objects that a block is beginning */
|
/* tell all of our utility objects that a block is beginning */
|
||||||
drchash_block_begin(drcbe->hash, block, instlist, numinst);
|
drcbe->hash->block_begin(*block, instlist, numinst);
|
||||||
drclabel_block_begin(drcbe->labels, block);
|
drcbe->labels->block_begin(*block);
|
||||||
drcmap_block_begin(drcbe->map, block);
|
drcbe->map->block_begin(*block);
|
||||||
|
|
||||||
/* begin codegen; fail if we can't */
|
/* begin codegen; fail if we can't */
|
||||||
cachetop = drcbe->cache->begin_codegen(numinst * sizeof(drcbec_instruction) * 4);
|
cachetop = drcbe->cache->begin_codegen(numinst * sizeof(drcbec_instruction) * 4);
|
||||||
@ -445,14 +439,14 @@ static void drcbec_generate(drcbe_state *drcbe, drcuml_block *block, const drcum
|
|||||||
/* when we hit a HASH opcode, register the current pointer for the mode/PC */
|
/* when we hit a HASH opcode, register the current pointer for the mode/PC */
|
||||||
case DRCUML_OP_HASH:
|
case DRCUML_OP_HASH:
|
||||||
/* we already verified the parameter count and types above */
|
/* we already verified the parameter count and types above */
|
||||||
drchash_set_codeptr(drcbe->hash, inst->param[0].value, inst->param[1].value, (drccodeptr)dst);
|
drcbe->hash->set_codeptr(inst->param[0].value, inst->param[1].value, (drccodeptr)dst);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* when we hit a LABEL opcode, register the current pointer for the label */
|
/* when we hit a LABEL opcode, register the current pointer for the label */
|
||||||
case DRCUML_OP_LABEL:
|
case DRCUML_OP_LABEL:
|
||||||
assert(inst->numparams == 1);
|
assert(inst->numparams == 1);
|
||||||
assert(inst->param[0].type == DRCUML_PTYPE_IMMEDIATE);
|
assert(inst->param[0].type == DRCUML_PTYPE_IMMEDIATE);
|
||||||
drclabel_set_codeptr(drcbe->labels, inst->param[0].value, (drccodeptr)dst);
|
drcbe->labels->set_codeptr(inst->param[0].value, (drccodeptr)dst);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* ignore COMMENT and NOP opcodes */
|
/* ignore COMMENT and NOP opcodes */
|
||||||
@ -465,7 +459,7 @@ static void drcbec_generate(drcbe_state *drcbe, drcuml_block *block, const drcum
|
|||||||
assert(inst->numparams == 2);
|
assert(inst->numparams == 2);
|
||||||
assert(inst->param[0].type == DRCUML_PTYPE_MAPVAR);
|
assert(inst->param[0].type == DRCUML_PTYPE_MAPVAR);
|
||||||
assert(inst->param[1].type == DRCUML_PTYPE_IMMEDIATE);
|
assert(inst->param[1].type == DRCUML_PTYPE_IMMEDIATE);
|
||||||
drcmap_set_value(drcbe->map, (drccodeptr)dst, inst->param[0].value, inst->param[1].value);
|
drcbe->map->set_value((drccodeptr)dst, inst->param[0].value, inst->param[1].value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* JMP instructions need to resolve their labels */
|
/* JMP instructions need to resolve their labels */
|
||||||
@ -473,7 +467,7 @@ static void drcbec_generate(drcbe_state *drcbe, drcuml_block *block, const drcum
|
|||||||
assert(inst->numparams == 1);
|
assert(inst->numparams == 1);
|
||||||
assert(inst->param[0].type == DRCUML_PTYPE_IMMEDIATE);
|
assert(inst->param[0].type == DRCUML_PTYPE_IMMEDIATE);
|
||||||
(dst++)->i = MAKE_OPCODE_FULL(opcode, inst->size, inst->condition, inst->flags, 1);
|
(dst++)->i = MAKE_OPCODE_FULL(opcode, inst->size, inst->condition, inst->flags, 1);
|
||||||
dst->inst = (drcbec_instruction *)drclabel_get_codeptr(drcbe->labels, inst->param[0].value, fixup_label, dst);
|
dst->inst = (drcbec_instruction *)drcbe->labels->get_codeptr(inst->param[0].value, fixup_label, dst);
|
||||||
dst++;
|
dst++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -562,9 +556,9 @@ static void drcbec_generate(drcbe_state *drcbe, drcuml_block *block, const drcum
|
|||||||
drcbe->cache->end_codegen();
|
drcbe->cache->end_codegen();
|
||||||
|
|
||||||
/* tell all of our utility objects that the block is finished */
|
/* tell all of our utility objects that the block is finished */
|
||||||
drchash_block_end(drcbe->hash, block);
|
drcbe->hash->block_end(*block);
|
||||||
drclabel_block_end(drcbe->labels, block);
|
drcbe->labels->block_end(*block);
|
||||||
drcmap_block_end(drcbe->map, block);
|
drcbe->map->block_end(*block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -575,7 +569,7 @@ static void drcbec_generate(drcbe_state *drcbe, drcuml_block *block, const drcum
|
|||||||
|
|
||||||
static int drcbec_hash_exists(drcbe_state *state, UINT32 mode, UINT32 pc)
|
static int drcbec_hash_exists(drcbe_state *state, UINT32 mode, UINT32 pc)
|
||||||
{
|
{
|
||||||
return drchash_code_exists(state->hash, mode, pc);
|
return state->hash->code_exists(mode, pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -641,7 +635,7 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
|
|||||||
|
|
||||||
case MAKE_OPCODE_SHORT(DRCUML_OP_HASHJMP, 4, 0): /* HASHJMP mode,pc,handle */
|
case MAKE_OPCODE_SHORT(DRCUML_OP_HASHJMP, 4, 0): /* HASHJMP mode,pc,handle */
|
||||||
sp = 0;
|
sp = 0;
|
||||||
newinst = (const drcbec_instruction *)drchash_get_codeptr(drcbe->hash, PARAM0, PARAM1);
|
newinst = (const drcbec_instruction *)drcbe->hash->get_codeptr(PARAM0, PARAM1);
|
||||||
if (newinst == NULL)
|
if (newinst == NULL)
|
||||||
{
|
{
|
||||||
assert(sp < ARRAY_LENGTH(callstack));
|
assert(sp < ARRAY_LENGTH(callstack));
|
||||||
@ -722,7 +716,7 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
|
|||||||
|
|
||||||
case MAKE_OPCODE_SHORT(DRCUML_OP_RECOVER, 4, 0): /* RECOVER dst,mapvar */
|
case MAKE_OPCODE_SHORT(DRCUML_OP_RECOVER, 4, 0): /* RECOVER dst,mapvar */
|
||||||
assert(sp > 0);
|
assert(sp > 0);
|
||||||
PARAM0 = drcmap_get_value(drcbe->map, (drccodeptr)callstack[0], PARAM1);
|
PARAM0 = drcbe->map->get_value((drccodeptr)callstack[0], PARAM1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
@ -2189,7 +2183,7 @@ static void output_parameter(drcbe_state *drcbe, drcbec_instruction **dstptr, vo
|
|||||||
{
|
{
|
||||||
/* convert mapvars to immediates */
|
/* convert mapvars to immediates */
|
||||||
case DRCUML_PTYPE_MAPVAR:
|
case DRCUML_PTYPE_MAPVAR:
|
||||||
temp_param.value = drcmap_get_last_value(drcbe->map, param->value);
|
temp_param.value = drcbe->map->get_last_value(param->value);
|
||||||
param = &temp_param;
|
param = &temp_param;
|
||||||
/* fall through to immediate case */
|
/* fall through to immediate case */
|
||||||
|
|
||||||
|
@ -21,251 +21,172 @@
|
|||||||
#define LOG_RECOVER (0)
|
#define LOG_RECOVER (0)
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
TYPE DEFINITIONS
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/* structure holding information about a single label */
|
|
||||||
typedef struct _drcmap_entry drcmap_entry;
|
|
||||||
struct _drcmap_entry
|
|
||||||
{
|
|
||||||
drcmap_entry * next; /* pointer to next map entry */
|
|
||||||
drccodeptr codeptr; /* pointer to the relevant code */
|
|
||||||
UINT32 mapvar; /* map variable id */
|
|
||||||
UINT32 newval; /* value of the variable starting at codeptr */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* structure describing the state of the code map */
|
|
||||||
struct _drcmap_state
|
|
||||||
{
|
|
||||||
drc_cache * cache; /* pointer to the cache */
|
|
||||||
UINT64 uniquevalue; /* unique value used to find the table */
|
|
||||||
drcmap_entry * head; /* head of the live list */
|
|
||||||
drcmap_entry ** tailptr; /* pointer to tail of the live list */
|
|
||||||
UINT32 numvalues; /* number of values in the list */
|
|
||||||
UINT32 mapvalue[DRCUML_MAPVAR_END - DRCUML_MAPVAR_M0]; /* array of current values */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* structure holding information about a single label */
|
|
||||||
typedef struct _drclabel drclabel;
|
|
||||||
struct _drclabel
|
|
||||||
{
|
|
||||||
drclabel * next; /* pointer to next label */
|
|
||||||
drcuml_codelabel label; /* the label specified */
|
|
||||||
drccodeptr codeptr; /* pointer to the relevant code */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* structure holding a live list of labels */
|
|
||||||
struct _drclabel_list
|
|
||||||
{
|
|
||||||
drc_cache * cache; /* pointer to the cache */
|
|
||||||
drclabel * head; /* head of the live list */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
FUNCTION PROTOTYPES
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static void label_list_reset(drclabel_list *list, int fatal_on_leftovers);
|
|
||||||
static drclabel *label_find_or_allocate(drclabel_list *list, drcuml_codelabel label);
|
|
||||||
static void label_oob_callback(drccodeptr *codeptr, void *param1, void *param2, void *param3);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
HASH TABLE MANAGEMENT
|
HASH TABLE MANAGEMENT
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
drchash_alloc - allocate memory in the cache
|
// drc_hash_table - constructor
|
||||||
for the hash table tracker (it auto-frees
|
//-------------------------------------------------
|
||||||
with the cache)
|
|
||||||
-------------------------------------------------*/
|
|
||||||
|
|
||||||
drchash_state *drchash_alloc(drc_cache *cache, int modes, int addrbits, int ignorebits)
|
drc_hash_table::drc_hash_table(drc_cache &cache, UINT32 modes, UINT8 addrbits, UINT8 ignorebits)
|
||||||
|
: m_cache(cache),
|
||||||
|
m_modes(modes),
|
||||||
|
m_nocodeptr(NULL),
|
||||||
|
m_l1bits((addrbits - ignorebits) / 2),
|
||||||
|
m_l2bits((addrbits - ignorebits) - m_l1bits),
|
||||||
|
m_l1shift(ignorebits + m_l2bits),
|
||||||
|
m_l2shift(ignorebits),
|
||||||
|
m_l1mask((1 << m_l1bits) - 1),
|
||||||
|
m_l2mask((1 << m_l2bits) - 1),
|
||||||
|
m_base(reinterpret_cast<drccodeptr ***>(cache.alloc(modes * sizeof(**m_base)))),
|
||||||
|
m_emptyl1(NULL),
|
||||||
|
m_emptyl2(NULL)
|
||||||
{
|
{
|
||||||
int effaddrbits = addrbits - ignorebits;
|
reset();
|
||||||
drchash_state *drchash;
|
|
||||||
|
|
||||||
/* allocate permanent state from the cache */
|
|
||||||
drchash = (drchash_state *)cache->alloc(sizeof(*drchash) + modes * sizeof(drchash->base[0]));
|
|
||||||
if (drchash == NULL)
|
|
||||||
return NULL;
|
|
||||||
memset(drchash, 0, sizeof(*drchash) + modes * sizeof(drchash->base[0]));
|
|
||||||
|
|
||||||
/* copy in parameters */
|
|
||||||
drchash->cache = cache;
|
|
||||||
drchash->modes = modes;
|
|
||||||
|
|
||||||
/* compute the sizes of the tables */
|
|
||||||
drchash->l1bits = effaddrbits / 2;
|
|
||||||
drchash->l2bits = effaddrbits - drchash->l1bits;
|
|
||||||
drchash->l1shift = ignorebits + drchash->l2bits;
|
|
||||||
drchash->l2shift = ignorebits;
|
|
||||||
drchash->l1mask = (1 << drchash->l1bits) - 1;
|
|
||||||
drchash->l2mask = (1 << drchash->l2bits) - 1;
|
|
||||||
|
|
||||||
/* reset the hash table, which allocates any subsequent tables */
|
|
||||||
if (!drchash_reset(drchash))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return drchash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
drchash_reset - flush existing hash tables and
|
// reset - flush existing hash tables and create
|
||||||
create new ones
|
// new ones
|
||||||
-------------------------------------------------*/
|
//-------------------------------------------------
|
||||||
|
|
||||||
int drchash_reset(drchash_state *drchash)
|
bool drc_hash_table::reset()
|
||||||
{
|
{
|
||||||
int modenum, entry;
|
// allocate an empty l2 hash table
|
||||||
|
m_emptyl2 = (drccodeptr *)m_cache.alloc_temporary(sizeof(drccodeptr) << m_l2bits);
|
||||||
|
if (m_emptyl2 == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
/* allocate an empty l2 hash table */
|
// populate it with pointers to the recompile_exit code
|
||||||
drchash->emptyl2 = (drccodeptr *)drchash->cache->alloc_temporary(sizeof(drccodeptr) << drchash->l2bits);
|
for (int entry = 0; entry < (1 << m_l2bits); entry++)
|
||||||
if (drchash->emptyl2 == NULL)
|
m_emptyl2[entry] = m_nocodeptr;
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* populate it with pointers to the recompile_exit code */
|
// allocate an empty l1 hash table
|
||||||
for (entry = 0; entry < (1 << drchash->l2bits); entry++)
|
m_emptyl1 = (drccodeptr **)m_cache.alloc_temporary(sizeof(drccodeptr *) << m_l1bits);
|
||||||
drchash->emptyl2[entry] = drchash->nocodeptr;
|
if (m_emptyl1 == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
/* allocate an empty l1 hash table */
|
// populate it with pointers to the empty l2 table
|
||||||
drchash->emptyl1 = (drccodeptr **)drchash->cache->alloc_temporary(sizeof(drccodeptr *) << drchash->l1bits);
|
for (int entry = 0; entry < (1 << m_l1bits); entry++)
|
||||||
if (drchash->emptyl1 == NULL)
|
m_emptyl1[entry] = m_emptyl2;
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* populate it with pointers to the empty l2 table */
|
// reset the hash tables
|
||||||
for (entry = 0; entry < (1 << drchash->l1bits); entry++)
|
for (int modenum = 0; modenum < m_modes; modenum++)
|
||||||
drchash->emptyl1[entry] = drchash->emptyl2;
|
m_base[modenum] = m_emptyl1;
|
||||||
|
|
||||||
/* reset the hash tables */
|
return true;
|
||||||
for (modenum = 0; modenum < drchash->modes; modenum++)
|
|
||||||
drchash->base[modenum] = drchash->emptyl1;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
drchash_block_begin - note the beginning of a
|
// block_begin - note the beginning of a block
|
||||||
block
|
//-------------------------------------------------
|
||||||
-------------------------------------------------*/
|
|
||||||
|
|
||||||
void drchash_block_begin(drchash_state *drchash, drcuml_block *block, const drcuml_instruction *instlist, UINT32 numinst)
|
void drc_hash_table::block_begin(drcuml_block &block, const drcuml_instruction *instlist, UINT32 numinst)
|
||||||
{
|
{
|
||||||
int inum;
|
// before generating code, pre-allocate any hash entries; we do this by setting dummy hash values
|
||||||
|
for (int inum = 0; inum < numinst; inum++)
|
||||||
/* before generating code, pre-allocate any hash entries; we do this by setting dummy hash values */
|
|
||||||
for (inum = 0; inum < numinst; inum++)
|
|
||||||
{
|
{
|
||||||
const drcuml_instruction *inst = &instlist[inum];
|
const drcuml_instruction &inst = instlist[inum];
|
||||||
|
|
||||||
/* if the opcode is a hash, verify that it makes sense and then set a NULL entry */
|
// if the opcode is a hash, verify that it makes sense and then set a NULL entry
|
||||||
if (inst->opcode == DRCUML_OP_HASH)
|
if (inst.opcode == DRCUML_OP_HASH)
|
||||||
{
|
{
|
||||||
assert(inst->numparams == 2);
|
assert(inst.numparams == 2);
|
||||||
assert(inst->param[0].type == DRCUML_PTYPE_IMMEDIATE);
|
assert(inst.param[0].type == DRCUML_PTYPE_IMMEDIATE);
|
||||||
assert(inst->param[1].type == DRCUML_PTYPE_IMMEDIATE);
|
assert(inst.param[1].type == DRCUML_PTYPE_IMMEDIATE);
|
||||||
|
|
||||||
/* if we fail to allocate, we must abort the block */
|
// if we fail to allocate, we must abort the block
|
||||||
if (!drchash_set_codeptr(drchash, inst->param[0].value, inst->param[1].value, NULL))
|
if (!set_codeptr(inst.param[0].value, inst.param[1].value, NULL))
|
||||||
drcuml_block_abort(block);
|
drcuml_block_abort(&block);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if the opcode is a hashjmp to a fixed location, make sure we preallocate the tables */
|
// if the opcode is a hashjmp to a fixed location, make sure we preallocate the tables
|
||||||
if (inst->opcode == DRCUML_OP_HASHJMP && inst->param[0].type == DRCUML_PTYPE_IMMEDIATE && inst->param[1].type == DRCUML_PTYPE_IMMEDIATE)
|
if (inst.opcode == DRCUML_OP_HASHJMP && inst.param[0].type == DRCUML_PTYPE_IMMEDIATE && inst.param[1].type == DRCUML_PTYPE_IMMEDIATE)
|
||||||
{
|
{
|
||||||
/* if we fail to allocate, we must abort the block */
|
// if we fail to allocate, we must abort the block
|
||||||
drccodeptr code = drchash_get_codeptr(drchash, inst->param[0].value, inst->param[1].value);
|
drccodeptr code = get_codeptr(inst.param[0].value, inst.param[1].value);
|
||||||
if (!drchash_set_codeptr(drchash, inst->param[0].value, inst->param[1].value, code))
|
if (!set_codeptr(inst.param[0].value, inst.param[1].value, code))
|
||||||
drcuml_block_abort(block);
|
drcuml_block_abort(&block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
drchash_block_end - note the end of a block
|
// block_end - note the end of a block
|
||||||
-------------------------------------------------*/
|
//-------------------------------------------------
|
||||||
|
|
||||||
void drchash_block_end(drchash_state *drchash, drcuml_block *block)
|
void drc_hash_table::block_end(drcuml_block &block)
|
||||||
{
|
{
|
||||||
/* nothing to do here, yet */
|
// nothing to do here, yet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
drchash_set_default_codeptr - change the
|
// set_default_codeptr - change the default
|
||||||
default codeptr
|
// codeptr
|
||||||
-------------------------------------------------*/
|
//-------------------------------------------------
|
||||||
|
|
||||||
void drchash_set_default_codeptr(drchash_state *drchash, drccodeptr nocodeptr)
|
void drc_hash_table::set_default_codeptr(drccodeptr nocodeptr)
|
||||||
{
|
{
|
||||||
drccodeptr old = drchash->nocodeptr;
|
// nothing to do if the same
|
||||||
int modenum, l1entry, l2entry;
|
drccodeptr old = m_nocodeptr;
|
||||||
|
|
||||||
/* nothing to do if the same */
|
|
||||||
if (old == nocodeptr)
|
if (old == nocodeptr)
|
||||||
return;
|
return;
|
||||||
drchash->nocodeptr = nocodeptr;
|
m_nocodeptr = nocodeptr;
|
||||||
|
|
||||||
/* update the empty L2 table first */
|
// update the empty L2 table first
|
||||||
for (l2entry = 0; l2entry < (1 << drchash->l2bits); l2entry++)
|
for (int l2entry = 0; l2entry < (1 << m_l2bits); l2entry++)
|
||||||
drchash->emptyl2[l2entry] = nocodeptr;
|
m_emptyl2[l2entry] = nocodeptr;
|
||||||
|
|
||||||
/* now scan all existing hashtables for entries */
|
// now scan all existing hashtables for entries
|
||||||
for (modenum = 0; modenum < drchash->modes; modenum++)
|
for (int modenum = 0; modenum < m_modes; modenum++)
|
||||||
if (drchash->base[modenum] != drchash->emptyl1)
|
if (m_base[modenum] != m_emptyl1)
|
||||||
for (l1entry = 0; l1entry < (1 << drchash->l1bits); l1entry++)
|
for (int l1entry = 0; l1entry < (1 << m_l1bits); l1entry++)
|
||||||
if (drchash->base[modenum][l1entry] != drchash->emptyl2)
|
if (m_base[modenum][l1entry] != m_emptyl2)
|
||||||
for (l2entry = 0; l2entry < (1 << drchash->l2bits); l2entry++)
|
for (int l2entry = 0; l2entry < (1 << m_l2bits); l2entry++)
|
||||||
if (drchash->base[modenum][l1entry][l2entry] == old)
|
if (m_base[modenum][l1entry][l2entry] == old)
|
||||||
drchash->base[modenum][l1entry][l2entry] = nocodeptr;
|
m_base[modenum][l1entry][l2entry] = nocodeptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
drchash_set_codeptr - set the codeptr for the
|
// set_codeptr - set the codeptr for the given
|
||||||
given mode/pc
|
// mode/pc
|
||||||
-------------------------------------------------*/
|
//-------------------------------------------------
|
||||||
|
|
||||||
int drchash_set_codeptr(drchash_state *drchash, UINT32 mode, UINT32 pc, drccodeptr code)
|
bool drc_hash_table::set_codeptr(UINT32 mode, UINT32 pc, drccodeptr code)
|
||||||
{
|
{
|
||||||
UINT32 l1 = (pc >> drchash->l1shift) & drchash->l1mask;
|
// copy-on-write for the l1 hash table
|
||||||
UINT32 l2 = (pc >> drchash->l2shift) & drchash->l2mask;
|
assert(mode < m_modes);
|
||||||
|
if (m_base[mode] == m_emptyl1)
|
||||||
assert(mode < drchash->modes);
|
|
||||||
|
|
||||||
/* copy-on-write for the l1 hash table */
|
|
||||||
if (drchash->base[mode] == drchash->emptyl1)
|
|
||||||
{
|
{
|
||||||
drccodeptr **newtable = (drccodeptr **)drchash->cache->alloc_temporary(sizeof(drccodeptr *) << drchash->l1bits);
|
drccodeptr **newtable = (drccodeptr **)m_cache.alloc_temporary(sizeof(drccodeptr *) << m_l1bits);
|
||||||
if (newtable == NULL)
|
if (newtable == NULL)
|
||||||
return FALSE;
|
return false;
|
||||||
memcpy(newtable, drchash->emptyl1, sizeof(drccodeptr *) << drchash->l1bits);
|
memcpy(newtable, m_emptyl1, sizeof(drccodeptr *) << m_l1bits);
|
||||||
drchash->base[mode] = newtable;
|
m_base[mode] = newtable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy-on-write for the l2 hash table */
|
// copy-on-write for the l2 hash table
|
||||||
if (drchash->base[mode][l1] == drchash->emptyl2)
|
UINT32 l1 = (pc >> m_l1shift) & m_l1mask;
|
||||||
|
if (m_base[mode][l1] == m_emptyl2)
|
||||||
{
|
{
|
||||||
drccodeptr *newtable = (drccodeptr *)drchash->cache->alloc_temporary(sizeof(drccodeptr) << drchash->l2bits);
|
drccodeptr *newtable = (drccodeptr *)m_cache.alloc_temporary(sizeof(drccodeptr) << m_l2bits);
|
||||||
if (newtable == NULL)
|
if (newtable == NULL)
|
||||||
return FALSE;
|
return false;
|
||||||
memcpy(newtable, drchash->emptyl2, sizeof(drccodeptr) << drchash->l2bits);
|
memcpy(newtable, m_emptyl2, sizeof(drccodeptr) << m_l2bits);
|
||||||
drchash->base[mode][l1] = newtable;
|
m_base[mode][l1] = newtable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the new entry */
|
// set the new entry
|
||||||
drchash->base[mode][l1][l2] = code;
|
UINT32 l2 = (pc >> m_l2shift) & m_l2mask;
|
||||||
return TRUE;
|
m_base[mode][l1][l2] = code;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -274,118 +195,103 @@ int drchash_set_codeptr(drchash_state *drchash, UINT32 mode, UINT32 pc, drccodep
|
|||||||
CODE MAP MANAGEMENT
|
CODE MAP MANAGEMENT
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
drcmap_alloc - allocate memory in the cache
|
// drc_map_variables - constructor
|
||||||
for the code mapper (it auto-frees with the
|
//-------------------------------------------------
|
||||||
cache)
|
|
||||||
-------------------------------------------------*/
|
|
||||||
|
|
||||||
drcmap_state *drcmap_alloc(drc_cache *cache, UINT64 uniquevalue)
|
drc_map_variables::drc_map_variables(drc_cache &cache, UINT64 uniquevalue)
|
||||||
|
: m_cache(cache),
|
||||||
|
m_uniquevalue(uniquevalue)
|
||||||
{
|
{
|
||||||
drcmap_state *drcmap;
|
memset(m_mapvalue, 0, sizeof(m_mapvalue));
|
||||||
|
|
||||||
/* allocate permanent state from the cache */
|
|
||||||
drcmap = (drcmap_state *)cache->alloc(sizeof(*drcmap));
|
|
||||||
if (drcmap == NULL)
|
|
||||||
return NULL;
|
|
||||||
memset(drcmap, 0, sizeof(*drcmap));
|
|
||||||
|
|
||||||
/* remember the cache */
|
|
||||||
drcmap->cache = cache;
|
|
||||||
drcmap->tailptr = &drcmap->head;
|
|
||||||
|
|
||||||
return drcmap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
drcmap_block_begin - note the beginning of a
|
// ~drc_map_variables - destructor
|
||||||
block
|
//-------------------------------------------------
|
||||||
-------------------------------------------------*/
|
|
||||||
|
|
||||||
void drcmap_block_begin(drcmap_state *drcmap, drcuml_block *block)
|
drc_map_variables::~drc_map_variables()
|
||||||
{
|
{
|
||||||
/* release any remaining live entries */
|
// must detach all items from the entry list so that the list object
|
||||||
while (drcmap->head != NULL)
|
// doesn't try to free them on exit
|
||||||
{
|
m_entry_list.detach_all();
|
||||||
drcmap_entry *entry = drcmap->head;
|
|
||||||
drcmap->head = entry->next;
|
|
||||||
drcmap->cache->dealloc(entry, sizeof(*entry));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reset the tailptr and count */
|
|
||||||
drcmap->tailptr = &drcmap->head;
|
|
||||||
drcmap->numvalues = 0;
|
|
||||||
|
|
||||||
/* reset the variable values */
|
|
||||||
memset(drcmap->mapvalue, 0, sizeof(drcmap->mapvalue));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
drcmap_block_end - note the end of a block
|
// block_begin - note the beginning of a block
|
||||||
-------------------------------------------------*/
|
//-------------------------------------------------
|
||||||
|
|
||||||
void drcmap_block_end(drcmap_state *drcmap, drcuml_block *block)
|
void drc_map_variables::block_begin(drcuml_block &block)
|
||||||
{
|
{
|
||||||
UINT32 curvalue[DRCUML_MAPVAR_END - DRCUML_MAPVAR_M0] = { 0 };
|
// release any remaining live entries
|
||||||
UINT8 changed[DRCUML_MAPVAR_END - DRCUML_MAPVAR_M0] = { 0 };
|
map_entry *entry;
|
||||||
drcmap_entry *entry;
|
while ((entry = m_entry_list.detach_head()) != NULL)
|
||||||
drccodeptr lastptr;
|
m_cache.dealloc(entry, sizeof(*entry));
|
||||||
drccodeptr *top;
|
|
||||||
UINT32 *dest;
|
|
||||||
|
|
||||||
/* only process if we have data */
|
// reset the variable values
|
||||||
if (drcmap->head == NULL)
|
memset(m_mapvalue, 0, sizeof(m_mapvalue));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// block_end - note the end of a block
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void drc_map_variables::block_end(drcuml_block &block)
|
||||||
|
{
|
||||||
|
// only process if we have data
|
||||||
|
if (m_entry_list.first() == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* begin "code generation" aligned to an 8-byte boundary */
|
// begin "code generation" aligned to an 8-byte boundary
|
||||||
top = drcmap->cache->begin_codegen(sizeof(UINT64) + sizeof(UINT32) + 2 * sizeof(UINT32) * drcmap->numvalues);
|
drccodeptr *top = m_cache.begin_codegen(sizeof(UINT64) + sizeof(UINT32) + 2 * sizeof(UINT32) * m_entry_list.count());
|
||||||
if (top == NULL)
|
if (top == NULL)
|
||||||
drcuml_block_abort(block);
|
drcuml_block_abort(&block);
|
||||||
dest = (UINT32 *)(((FPTR)*top + 7) & ~7);
|
UINT32 *dest = (UINT32 *)(((FPTR)*top + 7) & ~7);
|
||||||
|
|
||||||
/* store the cookie first */
|
// store the cookie first
|
||||||
*(UINT64 *)dest = drcmap->uniquevalue;
|
*(UINT64 *)dest = m_uniquevalue;
|
||||||
dest += 2;
|
dest += 2;
|
||||||
|
|
||||||
/* get the pointer to the first item and store an initial backwards offset */
|
// get the pointer to the first item and store an initial backwards offset
|
||||||
lastptr = drcmap->head->codeptr;
|
drccodeptr lastptr = m_entry_list.first()->m_codeptr;
|
||||||
*dest = (drccodeptr)dest - lastptr;
|
*dest = (drccodeptr)dest - lastptr;
|
||||||
dest++;
|
dest++;
|
||||||
|
|
||||||
/* now iterate over entries and store them */
|
// now iterate over entries and store them
|
||||||
for (entry = drcmap->head; entry != NULL; entry = entry->next)
|
UINT32 curvalue[DRCUML_MAPVAR_END - DRCUML_MAPVAR_M0] = { 0 };
|
||||||
|
bool changed[DRCUML_MAPVAR_END - DRCUML_MAPVAR_M0] = { false };
|
||||||
|
for (map_entry *entry = m_entry_list.first(); entry != NULL; entry = entry->next())
|
||||||
{
|
{
|
||||||
/* update the current value of the variable and detect changes */
|
// update the current value of the variable and detect changes
|
||||||
if (curvalue[entry->mapvar] != entry->newval)
|
if (curvalue[entry->m_mapvar] != entry->m_newval)
|
||||||
{
|
{
|
||||||
curvalue[entry->mapvar] = entry->newval;
|
curvalue[entry->m_mapvar] = entry->m_newval;
|
||||||
changed[entry->mapvar] = TRUE;
|
changed[entry->m_mapvar] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if the next code pointer is different, or if we're at the end, flush changes */
|
// if the next code pointer is different, or if we're at the end, flush changes
|
||||||
if (entry->next == NULL || entry->next->codeptr != entry->codeptr)
|
if (entry->next() == NULL || entry->next()->m_codeptr != entry->m_codeptr)
|
||||||
{
|
{
|
||||||
UINT32 codedelta = entry->codeptr - lastptr;
|
// build a mask of changed variables
|
||||||
|
int numchanged = 0;
|
||||||
UINT32 varmask = 0;
|
UINT32 varmask = 0;
|
||||||
int numchanged;
|
for (int varnum = 0; varnum < ARRAY_LENGTH(changed); varnum++)
|
||||||
int varnum;
|
|
||||||
|
|
||||||
/* build a mask of changed variables */
|
|
||||||
for (numchanged = varnum = 0; varnum < ARRAY_LENGTH(changed); varnum++)
|
|
||||||
if (changed[varnum])
|
if (changed[varnum])
|
||||||
{
|
{
|
||||||
changed[varnum] = FALSE;
|
changed[varnum] = false;
|
||||||
varmask |= 1 << varnum;
|
varmask |= 1 << varnum;
|
||||||
numchanged++;
|
numchanged++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if nothing really changed, skip it */
|
// if nothing really changed, skip it
|
||||||
if (numchanged == 0)
|
if (numchanged == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* first word is a code delta plus mask of changed variables */
|
// first word is a code delta plus mask of changed variables
|
||||||
|
UINT32 codedelta = entry->m_codeptr - lastptr;
|
||||||
while (codedelta > 0xffff)
|
while (codedelta > 0xffff)
|
||||||
{
|
{
|
||||||
*dest++ = 0xffff << 16;
|
*dest++ = 0xffff << 16;
|
||||||
@ -393,120 +299,107 @@ void drcmap_block_end(drcmap_state *drcmap, drcuml_block *block)
|
|||||||
}
|
}
|
||||||
*dest++ = (codedelta << 16) | (varmask << 4) | numchanged;
|
*dest++ = (codedelta << 16) | (varmask << 4) | numchanged;
|
||||||
|
|
||||||
/* now output updated variable values */
|
// now output updated variable values
|
||||||
for (varnum = 0; varnum < ARRAY_LENGTH(changed); varnum++)
|
for (int varnum = 0; varnum < ARRAY_LENGTH(changed); varnum++)
|
||||||
if ((varmask >> varnum) & 1)
|
if ((varmask >> varnum) & 1)
|
||||||
*dest++ = curvalue[varnum];
|
*dest++ = curvalue[varnum];
|
||||||
|
|
||||||
/* remember our lastptr */
|
// remember our lastptr
|
||||||
lastptr = entry->codeptr;
|
lastptr = entry->m_codeptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add a terminator */
|
// add a terminator
|
||||||
*dest++ = 0;
|
*dest++ = 0;
|
||||||
|
|
||||||
/* complete codegen */
|
// complete codegen
|
||||||
*top = (drccodeptr)dest;
|
*top = (drccodeptr)dest;
|
||||||
drcmap->cache->end_codegen();
|
m_cache.end_codegen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
drcmap_set_value - set a map value for the
|
// set_value - set a map value for the given
|
||||||
given code pointer
|
// code pointer
|
||||||
-------------------------------------------------*/
|
//-------------------------------------------------
|
||||||
|
|
||||||
void drcmap_set_value(drcmap_state *drcmap, drccodeptr codebase, UINT32 mapvar, UINT32 newvalue)
|
void drc_map_variables::set_value(drccodeptr codebase, UINT32 mapvar, UINT32 newvalue)
|
||||||
{
|
{
|
||||||
drcmap_entry *entry;
|
|
||||||
|
|
||||||
assert(mapvar >= DRCUML_MAPVAR_M0 && mapvar < DRCUML_MAPVAR_END);
|
assert(mapvar >= DRCUML_MAPVAR_M0 && mapvar < DRCUML_MAPVAR_END);
|
||||||
|
|
||||||
/* if this value isn't different, skip it */
|
// if this value isn't different, skip it
|
||||||
if (drcmap->mapvalue[mapvar - DRCUML_MAPVAR_M0] == newvalue)
|
if (m_mapvalue[mapvar - DRCUML_MAPVAR_M0] == newvalue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* allocate a new entry and fill it in */
|
// allocate a new entry and fill it in
|
||||||
entry = (drcmap_entry *)drcmap->cache->alloc(sizeof(*entry));
|
map_entry *entry = (map_entry *)m_cache.alloc(sizeof(*entry));
|
||||||
entry->next = NULL;
|
entry->m_next = NULL;
|
||||||
entry->codeptr = codebase;
|
entry->m_codeptr = codebase;
|
||||||
entry->mapvar = mapvar - DRCUML_MAPVAR_M0;
|
entry->m_mapvar = mapvar - DRCUML_MAPVAR_M0;
|
||||||
entry->newval = newvalue;
|
entry->m_newval = newvalue;
|
||||||
|
|
||||||
/* hook us into the end of the list */
|
// hook us into the end of the list
|
||||||
*drcmap->tailptr = entry;
|
m_entry_list.append(*entry);
|
||||||
drcmap->tailptr = &entry->next;
|
|
||||||
|
|
||||||
/* update our state in the table as well */
|
// update our state in the table as well
|
||||||
drcmap->mapvalue[mapvar - DRCUML_MAPVAR_M0] = newvalue;
|
m_mapvalue[mapvar - DRCUML_MAPVAR_M0] = newvalue;
|
||||||
|
|
||||||
/* and increment the count */
|
|
||||||
drcmap->numvalues++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
drcmap_get_value - return a map value for the
|
// get_value - return a map value for the given
|
||||||
given code pointer
|
// code pointer
|
||||||
-------------------------------------------------*/
|
//-------------------------------------------------
|
||||||
|
|
||||||
UINT32 drcmap_get_value(drcmap_state *drcmap, drccodeptr codebase, UINT32 mapvar)
|
UINT32 drc_map_variables::get_value(drccodeptr codebase, UINT32 mapvar) const
|
||||||
{
|
{
|
||||||
UINT64 *endscan = (UINT64 *)drcmap->cache->top();
|
|
||||||
UINT32 varmask = 0x10 << mapvar;
|
|
||||||
drccodeptr curcode;
|
|
||||||
UINT32 result = 0;
|
|
||||||
UINT64 *curscan;
|
|
||||||
UINT32 *data;
|
|
||||||
|
|
||||||
assert(mapvar >= DRCUML_MAPVAR_M0 && mapvar < DRCUML_MAPVAR_END);
|
assert(mapvar >= DRCUML_MAPVAR_M0 && mapvar < DRCUML_MAPVAR_END);
|
||||||
mapvar -= DRCUML_MAPVAR_M0;
|
mapvar -= DRCUML_MAPVAR_M0;
|
||||||
|
|
||||||
/* get an aligned pointer to start scanning */
|
// get an aligned pointer to start scanning
|
||||||
curscan = (UINT64 *)(((FPTR)codebase | 7) + 1);
|
UINT64 *curscan = (UINT64 *)(((FPTR)codebase | 7) + 1);
|
||||||
|
UINT64 *endscan = (UINT64 *)m_cache.top();
|
||||||
|
|
||||||
/* look for the signature */
|
// look for the signature
|
||||||
while (curscan < endscan && *curscan++ != drcmap->uniquevalue) ;
|
while (curscan < endscan && *curscan++ != m_uniquevalue) ;
|
||||||
if (curscan >= endscan)
|
if (curscan >= endscan)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* switch to 32-bit pointers for processing the rest */
|
// switch to 32-bit pointers for processing the rest
|
||||||
data = (UINT32 *)curscan;
|
UINT32 *data = (UINT32 *)curscan;
|
||||||
|
|
||||||
/* first get the 32-bit starting offset to the code */
|
// first get the 32-bit starting offset to the code
|
||||||
curcode = (drccodeptr)data - *data;
|
drccodeptr curcode = (drccodeptr)data - *data;
|
||||||
data++;
|
data++;
|
||||||
|
|
||||||
/* now loop until we advance past our target */
|
// now loop until we advance past our target
|
||||||
while (TRUE)
|
UINT32 varmask = 0x10 << mapvar;
|
||||||
|
UINT32 result = 0;
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
|
// a 0 is a terminator
|
||||||
UINT32 controlword = *data++;
|
UINT32 controlword = *data++;
|
||||||
|
|
||||||
/* a 0 is a terminator */
|
|
||||||
if (controlword == 0)
|
if (controlword == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* update the codeptr; if this puts us past the end, we're done */
|
// update the codeptr; if this puts us past the end, we're done
|
||||||
curcode += (controlword >> 16) & 0xffff;
|
curcode += (controlword >> 16) & 0xffff;
|
||||||
if (curcode > codebase)
|
if (curcode > codebase)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* if our mapvar has changed, process this word */
|
// if our mapvar has changed, process this word
|
||||||
if ((controlword & varmask) != 0)
|
if ((controlword & varmask) != 0)
|
||||||
{
|
{
|
||||||
|
// count how many words precede the one we care about
|
||||||
int dataoffs = 0;
|
int dataoffs = 0;
|
||||||
UINT32 skipmask;
|
for (UINT32 skipmask = (controlword & (varmask - 1)) >> 4; skipmask != 0; skipmask = skipmask & (skipmask - 1))
|
||||||
|
|
||||||
/* count how many words precede the one we care about */
|
|
||||||
for (skipmask = (controlword & (varmask - 1)) >> 4; skipmask != 0; skipmask = skipmask & (skipmask - 1))
|
|
||||||
dataoffs++;
|
dataoffs++;
|
||||||
|
|
||||||
/* fetch the one we want */
|
// fetch the one we want
|
||||||
result = data[dataoffs];
|
result = data[dataoffs];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* low 4 bits contain the total number of words of data */
|
// low 4 bits contain the total number of words of data
|
||||||
data += controlword & 0x0f;
|
data += controlword & 0x0f;
|
||||||
}
|
}
|
||||||
if (LOG_RECOVER)
|
if (LOG_RECOVER)
|
||||||
@ -514,16 +407,22 @@ UINT32 drcmap_get_value(drcmap_state *drcmap, drccodeptr codebase, UINT32 mapvar
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINT32 drc_map_variables::static_get_value(drc_map_variables &map, drccodeptr codebase, UINT32 mapvar)
|
||||||
|
{
|
||||||
|
return map.get_value(codebase, mapvar);
|
||||||
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------
|
|
||||||
drcmap_get_last_value - return the most
|
|
||||||
recently set map value
|
|
||||||
-------------------------------------------------*/
|
|
||||||
|
|
||||||
UINT32 drcmap_get_last_value(drcmap_state *drcmap, UINT32 mapvar)
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// get_last_value - return the most recently set
|
||||||
|
// map value
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
UINT32 drc_map_variables::get_last_value(UINT32 mapvar)
|
||||||
{
|
{
|
||||||
assert(mapvar >= DRCUML_MAPVAR_M0 && mapvar < DRCUML_MAPVAR_END);
|
assert(mapvar >= DRCUML_MAPVAR_M0 && mapvar < DRCUML_MAPVAR_END);
|
||||||
return drcmap->mapvalue[mapvar - DRCUML_MAPVAR_M0];
|
return m_mapvalue[mapvar - DRCUML_MAPVAR_M0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -532,150 +431,136 @@ UINT32 drcmap_get_last_value(drcmap_state *drcmap, UINT32 mapvar)
|
|||||||
LABEL MANAGEMENT
|
LABEL MANAGEMENT
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
drclabel_list_alloc - allocate a label
|
// drc_label_list - constructor
|
||||||
list within the cache (it auto-frees with the
|
//-------------------------------------------------
|
||||||
cache)
|
|
||||||
-------------------------------------------------*/
|
|
||||||
|
|
||||||
drclabel_list *drclabel_list_alloc(drc_cache *cache)
|
drc_label_list::drc_label_list(drc_cache &cache)
|
||||||
|
: m_cache(cache)
|
||||||
{
|
{
|
||||||
drclabel_list *list;
|
|
||||||
|
|
||||||
/* allocate permanent state from the cache */
|
|
||||||
list = (drclabel_list *)cache->alloc(sizeof(*list));
|
|
||||||
if (list == NULL)
|
|
||||||
return NULL;
|
|
||||||
memset(list, 0, sizeof(*list));
|
|
||||||
|
|
||||||
/* remember the cache */
|
|
||||||
list->cache = cache;
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
drclabel_block_begin - note the beginning of
|
// ~drc_label_list - destructor
|
||||||
a block
|
//-------------------------------------------------
|
||||||
-------------------------------------------------*/
|
|
||||||
|
|
||||||
void drclabel_block_begin(drclabel_list *list, drcuml_block *block)
|
drc_label_list::~drc_label_list()
|
||||||
{
|
{
|
||||||
/* make sure the label list is clear, but don't fatalerror */
|
// must detach all items from the entry list so that the list object
|
||||||
label_list_reset(list, FALSE);
|
// doesn't try to free them on exit
|
||||||
|
m_list.detach_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
drclabel_block_end - note the end of a block
|
// block_begin - note the beginning of a block
|
||||||
-------------------------------------------------*/
|
//-------------------------------------------------
|
||||||
|
|
||||||
void drclabel_block_end(drclabel_list *list, drcuml_block *block)
|
void drc_label_list::block_begin(drcuml_block &block)
|
||||||
{
|
{
|
||||||
/* make sure the label list is clear, and fatalerror if we missed anything */
|
// make sure the label list is clear, but don't fatalerror
|
||||||
label_list_reset(list, TRUE);
|
reset(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
drclabel_get_codeptr - find or allocate a new
|
// block_end - note the end of a block
|
||||||
label; returns NULL and requests an OOB
|
//-------------------------------------------------
|
||||||
callback if undefined
|
|
||||||
-------------------------------------------------*/
|
|
||||||
|
|
||||||
drccodeptr drclabel_get_codeptr(drclabel_list *list, drcuml_codelabel label, drclabel_fixup_func fixup, void *param)
|
void drc_label_list::block_end(drcuml_block &block)
|
||||||
{
|
{
|
||||||
drclabel *curlabel = label_find_or_allocate(list, label);
|
// make sure the label list is clear, and fatalerror if we missed anything
|
||||||
|
reset(true);
|
||||||
/* if no code pointer, request an OOB callback */
|
|
||||||
if (curlabel->codeptr == NULL && fixup != NULL)
|
|
||||||
list->cache->request_oob_codegen(label_oob_callback, curlabel, (void *)fixup, param);
|
|
||||||
|
|
||||||
return curlabel->codeptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
drclabel_set_codeptr - set the pointer to a new
|
// get_codeptr - find or allocate a new label;
|
||||||
label
|
// returns NULL and requests an OOB callback if
|
||||||
-------------------------------------------------*/
|
// undefined
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
void drclabel_set_codeptr(drclabel_list *list, drcuml_codelabel label, drccodeptr codeptr)
|
drccodeptr drc_label_list::get_codeptr(drcuml_codelabel label, fixup_func fixup, void *param)
|
||||||
{
|
{
|
||||||
/* set the code pointer */
|
label_entry *curlabel = find_or_allocate(label);
|
||||||
drclabel *curlabel = label_find_or_allocate(list, label);
|
|
||||||
assert(curlabel->codeptr == NULL);
|
// if no code pointer, request an OOB callback
|
||||||
curlabel->codeptr = codeptr;
|
if (curlabel->m_codeptr == NULL && fixup != NULL)
|
||||||
|
m_cache.request_oob_codegen(oob_callback, curlabel, (void *)fixup, param);
|
||||||
|
|
||||||
|
return curlabel->m_codeptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// set_codeptr - set the pointer to a new label
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
/***************************************************************************
|
void drc_label_list::set_codeptr(drcuml_codelabel label, drccodeptr codeptr)
|
||||||
LABEL MANAGEMENT
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
|
||||||
label_list_reset - reset a label
|
|
||||||
list (add all entries to the free list)
|
|
||||||
-------------------------------------------------*/
|
|
||||||
|
|
||||||
static void label_list_reset(drclabel_list *list, int fatal_on_leftovers)
|
|
||||||
{
|
{
|
||||||
/* loop until out of labels */
|
// set the code pointer
|
||||||
while (list->head != NULL)
|
label_entry *curlabel = find_or_allocate(label);
|
||||||
|
assert(curlabel->m_codeptr == NULL);
|
||||||
|
curlabel->m_codeptr = codeptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// reset - reset a label list (add all entries to
|
||||||
|
// the free list)
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void drc_label_list::reset(bool fatal_on_leftovers)
|
||||||
|
{
|
||||||
|
// loop until out of labels
|
||||||
|
label_entry *curlabel;
|
||||||
|
while ((curlabel = m_list.detach_head()) != NULL)
|
||||||
{
|
{
|
||||||
/* remove from the list */
|
// fatal if we were a leftover
|
||||||
drclabel *label = list->head;
|
if (fatal_on_leftovers && curlabel->m_codeptr == NULL)
|
||||||
list->head = label->next;
|
fatalerror("Label %08X never defined!", curlabel->m_label);
|
||||||
|
|
||||||
/* fatal if we were a leftover */
|
// free the label
|
||||||
if (fatal_on_leftovers && label->codeptr == NULL)
|
m_cache.dealloc(curlabel, sizeof(*curlabel));
|
||||||
fatalerror("Label %08X never defined!", label->label);
|
|
||||||
|
|
||||||
/* free the label */
|
|
||||||
list->cache->dealloc(label, sizeof(*label));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
label_find_or_allocate - look up a label and
|
// find_or_allocate - look up a label and
|
||||||
allocate a new one if not found
|
// allocate a new one if not found
|
||||||
-------------------------------------------------*/
|
//-------------------------------------------------
|
||||||
|
|
||||||
static drclabel *label_find_or_allocate(drclabel_list *list, drcuml_codelabel label)
|
drc_label_list::label_entry *drc_label_list::find_or_allocate(drcuml_codelabel label)
|
||||||
{
|
{
|
||||||
drclabel *curlabel;
|
// find the label, or else allocate a new one
|
||||||
|
label_entry *curlabel;
|
||||||
/* find the label, or else allocate a new one */
|
for (curlabel = m_list.first(); curlabel != NULL; curlabel = curlabel->next())
|
||||||
for (curlabel = list->head; curlabel != NULL; curlabel = curlabel->next)
|
if (curlabel->m_label == label)
|
||||||
if (curlabel->label == label)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* if none found, allocate */
|
// if none found, allocate
|
||||||
if (curlabel == NULL)
|
if (curlabel == NULL)
|
||||||
{
|
{
|
||||||
curlabel = (drclabel *)list->cache->alloc(sizeof(*curlabel));
|
curlabel = (label_entry *)m_cache.alloc(sizeof(*curlabel));
|
||||||
curlabel->next = list->head;
|
curlabel->m_label = label;
|
||||||
curlabel->label = label;
|
curlabel->m_codeptr = NULL;
|
||||||
curlabel->codeptr = NULL;
|
m_list.append(*curlabel);
|
||||||
list->head = curlabel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return curlabel;
|
return curlabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
//-------------------------------------------------
|
||||||
label_oob_callback - out-of-band codegen
|
// oob_callback - out-of-band codegen callback
|
||||||
callback for labels
|
// for labels
|
||||||
-------------------------------------------------*/
|
//-------------------------------------------------
|
||||||
|
|
||||||
static void label_oob_callback(drccodeptr *codeptr, void *param1, void *param2, void *param3)
|
void drc_label_list::oob_callback(drccodeptr *codeptr, void *param1, void *param2, void *param3)
|
||||||
{
|
{
|
||||||
drclabel *label = (drclabel *)param1;
|
label_entry *label = (label_entry *)param1;
|
||||||
drclabel_fixup_func callback = (drclabel_fixup_func)param2;
|
fixup_func callback = (fixup_func)param2;
|
||||||
|
|
||||||
(*callback)(param3, label->codeptr);
|
(*callback)(param3, label->m_codeptr);
|
||||||
}
|
}
|
||||||
|
@ -22,134 +22,138 @@
|
|||||||
TYPE DEFINITIONS
|
TYPE DEFINITIONS
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
/* callback function for forward-referenced labels */
|
// ======================> drc_hash_table
|
||||||
typedef void (*drclabel_fixup_func)(void *parameter, drccodeptr labelcodeptr);
|
|
||||||
|
|
||||||
|
// common hash table management
|
||||||
/* opaque structure representing a managed list of labels */
|
class drc_hash_table
|
||||||
typedef struct _drclabel_list drclabel_list;
|
|
||||||
|
|
||||||
|
|
||||||
/* opaque structure representing a managed code map */
|
|
||||||
typedef struct _drcmap_state drcmap_state;
|
|
||||||
|
|
||||||
|
|
||||||
/* information about the hash tables used by the UML and backend */
|
|
||||||
typedef struct _drchash_state drchash_state;
|
|
||||||
struct _drchash_state
|
|
||||||
{
|
{
|
||||||
drc_cache * cache; /* cache where allocations come from */
|
public:
|
||||||
int modes; /* number of modes supported */
|
// 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);
|
||||||
|
|
||||||
drccodeptr nocodeptr; /* pointer to code which will handle missing entries */
|
// block begin/end
|
||||||
|
void block_begin(drcuml_block &block, const drcuml_instruction *instlist, UINT32 numinst);
|
||||||
|
void block_end(drcuml_block &block);
|
||||||
|
|
||||||
UINT8 l1bits; /* bits worth of entries in l1 hash tables */
|
// code pointer access
|
||||||
UINT8 l1shift; /* shift to apply to the PC to get the l1 hash entry */
|
bool set_codeptr(UINT32 mode, UINT32 pc, drccodeptr code);
|
||||||
offs_t l1mask; /* mask to apply after shifting */
|
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]; }
|
||||||
UINT8 l2bits; /* bits worth of entries in l2 hash tables */
|
bool code_exists(UINT32 mode, UINT32 pc) { return get_codeptr(mode, pc) != m_nocodeptr; }
|
||||||
UINT8 l2shift; /* shift to apply to the PC to get the l2 hash entry */
|
|
||||||
offs_t l2mask; /* mask to apply after shifting */
|
|
||||||
|
|
||||||
drccodeptr ** emptyl1; /* pointer to empty l1 hash table */
|
private:
|
||||||
drccodeptr * emptyl2; /* pointer to empty l2 hash table */
|
// internal state
|
||||||
|
drc_cache & m_cache; // cache where allocations come from
|
||||||
|
UINT32 m_modes; // number of modes supported
|
||||||
|
|
||||||
drccodeptr ** base[1]; /* pointer to the l1 table for each mode */
|
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
|
||||||
FUNCTION PROTOTYPES
|
class drc_map_variables
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/* ----- hash table management ----- */
|
|
||||||
|
|
||||||
/* allocate memory in the cache for the hash table tracker (it auto-frees with the cache) */
|
|
||||||
drchash_state *drchash_alloc(drc_cache *cache, int modes, int addrbits, int ignorebits);
|
|
||||||
|
|
||||||
/* flush existing hash tables and create new ones */
|
|
||||||
int drchash_reset(drchash_state *drchash);
|
|
||||||
|
|
||||||
/* note the beginning of a block */
|
|
||||||
void drchash_block_begin(drchash_state *drchash, drcuml_block *block, const drcuml_instruction *instlist, UINT32 numinst);
|
|
||||||
|
|
||||||
/* note the end of a block */
|
|
||||||
void drchash_block_end(drchash_state *drchash, drcuml_block *block);
|
|
||||||
|
|
||||||
/* set the default codeptr for any empty hash entries (defaults to NULL) */
|
|
||||||
void drchash_set_default_codeptr(drchash_state *drchash, drccodeptr code);
|
|
||||||
|
|
||||||
/* set the codeptr for the given mode/pc */
|
|
||||||
int drchash_set_codeptr(drchash_state *drchash, UINT32 mode, UINT32 pc, drccodeptr code);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ----- code map management ----- */
|
|
||||||
|
|
||||||
/* allocate memory in the cache for the code mapper (it auto-frees with the cache) */
|
|
||||||
drcmap_state *drcmap_alloc(drc_cache *cache, UINT64 uniquevalue);
|
|
||||||
|
|
||||||
/* note the beginning of a block */
|
|
||||||
void drcmap_block_begin(drcmap_state *drcmap, drcuml_block *block);
|
|
||||||
|
|
||||||
/* note the end of a block */
|
|
||||||
void drcmap_block_end(drcmap_state *drcmap, drcuml_block *block);
|
|
||||||
|
|
||||||
/* set a map value for the given code pointer */
|
|
||||||
void drcmap_set_value(drcmap_state *drcmap, drccodeptr codebase, UINT32 mapvar, UINT32 newvalue);
|
|
||||||
|
|
||||||
/* return a map value for the given code pointer */
|
|
||||||
UINT32 drcmap_get_value(drcmap_state *drcmap, drccodeptr codebase, UINT32 mapvar);
|
|
||||||
|
|
||||||
/* return the most recently set map value */
|
|
||||||
UINT32 drcmap_get_last_value(drcmap_state *drcmap, UINT32 mapvar);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ----- label management ----- */
|
|
||||||
|
|
||||||
/* allocate a label list within the cache (it auto-frees with the cache) */
|
|
||||||
drclabel_list *drclabel_list_alloc(drc_cache *cache);
|
|
||||||
|
|
||||||
/* note the beginning of a block */
|
|
||||||
void drclabel_block_begin(drclabel_list *drcmap, drcuml_block *block);
|
|
||||||
|
|
||||||
/* note the end of a block */
|
|
||||||
void drclabel_block_end(drclabel_list *drcmap, drcuml_block *block);
|
|
||||||
|
|
||||||
/* find or allocate a new label; returns NULL and requests an OOB callback if undefined */
|
|
||||||
drccodeptr drclabel_get_codeptr(drclabel_list *list, drcuml_codelabel label, drclabel_fixup_func fixup, void *param);
|
|
||||||
|
|
||||||
/* set the pointer to a new label */
|
|
||||||
void drclabel_set_codeptr(drclabel_list *list, drcuml_codelabel label, drccodeptr codeptr);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
INLINE FUNCTIONS
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
|
||||||
drchash_get_codeptr - return the codeptr
|
|
||||||
allocated for the given mode/pc
|
|
||||||
-------------------------------------------------*/
|
|
||||||
|
|
||||||
INLINE drccodeptr drchash_get_codeptr(drchash_state *drchash, UINT32 mode, UINT32 pc)
|
|
||||||
{
|
{
|
||||||
assert(mode < drchash->modes);
|
public:
|
||||||
return drchash->base[mode][(pc >> drchash->l1shift) & drchash->l1mask][(pc >> drchash->l2shift) & drchash->l2mask];
|
// 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[DRCUML_MAPVAR_END - DRCUML_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<map_entry> m_entry_list; // list of entries
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
// ======================> drc_label_list
|
||||||
drchash_code_exists - return TRUE if there is
|
|
||||||
a matching hash entry for the given mode/pc
|
|
||||||
-------------------------------------------------*/
|
|
||||||
|
|
||||||
INLINE int drchash_code_exists(drchash_state *drchash, UINT32 mode, UINT32 pc)
|
// structure holding a live list of labels
|
||||||
|
class drc_label_list
|
||||||
{
|
{
|
||||||
return (drchash_get_codeptr(drchash, mode, pc) != drchash->nocodeptr);
|
// callback function for forward-referenced labels
|
||||||
}
|
typedef void (*fixup_func)(void *parameter, drccodeptr labelcodeptr);
|
||||||
|
|
||||||
|
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(drcuml_codelabel label, fixup_func fixup, void *param);
|
||||||
|
void set_codeptr(drcuml_codelabel label, drccodeptr codeptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct label_entry
|
||||||
|
{
|
||||||
|
label_entry *next() const { return m_next; }
|
||||||
|
label_entry * m_next; // pointer to next label
|
||||||
|
drcuml_codelabel m_label; // the label specified
|
||||||
|
drccodeptr m_codeptr; // pointer to the relevant code
|
||||||
|
};
|
||||||
|
|
||||||
|
// internal helpers
|
||||||
|
void reset(bool fatal_on_leftovers);
|
||||||
|
label_entry *find_or_allocate(drcuml_codelabel label);
|
||||||
|
static void oob_callback(drccodeptr *codeptr, void *param1, void *param2, void *param3);
|
||||||
|
|
||||||
|
// internal state
|
||||||
|
drc_cache & m_cache; // pointer to the cache
|
||||||
|
simple_list<label_entry> m_list; // head of the live list
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* __DRCBEUT_H__ */
|
#endif /* __DRCBEUT_H__ */
|
||||||
|
@ -266,9 +266,9 @@ struct _drcbe_state
|
|||||||
drcuml_state * drcuml; /* pointer back to our owner */
|
drcuml_state * drcuml; /* pointer back to our owner */
|
||||||
drc_cache * cache; /* pointer to the cache */
|
drc_cache * cache; /* pointer to the cache */
|
||||||
drcuml_machine_state state; /* state of the machine */
|
drcuml_machine_state state; /* state of the machine */
|
||||||
drchash_state * hash; /* hash table state */
|
drc_hash_table * hash; /* hash table state */
|
||||||
drcmap_state * map; /* code map */
|
drc_map_variables * map; /* code map */
|
||||||
drclabel_list * labels; /* label list */
|
drc_label_list * labels; /* label list */
|
||||||
|
|
||||||
x86_entry_point_func entry; /* entry point */
|
x86_entry_point_func entry; /* entry point */
|
||||||
x86code * exit; /* exit point */
|
x86code * exit; /* exit point */
|
||||||
@ -737,22 +737,16 @@ static drcbe_state *drcbex64_alloc(drcuml_state *drcuml, drc_cache *cache, devic
|
|||||||
drcbe->debug_log_hashjmp = (x86code *)debug_log_hashjmp;
|
drcbe->debug_log_hashjmp = (x86code *)debug_log_hashjmp;
|
||||||
drcbe->debug_log_hashjmp_fail = (x86code *)debug_log_hashjmp_fail;
|
drcbe->debug_log_hashjmp_fail = (x86code *)debug_log_hashjmp_fail;
|
||||||
}
|
}
|
||||||
drcbe->drcmap_get_value = (x86code *)drcmap_get_value;
|
drcbe->drcmap_get_value = (x86code *)&drc_map_variables::static_get_value;
|
||||||
|
|
||||||
/* allocate hash tables */
|
/* allocate hash tables */
|
||||||
drcbe->hash = drchash_alloc(cache, modes, addrbits, ignorebits);
|
drcbe->hash = auto_alloc(device->machine, drc_hash_table(*cache, modes, addrbits, ignorebits));
|
||||||
if (drcbe->hash == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* allocate code map */
|
/* allocate code map */
|
||||||
drcbe->map = drcmap_alloc(cache, 0);
|
drcbe->map = auto_alloc(device->machine, drc_map_variables(*cache, 0));
|
||||||
if (drcbe->map == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* allocate a label tracker */
|
/* allocate a label tracker */
|
||||||
drcbe->labels = drclabel_list_alloc(cache);
|
drcbe->labels = auto_alloc(device->machine, drc_label_list(*cache));
|
||||||
if (drcbe->labels == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* build the opcode table (static but it doesn't hurt to regenerate it) */
|
/* build the opcode table (static but it doesn't hurt to regenerate it) */
|
||||||
for (opnum = 0; opnum < ARRAY_LENGTH(opcode_table_source); opnum++)
|
for (opnum = 0; opnum < ARRAY_LENGTH(opcode_table_source); opnum++)
|
||||||
@ -877,8 +871,8 @@ static void drcbex64_reset(drcbe_state *drcbe)
|
|||||||
drcbe->cache->end_codegen();
|
drcbe->cache->end_codegen();
|
||||||
|
|
||||||
/* reset our hash tables */
|
/* reset our hash tables */
|
||||||
drchash_reset(drcbe->hash);
|
drcbe->hash->reset();
|
||||||
drchash_set_default_codeptr(drcbe->hash, drcbe->nocode);
|
drcbe->hash->set_default_codeptr(drcbe->nocode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -908,9 +902,9 @@ static void drcbex64_generate(drcbe_state *drcbe, drcuml_block *block, const drc
|
|||||||
int inum;
|
int inum;
|
||||||
|
|
||||||
/* tell all of our utility objects that a block is beginning */
|
/* tell all of our utility objects that a block is beginning */
|
||||||
drchash_block_begin(drcbe->hash, block, instlist, numinst);
|
drcbe->hash->block_begin(*block, instlist, numinst);
|
||||||
drclabel_block_begin(drcbe->labels, block);
|
drcbe->labels->block_begin(*block);
|
||||||
drcmap_block_begin(drcbe->map, block);
|
drcbe->map->block_begin(*block);
|
||||||
|
|
||||||
/* begin codegen; fail if we can't */
|
/* begin codegen; fail if we can't */
|
||||||
cachetop = drcbe->cache->begin_codegen(numinst * 8 * 4);
|
cachetop = drcbe->cache->begin_codegen(numinst * 8 * 4);
|
||||||
@ -960,9 +954,9 @@ static void drcbex64_generate(drcbe_state *drcbe, drcuml_block *block, const drc
|
|||||||
x86log_disasm_code_range(drcbe->log, (blockname == NULL) ? "Unknown block" : blockname, base, drcbe->cache->top());
|
x86log_disasm_code_range(drcbe->log, (blockname == NULL) ? "Unknown block" : blockname, base, drcbe->cache->top());
|
||||||
|
|
||||||
/* tell all of our utility objects that the block is finished */
|
/* tell all of our utility objects that the block is finished */
|
||||||
drchash_block_end(drcbe->hash, block);
|
drcbe->hash->block_end(*block);
|
||||||
drclabel_block_end(drcbe->labels, block);
|
drcbe->labels->block_end(*block);
|
||||||
drcmap_block_end(drcbe->map, block);
|
drcbe->map->block_end(*block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -973,7 +967,7 @@ static void drcbex64_generate(drcbe_state *drcbe, drcuml_block *block, const drc
|
|||||||
|
|
||||||
static int drcbex64_hash_exists(drcbe_state *drcbe, UINT32 mode, UINT32 pc)
|
static int drcbex64_hash_exists(drcbe_state *drcbe, UINT32 mode, UINT32 pc)
|
||||||
{
|
{
|
||||||
return drchash_code_exists(drcbe->hash, mode, pc);
|
return drcbe->hash->code_exists(mode, pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3049,7 +3043,7 @@ static x86code *op_hash(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
|
|||||||
assert(inst->param[1].type == DRCUML_PTYPE_IMMEDIATE);
|
assert(inst->param[1].type == DRCUML_PTYPE_IMMEDIATE);
|
||||||
|
|
||||||
/* register the current pointer for the mode/PC */
|
/* register the current pointer for the mode/PC */
|
||||||
drchash_set_codeptr(drcbe->hash, inst->param[0].value, inst->param[1].value, dst);
|
drcbe->hash->set_codeptr(inst->param[0].value, inst->param[1].value, dst);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3066,7 +3060,7 @@ static x86code *op_label(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
|
|||||||
assert(inst->param[0].type == DRCUML_PTYPE_IMMEDIATE);
|
assert(inst->param[0].type == DRCUML_PTYPE_IMMEDIATE);
|
||||||
|
|
||||||
/* register the current pointer for the label */
|
/* register the current pointer for the label */
|
||||||
drclabel_set_codeptr(drcbe->labels, inst->param[0].value, dst);
|
drcbe->labels->set_codeptr(inst->param[0].value, dst);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3100,7 +3094,7 @@ static x86code *op_mapvar(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
|
|||||||
assert(inst->param[1].type == DRCUML_PTYPE_IMMEDIATE);
|
assert(inst->param[1].type == DRCUML_PTYPE_IMMEDIATE);
|
||||||
|
|
||||||
/* set the value of the specified mapvar */
|
/* set the value of the specified mapvar */
|
||||||
drcmap_set_value(drcbe->map, dst, inst->param[0].value, inst->param[1].value);
|
drcbe->map->set_value(dst, inst->param[0].value, inst->param[1].value);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3212,14 +3206,14 @@ static x86code *op_hashjmp(drcbe_state *drcbe, x86code *dst, const drcuml_instru
|
|||||||
emit_mov_r64_m64(&dst, REG_RSP, MABS(drcbe, &drcbe->hashstacksave)); // mov rsp,[hashstacksave]
|
emit_mov_r64_m64(&dst, REG_RSP, MABS(drcbe, &drcbe->hashstacksave)); // mov rsp,[hashstacksave]
|
||||||
|
|
||||||
/* fixed mode cases */
|
/* fixed mode cases */
|
||||||
if (modep.type == DRCUML_PTYPE_IMMEDIATE && drcbe->hash->base[modep.value] != drcbe->hash->emptyl1)
|
if (modep.type == DRCUML_PTYPE_IMMEDIATE && drcbe->hash->is_mode_populated(modep.value))
|
||||||
{
|
{
|
||||||
/* a straight immediate jump is direct, though we need the PC in EAX in case of failure */
|
/* a straight immediate jump is direct, though we need the PC in EAX in case of failure */
|
||||||
if (pcp.type == DRCUML_PTYPE_IMMEDIATE)
|
if (pcp.type == DRCUML_PTYPE_IMMEDIATE)
|
||||||
{
|
{
|
||||||
UINT32 l1val = (pcp.value >> drcbe->hash->l1shift) & drcbe->hash->l1mask;
|
UINT32 l1val = (pcp.value >> drcbe->hash->l1shift()) & drcbe->hash->l1mask();
|
||||||
UINT32 l2val = (pcp.value >> drcbe->hash->l2shift) & drcbe->hash->l2mask;
|
UINT32 l2val = (pcp.value >> drcbe->hash->l2shift()) & drcbe->hash->l2mask();
|
||||||
emit_call_m64(&dst, MABS(drcbe, &drcbe->hash->base[modep.value][l1val][l2val]));
|
emit_call_m64(&dst, MABS(drcbe, &drcbe->hash->base()[modep.value][l1val][l2val]));
|
||||||
// call hash[modep][l1val][l2val]
|
// call hash[modep][l1val][l2val]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3228,11 +3222,11 @@ static x86code *op_hashjmp(drcbe_state *drcbe, x86code *dst, const drcuml_instru
|
|||||||
{
|
{
|
||||||
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &pcp); // mov eax,pcp
|
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &pcp); // mov eax,pcp
|
||||||
emit_mov_r32_r32(&dst, REG_EDX, REG_EAX); // mov edx,eax
|
emit_mov_r32_r32(&dst, REG_EDX, REG_EAX); // mov edx,eax
|
||||||
emit_shr_r32_imm(&dst, REG_EDX, drcbe->hash->l1shift); // shr edx,l1shift
|
emit_shr_r32_imm(&dst, REG_EDX, drcbe->hash->l1shift()); // shr edx,l1shift
|
||||||
emit_and_r32_imm(&dst, REG_EAX, drcbe->hash->l2mask << drcbe->hash->l2shift);// and eax,l2mask << l2shift
|
emit_and_r32_imm(&dst, REG_EAX, drcbe->hash->l2mask() << drcbe->hash->l2shift());// and eax,l2mask << l2shift
|
||||||
emit_mov_r64_m64(&dst, REG_RDX, MBISD(REG_RBP, REG_RDX, 8, offset_from_rbp(drcbe, (FPTR)&drcbe->hash->base[modep.value][0])));
|
emit_mov_r64_m64(&dst, REG_RDX, MBISD(REG_RBP, REG_RDX, 8, offset_from_rbp(drcbe, (FPTR)&drcbe->hash->base()[modep.value][0])));
|
||||||
// mov rdx,hash[modep+edx*8]
|
// mov rdx,hash[modep+edx*8]
|
||||||
emit_call_m64(&dst, MBISD(REG_RDX, REG_RAX, 8 >> drcbe->hash->l2shift, 0)); // call [rdx+rax*shift]
|
emit_call_m64(&dst, MBISD(REG_RDX, REG_RAX, 8 >> drcbe->hash->l2shift(), 0));// call [rdx+rax*shift]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3240,14 +3234,14 @@ static x86code *op_hashjmp(drcbe_state *drcbe, x86code *dst, const drcuml_instru
|
|||||||
/* variable mode */
|
/* variable mode */
|
||||||
int modereg = param_select_register(REG_ECX, &modep, NULL);
|
int modereg = param_select_register(REG_ECX, &modep, NULL);
|
||||||
emit_mov_r32_p32(drcbe, &dst, modereg, &modep); // mov modereg,modep
|
emit_mov_r32_p32(drcbe, &dst, modereg, &modep); // mov modereg,modep
|
||||||
emit_mov_r64_m64(&dst, REG_RCX, MBISD(REG_RBP, modereg, 8, offset_from_rbp(drcbe, (FPTR)&drcbe->hash->base[0])));
|
emit_mov_r64_m64(&dst, REG_RCX, MBISD(REG_RBP, modereg, 8, offset_from_rbp(drcbe, (FPTR)drcbe->hash->base())));
|
||||||
// mov rcx,hash[modereg*8]
|
// mov rcx,hash[modereg*8]
|
||||||
|
|
||||||
/* fixed PC */
|
/* fixed PC */
|
||||||
if (pcp.type == DRCUML_PTYPE_IMMEDIATE)
|
if (pcp.type == DRCUML_PTYPE_IMMEDIATE)
|
||||||
{
|
{
|
||||||
UINT32 l1val = (pcp.value >> drcbe->hash->l1shift) & drcbe->hash->l1mask;
|
UINT32 l1val = (pcp.value >> drcbe->hash->l1shift()) & drcbe->hash->l1mask();
|
||||||
UINT32 l2val = (pcp.value >> drcbe->hash->l2shift) & drcbe->hash->l2mask;
|
UINT32 l2val = (pcp.value >> drcbe->hash->l2shift()) & drcbe->hash->l2mask();
|
||||||
emit_mov_r64_m64(&dst, REG_RDX, MBD(REG_RCX, l1val*8)); // mov rdx,[rcx+l1val*8]
|
emit_mov_r64_m64(&dst, REG_RDX, MBD(REG_RCX, l1val*8)); // mov rdx,[rcx+l1val*8]
|
||||||
emit_call_m64(&dst, MBD(REG_RDX, l2val*8)); // call [l2val*8]
|
emit_call_m64(&dst, MBD(REG_RDX, l2val*8)); // call [l2val*8]
|
||||||
}
|
}
|
||||||
@ -3257,10 +3251,10 @@ static x86code *op_hashjmp(drcbe_state *drcbe, x86code *dst, const drcuml_instru
|
|||||||
{
|
{
|
||||||
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &pcp); // mov eax,pcp
|
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &pcp); // mov eax,pcp
|
||||||
emit_mov_r32_r32(&dst, REG_EDX, REG_EAX); // mov edx,eax
|
emit_mov_r32_r32(&dst, REG_EDX, REG_EAX); // mov edx,eax
|
||||||
emit_shr_r32_imm(&dst, REG_EDX, drcbe->hash->l1shift); // shr edx,l1shift
|
emit_shr_r32_imm(&dst, REG_EDX, drcbe->hash->l1shift()); // shr edx,l1shift
|
||||||
emit_mov_r64_m64(&dst, REG_RDX, MBISD(REG_RCX, REG_RDX, 8, 0)); // mov rdx,[rcx+rdx*8]
|
emit_mov_r64_m64(&dst, REG_RDX, MBISD(REG_RCX, REG_RDX, 8, 0)); // mov rdx,[rcx+rdx*8]
|
||||||
emit_and_r32_imm(&dst, REG_EAX, drcbe->hash->l2mask << drcbe->hash->l2shift);// and eax,l2mask << l2shift
|
emit_and_r32_imm(&dst, REG_EAX, drcbe->hash->l2mask() << drcbe->hash->l2shift());// and eax,l2mask << l2shift
|
||||||
emit_call_m64(&dst, MBISD(REG_RDX, REG_RAX, 8 >> drcbe->hash->l2shift, 0)); // call [rdx+rax*shift]
|
emit_call_m64(&dst, MBISD(REG_RDX, REG_RAX, 8 >> drcbe->hash->l2shift(), 0)); // call [rdx+rax*shift]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3294,7 +3288,7 @@ static x86code *op_jmp(drcbe_state *drcbe, x86code *dst, const drcuml_instructio
|
|||||||
param_normalize_1(drcbe, inst, &labelp, PTYPE_I);
|
param_normalize_1(drcbe, inst, &labelp, PTYPE_I);
|
||||||
|
|
||||||
/* look up the jump target and jump there */
|
/* look up the jump target and jump there */
|
||||||
jmptarget = (x86code *)drclabel_get_codeptr(drcbe->labels, labelp.value, fixup_label, dst);
|
jmptarget = (x86code *)drcbe->labels->get_codeptr(labelp.value, fixup_label, dst);
|
||||||
if (jmptarget == NULL)
|
if (jmptarget == NULL)
|
||||||
jmptarget = dst + 0x7ffffff0;
|
jmptarget = dst + 0x7ffffff0;
|
||||||
if (inst->condition == DRCUML_COND_ALWAYS)
|
if (inst->condition == DRCUML_COND_ALWAYS)
|
||||||
|
@ -158,9 +158,9 @@ struct _drcbe_state
|
|||||||
drcuml_state * drcuml; /* pointer back to our owner */
|
drcuml_state * drcuml; /* pointer back to our owner */
|
||||||
drc_cache * cache; /* pointer to the cache */
|
drc_cache * cache; /* pointer to the cache */
|
||||||
drcuml_machine_state state; /* state of the machine */
|
drcuml_machine_state state; /* state of the machine */
|
||||||
drchash_state * hash; /* hash table state */
|
drc_hash_table * hash; /* hash table state */
|
||||||
drcmap_state * map; /* code map */
|
drc_map_variables * map; /* code map */
|
||||||
drclabel_list * labels; /* label list */
|
drc_label_list * labels; /* label list */
|
||||||
|
|
||||||
x86_entry_point_func entry; /* entry point */
|
x86_entry_point_func entry; /* entry point */
|
||||||
x86code * exit; /* exit point */
|
x86code * exit; /* exit point */
|
||||||
@ -639,19 +639,13 @@ static drcbe_state *drcbex86_alloc(drcuml_state *drcuml, drc_cache *cache, devic
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* allocate hash tables */
|
/* allocate hash tables */
|
||||||
drcbe->hash = drchash_alloc(cache, modes, addrbits, ignorebits);
|
drcbe->hash = auto_alloc(device->machine, drc_hash_table(*cache, modes, addrbits, ignorebits));
|
||||||
if (drcbe->hash == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* allocate code map */
|
/* allocate code map */
|
||||||
drcbe->map = drcmap_alloc(cache, 0);
|
drcbe->map = auto_alloc(device->machine, drc_map_variables(*cache, 0));
|
||||||
if (drcbe->map == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* allocate a label tracker */
|
/* allocate a label tracker */
|
||||||
drcbe->labels = drclabel_list_alloc(cache);
|
drcbe->labels = auto_alloc(device->machine, drc_label_list(*cache));
|
||||||
if (drcbe->labels == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* build the opcode table (static but it doesn't hurt to regenerate it) */
|
/* build the opcode table (static but it doesn't hurt to regenerate it) */
|
||||||
for (opnum = 0; opnum < ARRAY_LENGTH(opcode_table_source); opnum++)
|
for (opnum = 0; opnum < ARRAY_LENGTH(opcode_table_source); opnum++)
|
||||||
@ -854,8 +848,8 @@ static void drcbex86_reset(drcbe_state *drcbe)
|
|||||||
drcbe->logged_common = TRUE;
|
drcbe->logged_common = TRUE;
|
||||||
|
|
||||||
/* reset our hash tables */
|
/* reset our hash tables */
|
||||||
drchash_reset(drcbe->hash);
|
drcbe->hash->reset();
|
||||||
drchash_set_default_codeptr(drcbe->hash, drcbe->nocode);
|
drcbe->hash->set_default_codeptr(drcbe->nocode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -885,9 +879,9 @@ static void drcbex86_generate(drcbe_state *drcbe, drcuml_block *block, const drc
|
|||||||
int inum;
|
int inum;
|
||||||
|
|
||||||
/* tell all of our utility objects that a block is beginning */
|
/* tell all of our utility objects that a block is beginning */
|
||||||
drchash_block_begin(drcbe->hash, block, instlist, numinst);
|
drcbe->hash->block_begin(*block, instlist, numinst);
|
||||||
drclabel_block_begin(drcbe->labels, block);
|
drcbe->labels->block_begin(*block);
|
||||||
drcmap_block_begin(drcbe->map, block);
|
drcbe->map->block_begin(*block);
|
||||||
|
|
||||||
/* begin codegen; fail if we can't */
|
/* begin codegen; fail if we can't */
|
||||||
cachetop = drcbe->cache->begin_codegen(numinst * 8 * 4);
|
cachetop = drcbe->cache->begin_codegen(numinst * 8 * 4);
|
||||||
@ -937,9 +931,9 @@ static void drcbex86_generate(drcbe_state *drcbe, drcuml_block *block, const drc
|
|||||||
x86log_disasm_code_range(drcbe->log, (blockname == NULL) ? "Unknown block" : blockname, base, drcbe->cache->top());
|
x86log_disasm_code_range(drcbe->log, (blockname == NULL) ? "Unknown block" : blockname, base, drcbe->cache->top());
|
||||||
|
|
||||||
/* tell all of our utility objects that the block is finished */
|
/* tell all of our utility objects that the block is finished */
|
||||||
drchash_block_end(drcbe->hash, block);
|
drcbe->hash->block_end(*block);
|
||||||
drclabel_block_end(drcbe->labels, block);
|
drcbe->labels->block_end(*block);
|
||||||
drcmap_block_end(drcbe->map, block);
|
drcbe->map->block_end(*block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -950,7 +944,7 @@ static void drcbex86_generate(drcbe_state *drcbe, drcuml_block *block, const drc
|
|||||||
|
|
||||||
static int drcbex86_hash_exists(drcbe_state *drcbe, UINT32 mode, UINT32 pc)
|
static int drcbex86_hash_exists(drcbe_state *drcbe, UINT32 mode, UINT32 pc)
|
||||||
{
|
{
|
||||||
return drchash_code_exists(drcbe->hash, mode, pc);
|
return drcbe->hash->code_exists(mode, pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3261,7 +3255,7 @@ static x86code *op_hash(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
|
|||||||
assert(inst->param[1].type == DRCUML_PTYPE_IMMEDIATE);
|
assert(inst->param[1].type == DRCUML_PTYPE_IMMEDIATE);
|
||||||
|
|
||||||
/* register the current pointer for the mode/PC */
|
/* register the current pointer for the mode/PC */
|
||||||
drchash_set_codeptr(drcbe->hash, inst->param[0].value, inst->param[1].value, dst);
|
drcbe->hash->set_codeptr(inst->param[0].value, inst->param[1].value, dst);
|
||||||
reset_last_upper_lower_reg(drcbe);
|
reset_last_upper_lower_reg(drcbe);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
@ -3279,7 +3273,7 @@ static x86code *op_label(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
|
|||||||
assert(inst->param[0].type == DRCUML_PTYPE_IMMEDIATE);
|
assert(inst->param[0].type == DRCUML_PTYPE_IMMEDIATE);
|
||||||
|
|
||||||
/* register the current pointer for the label */
|
/* register the current pointer for the label */
|
||||||
drclabel_set_codeptr(drcbe->labels, inst->param[0].value, dst);
|
drcbe->labels->set_codeptr(inst->param[0].value, dst);
|
||||||
reset_last_upper_lower_reg(drcbe);
|
reset_last_upper_lower_reg(drcbe);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
@ -3314,7 +3308,7 @@ static x86code *op_mapvar(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
|
|||||||
assert(inst->param[1].type == DRCUML_PTYPE_IMMEDIATE);
|
assert(inst->param[1].type == DRCUML_PTYPE_IMMEDIATE);
|
||||||
|
|
||||||
/* set the value of the specified mapvar */
|
/* set the value of the specified mapvar */
|
||||||
drcmap_set_value(drcbe->map, dst, inst->param[0].value, inst->param[1].value);
|
drcbe->map->set_value(dst, inst->param[0].value, inst->param[1].value);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3425,14 +3419,14 @@ static x86code *op_hashjmp(drcbe_state *drcbe, x86code *dst, const drcuml_instru
|
|||||||
emit_mov_r32_m32(&dst, REG_ESP, MABS(&drcbe->hashstacksave)); // mov esp,[hashstacksave]
|
emit_mov_r32_m32(&dst, REG_ESP, MABS(&drcbe->hashstacksave)); // mov esp,[hashstacksave]
|
||||||
|
|
||||||
/* fixed mode cases */
|
/* fixed mode cases */
|
||||||
if (modep.type == DRCUML_PTYPE_IMMEDIATE && drcbe->hash->base[modep.value] != drcbe->hash->emptyl1)
|
if (modep.type == DRCUML_PTYPE_IMMEDIATE && drcbe->hash->is_mode_populated(modep.value))
|
||||||
{
|
{
|
||||||
/* a straight immediate jump is direct, though we need the PC in EAX in case of failure */
|
/* a straight immediate jump is direct, though we need the PC in EAX in case of failure */
|
||||||
if (pcp.type == DRCUML_PTYPE_IMMEDIATE)
|
if (pcp.type == DRCUML_PTYPE_IMMEDIATE)
|
||||||
{
|
{
|
||||||
UINT32 l1val = (pcp.value >> drcbe->hash->l1shift) & drcbe->hash->l1mask;
|
UINT32 l1val = (pcp.value >> drcbe->hash->l1shift()) & drcbe->hash->l1mask();
|
||||||
UINT32 l2val = (pcp.value >> drcbe->hash->l2shift) & drcbe->hash->l2mask;
|
UINT32 l2val = (pcp.value >> drcbe->hash->l2shift()) & drcbe->hash->l2mask();
|
||||||
emit_call_m32(&dst, MABS(&drcbe->hash->base[modep.value][l1val][l2val])); // call hash[modep][l1val][l2val]
|
emit_call_m32(&dst, MABS(&drcbe->hash->base()[modep.value][l1val][l2val])); // call hash[modep][l1val][l2val]
|
||||||
}
|
}
|
||||||
|
|
||||||
/* a fixed mode but variable PC */
|
/* a fixed mode but variable PC */
|
||||||
@ -3440,11 +3434,11 @@ static x86code *op_hashjmp(drcbe_state *drcbe, x86code *dst, const drcuml_instru
|
|||||||
{
|
{
|
||||||
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &pcp); // mov eax,pcp
|
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &pcp); // mov eax,pcp
|
||||||
emit_mov_r32_r32(&dst, REG_EDX, REG_EAX); // mov edx,eax
|
emit_mov_r32_r32(&dst, REG_EDX, REG_EAX); // mov edx,eax
|
||||||
emit_shr_r32_imm(&dst, REG_EDX, drcbe->hash->l1shift); // shr edx,l1shift
|
emit_shr_r32_imm(&dst, REG_EDX, drcbe->hash->l1shift()); // shr edx,l1shift
|
||||||
emit_and_r32_imm(&dst, REG_EAX, drcbe->hash->l2mask << drcbe->hash->l2shift);// and eax,l2mask << l2shift
|
emit_and_r32_imm(&dst, REG_EAX, drcbe->hash->l2mask() << drcbe->hash->l2shift());// and eax,l2mask << l2shift
|
||||||
emit_mov_r32_m32(&dst, REG_EDX, MISD(REG_EDX, 4, &drcbe->hash->base[modep.value][0]));
|
emit_mov_r32_m32(&dst, REG_EDX, MISD(REG_EDX, 4, &drcbe->hash->base()[modep.value][0]));
|
||||||
// mov edx,hash[modep+edx*4]
|
// mov edx,hash[modep+edx*4]
|
||||||
emit_call_m32(&dst, MBISD(REG_EDX, REG_EAX, 4 >> drcbe->hash->l2shift, 0)); // call [edx+eax*shift]
|
emit_call_m32(&dst, MBISD(REG_EDX, REG_EAX, 4 >> drcbe->hash->l2shift(), 0));// call [edx+eax*shift]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3452,13 +3446,13 @@ static x86code *op_hashjmp(drcbe_state *drcbe, x86code *dst, const drcuml_instru
|
|||||||
/* variable mode */
|
/* variable mode */
|
||||||
int modereg = param_select_register(REG_ECX, &modep, NULL);
|
int modereg = param_select_register(REG_ECX, &modep, NULL);
|
||||||
emit_mov_r32_p32(drcbe, &dst, modereg, &modep); // mov modereg,modep
|
emit_mov_r32_p32(drcbe, &dst, modereg, &modep); // mov modereg,modep
|
||||||
emit_mov_r32_m32(&dst, REG_ECX, MISD(modereg, 4, &drcbe->hash->base[0])); // mov ecx,hash[modereg*4]
|
emit_mov_r32_m32(&dst, REG_ECX, MISD(modereg, 4, drcbe->hash->base())); // mov ecx,hash[modereg*4]
|
||||||
|
|
||||||
/* fixed PC */
|
/* fixed PC */
|
||||||
if (pcp.type == DRCUML_PTYPE_IMMEDIATE)
|
if (pcp.type == DRCUML_PTYPE_IMMEDIATE)
|
||||||
{
|
{
|
||||||
UINT32 l1val = (pcp.value >> drcbe->hash->l1shift) & drcbe->hash->l1mask;
|
UINT32 l1val = (pcp.value >> drcbe->hash->l1shift()) & drcbe->hash->l1mask();
|
||||||
UINT32 l2val = (pcp.value >> drcbe->hash->l2shift) & drcbe->hash->l2mask;
|
UINT32 l2val = (pcp.value >> drcbe->hash->l2shift()) & drcbe->hash->l2mask();
|
||||||
emit_mov_r32_m32(&dst, REG_EDX, MBD(REG_ECX, l1val*4)); // mov edx,[ecx+l1val*4]
|
emit_mov_r32_m32(&dst, REG_EDX, MBD(REG_ECX, l1val*4)); // mov edx,[ecx+l1val*4]
|
||||||
emit_call_m32(&dst, MBD(REG_EDX, l2val*4)); // call [l2val*4]
|
emit_call_m32(&dst, MBD(REG_EDX, l2val*4)); // call [l2val*4]
|
||||||
}
|
}
|
||||||
@ -3468,10 +3462,10 @@ static x86code *op_hashjmp(drcbe_state *drcbe, x86code *dst, const drcuml_instru
|
|||||||
{
|
{
|
||||||
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &pcp); // mov eax,pcp
|
emit_mov_r32_p32(drcbe, &dst, REG_EAX, &pcp); // mov eax,pcp
|
||||||
emit_mov_r32_r32(&dst, REG_EDX, REG_EAX); // mov edx,eax
|
emit_mov_r32_r32(&dst, REG_EDX, REG_EAX); // mov edx,eax
|
||||||
emit_shr_r32_imm(&dst, REG_EDX, drcbe->hash->l1shift); // shr edx,l1shift
|
emit_shr_r32_imm(&dst, REG_EDX, drcbe->hash->l1shift()); // shr edx,l1shift
|
||||||
emit_mov_r32_m32(&dst, REG_EDX, MBISD(REG_ECX, REG_EDX, 4, 0)); // mov edx,[ecx+edx*4]
|
emit_mov_r32_m32(&dst, REG_EDX, MBISD(REG_ECX, REG_EDX, 4, 0)); // mov edx,[ecx+edx*4]
|
||||||
emit_and_r32_imm(&dst, REG_EAX, drcbe->hash->l2mask << drcbe->hash->l2shift);// and eax,l2mask << l2shift
|
emit_and_r32_imm(&dst, REG_EAX, drcbe->hash->l2mask() << drcbe->hash->l2shift());// and eax,l2mask << l2shift
|
||||||
emit_call_m32(&dst, MBISD(REG_EDX, REG_EAX, 4 >> drcbe->hash->l2shift, 0)); // call [edx+eax*shift]
|
emit_call_m32(&dst, MBISD(REG_EDX, REG_EAX, 4 >> drcbe->hash->l2shift(), 0));// call [edx+eax*shift]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3502,7 +3496,7 @@ static x86code *op_jmp(drcbe_state *drcbe, x86code *dst, const drcuml_instructio
|
|||||||
param_normalize_1(drcbe, inst, &labelp, PTYPE_I);
|
param_normalize_1(drcbe, inst, &labelp, PTYPE_I);
|
||||||
|
|
||||||
/* look up the jump target and jump there */
|
/* look up the jump target and jump there */
|
||||||
jmptarget = (x86code *)drclabel_get_codeptr(drcbe->labels, labelp.value, fixup_label, dst);
|
jmptarget = (x86code *)drcbe->labels->get_codeptr(labelp.value, fixup_label, dst);
|
||||||
if (inst->condition == DRCUML_COND_ALWAYS)
|
if (inst->condition == DRCUML_COND_ALWAYS)
|
||||||
emit_jmp(&dst, jmptarget); // jmp target
|
emit_jmp(&dst, jmptarget); // jmp target
|
||||||
else
|
else
|
||||||
@ -3674,7 +3668,7 @@ static x86code *op_recover(drcbe_state *drcbe, x86code *dst, const drcuml_instru
|
|||||||
emit_mov_m32_imm(&dst, MBD(REG_ESP, 8), inst->param[1].value); // mov [esp+8],param1
|
emit_mov_m32_imm(&dst, MBD(REG_ESP, 8), inst->param[1].value); // mov [esp+8],param1
|
||||||
emit_mov_m32_r32(&dst, MBD(REG_ESP, 4), REG_EAX); // mov [esp+4],eax
|
emit_mov_m32_r32(&dst, MBD(REG_ESP, 4), REG_EAX); // mov [esp+4],eax
|
||||||
emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (FPTR)drcbe->map); // mov [esp],drcbe->map
|
emit_mov_m32_imm(&dst, MBD(REG_ESP, 0), (FPTR)drcbe->map); // mov [esp],drcbe->map
|
||||||
emit_call(&dst, (x86code *)drcmap_get_value); // call drcmap_get_value
|
emit_call(&dst, (x86code *)&drc_map_variables::static_get_value); // call drcmap_get_value
|
||||||
emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
|
emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
|
||||||
|
|
||||||
return dst;
|
return dst;
|
||||||
|
Loading…
Reference in New Issue
Block a user