--- upstream/dynamips-0.2.7-RC1/insn_lookup.c 2007/10/06 16:23:47 7 +++ upstream/dynamips-0.2.7-RC2/insn_lookup.c 2007/10/06 16:24:54 8 @@ -17,6 +17,7 @@ #include "utils.h" #include "hash.h" #include "insn_lookup.h" +#include "dynamips.h" /* Hash function for a CBM */ static inline u_int cbm_hash_f(void *ccbm) @@ -313,12 +314,169 @@ ilt_postprocessing(ilt); } +/* Dump an instruction lookup table */ +static void ilt_dump(insn_lookup_t *ilt) +{ + rfc_array_t *rfct; + int i,j; + + printf("ILT %p: nr_insn=%d, cbm_size=%d\n",ilt,ilt->nr_insn,ilt->cbm_size); + + for(i=0;irfct[i]; + + for(j=0;jnr_elements;j++) + printf(" (0x%4.4x,0x%4.4x) = 0x%4.4x\n",i,j,rfct->eqID[j]); + } +} + +/* Write the specified RFC array to disk */ +static void ilt_store_rfct(FILE *fd,int id,rfc_array_t *rfct) +{ + /* Store RFC array ID + number of elements */ + fwrite(&id,sizeof(id),1,fd); + fwrite(&rfct->nr_elements,sizeof(rfct->nr_elements),1,fd); + fwrite(&rfct->nr_eqid,sizeof(rfct->nr_eqid),1,fd); + + fwrite(rfct->eqID,rfct->nr_elements,sizeof(int),fd); +} + +/* Write the full instruction lookup table */ +static void ilt_store_table(FILE *fd,insn_lookup_t *ilt) +{ + int i; + + for(i=0;irfct[i] != NULL) + ilt_store_rfct(fd,i,ilt->rfct[i]); +} + +/* Load an RFC array from disk */ +static int ilt_load_rfct(FILE *fd,insn_lookup_t *ilt) +{ + u_int id,nr_elements,nr_eqid; + rfc_array_t *rfct; + size_t len; + + /* Read ID and number of elements */ + if ((fread(&id,sizeof(id),1,fd) != 1) || + (fread(&nr_elements,sizeof(nr_elements),1,fd) != 1) || + (fread(&nr_eqid,sizeof(nr_eqid),1,fd) != 1)) + return(-1); + + if ((id >= RFC_ARRAY_NUMBER) || (nr_elements > RFC_ARRAY_MAXSIZE)) + return(-1); + + /* Allocate the RFC array with the eqID table */ + len = sizeof(*rfct) + (nr_elements * sizeof(int)); + + if (!(rfct = malloc(len))) + return(-1); + + memset(rfct,0,sizeof(*rfct)); + rfct->nr_elements = nr_elements; + rfct->nr_eqid = nr_eqid; + + /* Read the equivalent ID array */ + fread(rfct->eqID,rfct->nr_elements,sizeof(int),fd); + + ilt->rfct[id] = rfct; + return(0); +} + +/* Check an instruction table loaded from disk */ +static int ilt_check_cached_table(insn_lookup_t *ilt) +{ + int i; + + /* All arrays must have been loaded */ + for(i=0;irfct[i]) + return(-1); + + return(0); +} + +/* Load a full instruction table from disk */ +static insn_lookup_t *ilt_load_table(FILE *fd) +{ + insn_lookup_t *ilt; + + if (!(ilt = malloc(sizeof(*ilt)))) + return NULL; + + memset(ilt,0,sizeof(*ilt)); + + while(!feof(fd)) { + if (ilt_load_rfct(fd,ilt) == -1) + break; + } + + if (ilt_check_cached_table(ilt) == -1) + return NULL; + + return ilt; +} + +/* Build a filename for a cached ILT table on disk */ +static char *ilt_build_filename(char *table_name) +{ + return(dyn_sprintf("ilt_%s_%s",sw_version_tag,table_name)); +} + +/* Try to load a cached ILT table from disk */ +static insn_lookup_t *ilt_cache_load(char *table_name) +{ + insn_lookup_t *ilt; + char *filename; + FILE *fd; + + if (!(filename = ilt_build_filename(table_name))) + return NULL; + + if (!(fd = fopen(filename,"r"))) { + free(filename); + return NULL; + } + + ilt = ilt_load_table(fd); + fclose(fd); + return ilt; +} + +/* Store the specified ILT table on disk for future use (cache) */ +static int ilt_cache_store(char *table_name,insn_lookup_t *ilt) +{ + char *filename; + FILE *fd; + + if (!(filename = ilt_build_filename(table_name))) + return(-1); + + if (!(fd = fopen(filename,"w"))) { + free(filename); + return(-1); + } + + ilt_store_table(fd,ilt); + fclose(fd); + return(0); +} + /* Create an instruction lookup table */ -insn_lookup_t *ilt_create(int nr_insn,ilt_get_insn_cbk_t get_insn, +insn_lookup_t *ilt_create(char *table_name, + int nr_insn,ilt_get_insn_cbk_t get_insn, ilt_check_cbk_t chk_lo,ilt_check_cbk_t chk_hi) { insn_lookup_t *ilt; + /* Try to load a cached table from disk */ + if ((ilt = ilt_cache_load(table_name))) { + printf("ILT: loaded table \"%s\" from cache.\n",table_name); + return ilt; + } + + /* We have to build the full table... */ ilt = malloc(sizeof(*ilt)); assert(ilt); memset(ilt,0,sizeof(*ilt)); @@ -329,6 +487,10 @@ ilt->chk_lo = chk_lo; ilt->chk_hi = chk_hi; + /* Compile the instruction opcodes */ ilt_compile(ilt); + + /* Store the result on disk for future exec */ + ilt_cache_store(table_name,ilt); return(ilt); }