Convert drccache to C++

This commit is contained in:
Aaron Giles 2011-01-05 16:33:00 +00:00
parent 7c15acffe2
commit c12dd417cd
14 changed files with 363 additions and 474 deletions

View File

@ -215,7 +215,7 @@ struct _drcbe_state
device_t * device; /* CPU device we are associated with */ device_t * device; /* CPU device we are associated with */
address_space * space[ADDRESS_SPACES]; /* pointers to CPU's address space */ address_space * space[ADDRESS_SPACES]; /* pointers to CPU's address space */
drcuml_state * drcuml; /* pointer back to our owner */ drcuml_state * drcuml; /* pointer back to our owner */
drccache * 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 */ drchash_state * hash; /* hash table state */
drcmap_state * map; /* code map */ drcmap_state * map; /* code map */
@ -254,7 +254,7 @@ union _drcbec_instruction
***************************************************************************/ ***************************************************************************/
/* primary back-end callbacks */ /* primary back-end callbacks */
static drcbe_state *drcbec_alloc(drcuml_state *drcuml, drccache *cache, device_t *device, UINT32 flags, int modes, int addrbits, int ignorebits); static drcbe_state *drcbec_alloc(drcuml_state *drcuml, drc_cache *cache, device_t *device, UINT32 flags, int modes, int addrbits, int ignorebits);
static void drcbec_free(drcbe_state *drcbe); static void drcbec_free(drcbe_state *drcbe);
static void drcbec_reset(drcbe_state *drcbe); static void drcbec_reset(drcbe_state *drcbe);
static int drcbec_execute(drcbe_state *state, drcuml_codehandle *entry); static int drcbec_execute(drcbe_state *state, drcuml_codehandle *entry);
@ -340,12 +340,12 @@ extern const drcbe_interface drcbe_c_be_interface =
state state
-------------------------------------------------*/ -------------------------------------------------*/
static drcbe_state *drcbec_alloc(drcuml_state *drcuml, drccache *cache, device_t *device, UINT32 flags, int modes, int addrbits, int ignorebits) static drcbe_state *drcbec_alloc(drcuml_state *drcuml, drc_cache *cache, device_t *device, UINT32 flags, int modes, int addrbits, int ignorebits)
{ {
int spacenum; int spacenum;
/* allocate space in the cache for our state */ /* allocate space in the cache for our state */
drcbe_state *drcbe = (drcbe_state *)drccache_memory_alloc(cache, sizeof(*drcbe)); drcbe_state *drcbe = (drcbe_state *)cache->alloc(sizeof(*drcbe));
if (drcbe == NULL) if (drcbe == NULL)
return NULL; return NULL;
memset(drcbe, 0, sizeof(*drcbe)); memset(drcbe, 0, sizeof(*drcbe));
@ -414,7 +414,7 @@ static void drcbec_generate(drcbe_state *drcbe, drcuml_block *block, const drcum
drcmap_block_begin(drcbe->map, block); drcmap_block_begin(drcbe->map, block);
/* begin codegen; fail if we can't */ /* begin codegen; fail if we can't */
cachetop = drccache_begin_codegen(drcbe->cache, numinst * sizeof(drcbec_instruction) * 4); cachetop = drcbe->cache->begin_codegen(numinst * sizeof(drcbec_instruction) * 4);
if (cachetop == NULL) if (cachetop == NULL)
drcuml_block_abort(block); drcuml_block_abort(block);
@ -559,7 +559,7 @@ static void drcbec_generate(drcbe_state *drcbe, drcuml_block *block, const drcum
/* complete codegen */ /* complete codegen */
*cachetop = (drccodeptr)dst; *cachetop = (drccodeptr)dst;
drccache_end_codegen(drcbe->cache); 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); drchash_block_end(drcbe->hash, block);

View File

@ -39,7 +39,7 @@ struct _drcmap_entry
/* structure describing the state of the code map */ /* structure describing the state of the code map */
struct _drcmap_state struct _drcmap_state
{ {
drccache * cache; /* pointer to the cache */ drc_cache * cache; /* pointer to the cache */
UINT64 uniquevalue; /* unique value used to find the table */ UINT64 uniquevalue; /* unique value used to find the table */
drcmap_entry * head; /* head of the live list */ drcmap_entry * head; /* head of the live list */
drcmap_entry ** tailptr; /* pointer to tail of the live list */ drcmap_entry ** tailptr; /* pointer to tail of the live list */
@ -61,7 +61,7 @@ struct _drclabel
/* structure holding a live list of labels */ /* structure holding a live list of labels */
struct _drclabel_list struct _drclabel_list
{ {
drccache * cache; /* pointer to the cache */ drc_cache * cache; /* pointer to the cache */
drclabel * head; /* head of the live list */ drclabel * head; /* head of the live list */
}; };
@ -87,13 +87,13 @@ static void label_oob_callback(drccodeptr *codeptr, void *param1, void *param2,
with the cache) with the cache)
-------------------------------------------------*/ -------------------------------------------------*/
drchash_state *drchash_alloc(drccache *cache, int modes, int addrbits, int ignorebits) drchash_state *drchash_alloc(drc_cache *cache, int modes, int addrbits, int ignorebits)
{ {
int effaddrbits = addrbits - ignorebits; int effaddrbits = addrbits - ignorebits;
drchash_state *drchash; drchash_state *drchash;
/* allocate permanent state from the cache */ /* allocate permanent state from the cache */
drchash = (drchash_state *)drccache_memory_alloc(cache, sizeof(*drchash) + modes * sizeof(drchash->base[0])); drchash = (drchash_state *)cache->alloc(sizeof(*drchash) + modes * sizeof(drchash->base[0]));
if (drchash == NULL) if (drchash == NULL)
return NULL; return NULL;
memset(drchash, 0, sizeof(*drchash) + modes * sizeof(drchash->base[0])); memset(drchash, 0, sizeof(*drchash) + modes * sizeof(drchash->base[0]));
@ -128,7 +128,7 @@ int drchash_reset(drchash_state *drchash)
int modenum, entry; int modenum, entry;
/* allocate an empty l2 hash table */ /* allocate an empty l2 hash table */
drchash->emptyl2 = (drccodeptr *)drccache_memory_alloc_temporary(drchash->cache, sizeof(drccodeptr) << drchash->l2bits); drchash->emptyl2 = (drccodeptr *)drchash->cache->alloc_temporary(sizeof(drccodeptr) << drchash->l2bits);
if (drchash->emptyl2 == NULL) if (drchash->emptyl2 == NULL)
return FALSE; return FALSE;
@ -137,7 +137,7 @@ int drchash_reset(drchash_state *drchash)
drchash->emptyl2[entry] = drchash->nocodeptr; drchash->emptyl2[entry] = drchash->nocodeptr;
/* allocate an empty l1 hash table */ /* allocate an empty l1 hash table */
drchash->emptyl1 = (drccodeptr **)drccache_memory_alloc_temporary(drchash->cache, sizeof(drccodeptr *) << drchash->l1bits); drchash->emptyl1 = (drccodeptr **)drchash->cache->alloc_temporary(sizeof(drccodeptr *) << drchash->l1bits);
if (drchash->emptyl1 == NULL) if (drchash->emptyl1 == NULL)
return FALSE; return FALSE;
@ -246,7 +246,7 @@ int drchash_set_codeptr(drchash_state *drchash, UINT32 mode, UINT32 pc, drccodep
/* copy-on-write for the l1 hash table */ /* copy-on-write for the l1 hash table */
if (drchash->base[mode] == drchash->emptyl1) if (drchash->base[mode] == drchash->emptyl1)
{ {
drccodeptr **newtable = (drccodeptr **)drccache_memory_alloc_temporary(drchash->cache, sizeof(drccodeptr *) << drchash->l1bits); drccodeptr **newtable = (drccodeptr **)drchash->cache->alloc_temporary(sizeof(drccodeptr *) << drchash->l1bits);
if (newtable == NULL) if (newtable == NULL)
return FALSE; return FALSE;
memcpy(newtable, drchash->emptyl1, sizeof(drccodeptr *) << drchash->l1bits); memcpy(newtable, drchash->emptyl1, sizeof(drccodeptr *) << drchash->l1bits);
@ -256,7 +256,7 @@ int drchash_set_codeptr(drchash_state *drchash, UINT32 mode, UINT32 pc, drccodep
/* copy-on-write for the l2 hash table */ /* copy-on-write for the l2 hash table */
if (drchash->base[mode][l1] == drchash->emptyl2) if (drchash->base[mode][l1] == drchash->emptyl2)
{ {
drccodeptr *newtable = (drccodeptr *)drccache_memory_alloc_temporary(drchash->cache, sizeof(drccodeptr) << drchash->l2bits); drccodeptr *newtable = (drccodeptr *)drchash->cache->alloc_temporary(sizeof(drccodeptr) << drchash->l2bits);
if (newtable == NULL) if (newtable == NULL)
return FALSE; return FALSE;
memcpy(newtable, drchash->emptyl2, sizeof(drccodeptr) << drchash->l2bits); memcpy(newtable, drchash->emptyl2, sizeof(drccodeptr) << drchash->l2bits);
@ -280,12 +280,12 @@ int drchash_set_codeptr(drchash_state *drchash, UINT32 mode, UINT32 pc, drccodep
cache) cache)
-------------------------------------------------*/ -------------------------------------------------*/
drcmap_state *drcmap_alloc(drccache *cache, UINT64 uniquevalue) drcmap_state *drcmap_alloc(drc_cache *cache, UINT64 uniquevalue)
{ {
drcmap_state *drcmap; drcmap_state *drcmap;
/* allocate permanent state from the cache */ /* allocate permanent state from the cache */
drcmap = (drcmap_state *)drccache_memory_alloc(cache, sizeof(*drcmap)); drcmap = (drcmap_state *)cache->alloc(sizeof(*drcmap));
if (drcmap == NULL) if (drcmap == NULL)
return NULL; return NULL;
memset(drcmap, 0, sizeof(*drcmap)); memset(drcmap, 0, sizeof(*drcmap));
@ -310,7 +310,7 @@ void drcmap_block_begin(drcmap_state *drcmap, drcuml_block *block)
{ {
drcmap_entry *entry = drcmap->head; drcmap_entry *entry = drcmap->head;
drcmap->head = entry->next; drcmap->head = entry->next;
drccache_memory_free(drcmap->cache, entry, sizeof(*entry)); drcmap->cache->dealloc(entry, sizeof(*entry));
} }
/* reset the tailptr and count */ /* reset the tailptr and count */
@ -340,7 +340,7 @@ void drcmap_block_end(drcmap_state *drcmap, drcuml_block *block)
return; return;
/* begin "code generation" aligned to an 8-byte boundary */ /* begin "code generation" aligned to an 8-byte boundary */
top = drccache_begin_codegen(drcmap->cache, sizeof(UINT64) + sizeof(UINT32) + 2 * sizeof(UINT32) * drcmap->numvalues); top = drcmap->cache->begin_codegen(sizeof(UINT64) + sizeof(UINT32) + 2 * sizeof(UINT32) * drcmap->numvalues);
if (top == NULL) if (top == NULL)
drcuml_block_abort(block); drcuml_block_abort(block);
dest = (UINT32 *)(((FPTR)*top + 7) & ~7); dest = (UINT32 *)(((FPTR)*top + 7) & ~7);
@ -408,7 +408,7 @@ void drcmap_block_end(drcmap_state *drcmap, drcuml_block *block)
/* complete codegen */ /* complete codegen */
*top = (drccodeptr)dest; *top = (drccodeptr)dest;
drccache_end_codegen(drcmap->cache); drcmap->cache->end_codegen();
} }
@ -428,7 +428,7 @@ void drcmap_set_value(drcmap_state *drcmap, drccodeptr codebase, UINT32 mapvar,
return; return;
/* allocate a new entry and fill it in */ /* allocate a new entry and fill it in */
entry = (drcmap_entry *)drccache_memory_alloc(drcmap->cache, sizeof(*entry)); entry = (drcmap_entry *)drcmap->cache->alloc(sizeof(*entry));
entry->next = NULL; entry->next = NULL;
entry->codeptr = codebase; entry->codeptr = codebase;
entry->mapvar = mapvar - DRCUML_MAPVAR_M0; entry->mapvar = mapvar - DRCUML_MAPVAR_M0;
@ -453,7 +453,7 @@ void drcmap_set_value(drcmap_state *drcmap, drccodeptr codebase, UINT32 mapvar,
UINT32 drcmap_get_value(drcmap_state *drcmap, drccodeptr codebase, UINT32 mapvar) UINT32 drcmap_get_value(drcmap_state *drcmap, drccodeptr codebase, UINT32 mapvar)
{ {
UINT64 *endscan = (UINT64 *)drccache_top(drcmap->cache); UINT64 *endscan = (UINT64 *)drcmap->cache->top();
UINT32 varmask = 0x10 << mapvar; UINT32 varmask = 0x10 << mapvar;
drccodeptr curcode; drccodeptr curcode;
UINT32 result = 0; UINT32 result = 0;
@ -538,12 +538,12 @@ UINT32 drcmap_get_last_value(drcmap_state *drcmap, UINT32 mapvar)
cache) cache)
-------------------------------------------------*/ -------------------------------------------------*/
drclabel_list *drclabel_list_alloc(drccache *cache) drclabel_list *drclabel_list_alloc(drc_cache *cache)
{ {
drclabel_list *list; drclabel_list *list;
/* allocate permanent state from the cache */ /* allocate permanent state from the cache */
list = (drclabel_list *)drccache_memory_alloc(cache, sizeof(*list)); list = (drclabel_list *)cache->alloc(sizeof(*list));
if (list == NULL) if (list == NULL)
return NULL; return NULL;
memset(list, 0, sizeof(*list)); memset(list, 0, sizeof(*list));
@ -590,7 +590,7 @@ drccodeptr drclabel_get_codeptr(drclabel_list *list, drcuml_codelabel label, drc
/* if no code pointer, request an OOB callback */ /* if no code pointer, request an OOB callback */
if (curlabel->codeptr == NULL && fixup != NULL) if (curlabel->codeptr == NULL && fixup != NULL)
drccache_request_oob_codegen(list->cache, label_oob_callback, curlabel, (void *)fixup, param); list->cache->request_oob_codegen(label_oob_callback, curlabel, (void *)fixup, param);
return curlabel->codeptr; return curlabel->codeptr;
} }
@ -634,7 +634,7 @@ static void label_list_reset(drclabel_list *list, int fatal_on_leftovers)
fatalerror("Label %08X never defined!", label->label); fatalerror("Label %08X never defined!", label->label);
/* free the label */ /* free the label */
drccache_memory_free(list->cache, label, sizeof(*label)); list->cache->dealloc(label, sizeof(*label));
} }
} }
@ -656,7 +656,7 @@ static drclabel *label_find_or_allocate(drclabel_list *list, drcuml_codelabel la
/* if none found, allocate */ /* if none found, allocate */
if (curlabel == NULL) if (curlabel == NULL)
{ {
curlabel = (drclabel *)drccache_memory_alloc(list->cache, sizeof(*curlabel)); curlabel = (drclabel *)list->cache->alloc(sizeof(*curlabel));
curlabel->next = list->head; curlabel->next = list->head;
curlabel->label = label; curlabel->label = label;
curlabel->codeptr = NULL; curlabel->codeptr = NULL;

View File

@ -38,7 +38,7 @@ typedef struct _drcmap_state drcmap_state;
typedef struct _drchash_state drchash_state; typedef struct _drchash_state drchash_state;
struct _drchash_state struct _drchash_state
{ {
drccache * cache; /* cache where allocations come from */ drc_cache * cache; /* cache where allocations come from */
int modes; /* number of modes supported */ int modes; /* number of modes supported */
drccodeptr nocodeptr; /* pointer to code which will handle missing entries */ drccodeptr nocodeptr; /* pointer to code which will handle missing entries */
@ -65,7 +65,7 @@ struct _drchash_state
/* ----- hash table management ----- */ /* ----- hash table management ----- */
/* allocate memory in the cache for the hash table tracker (it auto-frees with the cache) */ /* allocate memory in the cache for the hash table tracker (it auto-frees with the cache) */
drchash_state *drchash_alloc(drccache *cache, int modes, int addrbits, int ignorebits); drchash_state *drchash_alloc(drc_cache *cache, int modes, int addrbits, int ignorebits);
/* flush existing hash tables and create new ones */ /* flush existing hash tables and create new ones */
int drchash_reset(drchash_state *drchash); int drchash_reset(drchash_state *drchash);
@ -87,7 +87,7 @@ int drchash_set_codeptr(drchash_state *drchash, UINT32 mode, UINT32 pc, drccodep
/* ----- code map management ----- */ /* ----- code map management ----- */
/* allocate memory in the cache for the code mapper (it auto-frees with the cache) */ /* allocate memory in the cache for the code mapper (it auto-frees with the cache) */
drcmap_state *drcmap_alloc(drccache *cache, UINT64 uniquevalue); drcmap_state *drcmap_alloc(drc_cache *cache, UINT64 uniquevalue);
/* note the beginning of a block */ /* note the beginning of a block */
void drcmap_block_begin(drcmap_state *drcmap, drcuml_block *block); void drcmap_block_begin(drcmap_state *drcmap, drcuml_block *block);
@ -109,7 +109,7 @@ UINT32 drcmap_get_last_value(drcmap_state *drcmap, UINT32 mapvar);
/* ----- label management ----- */ /* ----- label management ----- */
/* allocate a label list within the cache (it auto-frees with the cache) */ /* allocate a label list within the cache (it auto-frees with the cache) */
drclabel_list *drclabel_list_alloc(drccache *cache); drclabel_list *drclabel_list_alloc(drc_cache *cache);
/* note the beginning of a block */ /* note the beginning of a block */
void drclabel_block_begin(drclabel_list *drcmap, drcuml_block *block); void drclabel_block_begin(drclabel_list *drcmap, drcuml_block *block);

View File

@ -264,7 +264,7 @@ struct _drcbe_state
{ {
device_t * device; /* CPU device we are associated with */ device_t * device; /* CPU device we are associated with */
drcuml_state * drcuml; /* pointer back to our owner */ drcuml_state * drcuml; /* pointer back to our owner */
drccache * 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 */ drchash_state * hash; /* hash table state */
drcmap_state * map; /* code map */ drcmap_state * map; /* code map */
@ -307,7 +307,7 @@ struct _drcbe_state
***************************************************************************/ ***************************************************************************/
/* primary back-end callbacks */ /* primary back-end callbacks */
static drcbe_state *drcbex64_alloc(drcuml_state *drcuml, drccache *cache, device_t *device, UINT32 flags, int modes, int addrbits, int ignorebits); static drcbe_state *drcbex64_alloc(drcuml_state *drcuml, drc_cache *cache, device_t *device, UINT32 flags, int modes, int addrbits, int ignorebits);
static void drcbex64_free(drcbe_state *drcbe); static void drcbex64_free(drcbe_state *drcbe);
static void drcbex64_reset(drcbe_state *drcbe); static void drcbex64_reset(drcbe_state *drcbe);
static int drcbex64_execute(drcbe_state *drcbe, drcuml_codehandle *entry); static int drcbex64_execute(drcbe_state *drcbe, drcuml_codehandle *entry);
@ -686,7 +686,7 @@ INLINE void emit_smart_call_m64(drcbe_state *drcbe, x86code **dst, x86code **tar
state state
-------------------------------------------------*/ -------------------------------------------------*/
static drcbe_state *drcbex64_alloc(drcuml_state *drcuml, drccache *cache, device_t *device, UINT32 flags, int modes, int addrbits, int ignorebits) static drcbe_state *drcbex64_alloc(drcuml_state *drcuml, drc_cache *cache, device_t *device, UINT32 flags, int modes, int addrbits, int ignorebits)
{ {
/* SSE control register mapping */ /* SSE control register mapping */
static const UINT32 sse_control[4] = static const UINT32 sse_control[4] =
@ -701,7 +701,7 @@ static drcbe_state *drcbex64_alloc(drcuml_state *drcuml, drccache *cache, device
int spacenum; int spacenum;
/* allocate space in the cache for our state */ /* allocate space in the cache for our state */
drcbe = (drcbe_state *)drccache_memory_alloc_near(cache, sizeof(*drcbe)); drcbe = (drcbe_state *)cache->alloc_near(sizeof(*drcbe));
if (drcbe == NULL) if (drcbe == NULL)
return NULL; return NULL;
memset(drcbe, 0, sizeof(*drcbe)); memset(drcbe, 0, sizeof(*drcbe));
@ -710,7 +710,7 @@ static drcbe_state *drcbex64_alloc(drcuml_state *drcuml, drccache *cache, device
drcbe->device = device; drcbe->device = device;
drcbe->drcuml = drcuml; drcbe->drcuml = drcuml;
drcbe->cache = cache; drcbe->cache = cache;
drcbe->rbpvalue = drccache_near(cache) + 0x80; drcbe->rbpvalue = cache->near() + 0x80;
/* get address spaces and accessors */ /* get address spaces and accessors */
for (spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++) for (spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++)
@ -722,7 +722,7 @@ static drcbe_state *drcbex64_alloc(drcuml_state *drcuml, drccache *cache, device
/* build up necessary arrays */ /* build up necessary arrays */
memcpy(drcbe->ssecontrol, sse_control, sizeof(drcbe->ssecontrol)); memcpy(drcbe->ssecontrol, sse_control, sizeof(drcbe->ssecontrol));
drcbe->absmask32 = (UINT32 *)drccache_memory_alloc_near(cache, 16*2 + 15); drcbe->absmask32 = (UINT32 *)cache->alloc_near(16*2 + 15);
drcbe->absmask32 = (UINT32 *)(((FPTR)drcbe->absmask32 + 15) & ~15); drcbe->absmask32 = (UINT32 *)(((FPTR)drcbe->absmask32 + 15) & ~15);
drcbe->absmask32[0] = drcbe->absmask32[1] = drcbe->absmask32[2] = drcbe->absmask32[3] = 0x7fffffff; drcbe->absmask32[0] = drcbe->absmask32[1] = drcbe->absmask32[2] = drcbe->absmask32[3] = 0x7fffffff;
drcbe->absmask64 = (UINT64 *)&drcbe->absmask32[4]; drcbe->absmask64 = (UINT64 *)&drcbe->absmask32[4];
@ -814,7 +814,7 @@ static void drcbex64_reset(drcbe_state *drcbe)
x86log_printf(drcbe->log, "\n\n===========\nCACHE RESET\n===========\n\n"); x86log_printf(drcbe->log, "\n\n===========\nCACHE RESET\n===========\n\n");
/* generate a little bit of glue code to set up the environment */ /* generate a little bit of glue code to set up the environment */
dst = (x86code **)drccache_begin_codegen(drcbe->cache, 500); dst = (x86code **)drcbe->cache->begin_codegen(500);
if (dst == NULL) if (dst == NULL)
fatalerror("Out of cache space after a reset!"); fatalerror("Out of cache space after a reset!");
@ -874,7 +874,7 @@ static void drcbex64_reset(drcbe_state *drcbe)
x86log_disasm_code_range(drcbe->log, "nocode", drcbe->nocode, *dst); x86log_disasm_code_range(drcbe->log, "nocode", drcbe->nocode, *dst);
/* finish up codegen */ /* finish up codegen */
drccache_end_codegen(drcbe->cache); drcbe->cache->end_codegen();
/* reset our hash tables */ /* reset our hash tables */
drchash_reset(drcbe->hash); drchash_reset(drcbe->hash);
@ -913,7 +913,7 @@ static void drcbex64_generate(drcbe_state *drcbe, drcuml_block *block, const drc
drcmap_block_begin(drcbe->map, block); drcmap_block_begin(drcbe->map, block);
/* begin codegen; fail if we can't */ /* begin codegen; fail if we can't */
cachetop = drccache_begin_codegen(drcbe->cache, numinst * 8 * 4); cachetop = drcbe->cache->begin_codegen(numinst * 8 * 4);
if (cachetop == NULL) if (cachetop == NULL)
drcuml_block_abort(block); drcuml_block_abort(block);
@ -953,11 +953,11 @@ static void drcbex64_generate(drcbe_state *drcbe, drcuml_block *block, const drc
/* complete codegen */ /* complete codegen */
*cachetop = (drccodeptr)dst; *cachetop = (drccodeptr)dst;
drccache_end_codegen(drcbe->cache); drcbe->cache->end_codegen();
/* log it */ /* log it */
if (drcbe->log != NULL) if (drcbe->log != NULL)
x86log_disasm_code_range(drcbe->log, (blockname == NULL) ? "Unknown block" : blockname, base, drccache_top(drcbe->cache)); 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); drchash_block_end(drcbe->hash, block);
@ -3340,7 +3340,7 @@ static x86code *op_exh(drcbe_state *drcbe, x86code *dst, const drcuml_instructio
else else
{ {
emit_jcc(&dst, X86_CONDITION(inst->condition), dst + 0x7ffffff0); // jcc exception emit_jcc(&dst, X86_CONDITION(inst->condition), dst + 0x7ffffff0); // jcc exception
drccache_request_oob_codegen(drcbe->cache, fixup_exception, drcbe, dst, (void *)inst); drcbe->cache->request_oob_codegen(fixup_exception, drcbe, dst, (void *)inst);
} }
return dst; return dst;
} }

View File

@ -156,7 +156,7 @@ struct _drcbe_state
{ {
device_t * device; /* CPU device we are associated with */ device_t * device; /* CPU device we are associated with */
drcuml_state * drcuml; /* pointer back to our owner */ drcuml_state * drcuml; /* pointer back to our owner */
drccache * 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 */ drchash_state * hash; /* hash table state */
drcmap_state * map; /* code map */ drcmap_state * map; /* code map */
@ -201,7 +201,7 @@ struct _drcbe_state
***************************************************************************/ ***************************************************************************/
/* primary back-end callbacks */ /* primary back-end callbacks */
static drcbe_state *drcbex86_alloc(drcuml_state *drcuml, drccache *cache, device_t *device, UINT32 flags, int modes, int addrbits, int ignorebits); static drcbe_state *drcbex86_alloc(drcuml_state *drcuml, drc_cache *cache, device_t *device, UINT32 flags, int modes, int addrbits, int ignorebits);
static void drcbex86_free(drcbe_state *drcbe); static void drcbex86_free(drcbe_state *drcbe);
static void drcbex86_reset(drcbe_state *drcbe); static void drcbex86_reset(drcbe_state *drcbe);
static int drcbex86_execute(drcbe_state *drcbe, drcuml_codehandle *entry); static int drcbex86_execute(drcbe_state *drcbe, drcuml_codehandle *entry);
@ -614,13 +614,13 @@ INLINE void track_resolve_link(drcbe_state *drcbe, x86code **destptr, const emit
state state
-------------------------------------------------*/ -------------------------------------------------*/
static drcbe_state *drcbex86_alloc(drcuml_state *drcuml, drccache *cache, device_t *device, UINT32 flags, int modes, int addrbits, int ignorebits) static drcbe_state *drcbex86_alloc(drcuml_state *drcuml, drc_cache *cache, device_t *device, UINT32 flags, int modes, int addrbits, int ignorebits)
{ {
int opnum, regnum, entry, spacenum; int opnum, regnum, entry, spacenum;
drcbe_state *drcbe; drcbe_state *drcbe;
/* allocate space in the cache for our state */ /* allocate space in the cache for our state */
drcbe = (drcbe_state *)drccache_memory_alloc(cache, sizeof(*drcbe)); drcbe = (drcbe_state *)cache->alloc(sizeof(*drcbe));
if (drcbe == NULL) if (drcbe == NULL)
return NULL; return NULL;
memset(drcbe, 0, sizeof(*drcbe)); memset(drcbe, 0, sizeof(*drcbe));
@ -722,7 +722,7 @@ static void drcbex86_reset(drcbe_state *drcbe)
x86log_printf(drcbe->log, "\n\n===========\nCACHE RESET\n===========\n\n"); x86log_printf(drcbe->log, "\n\n===========\nCACHE RESET\n===========\n\n");
/* generate a little bit of glue code to set up the environment */ /* generate a little bit of glue code to set up the environment */
dst = (x86code **)drccache_begin_codegen(drcbe->cache, 500); dst = (x86code **)drcbe->cache->begin_codegen(500);
if (dst == NULL) if (dst == NULL)
fatalerror("Out of cache space after a reset!"); fatalerror("Out of cache space after a reset!");
@ -850,7 +850,7 @@ static void drcbex86_reset(drcbe_state *drcbe)
x86log_disasm_code_range(drcbe->log, "restore", drcbe->restore, *dst); x86log_disasm_code_range(drcbe->log, "restore", drcbe->restore, *dst);
/* finish up codegen */ /* finish up codegen */
drccache_end_codegen(drcbe->cache); drcbe->cache->end_codegen();
drcbe->logged_common = TRUE; drcbe->logged_common = TRUE;
/* reset our hash tables */ /* reset our hash tables */
@ -890,7 +890,7 @@ static void drcbex86_generate(drcbe_state *drcbe, drcuml_block *block, const drc
drcmap_block_begin(drcbe->map, block); drcmap_block_begin(drcbe->map, block);
/* begin codegen; fail if we can't */ /* begin codegen; fail if we can't */
cachetop = drccache_begin_codegen(drcbe->cache, numinst * 8 * 4); cachetop = drcbe->cache->begin_codegen(numinst * 8 * 4);
if (cachetop == NULL) if (cachetop == NULL)
drcuml_block_abort(block); drcuml_block_abort(block);
@ -930,11 +930,11 @@ static void drcbex86_generate(drcbe_state *drcbe, drcuml_block *block, const drc
/* complete codegen */ /* complete codegen */
*cachetop = (drccodeptr)dst; *cachetop = (drccodeptr)dst;
drccache_end_codegen(drcbe->cache); drcbe->cache->end_codegen();
/* log it */ /* log it */
if (drcbe->log != NULL) if (drcbe->log != NULL)
x86log_disasm_code_range(drcbe->log, (blockname == NULL) ? "Unknown block" : blockname, base, drccache_top(drcbe->cache)); 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); drchash_block_end(drcbe->hash, block);
@ -3546,7 +3546,7 @@ static x86code *op_exh(drcbe_state *drcbe, x86code *dst, const drcuml_instructio
else else
{ {
emit_jcc(&dst, X86_CONDITION(inst->condition), 0); // jcc exception emit_jcc(&dst, X86_CONDITION(inst->condition), 0); // jcc exception
drccache_request_oob_codegen(drcbe->cache, fixup_exception, drcbe, dst, (void *)inst); drcbe->cache->request_oob_codegen(fixup_exception, drcbe, dst, (void *)inst);
} }
return dst; return dst;
} }

View File

@ -1,12 +1,39 @@
/*************************************************************************** /***************************************************************************
drccache.h drccache.c
Universal dynamic recompiler cache management. Universal dynamic recompiler cache management.
****************************************************************************
Copyright Aaron Giles Copyright Aaron Giles
Released for general non-commercial use under the MAME license All rights reserved.
Visit http://mamedev.org for licensing and usage restrictions.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/ ***************************************************************************/
@ -15,403 +42,241 @@
/*************************************************************************** //**************************************************************************
CONSTANTS // MACROS
***************************************************************************/ //**************************************************************************
/* largest block of code that can be generated at once */ // ensure that all memory allocated is aligned to an 8-byte boundary
#define CODEGEN_MAX_BYTES 65536
/* minimum alignment, in bytes (must be power of 2) */
#define CACHE_ALIGNMENT 8
/* largest permanent allocation we allow */
#define MAX_PERMANENT_ALLOC 1024
/* size of "near" area at the base of the cache */
#define NEAR_CACHE_SIZE 65536
/***************************************************************************
MACROS
***************************************************************************/
/* ensure that all memory allocated is aligned to an 8-byte boundary */
#define ALIGN_PTR_UP(p) ((void *)(((FPTR)(p) + (CACHE_ALIGNMENT - 1)) & ~(CACHE_ALIGNMENT - 1))) #define ALIGN_PTR_UP(p) ((void *)(((FPTR)(p) + (CACHE_ALIGNMENT - 1)) & ~(CACHE_ALIGNMENT - 1)))
#define ALIGN_PTR_DOWN(p) ((void *)((FPTR)(p) & ~(CACHE_ALIGNMENT - 1))) #define ALIGN_PTR_DOWN(p) ((void *)((FPTR)(p) & ~(CACHE_ALIGNMENT - 1)))
/*************************************************************************** //**************************************************************************
TYPE DEFINITIONS // DRC CACHE
***************************************************************************/ //**************************************************************************
/* out-of-bounds codegen handlers */ //-------------------------------------------------
typedef struct _oob_handler oob_handler; // drc_cache - constructor
struct _oob_handler //-------------------------------------------------
drc_cache::drc_cache(size_t bytes)
: m_near((drccodeptr)osd_alloc_executable(bytes)),
m_neartop(m_near),
m_base(m_near + NEAR_CACHE_SIZE),
m_top(m_base),
m_end(m_near + bytes),
m_codegen(0),
m_size(bytes)
{ {
oob_handler * next; /* next handler */ memset(m_free, 0, sizeof(m_free));
drccache_oob_func callback; /* callback function */ memset(m_nearfree, 0, sizeof(m_nearfree));
void * param1; /* 1st pointer parameter */
void * param2; /* 2nd pointer parameter */
void * param3; /* 3rd pointer parameter */
};
/* a linked list of free items */
typedef struct _free_link free_link;
struct _free_link
{
free_link * next; /* pointer to the next guy */
};
/* cache state */
struct _drccache
{
/* core parameters */
drccodeptr near; /* pointer to the near part of the cache */
drccodeptr neartop; /* top of the near part of the cache */
drccodeptr base; /* base pointer to the compiler cache */
drccodeptr top; /* current top of cache */
drccodeptr end; /* end of cache memory */
drccodeptr codegen; /* start of generated code */
size_t size; /* size of the cache in bytes */
/* oob management */
oob_handler * ooblist; /* list of oob handlers */
oob_handler ** oobtail; /* pointer to tail oob pointer */
/* free lists */
free_link * free[MAX_PERMANENT_ALLOC / CACHE_ALIGNMENT];
free_link * nearfree[MAX_PERMANENT_ALLOC / CACHE_ALIGNMENT];
};
/***************************************************************************
INITIALIZATION/TEARDOWN
***************************************************************************/
/*-------------------------------------------------
drccache_alloc - allocate the cache itself
-------------------------------------------------*/
drccache *drccache_alloc(size_t bytes)
{
drccache cache, *cacheptr;
assert(bytes >= sizeof(cache) + NEAR_CACHE_SIZE);
/* build a local structure first */
memset(&cache, 0, sizeof(cache));
cache.near = (drccodeptr)osd_alloc_executable(bytes);
cache.neartop = cache.near;
cache.base = cache.near + NEAR_CACHE_SIZE;
cache.top = cache.base;
cache.end = cache.near + bytes;
cache.size = bytes;
/* now allocate the cache structure itself from that */
cacheptr = (drccache *)drccache_memory_alloc(&cache, sizeof(cache));
*cacheptr = cache;
/* return the allocated result */
return cacheptr;
} }
/*------------------------------------------------- //-------------------------------------------------
drccache_free - free the cache // ~drc_cache - destructor
-------------------------------------------------*/ //-------------------------------------------------
void drccache_free(drccache *cache) drc_cache::~drc_cache()
{ {
/* release the memory; this includes the cache object itself */ // release the memory
osd_free_executable(cache->near, cache->size); osd_free_executable(m_near, m_size);
} }
/*************************************************************************** //-------------------------------------------------
CACHE INFORMATION // flush - flush the cache contents
***************************************************************************/ //-------------------------------------------------
/*------------------------------------------------- void drc_cache::flush()
drccache_contains_pointer - return true if a
pointer is within the cache
-------------------------------------------------*/
int drccache_contains_pointer(drccache *cache, const void *ptr)
{ {
return ((const drccodeptr)ptr >= cache->near && (const drccodeptr)ptr < cache->near + cache->size); // can't flush in the middle of codegen
assert(m_codegen == NULL);
// just reset the top back to the base and re-seed
m_top = m_base;
} }
/*------------------------------------------------- //-------------------------------------------------
drccache_contains_near_pointer - return true // alloc - allocate permanent memory from the
if a pointer is within the cache // cache
-------------------------------------------------*/ //-------------------------------------------------
int drccache_contains_near_pointer(drccache *cache, const void *ptr) void *drc_cache::alloc(size_t bytes)
{ {
return ((const drccodeptr)ptr >= cache->near && (const drccodeptr)ptr < cache->neartop);
}
/*-------------------------------------------------
drccache_near - return a pointer to the near
part of the cache
-------------------------------------------------*/
drccodeptr drccache_near(drccache *cache)
{
return cache->near;
}
/*-------------------------------------------------
drccache_base - return a pointer to the base
of the cache
-------------------------------------------------*/
drccodeptr drccache_base(drccache *cache)
{
return cache->base;
}
/*-------------------------------------------------
drccache_top - return the current top of the
cache
-------------------------------------------------*/
drccodeptr drccache_top(drccache *cache)
{
return cache->top;
}
/***************************************************************************
MEMORY MANAGEMENT
***************************************************************************/
/*-------------------------------------------------
drccache_flush - flush the cache contents
-------------------------------------------------*/
void drccache_flush(drccache *cache)
{
/* can't flush in the middle of codegen */
assert(cache->codegen == NULL);
/* just reset the top back to the base and re-seed */
cache->top = cache->base;
}
/*-------------------------------------------------
drccache_memory_alloc - allocate permanent
memory from the cache
-------------------------------------------------*/
void *drccache_memory_alloc(drccache *cache, size_t bytes)
{
drccodeptr ptr;
assert(bytes > 0); assert(bytes > 0);
/* pick first from the free list */ // pick first from the free list
if (bytes < MAX_PERMANENT_ALLOC) if (bytes < MAX_PERMANENT_ALLOC)
{ {
free_link **linkptr = &cache->free[(bytes + CACHE_ALIGNMENT - 1) / CACHE_ALIGNMENT]; free_link **linkptr = &m_free[(bytes + CACHE_ALIGNMENT - 1) / CACHE_ALIGNMENT];
free_link *link = *linkptr; free_link *link = *linkptr;
if (link != NULL) if (link != NULL)
{ {
*linkptr = link->next; *linkptr = link->m_next;
return link; return link;
} }
} }
/* if no space, we just fail */ // if no space, we just fail
ptr = (drccodeptr)ALIGN_PTR_DOWN(cache->end - bytes); drccodeptr ptr = (drccodeptr)ALIGN_PTR_DOWN(m_end - bytes);
if (cache->top > ptr) if (m_top > ptr)
return NULL; return NULL;
/* otherwise update the end of the cache */ // otherwise update the end of the cache
cache->end = ptr; m_end = ptr;
return ptr; return ptr;
} }
/*------------------------------------------------- //-------------------------------------------------
drccache_memory_alloc_near - allocate // alloc_near - allocate permanent memory from
permanent memory from the near part of the // the near part of the cache
cache //-------------------------------------------------
-------------------------------------------------*/
void *drccache_memory_alloc_near(drccache *cache, size_t bytes) void *drc_cache::alloc_near(size_t bytes)
{ {
drccodeptr ptr;
assert(bytes > 0); assert(bytes > 0);
/* pick first from the free list */ // pick first from the free list
if (bytes < MAX_PERMANENT_ALLOC) if (bytes < MAX_PERMANENT_ALLOC)
{ {
free_link **linkptr = &cache->nearfree[(bytes + CACHE_ALIGNMENT - 1) / CACHE_ALIGNMENT]; free_link **linkptr = &m_nearfree[(bytes + CACHE_ALIGNMENT - 1) / CACHE_ALIGNMENT];
free_link *link = *linkptr; free_link *link = *linkptr;
if (link != NULL) if (link != NULL)
{ {
*linkptr = link->next; *linkptr = link->m_next;
return link; return link;
} }
} }
/* if no space, we just fail */ // if no space, we just fail
ptr = (drccodeptr)ALIGN_PTR_UP(cache->neartop); drccodeptr ptr = (drccodeptr)ALIGN_PTR_UP(m_neartop);
if (ptr + bytes > cache->base) if (ptr + bytes > m_base)
return NULL; return NULL;
/* otherwise update the top of the near part of the cache */ // otherwise update the top of the near part of the cache
cache->neartop = ptr + bytes; m_neartop = ptr + bytes;
return ptr; return ptr;
} }
/*------------------------------------------------- //-------------------------------------------------
drccache_memory_free - release permanent // alloc_temporary - allocate temporary memory
memory allocated from the cache // from the cache
-------------------------------------------------*/ //-------------------------------------------------
void drccache_memory_free(drccache *cache, void *memory, size_t bytes) void *drc_cache::alloc_temporary(size_t bytes)
{ {
free_link **linkptr; // can't allocate in the middle of codegen
free_link *link = (free_link *)memory; assert(m_codegen == NULL);
// if no space, we just fail
drccodeptr ptr = m_top;
if (ptr + bytes >= m_end)
return NULL;
// otherwise, update the cache top
m_top = (drccodeptr)ALIGN_PTR_UP(ptr + bytes);
return ptr;
}
//-------------------------------------------------
// free - release permanent memory allocated from
// the cache
//-------------------------------------------------
void drc_cache::dealloc(void *memory, size_t bytes)
{
assert(bytes < MAX_PERMANENT_ALLOC); assert(bytes < MAX_PERMANENT_ALLOC);
assert(((drccodeptr)memory >= cache->near && (drccodeptr)memory < cache->base) || ((drccodeptr)memory >= cache->end && (drccodeptr)memory < cache->near + cache->size)); assert(((drccodeptr)memory >= m_near && (drccodeptr)memory < m_base) || ((drccodeptr)memory >= m_end && (drccodeptr)memory < m_near + m_size));
/* determine which free list to add to */ // determine which free list to add to
if ((drccodeptr)memory < cache->base) free_link **linkptr;
linkptr = &cache->nearfree[(bytes + CACHE_ALIGNMENT - 1) / CACHE_ALIGNMENT]; if ((drccodeptr)memory < m_base)
linkptr = &m_nearfree[(bytes + CACHE_ALIGNMENT - 1) / CACHE_ALIGNMENT];
else else
linkptr = &cache->free[(bytes + CACHE_ALIGNMENT - 1) / CACHE_ALIGNMENT]; linkptr = &m_free[(bytes + CACHE_ALIGNMENT - 1) / CACHE_ALIGNMENT];
/* link is into the free list for our size */ // link is into the free list for our size
link->next = *linkptr; free_link *link = (free_link *)memory;
link->m_next = *linkptr;
*linkptr = link; *linkptr = link;
} }
/*------------------------------------------------- //-------------------------------------------------
drccache_memory_alloc_temporary - allocate // begin_codegen - begin code generation
temporary memory from the cache //-------------------------------------------------
-------------------------------------------------*/
void *drccache_memory_alloc_temporary(drccache *cache, size_t bytes) drccodeptr *drc_cache::begin_codegen(UINT32 reserve_bytes)
{ {
drccodeptr ptr = cache->top; // can't restart in the middle of codegen
assert(m_codegen == NULL);
assert(m_ooblist == NULL);
/* can't allocate in the middle of codegen */ // if still no space, we just fail
assert(cache->codegen == NULL); drccodeptr ptr = m_top;
if (ptr + reserve_bytes >= m_end)
/* if no space, we just fail */
if (ptr + bytes >= cache->end)
return NULL; return NULL;
/* otherwise, update the cache top */ // otherwise, return a pointer to the cache top
cache->top = (drccodeptr)ALIGN_PTR_UP(ptr + bytes); m_codegen = m_top;
return ptr; return &m_top;
} }
//-------------------------------------------------
// end_codegen - complete code generation
//-------------------------------------------------
/*************************************************************************** drccodeptr drc_cache::end_codegen()
CODE GENERATION
***************************************************************************/
/*-------------------------------------------------
drccache_begin_codegen - begin code
generation
-------------------------------------------------*/
drccodeptr *drccache_begin_codegen(drccache *cache, UINT32 reserve_bytes)
{ {
drccodeptr ptr = cache->top; drccodeptr result = m_codegen;
/* can't restart in the middle of codegen */ // run the OOB handlers
assert(cache->codegen == NULL); oob_handler *oob;
assert(cache->ooblist == NULL); while ((oob = m_ooblist.detach_head()) != NULL)
/* if still no space, we just fail */
if (ptr + reserve_bytes >= cache->end)
return NULL;
/* otherwise, return a pointer to the cache top */
cache->codegen = cache->top;
cache->oobtail = &cache->ooblist;
return &cache->top;
}
/*-------------------------------------------------
drccache_end_codegen - complete code
generation
-------------------------------------------------*/
drccodeptr drccache_end_codegen(drccache *cache)
{
drccodeptr result = cache->codegen;
/* run the OOB handlers */
while (cache->ooblist != NULL)
{ {
/* remove us from the list */ // call the callback
oob_handler *oob = cache->ooblist; (*oob->m_callback)(&m_top, oob->m_param1, oob->m_param2, oob->m_param3);
cache->ooblist = oob->next; assert(m_top - m_codegen < CODEGEN_MAX_BYTES);
/* call the callback */ // release our memory
(*oob->callback)(&cache->top, oob->param1, oob->param2, oob->param3); dealloc(oob, sizeof(*oob));
assert(cache->top - cache->codegen < CODEGEN_MAX_BYTES);
/* release our memory */
drccache_memory_free(cache, oob, sizeof(*oob));
} }
/* update the cache top */ // update the cache top
cache->top = (drccodeptr)ALIGN_PTR_UP(cache->top); m_top = (drccodeptr)ALIGN_PTR_UP(m_top);
cache->codegen = NULL; m_codegen = NULL;
return result; return result;
} }
/*------------------------------------------------- //-------------------------------------------------
drccache_request_oob_codegen - request // request_oob_codegen - request callback for
callback for out-of-band codegen // out-of-band codegen
-------------------------------------------------*/ //-------------------------------------------------
void drccache_request_oob_codegen(drccache *cache, drccache_oob_func callback, void *param1, void *param2, void *param3) void drc_cache::request_oob_codegen(oob_func callback, void *param1, void *param2, void *param3)
{ {
oob_handler *oob; assert(m_codegen != NULL);
assert(cache->codegen != NULL); // pull an item from the free list
oob_handler *oob = (oob_handler *)alloc(sizeof(*oob));
/* pull an item from the free list */
oob = (oob_handler *)drccache_memory_alloc(cache, sizeof(*oob));
assert(oob != NULL); assert(oob != NULL);
/* fill it in */ // fill it in
oob->next = NULL; oob->m_callback = callback;
oob->callback = callback; oob->m_param1 = param1;
oob->param1 = param1; oob->m_param2 = param2;
oob->param2 = param2; oob->m_param3 = param3;
oob->param3 = param3;
/* add to the tail */ // add to the tail
*cache->oobtail = oob; m_ooblist.append(*oob);
cache->oobtail = &oob->next;
} }

View File

@ -4,9 +4,36 @@
Universal dynamic recompiler cache management. Universal dynamic recompiler cache management.
****************************************************************************
Copyright Aaron Giles Copyright Aaron Giles
Released for general non-commercial use under the MAME license All rights reserved.
Visit http://mamedev.org for licensing and usage restrictions.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/ ***************************************************************************/
@ -17,93 +44,98 @@
/*************************************************************************** //**************************************************************************
MACROS // MACROS
***************************************************************************/ //**************************************************************************
/* ensure that a given pointer is within the cache boundaries */ // ensure that a given pointer is within the cache boundaries
#define assert_in_cache(c,p) assert(drccache_contains_pointer(c, p)) #define assert_in_cache(c,p) assert((c)->contains_pointer(p))
#define assert_in_near_cache(c,p) assert(drccache_contains_near_pointer(c, p)) #define assert_in_near_cache(c,p) assert((c)->contains_near_pointer(p))
/*************************************************************************** //**************************************************************************
TYPE DEFINITIONS // TYPE DEFINITIONS
***************************************************************************/ //**************************************************************************
/* generic code pointer */ // generic code pointer
typedef UINT8 *drccodeptr; typedef UINT8 *drccodeptr;
/* opaque cache state */ // drc_cache
typedef struct _drccache drccache; class drc_cache
{
public:
// out of band codegen callback
typedef void (*oob_func)(drccodeptr *codeptr, void *param1, void *param2, void *param3);
/* out of band codegen callback */ // construction/destruction
typedef void (*drccache_oob_func)(drccodeptr *codeptr, void *param1, void *param2, void *param3); drc_cache(size_t bytes);
~drc_cache();
// getters
drccodeptr near() const { return m_near; }
drccodeptr base() const { return m_base; }
drccodeptr top() const { return m_top; }
// pointer checking
bool contains_pointer(const void *ptr) const { return ((const drccodeptr)ptr >= m_near && (const drccodeptr)ptr < m_near + m_size); }
bool contains_near_pointer(const void *ptr) const { return ((const drccodeptr)ptr >= m_near && (const drccodeptr)ptr < m_neartop); }
// memory management
void flush();
void *alloc(size_t bytes);
void *alloc_near(size_t bytes);
void *alloc_temporary(size_t bytes);
void dealloc(void *memory, size_t bytes);
// codegen helpers
drccodeptr *begin_codegen(UINT32 reserve_bytes);
drccodeptr end_codegen();
void request_oob_codegen(oob_func callback, void *param1 = NULL, void *param2 = NULL, void *param3 = NULL);
/*************************************************************************** private:
FUNCTION PROTOTYPES // largest block of code that can be generated at once
***************************************************************************/ static const size_t CODEGEN_MAX_BYTES = 65536;
/* ----- initialization/teardown ----- */ // minimum alignment, in bytes (must be power of 2)
static const size_t CACHE_ALIGNMENT = 8;
/* allocate the cache itself */ // largest permanent allocation we allow
drccache *drccache_alloc(size_t bytes); static const size_t MAX_PERMANENT_ALLOC = 1024;
/* free the cache */ // size of "near" area at the base of the cache
void drccache_free(drccache *cache); static const size_t NEAR_CACHE_SIZE = 65536;
// core parameters
drccodeptr m_near; // pointer to the near part of the cache
drccodeptr m_neartop; // top of the near part of the cache
drccodeptr m_base; // base pointer to the compiler cache
drccodeptr m_top; // current top of cache
drccodeptr m_end; // end of cache memory
drccodeptr m_codegen; // start of generated code
size_t m_size; // size of the cache in bytes
// oob management
struct oob_handler
{
oob_handler *next() const { return m_next; }
oob_handler * m_next; // next handler
oob_func m_callback; // callback function
void * m_param1; // 1st pointer parameter
void * m_param2; // 2nd pointer parameter
void * m_param3; // 3rd pointer parameter
};
simple_list<oob_handler> m_ooblist; // list of oob handlers
/* ----- cache information ----- */ // free lists
struct free_link
/* return true if a pointer is within the cache */ {
int drccache_contains_pointer(drccache *cache, const void *ptr); free_link * m_next; // pointer to the next guy
};
/* return true if a pointer is within the near area of the cache */ free_link * m_free[MAX_PERMANENT_ALLOC / CACHE_ALIGNMENT];
int drccache_contains_near_pointer(drccache *cache, const void *ptr); free_link * m_nearfree[MAX_PERMANENT_ALLOC / CACHE_ALIGNMENT];
};
/* return a pointer to the near part of the cache */
drccodeptr drccache_near(drccache *cache);
/* return a pointer to the base of the cache, which is where code generation starts */
drccodeptr drccache_base(drccache *cache);
/* return the current top of the cache, which is where the next code will be generated */
drccodeptr drccache_top(drccache *cache);
/* ----- memory management ----- */
/* flush the cache contents */
void drccache_flush(drccache *cache);
/* allocate permanent memory from the cache */
void *drccache_memory_alloc(drccache *cache, size_t bytes);
/* allocate permanent memory from the near portion of the cache */
void *drccache_memory_alloc_near(drccache *cache, size_t bytes);
/* release permanent memory allocated from the cache */
void drccache_memory_free(drccache *cache, void *memory, size_t bytes);
/* allocate temporary memory from the cache (released on a reset) */
void *drccache_memory_alloc_temporary(drccache *cache, size_t bytes);
/* ----- code generation ----- */
/* begin code generation */
drccodeptr *drccache_begin_codegen(drccache *cache, UINT32 reserve_bytes);
/* complete code generation */
drccodeptr drccache_end_codegen(drccache *cache);
/* request callback for out-of-band codegen */
void drccache_request_oob_codegen(drccache *cache, drccache_oob_func callback, void *param1, void *param2, void *param3);
#endif /* __DRCCACHE_H__ */ #endif /* __DRCCACHE_H__ */

View File

@ -136,7 +136,7 @@ struct _drcuml_symbol
struct _drcuml_state struct _drcuml_state
{ {
device_t * device; /* CPU device we are associated with */ device_t * device; /* CPU device we are associated with */
drccache * cache; /* pointer to the codegen cache */ drc_cache * cache; /* pointer to the codegen cache */
drcuml_block * blocklist; /* list of active blocks */ drcuml_block * blocklist; /* list of active blocks */
const drcbe_interface * beintf; /* backend interface pointer */ const drcbe_interface * beintf; /* backend interface pointer */
drcbe_state * bestate; /* pointer to the back-end state */ drcbe_state * bestate; /* pointer to the back-end state */
@ -538,13 +538,13 @@ INLINE void convert_to_mov_param(drcuml_instruction *inst, int pnum)
generator and initialize the back-end generator and initialize the back-end
-------------------------------------------------*/ -------------------------------------------------*/
drcuml_state *drcuml_alloc(device_t *device, drccache *cache, UINT32 flags, int modes, int addrbits, int ignorebits) drcuml_state *drcuml_alloc(device_t *device, drc_cache *cache, UINT32 flags, int modes, int addrbits, int ignorebits)
{ {
drcuml_state *drcuml; drcuml_state *drcuml;
int opnum; int opnum;
/* allocate state */ /* allocate state */
drcuml = (drcuml_state *)drccache_memory_alloc(cache, sizeof(*drcuml)); drcuml = (drcuml_state *)cache->alloc(sizeof(*drcuml));
if (drcuml == NULL) if (drcuml == NULL)
return NULL; return NULL;
memset(drcuml, 0, sizeof(*drcuml)); memset(drcuml, 0, sizeof(*drcuml));
@ -597,7 +597,7 @@ void drcuml_reset(drcuml_state *drcuml)
jmp_buf errorbuf; jmp_buf errorbuf;
/* flush the cache */ /* flush the cache */
drccache_flush(drcuml->cache); drcuml->cache->flush();
/* if we error here, we are screwed */ /* if we error here, we are screwed */
if (setjmp(errorbuf) != 0) if (setjmp(errorbuf) != 0)
@ -946,16 +946,16 @@ drcuml_codehandle *drcuml_handle_alloc(drcuml_state *drcuml, const char *name)
char *string; char *string;
/* allocate space for a copy of the string */ /* allocate space for a copy of the string */
string = (char *)drccache_memory_alloc(drcuml->cache, strlen(name) + 1); string = (char *)drcuml->cache->alloc(strlen(name) + 1);
if (string == NULL) if (string == NULL)
return NULL; return NULL;
strcpy(string, name); strcpy(string, name);
/* allocate a new handle info */ /* allocate a new handle info */
handle = (drcuml_codehandle *)drccache_memory_alloc_near(drcuml->cache, sizeof(*handle)); handle = (drcuml_codehandle *)drcuml->cache->alloc_near(sizeof(*handle));
if (handle == NULL) if (handle == NULL)
{ {
drccache_memory_free(drcuml->cache, string, strlen(name) + 1); drcuml->cache->dealloc(string, strlen(name) + 1);
return NULL; return NULL;
} }
memset(handle, 0, sizeof(*handle)); memset(handle, 0, sizeof(*handle));
@ -1113,7 +1113,7 @@ void drcuml_add_comment(drcuml_block *block, const char *format, ...)
va_end(va); va_end(va);
/* allocate space in the cache to hold the comment */ /* allocate space in the cache to hold the comment */
comment = (char *)drccache_memory_alloc_temporary(block->drcuml->cache, strlen(buffer) + 1); comment = (char *)block->drcuml->cache->alloc_temporary(strlen(buffer) + 1);
if (comment == NULL) if (comment == NULL)
return; return;
strcpy(comment, buffer); strcpy(comment, buffer);
@ -1263,8 +1263,8 @@ void drcuml_disasm(const drcuml_instruction *inst, char *buffer, drcuml_state *d
} }
/* cache memory */ /* cache memory */
else if (drcuml != NULL && drccache_contains_pointer(drcuml->cache, (void *)(FPTR)param->value)) else if (drcuml != NULL && drcuml->cache->contains_pointer((void *)(FPTR)param->value))
dest += sprintf(dest, "[+$%X]", (UINT32)(FPTR)((drccodeptr)(FPTR)param->value - drccache_near(drcuml->cache))); dest += sprintf(dest, "[+$%X]", (UINT32)(FPTR)((drccodeptr)(FPTR)param->value - drcuml->cache->near()));
/* general memory */ /* general memory */
else else
@ -2181,7 +2181,7 @@ static void bevalidate_execute(drcuml_state *drcuml, drcuml_codehandle **handles
int numparams; int numparams;
/* allocate memory for parameters */ /* allocate memory for parameters */
parammem = (UINT64 *)drccache_memory_alloc_near(drcuml->cache, sizeof(UINT64) * (ARRAY_LENGTH(test->param) + 1)); parammem = (UINT64 *)drcuml->cache->alloc_near(sizeof(UINT64) * (ARRAY_LENGTH(test->param) + 1));
/* flush the cache */ /* flush the cache */
drcuml_reset(drcuml); drcuml_reset(drcuml);
@ -2237,7 +2237,7 @@ static void bevalidate_execute(drcuml_state *drcuml, drcuml_codehandle **handles
bevalidate_verify_state(drcuml, &istate, &fstate, test, *(UINT32 *)&parammem[ARRAY_LENGTH(test->param)], params, &testinst, handles[1]->code, handles[2]->code, flagmask); bevalidate_verify_state(drcuml, &istate, &fstate, test, *(UINT32 *)&parammem[ARRAY_LENGTH(test->param)], params, &testinst, handles[1]->code, handles[2]->code, flagmask);
/* free memory */ /* free memory */
drccache_memory_free(drcuml->cache, parammem, sizeof(UINT64) * (ARRAY_LENGTH(test->param) + 1)); drcuml->cache->dealloc(parammem, sizeof(UINT64) * (ARRAY_LENGTH(test->param) + 1));
} }

View File

@ -417,7 +417,7 @@ struct _drcbe_info
/* typedefs for back-end callback functions */ /* typedefs for back-end callback functions */
typedef drcbe_state *(*drcbe_alloc_func)(drcuml_state *drcuml, drccache *cache, device_t *device, UINT32 flags, int modes, int addrbits, int ignorebits); typedef drcbe_state *(*drcbe_alloc_func)(drcuml_state *drcuml, drc_cache *cache, device_t *device, UINT32 flags, int modes, int addrbits, int ignorebits);
typedef void (*drcbe_free_func)(drcbe_state *state); typedef void (*drcbe_free_func)(drcbe_state *state);
typedef void (*drcbe_reset_func)(drcbe_state *state); typedef void (*drcbe_reset_func)(drcbe_state *state);
typedef int (*drcbe_execute_func)(drcbe_state *state, drcuml_codehandle *entry); typedef int (*drcbe_execute_func)(drcbe_state *state, drcuml_codehandle *entry);
@ -448,7 +448,7 @@ struct _drcbe_interface
/* ----- initialization/teardown ----- */ /* ----- initialization/teardown ----- */
/* allocate state for the code generator and initialize the back-end */ /* allocate state for the code generator and initialize the back-end */
drcuml_state *drcuml_alloc(device_t *device, drccache *cache, UINT32 flags, int modes, int addrbits, int ignorebits); drcuml_state *drcuml_alloc(device_t *device, drc_cache *cache, UINT32 flags, int modes, int addrbits, int ignorebits);
/* return information about the back-end */ /* return information about the back-end */
void drcuml_get_backend_info(drcuml_state *drcuml, drcbe_info *info); void drcuml_get_backend_info(drcuml_state *drcuml, drcbe_info *info);

View File

@ -184,7 +184,7 @@ struct _compiler_state
struct _mips3imp_state struct _mips3imp_state
{ {
/* core state */ /* core state */
drccache * cache; /* pointer to the DRC code cache */ drc_cache * cache; /* pointer to the DRC code cache */
drcuml_state * drcuml; /* DRC UML generator state */ drcuml_state * drcuml; /* DRC UML generator state */
mips3_frontend * drcfe; /* pointer to the DRC front-end state */ mips3_frontend * drcfe; /* pointer to the DRC front-end state */
UINT32 drcoptions; /* configurable DRC options */ UINT32 drcoptions; /* configurable DRC options */
@ -388,25 +388,25 @@ INLINE void save_fast_iregs(mips3_state *mips3, drcuml_block *block)
static void mips3_init(mips3_flavor flavor, int bigendian, legacy_cpu_device *device, device_irq_callback irqcallback) static void mips3_init(mips3_flavor flavor, int bigendian, legacy_cpu_device *device, device_irq_callback irqcallback)
{ {
mips3_state *mips3; mips3_state *mips3;
drccache *cache; drc_cache *cache;
drcbe_info beinfo; drcbe_info beinfo;
UINT32 flags = 0; UINT32 flags = 0;
int regnum; int regnum;
/* allocate enough space for the cache and the core */ /* allocate enough space for the cache and the core */
cache = (drccache *)drccache_alloc(CACHE_SIZE + sizeof(*mips3)); cache = auto_alloc(device->machine, drc_cache(CACHE_SIZE + sizeof(*mips3)));
if (cache == NULL) if (cache == NULL)
fatalerror("Unable to allocate cache of size %d", (UINT32)(CACHE_SIZE + sizeof(*mips3))); fatalerror("Unable to allocate cache of size %d", (UINT32)(CACHE_SIZE + sizeof(*mips3)));
/* allocate the core memory */ /* allocate the core memory */
*(mips3_state **)device->token() = mips3 = (mips3_state *)drccache_memory_alloc_near(cache, sizeof(*mips3)); *(mips3_state **)device->token() = mips3 = (mips3_state *)cache->alloc_near(sizeof(*mips3));
memset(mips3, 0, sizeof(*mips3)); memset(mips3, 0, sizeof(*mips3));
/* initialize the core */ /* initialize the core */
mips3com_init(mips3, flavor, bigendian, device, irqcallback); mips3com_init(mips3, flavor, bigendian, device, irqcallback);
/* allocate the implementation-specific state from the full cache */ /* allocate the implementation-specific state from the full cache */
mips3->impstate = (mips3imp_state *)drccache_memory_alloc_near(cache, sizeof(*mips3->impstate)); mips3->impstate = (mips3imp_state *)cache->alloc_near(sizeof(*mips3->impstate));
memset(mips3->impstate, 0, sizeof(*mips3->impstate)); memset(mips3->impstate, 0, sizeof(*mips3->impstate));
mips3->impstate->cache = cache; mips3->impstate->cache = cache;
@ -566,7 +566,7 @@ static CPU_EXIT( mips3 )
/* clean up the DRC */ /* clean up the DRC */
auto_free(device->machine, mips3->impstate->drcfe); auto_free(device->machine, mips3->impstate->drcfe);
drcuml_free(mips3->impstate->drcuml); drcuml_free(mips3->impstate->drcuml);
drccache_free(mips3->impstate->cache); auto_free(device->machine, mips3->impstate->cache);
} }

View File

@ -163,7 +163,7 @@ struct _compiler_state
struct _ppcimp_state struct _ppcimp_state
{ {
/* core state */ /* core state */
drccache * cache; /* pointer to the DRC code cache */ drc_cache * cache; /* pointer to the DRC code cache */
drcuml_state * drcuml; /* DRC UML generator state */ drcuml_state * drcuml; /* DRC UML generator state */
ppc_frontend * drcfe; /* pointer to the DRC front-end state */ ppc_frontend * drcfe; /* pointer to the DRC front-end state */
UINT32 drcoptions; /* configurable DRC options */ UINT32 drcoptions; /* configurable DRC options */
@ -551,23 +551,21 @@ static void ppcdrc_init(powerpc_flavor flavor, UINT8 cap, int tb_divisor, legacy
powerpc_state *ppc; powerpc_state *ppc;
drcbe_info beinfo; drcbe_info beinfo;
UINT32 flags = 0; UINT32 flags = 0;
drccache *cache; drc_cache *cache;
int regnum; int regnum;
/* allocate enough space for the cache and the core */ /* allocate enough space for the cache and the core */
cache = drccache_alloc(CACHE_SIZE + sizeof(*ppc)); cache = auto_alloc(device->machine, drc_cache(CACHE_SIZE + sizeof(*ppc)));
if (cache == NULL)
fatalerror("Unable to allocate cache of size %d", (UINT32)(CACHE_SIZE + sizeof(*ppc)));
/* allocate the core from the near cache */ /* allocate the core from the near cache */
*(powerpc_state **)device->token() = ppc = (powerpc_state *)drccache_memory_alloc_near(cache, sizeof(*ppc)); *(powerpc_state **)device->token() = ppc = (powerpc_state *)cache->alloc_near(sizeof(*ppc));
memset(ppc, 0, sizeof(*ppc)); memset(ppc, 0, sizeof(*ppc));
/* initialize the core */ /* initialize the core */
ppccom_init(ppc, flavor, cap, tb_divisor, device, irqcallback); ppccom_init(ppc, flavor, cap, tb_divisor, device, irqcallback);
/* allocate the implementation-specific state from the full cache */ /* allocate the implementation-specific state from the full cache */
ppc->impstate = (ppcimp_state *)drccache_memory_alloc_near(cache, sizeof(*ppc->impstate)); ppc->impstate = (ppcimp_state *)cache->alloc_near(sizeof(*ppc->impstate));
memset(ppc->impstate, 0, sizeof(*ppc->impstate)); memset(ppc->impstate, 0, sizeof(*ppc->impstate));
ppc->impstate->cache = cache; ppc->impstate->cache = cache;
@ -731,7 +729,7 @@ static CPU_EXIT( ppcdrc )
/* clean up the DRC */ /* clean up the DRC */
auto_free(device->machine, ppc->impstate->drcfe); auto_free(device->machine, ppc->impstate->drcfe);
drcuml_free(ppc->impstate->drcuml); drcuml_free(ppc->impstate->drcuml);
drccache_free(ppc->impstate->cache); auto_free(device->machine, ppc->impstate->cache);
} }

View File

@ -104,7 +104,7 @@ struct _compiler_state
struct _rspimp_state struct _rspimp_state
{ {
/* core state */ /* core state */
drccache * cache; /* pointer to the DRC code cache */ drc_cache * cache; /* pointer to the DRC code cache */
drcuml_state * drcuml; /* DRC UML generator state */ drcuml_state * drcuml; /* DRC UML generator state */
rsp_frontend * drcfe; /* pointer to the DRC front-end state */ rsp_frontend * drcfe; /* pointer to the DRC front-end state */
UINT32 drcoptions; /* configurable DRC options */ UINT32 drcoptions; /* configurable DRC options */
@ -604,26 +604,22 @@ static void rspcom_init(rsp_state *rsp, legacy_cpu_device *device, device_irq_ca
static CPU_INIT( rsp ) static CPU_INIT( rsp )
{ {
rsp_state *rsp; rsp_state *rsp;
drccache *cache; drc_cache *cache;
UINT32 flags = 0; UINT32 flags = 0;
int regnum; int regnum;
//int elnum; //int elnum;
/* allocate enough space for the cache and the core */ /* allocate enough space for the cache and the core */
cache = (drccache *)drccache_alloc(CACHE_SIZE + sizeof(*rsp)); cache = auto_alloc(device->machine, drc_cache(CACHE_SIZE + sizeof(*rsp)));
if (cache == NULL)
{
fatalerror("Unable to allocate cache of size %d", (UINT32)(CACHE_SIZE + sizeof(*rsp)));
}
/* allocate the core memory */ /* allocate the core memory */
*(rsp_state **)device->token() = rsp = (rsp_state *)drccache_memory_alloc_near(cache, sizeof(*rsp)); *(rsp_state **)device->token() = rsp = (rsp_state *)cache->alloc_near(sizeof(*rsp));
memset(rsp, 0, sizeof(*rsp)); memset(rsp, 0, sizeof(*rsp));
rspcom_init(rsp, device, irqcallback); rspcom_init(rsp, device, irqcallback);
/* allocate the implementation-specific state from the full cache */ /* allocate the implementation-specific state from the full cache */
rsp->impstate = (rspimp_state *)drccache_memory_alloc_near(cache, sizeof(*rsp->impstate)); rsp->impstate = (rspimp_state *)cache->alloc_near(sizeof(*rsp->impstate));
memset(rsp->impstate, 0, sizeof(*rsp->impstate)); memset(rsp->impstate, 0, sizeof(*rsp->impstate));
rsp->impstate->cache = cache; rsp->impstate->cache = cache;
@ -712,7 +708,7 @@ static CPU_EXIT( rsp )
/* clean up the DRC */ /* clean up the DRC */
auto_free(device->machine, rsp->impstate->drcfe); auto_free(device->machine, rsp->impstate->drcfe);
drcuml_free(rsp->impstate->drcuml); drcuml_free(rsp->impstate->drcuml);
drccache_free(rsp->impstate->cache); auto_free(device->machine, rsp->impstate->cache);
} }

View File

@ -154,7 +154,7 @@ typedef struct
void (*ftcsr_read_callback)(UINT32 data); void (*ftcsr_read_callback)(UINT32 data);
#ifdef USE_SH2DRC #ifdef USE_SH2DRC
drccache * cache; /* pointer to the DRC code cache */ drc_cache * cache; /* pointer to the DRC code cache */
drcuml_state * drcuml; /* DRC UML generator state */ drcuml_state * drcuml; /* DRC UML generator state */
sh2_frontend * drcfe; /* pointer to the DRC front-end state */ sh2_frontend * drcfe; /* pointer to the DRC front-end state */
UINT32 drcoptions; /* configurable DRC options */ UINT32 drcoptions; /* configurable DRC options */

View File

@ -675,18 +675,16 @@ static void cfunc_SUBV(void *param)
static CPU_INIT( sh2 ) static CPU_INIT( sh2 )
{ {
sh2_state *sh2 = get_safe_token(device); sh2_state *sh2 = get_safe_token(device);
drccache *cache; drc_cache *cache;
drcbe_info beinfo; drcbe_info beinfo;
UINT32 flags = 0; UINT32 flags = 0;
int regnum; int regnum;
/* allocate enough space for the cache and the core */ /* allocate enough space for the cache and the core */
cache = drccache_alloc(CACHE_SIZE + sizeof(sh2_state)); cache = auto_alloc(device->machine, drc_cache(CACHE_SIZE + sizeof(sh2_state)));
if (cache == NULL)
fatalerror("Unable to allocate cache of size %d", (UINT32)(CACHE_SIZE + sizeof(sh2_state)));
/* allocate the core memory */ /* allocate the core memory */
*(sh2_state **)device->token() = sh2 = (sh2_state *)drccache_memory_alloc_near(cache, sizeof(sh2_state)); *(sh2_state **)device->token() = sh2 = (sh2_state *)cache->alloc_near(sizeof(sh2_state));
memset(sh2, 0, sizeof(sh2_state)); memset(sh2, 0, sizeof(sh2_state));
/* initialize the common core parts */ /* initialize the common core parts */
@ -772,7 +770,7 @@ static CPU_EXIT( sh2 )
/* clean up the DRC */ /* clean up the DRC */
auto_free(device->machine, sh2->drcfe); auto_free(device->machine, sh2->drcfe);
drcuml_free(sh2->drcuml); drcuml_free(sh2->drcuml);
drccache_free(sh2->cache); auto_free(device->machine, sh2->cache);
} }