* Personal prototype "gx" translation-based JIT engine for M32R.
[ChangeLog] start-sanitize-gxsim 1998-11-13 Frank Ch. Eigler <fche@elastic.org> * configure.in: Added "--enable-sim-gx" option. * configure: Regenerated. end-sanitize-gxsim [common/ChangeLog] 1998-11-13 Frank Ch. Eigler <fche@elastic.org> start-sanitize-gxsim * Make-common.im: Build sim-gx.o and sim-gx-run.o. * sim-gx.c: New file: target-independent gx routines. * sim-gx.h: Declarations for gx structs and routines. * sim-gx-run.c: New file: target-independent gx driver. * sim-base.h: Add gx block vector to state struct. end-sanitize-gxsim * aclocal.m4: Add tests for dlopen family.
This commit is contained in:
parent
fca5abc13a
commit
92fa45795d
23 changed files with 11603 additions and 0 deletions
|
@ -22,6 +22,13 @@ else
|
|||
lose_these_too="${tic80_files} ${lose_these_too}"
|
||||
fi
|
||||
|
||||
gxsim_files="m32r-gx"
|
||||
if ( echo $* | grep keep\-gxsim > /dev/null ) ; then
|
||||
keep_these_too="${gxsim_files} ${keep_these_too}"
|
||||
else
|
||||
lose_these_too="${gxsim_files} ${lose_these_too}"
|
||||
fi
|
||||
|
||||
lose_these_too="${lose_these_too}"
|
||||
|
||||
# All files listed between the "Things-to-keep:" line and the
|
||||
|
@ -90,6 +97,34 @@ else
|
|||
done
|
||||
fi
|
||||
|
||||
gxsim_files="configure configure.in ChangeLog"
|
||||
if ( echo $* | grep keep\-gxsim > /dev/null ) ; then
|
||||
for i in $gxsim_files ; do
|
||||
if test ! -d $i && (grep sanitize-gxsim $i > /dev/null) ; then
|
||||
if [ -n "${verbose}" ] ; then
|
||||
echo Keeping gxsim stuff in $i
|
||||
fi
|
||||
fi
|
||||
done
|
||||
else
|
||||
for i in $gxsim_files ; do
|
||||
if test ! -d $i && (grep sanitize-gxsim $i > /dev/null) ; then
|
||||
if [ -n "${verbose}" ] ; then
|
||||
echo Removing traces of \"gxsim\" from $i...
|
||||
fi
|
||||
cp $i new
|
||||
sed '/start\-sanitize\-gxsim/,/end-\sanitize\-gxsim/d' < $i > new
|
||||
if [ -n "${safe}" -a ! -f .Recover/$i ] ; then
|
||||
if [ -n "${verbose}" ] ; then
|
||||
echo Caching $i in .Recover...
|
||||
fi
|
||||
mv $i .Recover
|
||||
fi
|
||||
mv new $i
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
v850_files="configure configure.in ChangeLog"
|
||||
if ( echo $* | grep keep\-v850e > /dev/null ) ; then
|
||||
for i in $v850_files ; do
|
||||
|
|
|
@ -22,6 +22,13 @@ else
|
|||
lose_these_too="${cygnus_files} ${lose_these_too}"
|
||||
fi
|
||||
|
||||
gxsim_files="sim-gx-run.c sim-gx.c sim-gx.h"
|
||||
if ( echo $* | grep keep\-gxsim > /dev/null ) ; then
|
||||
keep_these_too="${gxsim_files} ${keep_these_too}"
|
||||
else
|
||||
lose_these_too="${gxsim_files} ${lose_these_too}"
|
||||
fi
|
||||
|
||||
# All files listed between the "Things-to-keep:" line and the
|
||||
# "Files-to-sed:" line will be kept. All other files will be removed.
|
||||
# Directories listed in this section will have their own Sanitize
|
||||
|
@ -179,4 +186,32 @@ else
|
|||
done
|
||||
fi
|
||||
|
||||
gxsim_files="ChangeLog Make-common.in sim-base.h"
|
||||
if ( echo $* | grep keep\-gxsim > /dev/null ) ; then
|
||||
for i in $gxsim_files ; do
|
||||
if test ! -d $i && (grep sanitize-gxsim $i > /dev/null) ; then
|
||||
if [ -n "${verbose}" ] ; then
|
||||
echo Keeping gxsim stuff in $i
|
||||
fi
|
||||
fi
|
||||
done
|
||||
else
|
||||
for i in $gxsim_files ; do
|
||||
if test ! -d $i && (grep sanitize-gxsim $i > /dev/null) ; then
|
||||
if [ -n "${verbose}" ] ; then
|
||||
echo Removing traces of \"gxsim\" from $i...
|
||||
fi
|
||||
cp $i new
|
||||
sed '/start\-sanitize\-gxsim/,/end-\sanitize\-gxsim/d' < $i > new
|
||||
if [ -n "${safe}" -a ! -f .Recover/$i ] ; then
|
||||
if [ -n "${verbose}" ] ; then
|
||||
echo Caching $i in .Recover...
|
||||
fi
|
||||
mv $i .Recover
|
||||
fi
|
||||
mv new $i
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# End of file.
|
||||
|
|
|
@ -1,3 +1,15 @@
|
|||
1998-11-13 Frank Ch. Eigler <fche@elastic.org>
|
||||
|
||||
start-sanitize-gxsim
|
||||
* Make-common.im: Build sim-gx.o and sim-gx-run.o.
|
||||
* sim-gx.c: New file: target-independent gx routines.
|
||||
* sim-gx.h: Declarations for gx structs and routines.
|
||||
* sim-gx-run.c: New file: target-independent gx driver.
|
||||
* sim-base.h: Add gx block vector to state struct.
|
||||
end-sanitize-gxsim
|
||||
* aclocal.m4: Add tests for dlopen family.
|
||||
* config.in: Regenerated.
|
||||
|
||||
Wed Nov 11 14:02:25 1998 Doug Evans <devans@canuck.cygnus.com>
|
||||
|
||||
* sim-hload.c (sim_load): Pass `prog_name' to sim_load_file, not NULL.
|
||||
|
|
|
@ -318,6 +318,9 @@ sim-n-core_h = $(srccom)/sim-n-core.h
|
|||
sim-engine_h = $(srccom)/sim-engine.h
|
||||
sim-events_h = $(srccom)/sim-events.h
|
||||
sim-fpu_h = $(srccom)/sim-fpu.h
|
||||
# start-sanitize-gxsim
|
||||
sim-gx_h = $(srccom)/sim-gx.h
|
||||
# end-sanitize-gxsim
|
||||
sim-io_h = $(srccom)/sim-io.h
|
||||
sim-options_h = $(srccom)/sim-options.h
|
||||
sim-break_h = $(srccom)/sim-break.h
|
||||
|
@ -383,6 +386,18 @@ sim-fpu.o: $(srccom)/sim-fpu.c $(sim-fpu_h) \
|
|||
$(SIM_EXTRA_DEPS)
|
||||
$(CC) -c $(srccom)/sim-fpu.c $(ALL_CFLAGS)
|
||||
|
||||
# start-sanitize-gxsim
|
||||
sim-gx.o: $(srccom)/sim-gx.c $(sim_main_headers) \
|
||||
$(sim-gx_h) \
|
||||
$(SIM_EXTRA_DEPS)
|
||||
$(CC) -c $(srccom)/sim-gx.c $(ALL_CFLAGS)
|
||||
|
||||
sim-gx-run.o: $(srccom)/sim-gx-run.c $(sim_main_headers) \
|
||||
$(sim-gx_h) \
|
||||
$(SIM_EXTRA_DEPS)
|
||||
$(CC) -c $(srccom)/sim-gx-run.c $(ALL_CFLAGS)
|
||||
# end-sanitize-gxsim
|
||||
|
||||
sim-hload.o: $(srccom)/sim-hload.c $(sim-assert_h) \
|
||||
$(srcroot)/include/remote-sim.h \
|
||||
$(SIM_EXTRA_DEPS)
|
||||
|
|
148
sim/common/sim-gx-run.c
Normal file
148
sim/common/sim-gx-run.c
Normal file
|
@ -0,0 +1,148 @@
|
|||
/* GX generic simulator run.
|
||||
Copyright (C) 1998 Cygnus Solutions.
|
||||
*/
|
||||
|
||||
#include "sim-main.h"
|
||||
#include "sim-assert.h"
|
||||
#include "sim-gx.h"
|
||||
|
||||
#ifdef HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* GX implementation of sim_engine_run that works within the
|
||||
sim_engine setjmp/longjmp framework. */
|
||||
|
||||
|
||||
void
|
||||
sim_engine_run (SIM_DESC sd,
|
||||
int next_cpu_nr,
|
||||
int nr_cpus, /* ignore */
|
||||
int siggnal) /* ignore */
|
||||
{
|
||||
sim_cpu* cpu;
|
||||
int cont = 1;
|
||||
int rc;
|
||||
|
||||
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
|
||||
cpu = STATE_CPU (sd, next_cpu_nr);
|
||||
|
||||
while(cont)
|
||||
{
|
||||
sim_gx_block* block;
|
||||
sim_gx_compiled_block* compiled_block;
|
||||
sim_gx_function f;
|
||||
sim_cia cia = CIA_GET(cpu);
|
||||
int optimized;
|
||||
int pre_checksum, post_checksum;
|
||||
|
||||
/* find optimized gx block that includes this PC */
|
||||
block = sim_gx_block_find(cia);
|
||||
if(block == NULL)
|
||||
{
|
||||
/* start new learning block */
|
||||
block = sim_gx_block_create(cia);
|
||||
}
|
||||
ASSERT(block != NULL);
|
||||
|
||||
/* pick preferred compiled block */
|
||||
if(block->optimized_block != NULL)
|
||||
{
|
||||
compiled_block = block->optimized_block;
|
||||
/* no stats */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* test for optimization policy */
|
||||
if(tgx_optimize_test(block))
|
||||
{
|
||||
block->opt_compile_count ++;
|
||||
sim_gx_block_translate(block, 1 /* optimized */);
|
||||
compiled_block = block->optimized_block;
|
||||
optimized = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
compiled_block = block->learning_block;
|
||||
optimized = 0;
|
||||
}
|
||||
}
|
||||
ASSERT(compiled_block != NULL);
|
||||
|
||||
/* load & resolve gx function */
|
||||
f = sim_gx_compiled_block_f(compiled_block);
|
||||
|
||||
/* XXX: debug
|
||||
printf("calling into gx function %p, pc=%08lx, opt %d\n",
|
||||
(void*) f, (unsigned long) cpu->regs.h_pc, optimized);
|
||||
*/
|
||||
|
||||
/* compute pc_flags checksum */
|
||||
if(! optimized)
|
||||
{
|
||||
int i;
|
||||
pre_checksum = 0;
|
||||
for(i=0; i < block->length / block->divisor; i++)
|
||||
pre_checksum += block->pc_flags[i];
|
||||
}
|
||||
|
||||
/* call into gx function */
|
||||
rc = (*f)(& cpu->regs, block->pc_flags, block->callbacks);
|
||||
|
||||
/* compute pc_flags checksum */
|
||||
if(! optimized)
|
||||
{
|
||||
int i;
|
||||
post_checksum = 0;
|
||||
for(i=0; i < block->length / block->divisor; i++)
|
||||
post_checksum += block->pc_flags[i];
|
||||
|
||||
if(post_checksum != pre_checksum) /* system changing */
|
||||
{
|
||||
block->learn_last_change = time(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: debug
|
||||
printf("returned from gx function %p, rc=%d, pc=%08lx\n",
|
||||
(void*) f, rc, (unsigned long) cpu->regs.h_pc);
|
||||
*/
|
||||
|
||||
switch(rc)
|
||||
{
|
||||
case GX_F_YIELD: /* gx block voluntarily gave up control */
|
||||
case GX_F_RANGE: /* PC travelled outside this block */
|
||||
; /* continue block dispatch loop */
|
||||
break;
|
||||
|
||||
case GX_F_NONPC: /* non-instruction PC in this block */
|
||||
if(compiled_block == block->optimized_block)
|
||||
{
|
||||
/* sim_io_printf(sd, "NOTE: cancelling premature optimization, GX block %p, PC %08lx\n",
|
||||
block, (long) cpu->regs.h_pc); */
|
||||
sim_gx_compiled_block_dispose(compiled_block);
|
||||
block->learn_last_change = time(NULL);
|
||||
block->optimized_block = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* learning-mode gx block should not fail this way */
|
||||
sim_io_error(sd, "Internal error - GX block cia %08lx NONPC\n", (long) cia);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_F_HALT: /* gx function returning control */
|
||||
cont = 0; /* merely exit loop */
|
||||
break;
|
||||
|
||||
/* should not happen */
|
||||
default:
|
||||
sim_io_error(sd, "Translation error (bad rc 0x%d in gx block)", rc);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
if(sim_events_tick(sd))
|
||||
sim_events_process(sd);
|
||||
}
|
||||
}
|
807
sim/common/sim-gx.c
Normal file
807
sim/common/sim-gx.c
Normal file
|
@ -0,0 +1,807 @@
|
|||
/* GX target-independent functions for block translation.
|
||||
Copyright (C) 1998 Cygnus Solutions. */
|
||||
|
||||
|
||||
#include "sim-main.h"
|
||||
#include "sim-assert.h"
|
||||
#include "sim-gx.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "cconfig.h"
|
||||
|
||||
/* shared object functions */
|
||||
#ifdef HAVE_DLFCN_H
|
||||
#include <dlfcn.h>
|
||||
#else
|
||||
#error "need dlfcn.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#else
|
||||
#error "need errno.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#ifdef HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include "bfd.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/* Load the object file with given gx block. Return pointer to GX
|
||||
function or NULL on failure. */
|
||||
|
||||
sim_gx_function
|
||||
sim_gx_compiled_block_f(sim_gx_compiled_block* gx)
|
||||
{
|
||||
sim_gx_function f = gx->function_dlhandle;
|
||||
SIM_DESC sd = current_state;
|
||||
int rc;
|
||||
|
||||
if(f == NULL)
|
||||
{
|
||||
/* compile object */
|
||||
if(gx->object_name == NULL && gx->source_name != NULL)
|
||||
{
|
||||
char compile_command[2000];
|
||||
|
||||
gx->object_name = strdup(gx->source_name);
|
||||
/* turn *.c into *.o */
|
||||
gx->object_name[strlen(gx->object_name)]='o';
|
||||
|
||||
/* compute command string to compile object */
|
||||
sprintf(compile_command,
|
||||
"make -f %s OBJ=%s SRC=%s gx",
|
||||
#define GX_MAKEFILE "--no-makefile-yet--"
|
||||
GX_MAKEFILE,
|
||||
gx->object_name,
|
||||
gx->source_name);
|
||||
|
||||
rc = system(compile_command);
|
||||
if(rc != 0)
|
||||
{
|
||||
sim_io_error(sd, "Compile error rc %d for GX source %s: %s",
|
||||
rc,
|
||||
gx->source_name,
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/* load object */
|
||||
if(gx->object_dlhandle == NULL && gx->object_name != NULL)
|
||||
{
|
||||
gx->object_dlhandle = dlopen(gx->object_name, RTLD_NOW);
|
||||
if(gx->object_dlhandle == NULL)
|
||||
{
|
||||
sim_io_error(sd, "Load error for GX object %s: %s",
|
||||
gx->object_name,
|
||||
dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
/* locate function */
|
||||
if(gx->function_dlhandle == NULL && gx->object_dlhandle != NULL && gx->symbol_name != NULL)
|
||||
{
|
||||
f = gx->function_dlhandle = dlsym(gx->object_dlhandle, gx->symbol_name);
|
||||
if(f == NULL)
|
||||
{
|
||||
sim_io_error(sd, "Resolve error for GX object %s symbol %s: %s",
|
||||
gx->object_name,
|
||||
gx->symbol_name,
|
||||
dlerror());
|
||||
}
|
||||
}
|
||||
} /* f == NULL */
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Forget about given GX block. Remove its source/object; unload it
|
||||
from memory. */
|
||||
void
|
||||
sim_gx_compiled_block_dispose(sim_gx_compiled_block* gx)
|
||||
{
|
||||
SIM_DESC sd = current_state;
|
||||
int rc;
|
||||
|
||||
/* forget dl information */
|
||||
gx->function_dlhandle = NULL;
|
||||
|
||||
/* unload shared library */
|
||||
if(gx->object_dlhandle != NULL)
|
||||
{
|
||||
rc = dlclose(gx->object_dlhandle);
|
||||
if(rc != 0)
|
||||
{
|
||||
sim_io_error(sd, "dlclose() error for GX object %s: %s",
|
||||
gx->object_name,
|
||||
dlerror());
|
||||
}
|
||||
gx->object_dlhandle = NULL;
|
||||
}
|
||||
|
||||
/* final gasps */
|
||||
zfree(gx->source_name);
|
||||
zfree(gx->object_name);
|
||||
zfree(gx->symbol_name);
|
||||
zfree(gx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Translate a piece of the code segment around given PC, in given mode. */
|
||||
sim_gx_block*
|
||||
sim_gx_block_create(sim_cia cia)
|
||||
{
|
||||
sim_gx_block* block;
|
||||
|
||||
/* allocate emtpy block */
|
||||
block = zalloc(sizeof(sim_gx_block));
|
||||
|
||||
/* initialize block bounds, callback struct etc. */
|
||||
tgx_block_ctor(block, cia);
|
||||
|
||||
/* create learning mode translation */
|
||||
sim_gx_block_translate(block, 0 /* learning mode */);
|
||||
|
||||
/* add block to block list */
|
||||
sim_gx_block_add(block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Write the current block list to the state file */
|
||||
void
|
||||
sim_gx_write_block_list()
|
||||
{
|
||||
int i;
|
||||
SIM_DESC sd = current_state;
|
||||
sim_gx_block_list* blocks = STATE_BLOCKS(sd);
|
||||
FILE* f;
|
||||
char state_file_name[PATH_MAX];
|
||||
char *exec_name;
|
||||
|
||||
/* get base of executable name */
|
||||
exec_name = bfd_get_filename(STATE_PROG_BFD(sd));
|
||||
if(strrchr(exec_name, '/') != NULL)
|
||||
exec_name = strrchr(exec_name, '/') + 1;
|
||||
|
||||
/* generate base name */
|
||||
sprintf(state_file_name, "%s/%s.gx",
|
||||
GX_DIR,
|
||||
exec_name);
|
||||
|
||||
f = fopen(state_file_name, "w");
|
||||
if(f == NULL)
|
||||
{
|
||||
sim_io_error(sd, "Error: cannot write to state file %s, errno %d",
|
||||
state_file_name, errno);
|
||||
}
|
||||
|
||||
fprintf(f, "# This file was automatically generated. Do not edit.\n");
|
||||
|
||||
/* write block descriptors into state file */
|
||||
for(i=0; i<blocks->gx_blocks_used; i++)
|
||||
{
|
||||
sim_gx_block* gx = blocks->gx_blocks[i];
|
||||
sim_gx_compiled_block* block;
|
||||
int j;
|
||||
int age;
|
||||
|
||||
age = time(NULL) - gx->learn_last_change; /* store interval */
|
||||
fprintf(f, "BLOCK 0x%lx 0x%lx %u %u\n", gx->origin, gx->length, gx->divisor, age);
|
||||
fprintf(f, "FLAGS ");
|
||||
for(j=0; j<GX_PC_FLAGS_INDEX(gx, gx->origin + gx->length); j++)
|
||||
{
|
||||
fprintf(f, "%2x ", gx->pc_flags[j]);
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
|
||||
/* write learning mode names */
|
||||
block = gx->learning_block;
|
||||
fprintf(f, "LEARNING %s %s %s %lu %u\n",
|
||||
block->source_name, block->object_name, block->symbol_name,
|
||||
gx->compile_time, gx->opt_compile_count);
|
||||
|
||||
/* write optimized mode names */
|
||||
block = gx->optimized_block;
|
||||
if(block)
|
||||
fprintf(f, "OPTIMIZED %s %s %s\n",
|
||||
block->source_name, block->object_name, block->symbol_name);
|
||||
|
||||
/* NB: other fields will be filled in with freshly guessed values */
|
||||
}
|
||||
|
||||
(void) fclose(f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
print_gx_blocks(sim_gx_block_list* blocks, char* where)
|
||||
{
|
||||
printf("print_gx_blocks: %s\n", where);
|
||||
|
||||
if(blocks == NULL)
|
||||
printf("(null)\n");
|
||||
else
|
||||
{
|
||||
int i;
|
||||
printf("size: %d, used: %d\n",
|
||||
blocks->gx_blocks_size, blocks->gx_blocks_used);
|
||||
|
||||
/* linear search */
|
||||
for(i=0; i<blocks->gx_blocks_used; i++)
|
||||
{
|
||||
sim_gx_block* gx = blocks->gx_blocks[i];
|
||||
printf("block %d: %p\n", i, (void*) gx);
|
||||
if(gx == NULL)
|
||||
printf("** NULL!\n");
|
||||
else
|
||||
printf(" begin 0x%08x length 0x%08x [opt %d%s]\n",
|
||||
(unsigned)gx->origin, (unsigned)gx->length,
|
||||
gx->opt_compile_count,
|
||||
(gx->optimized_block ? " loaded" : " discarded"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Read the current block list from the cache */
|
||||
void
|
||||
sim_gx_read_block_list()
|
||||
{
|
||||
SIM_DESC sd = current_state;
|
||||
FILE* f;
|
||||
char state_file_name[PATH_MAX];
|
||||
char *exec_name;
|
||||
|
||||
/* check for block */
|
||||
if(STATE_PROG_BFD(sd) == NULL)
|
||||
return;
|
||||
|
||||
/* get base of executable name */
|
||||
exec_name = bfd_get_filename(STATE_PROG_BFD(sd));
|
||||
if(strrchr(exec_name, '/') != NULL)
|
||||
exec_name = strrchr(exec_name, '/') + 1;
|
||||
|
||||
/* generate base name */
|
||||
sprintf(state_file_name, "%s/%s.gx",
|
||||
GX_DIR,
|
||||
exec_name);
|
||||
|
||||
f = fopen(state_file_name, "r");
|
||||
if(f == NULL)
|
||||
{
|
||||
/* XXX: print warning */
|
||||
return;
|
||||
}
|
||||
|
||||
fscanf(f, "#%*[^\n]\n"); /* swallow # comment line */
|
||||
|
||||
while(1)
|
||||
{
|
||||
unsigned_4 origin, length;
|
||||
unsigned divisor;
|
||||
sim_gx_block* gx;
|
||||
int rc;
|
||||
sim_gx_compiled_block* block;
|
||||
unsigned age;
|
||||
int j;
|
||||
|
||||
rc = fscanf(f, "BLOCK 0x%0lx 0x%lx %u %u\n", & origin, & length, & divisor, & age);
|
||||
if(rc != 4) /* not all fields matched - assume EOF */
|
||||
break;
|
||||
|
||||
gx = zalloc(sizeof(sim_gx_block));
|
||||
|
||||
/* initialize block bounds, callback struct etc. */
|
||||
tgx_block_ctor2(gx, origin, length, divisor);
|
||||
|
||||
/* read flags */
|
||||
fscanf(f, "FLAGS");
|
||||
for(j=0; j<GX_PC_FLAGS_INDEX(gx, gx->origin + gx->length); j++)
|
||||
{
|
||||
unsigned value;
|
||||
fscanf(f, "%2x ", & value);
|
||||
gx->pc_flags[j] = (unsigned_1) value;
|
||||
}
|
||||
fscanf(f, "\n");
|
||||
|
||||
/* read learning mode info */
|
||||
block = zalloc(sizeof(sim_gx_compiled_block));
|
||||
gx->learning_block = block;
|
||||
block->source_name = zalloc(PATH_MAX);
|
||||
block->object_name = zalloc(PATH_MAX);
|
||||
block->symbol_name = zalloc(PATH_MAX);
|
||||
fscanf(f, "LEARNING %s %s %s %lu %u\n",
|
||||
block->source_name, block->object_name, block->symbol_name,
|
||||
& gx->compile_time, & gx->opt_compile_count);
|
||||
|
||||
/* read optimized mode info */
|
||||
block = zalloc(sizeof(sim_gx_compiled_block));
|
||||
gx->optimized_block = block;
|
||||
block->source_name = zalloc(PATH_MAX);
|
||||
block->object_name = zalloc(PATH_MAX);
|
||||
block->symbol_name = zalloc(PATH_MAX);
|
||||
rc = fscanf(f, "OPTIMIZED %s %s %s\n",
|
||||
block->source_name, block->object_name, block->symbol_name);
|
||||
if(rc != 3)
|
||||
{
|
||||
/* oops, not an optimized block */
|
||||
zfree(block->source_name);
|
||||
zfree(block->object_name);
|
||||
zfree(block->symbol_name);
|
||||
zfree(block);
|
||||
gx->optimized_block = NULL;
|
||||
}
|
||||
|
||||
/* fill in remaining fields */
|
||||
gx->learn_last_change = time(NULL) - age; /* make absolute */
|
||||
|
||||
/* store it away */
|
||||
sim_gx_block_add(gx);
|
||||
}
|
||||
|
||||
print_gx_blocks(STATE_BLOCKS(sd), "after restoring state");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Add a gx block to list */
|
||||
void
|
||||
sim_gx_block_add(sim_gx_block* block)
|
||||
{
|
||||
SIM_DESC sd = current_state;
|
||||
sim_gx_block_list* blocks = STATE_BLOCKS(sd);
|
||||
int i;
|
||||
|
||||
/* print_gx_blocks(blocks, "pre add"); */
|
||||
|
||||
if(blocks == NULL)
|
||||
blocks = STATE_BLOCKS(sd) = zalloc(sizeof(sim_gx_block_list));
|
||||
|
||||
/* need to enlarge block vector? */
|
||||
if(blocks->gx_blocks_used == blocks->gx_blocks_size)
|
||||
{
|
||||
sim_gx_block** new_blocks;
|
||||
int j;
|
||||
|
||||
blocks->gx_blocks_size += 20;
|
||||
new_blocks = zalloc(blocks->gx_blocks_size * sizeof(sim_gx_block*));
|
||||
for(j=0; j<blocks->gx_blocks_used; j++)
|
||||
new_blocks[j] = blocks->gx_blocks[j];
|
||||
if(blocks->gx_blocks) zfree(blocks->gx_blocks);
|
||||
blocks->gx_blocks = new_blocks;
|
||||
}
|
||||
|
||||
/* insert new block */
|
||||
for(i=0; i<blocks->gx_blocks_used; i++)
|
||||
{
|
||||
ASSERT(blocks->gx_blocks[i] != NULL);
|
||||
|
||||
/* insertion point reached? */
|
||||
if(blocks->gx_blocks[i]->origin > block->origin)
|
||||
{
|
||||
int j;
|
||||
for(j=blocks->gx_blocks_used; j>=i; j--)
|
||||
blocks->gx_blocks[j] = blocks->gx_blocks[j-1];
|
||||
blocks->gx_blocks[i] = block;
|
||||
blocks->gx_blocks_used ++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* end of block vector */
|
||||
if(i == blocks->gx_blocks_used)
|
||||
{
|
||||
blocks->gx_blocks[blocks->gx_blocks_used ++] = block;
|
||||
}
|
||||
|
||||
/* print_gx_blocks(blocks, "post add"); */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Remove a gx block from list */
|
||||
void
|
||||
sim_gx_block_remove(sim_gx_block* block)
|
||||
{
|
||||
SIM_DESC sd = current_state;
|
||||
sim_gx_block_list* blocks = STATE_BLOCKS(sd);
|
||||
int i;
|
||||
|
||||
/* print_gx_blocks(blocks, "pre remove"); */
|
||||
|
||||
/* linear search */
|
||||
for(i=0; i<blocks->gx_blocks_used; i++)
|
||||
{
|
||||
if(blocks->gx_blocks[i] == block)
|
||||
{
|
||||
/* found it */
|
||||
while(i < blocks->gx_blocks_used - 1)
|
||||
{
|
||||
blocks->gx_blocks[i] = blocks->gx_blocks[i+1];
|
||||
i++;
|
||||
}
|
||||
blocks->gx_blocks_used --;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* print_gx_blocks(blocks, "post remove"); */
|
||||
}
|
||||
|
||||
|
||||
/* Find a gx block from list */
|
||||
sim_gx_block*
|
||||
sim_gx_block_find(sim_cia cia)
|
||||
{
|
||||
SIM_DESC sd = current_state;
|
||||
sim_gx_block_list* blocks = STATE_BLOCKS(sd);
|
||||
int i;
|
||||
|
||||
if(blocks == NULL) return NULL;
|
||||
|
||||
/* print_gx_blocks(blocks, "pre find"); */
|
||||
|
||||
/* linear search */
|
||||
for(i=0; i<blocks->gx_blocks_used; i++)
|
||||
{
|
||||
sim_gx_block* gx = blocks->gx_blocks[i];
|
||||
ASSERT(gx != NULL);
|
||||
|
||||
if(GX_PC_INCLUDES(gx,cia))
|
||||
{
|
||||
return gx;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* generate */
|
||||
void
|
||||
sim_gx_block_translate(sim_gx_block* gx, int optimized)
|
||||
{
|
||||
char pwd_name[PATH_MAX];
|
||||
char dir_name[PATH_MAX];
|
||||
char base_name[PATH_MAX];
|
||||
char compile_command[PATH_MAX*4];
|
||||
char* exec_name;
|
||||
SIM_DESC sd = current_state;
|
||||
int rc;
|
||||
sim_cia gx_cia;
|
||||
sim_gx_compiled_block* block = zalloc(sizeof(sim_gx_compiled_block));
|
||||
unsigned time_begin, time_end;
|
||||
|
||||
time_begin = time(NULL);
|
||||
|
||||
if(optimized) gx->optimized_block = block;
|
||||
else gx->learning_block = block;
|
||||
|
||||
/* get base of executable name */
|
||||
exec_name = bfd_get_filename(STATE_PROG_BFD(sd));
|
||||
if(strrchr(exec_name, '/') != NULL)
|
||||
exec_name = strrchr(exec_name, '/') + 1;
|
||||
|
||||
/* generate base name */
|
||||
sprintf(dir_name, "%s/%s",
|
||||
GX_DIR,
|
||||
exec_name);
|
||||
|
||||
/* generate base name */
|
||||
getcwd(pwd_name, sizeof(pwd_name));
|
||||
|
||||
/* create work directory */
|
||||
rc = mkdir(GX_DIR, 0777);
|
||||
if(rc != 0 &&
|
||||
errno != EEXIST)
|
||||
{
|
||||
sim_io_error(sd, "Error: cannot create directory %s, errno %d",
|
||||
GX_DIR, errno);
|
||||
}
|
||||
|
||||
rc = mkdir(dir_name, 0777);
|
||||
if(rc != 0 &&
|
||||
errno != EEXIST)
|
||||
{
|
||||
sim_io_error(sd, "Error: cannot create directory %s, errno %d",
|
||||
dir_name, errno);
|
||||
}
|
||||
|
||||
/* compute base name */
|
||||
if(optimized)
|
||||
sprintf(base_name, "%08lx_opt%d", gx->origin, gx->opt_compile_count);
|
||||
else
|
||||
sprintf(base_name, "%08lx", gx->origin);
|
||||
|
||||
/* generate source/object file names */
|
||||
block->source_name = zalloc(PATH_MAX);
|
||||
block->object_name = zalloc(PATH_MAX);
|
||||
sprintf(block->source_name, "%s/%s.c", dir_name, base_name);
|
||||
|
||||
/* generate symbol name for gx function */
|
||||
block->symbol_name = zalloc(PATH_MAX);
|
||||
sprintf(block->symbol_name, "gx_%s", base_name);
|
||||
|
||||
/* open source file */
|
||||
block->source_file = fopen(block->source_name, "w");
|
||||
if(block->source_file == NULL)
|
||||
{
|
||||
sim_io_error(sd, "Error: cannot open file %s, errno %d",
|
||||
block->source_name, errno);
|
||||
}
|
||||
|
||||
/* front matter */
|
||||
fprintf(block->source_file, "/* sim-gx version %d */\n", GX_VERSION);
|
||||
fprintf(block->source_file, "/* gx block date stamp %lu */\n\n", time(NULL));
|
||||
|
||||
/* emit head end of source */
|
||||
tgx_emit_pre_function(gx, optimized);
|
||||
|
||||
/* emit function header */
|
||||
fprintf(block->source_file, "\n\n");
|
||||
fprintf(block->source_file, "extern int\n");
|
||||
fprintf(block->source_file, "%s", block->symbol_name);
|
||||
fprintf(block->source_file, "(struct tgx_cpu_regs* regs, char* pc_flags, struct tgx_callbacks* callbacks)\n");
|
||||
fprintf(block->source_file, "{\n");
|
||||
fprintf(block->source_file, " int rc = 0;\n");
|
||||
if(! optimized)
|
||||
fprintf(block->source_file, " unsigned int insn_count = 0;\n");
|
||||
|
||||
/* pre-block gunk: register load */
|
||||
tgx_emit_load_block(gx, optimized);
|
||||
|
||||
/* emit intra-block jump label */
|
||||
fprintf(block->source_file, "\n");
|
||||
fprintf(block->source_file, "shortjump:\n");
|
||||
fprintf(block->source_file, " pc = npc;\n");
|
||||
|
||||
/* translate jumptarget table */
|
||||
if(! optimized)
|
||||
{
|
||||
fprintf(block->source_file, " pc_flags[(pc - 0x%08x) / %u] |= %d;\n",
|
||||
(unsigned)gx->origin, gx->divisor, GX_PCF_JUMPTARGET);
|
||||
}
|
||||
|
||||
/* enforce learning mode run limit */
|
||||
if(! optimized)
|
||||
{
|
||||
fprintf(block->source_file, " insn_count++;\n");
|
||||
fprintf(block->source_file, " if (insn_count > %d)\n", GX_LEARN_RUN_LIMIT);
|
||||
fprintf(block->source_file, " {\n");
|
||||
fprintf(block->source_file, " rc = %d;\n", GX_F_YIELD);
|
||||
fprintf(block->source_file, " npc = pc;\n");
|
||||
fprintf(block->source_file, " goto save;\n");
|
||||
fprintf(block->source_file, " }\n");
|
||||
}
|
||||
|
||||
/* emit PC switch, use compressed case numbers */
|
||||
fprintf(block->source_file, "\n");
|
||||
fprintf(block->source_file, " switch((pc - 0x%08x) / %u)\n",
|
||||
(unsigned)gx->origin, gx->divisor);
|
||||
fprintf(block->source_file, " {\n");
|
||||
|
||||
/* handle bad-PC event */
|
||||
fprintf(block->source_file, " /* handle unknown jump target */\n");
|
||||
fprintf(block->source_file, " default:\n");
|
||||
fprintf(block->source_file, " rc = %d;\n", GX_F_NONPC);
|
||||
fprintf(block->source_file, " npc = pc;\n");
|
||||
fprintf(block->source_file, " goto save;\n");
|
||||
|
||||
/* start translating at the origin */
|
||||
gx_cia = gx->origin;
|
||||
|
||||
/* translate instructions in block */
|
||||
while(GX_PC_INCLUDES(gx,gx_cia))
|
||||
{
|
||||
sim_cia next_gx_cia;
|
||||
|
||||
/* translate PC case statement */
|
||||
fprintf(block->source_file, "\n");
|
||||
fprintf(block->source_file, " /* PC: 0x%08x, flags %02x */\n",
|
||||
gx_cia, (int) GX_PC_FLAGS(gx, gx_cia));
|
||||
|
||||
|
||||
/* skip over this instruction if it is not executed */
|
||||
if(optimized && !(GX_PC_FLAGS(gx, gx_cia) & GX_PCF_INSTRUCTION))
|
||||
{
|
||||
fprintf(block->source_file, " /* (not reached) */\n");
|
||||
|
||||
/* prevent fall-through from previous translated insn */
|
||||
if(gx_cia > gx->origin &&
|
||||
GX_PC_FLAGS(gx, (gx_cia - gx->divisor)) & GX_PCF_INSTRUCTION)
|
||||
{
|
||||
fprintf(block->source_file, " /* prevent fall-through */\n");
|
||||
fprintf(block->source_file, " npc = 0x%08x;\n", gx_cia);
|
||||
fprintf(block->source_file, " rc = %d;\n", GX_F_NONPC);
|
||||
fprintf(block->source_file, " goto save;\n");
|
||||
}
|
||||
|
||||
next_gx_cia = gx_cia + gx->divisor;
|
||||
goto skip_instruction;
|
||||
}
|
||||
|
||||
/* translate PC case statement */
|
||||
if((! optimized) ||
|
||||
(GX_PC_FLAGS(gx, gx_cia) & GX_PCF_JUMPTARGET))
|
||||
{
|
||||
fprintf(block->source_file, " case %ld:\n",
|
||||
((gx_cia - gx->origin) / gx->divisor));
|
||||
}
|
||||
|
||||
/* translate breakpoint check & exit */
|
||||
if(GX_PC_FLAGS(gx, gx_cia) & GX_PCF_COND_HALT)
|
||||
{
|
||||
fprintf(block->source_file, " if(pc_flags[%ld] & %d)\n",
|
||||
GX_PC_FLAGS_INDEX(gx, gx_cia),
|
||||
GX_PCF_HALT);
|
||||
fprintf(block->source_file, " {\n");
|
||||
fprintf(block->source_file, " rc = %d;\n", GX_F_HALT);
|
||||
fprintf(block->source_file, " npc = pc;\n");
|
||||
fprintf(block->source_file, " goto save;\n");
|
||||
fprintf(block->source_file, " }\n");
|
||||
}
|
||||
|
||||
/* [don't] emit PC-setting */
|
||||
/* fprintf(block->source_file, " pc = 0x%08x;\n", gx_cia); */
|
||||
|
||||
/* mark traversed instructions */
|
||||
if(! optimized)
|
||||
{
|
||||
fprintf(block->source_file, " pc_flags[%ld] |= %d;\n",
|
||||
GX_PC_FLAGS_INDEX(gx, gx_cia),
|
||||
GX_PCF_INSTRUCTION);
|
||||
}
|
||||
|
||||
|
||||
/* translate instruction semantics */
|
||||
next_gx_cia = tgx_emit_insn(gx, gx_cia, optimized);
|
||||
|
||||
skip_instruction:
|
||||
|
||||
/* go to next instruction */
|
||||
gx_cia = next_gx_cia;
|
||||
}
|
||||
fprintf(block->source_file, " }\n");
|
||||
|
||||
/* dropped through last instruction in switch block */
|
||||
fprintf(block->source_file, "\n");
|
||||
fprintf(block->source_file, " /* dropped through PC switch */\n");
|
||||
fprintf(block->source_file, " npc = 0x%08x;\n", gx_cia);
|
||||
fprintf(block->source_file, " rc = %d;\n", GX_F_RANGE);
|
||||
fprintf(block->source_file, " goto save;\n");
|
||||
|
||||
/* unknown length jump */
|
||||
fprintf(block->source_file, "\n");
|
||||
fprintf(block->source_file, "unknownjump:\n");
|
||||
fprintf(block->source_file, " if(npc >= 0x%08lx && npc < 0x%08lx)\n",
|
||||
gx->origin, gx->origin + gx->length);
|
||||
fprintf(block->source_file, " goto shortjump;\n");
|
||||
|
||||
/* long jump */
|
||||
fprintf(block->source_file, "\n");
|
||||
fprintf(block->source_file, "longjump:\n");
|
||||
fprintf(block->source_file, " rc = %d;\n", GX_F_RANGE);
|
||||
|
||||
/* post-block gunk: SAVE etc. */
|
||||
fprintf(block->source_file, "\n");
|
||||
fprintf(block->source_file, "save:\n");
|
||||
|
||||
tgx_emit_save_block(gx, optimized);
|
||||
|
||||
/* emit tail end of function */
|
||||
fprintf(block->source_file, "\n");
|
||||
fprintf(block->source_file, " return rc;\n");
|
||||
fprintf(block->source_file, "}\n");
|
||||
|
||||
/* emit tail end of source */
|
||||
tgx_emit_post_function(gx, optimized);
|
||||
|
||||
/* close source file */
|
||||
fclose(block->source_file);
|
||||
block->source_file = NULL;
|
||||
|
||||
/* compile source & produce shared object */
|
||||
|
||||
sprintf(compile_command,
|
||||
"gxtool --silent --mode=compile gcc -c -g %s %s",
|
||||
(optimized ? "-O3" : "-O"), block->source_name);
|
||||
|
||||
rc = system(compile_command);
|
||||
if(rc != 0)
|
||||
{
|
||||
sim_io_error(sd, "Error during compiling: `%s' rc %d",
|
||||
compile_command, rc);
|
||||
}
|
||||
|
||||
/* link source */
|
||||
|
||||
sprintf(compile_command,
|
||||
"gxtool --silent --mode=link gcc -export-dynamic -rpath %s -g -o lib%s.la %s.lo",
|
||||
dir_name, base_name, base_name);
|
||||
|
||||
rc = system(compile_command);
|
||||
if(rc != 0)
|
||||
{
|
||||
sim_io_error(sd, "Error during linking: `%s' rc %d",
|
||||
compile_command, rc);
|
||||
}
|
||||
|
||||
|
||||
/* install */
|
||||
|
||||
sprintf(compile_command,
|
||||
"gxtool --silent --mode=install cp lib%s.la %s/%s >/dev/null 2>/dev/null",
|
||||
base_name, pwd_name, dir_name);
|
||||
|
||||
rc = system(compile_command);
|
||||
if(rc != 0)
|
||||
{
|
||||
sim_io_error(sd, "Error during install: `%s' rc %d",
|
||||
compile_command, rc);
|
||||
}
|
||||
|
||||
|
||||
/* finish */
|
||||
|
||||
sprintf(compile_command,
|
||||
"gxtool --silent --mode=finish %s >/dev/null 2>/dev/null",
|
||||
dir_name);
|
||||
|
||||
rc = system(compile_command);
|
||||
if(rc != 0)
|
||||
{
|
||||
sim_io_error(sd, "Error during finish: `%s' rc %d",
|
||||
compile_command, rc);
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
|
||||
sprintf(compile_command, "rm -f lib%s.la %s.lo", base_name, base_name);
|
||||
rc = system(compile_command);
|
||||
if(rc != 0)
|
||||
{
|
||||
sim_io_error(sd, "Error during cleanup: `%s' rc %d",
|
||||
compile_command, rc);
|
||||
}
|
||||
|
||||
/* XXX: FILL IN block->object_name from .la file */
|
||||
sprintf(block->object_name, "%s/%s/lib%s.so.0",
|
||||
pwd_name, dir_name, base_name);
|
||||
|
||||
/* measure compile time */
|
||||
time_end = time(NULL);
|
||||
|
||||
if(time_end == time_begin) time_end ++; /* clamp minimum duration to 1 */
|
||||
gx->compile_time += time_end - time_begin;
|
||||
/* fprintf(stderr, "*** compile time: %d\n", gx->compile_time); */
|
||||
}
|
||||
|
142
sim/common/sim-gx.h
Normal file
142
sim/common/sim-gx.h
Normal file
|
@ -0,0 +1,142 @@
|
|||
/* GX generic simulator structs.
|
||||
Copyright (C) 1998 Cygnus Solutions.
|
||||
*/
|
||||
|
||||
#ifndef SIM_GX_H
|
||||
#define SIM_GX_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "sim-base.h"
|
||||
#include "sim-core.h"
|
||||
|
||||
|
||||
/*
|
||||
#ifndef SIM_GX
|
||||
#error "Compile this file only if configured SIM_GX"
|
||||
#endif
|
||||
*/
|
||||
|
||||
|
||||
/* configuration */
|
||||
|
||||
#define GX_DIR ".gx"
|
||||
#define GX_VERSION 1
|
||||
|
||||
|
||||
struct sim_gx_compiled_block;
|
||||
|
||||
|
||||
/* record for a particular GX block */
|
||||
typedef struct sim_gx_block
|
||||
{
|
||||
/* ---- BLOCK EXTENT ---- */
|
||||
address_word origin; /* first code-segment address translated */
|
||||
unsigned_4 length; /* length of translated code-segment */
|
||||
|
||||
#define GX_PC_INCLUDES(gx,pc) ((gx)->origin <= (pc) && (pc) < (gx)->origin + (gx)->length)
|
||||
|
||||
short divisor; /* minimum instruction word size; address_word -> index divisor */
|
||||
char* pc_flags; /* see GX_PC_* below */
|
||||
|
||||
#define GX_PCF_INSTRUCTION 0x01 /* learned */
|
||||
#define GX_PCF_JUMPTARGET 0x02 /* learned */
|
||||
#define GX_PCF_COND_HALT 0x10 /* translate-time input */
|
||||
#define GX_PCF_HALT 0x20 /* run-time input */
|
||||
#define GX_PC_FLAGS_INDEX(gx,pc) ((((pc) - ((gx)->origin)) / (gx)->divisor))
|
||||
#define GX_PC_FLAGS(gx,pc) ((gx)->pc_flags[GX_PC_FLAGS_INDEX((gx),(pc))])
|
||||
|
||||
/* GX callbacks */
|
||||
struct tgx_callbacks* callbacks;
|
||||
|
||||
/* compilation statistics */
|
||||
unsigned_4 compile_time; /* time to compile [s] */
|
||||
|
||||
/* ---- LEARNING MODE STATE ---- */
|
||||
unsigned_4 learn_last_change; /* time of last flag change */
|
||||
struct sim_gx_compiled_block* learning_block;
|
||||
|
||||
/* ---- OPTIMIZED MODE STATE ---- */
|
||||
unsigned opt_compile_count; /* number of optimized compile attempts */
|
||||
struct sim_gx_compiled_block* optimized_block;
|
||||
} sim_gx_block;
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct sim_gx_compiled_block
|
||||
{
|
||||
/* ---- TRANSLATION OBJECTS ---- */
|
||||
char* source_name; /* source file for translated object */
|
||||
char* object_name; /* file name of translated object */
|
||||
char* symbol_name; /* symbol name of function */
|
||||
/* (all above pointers are zalloc()'d buffers, to be zfree()'d. */
|
||||
|
||||
FILE* source_file; /* working file pointer during translation */
|
||||
|
||||
/* ---- LOADED TRANSLATIONS ---- */
|
||||
void* object_dlhandle; /* dlopen() handle to loaded object (if open) */
|
||||
void* function_dlhandle; /* dlsym() pointer to function (if found) */
|
||||
} sim_gx_compiled_block;
|
||||
|
||||
|
||||
|
||||
/* GX block vector: for quick search of translated blocks */
|
||||
typedef struct sim_gx_block_list
|
||||
{
|
||||
/* ---- BLOCK VECTOR ---- */
|
||||
sim_gx_block** gx_blocks; /* vector of GX blocks, sorted by origin field */
|
||||
unsigned gx_blocks_size; /* vector length */
|
||||
unsigned gx_blocks_used; /* number of elements used in vector */
|
||||
address_word gx_first, gx_last; /* first & last addresses translated by any gx block */
|
||||
} sim_gx_block_list;
|
||||
|
||||
|
||||
/* actual gx function pointer type */
|
||||
struct tgx_cpu_regs;
|
||||
typedef int (*sim_gx_function)(struct tgx_cpu_regs* cpu, char* pc_flags, struct tgx_callbacks* callbacks);
|
||||
|
||||
|
||||
/* return values from gx function */
|
||||
#define GX_F_HALT 0
|
||||
#define GX_F_NONPC 1
|
||||
#define GX_F_RANGE 2
|
||||
#define GX_F_YIELD 3
|
||||
|
||||
|
||||
/* Limit on loop cycles within a learning mode gx block */
|
||||
#define GX_LEARN_RUN_LIMIT 10000
|
||||
|
||||
/* Operations */
|
||||
sim_gx_block* sim_gx_block_create(sim_cia cia);
|
||||
|
||||
sim_gx_block* sim_gx_block_find(sim_cia cia);
|
||||
void sim_gx_block_add(sim_gx_block* block);
|
||||
void sim_gx_block_remove(sim_gx_block* block);
|
||||
|
||||
/* State save/restore */
|
||||
void sim_gx_write_block_list();
|
||||
void sim_gx_read_block_list();
|
||||
|
||||
sim_gx_function sim_gx_compiled_block_f(sim_gx_compiled_block* gx);
|
||||
void sim_gx_compiled_block_dispose(sim_gx_compiled_block* gx);
|
||||
void sim_gx_block_translate(sim_gx_block* gx, int optimized);
|
||||
|
||||
|
||||
|
||||
/* Target-specific translation operations */
|
||||
|
||||
int tgx_optimize_test(sim_gx_block* block);
|
||||
|
||||
void tgx_block_ctor(sim_gx_block* block, sim_cia cia);
|
||||
void tgx_block_ctor2(sim_gx_block* block, unsigned_4 origin,
|
||||
unsigned_4 length, unsigned_4 divisor);
|
||||
void tgx_block_dtor(sim_gx_block* block);
|
||||
|
||||
void tgx_emit_pre_function(sim_gx_block* block, int optimized);
|
||||
void tgx_emit_load_block(sim_gx_block* block, int optimized);
|
||||
sim_cia tgx_emit_insn(sim_gx_block* block, sim_cia cia, int optimized);
|
||||
void tgx_emit_save_block(sim_gx_block* block, int optimized);
|
||||
void tgx_emit_post_function(sim_gx_block* block, int optimized);
|
||||
|
||||
|
||||
#endif /* SIM_GX_H */
|
|
@ -136,6 +136,19 @@ case "${target}" in
|
|||
esac
|
||||
|
||||
|
||||
# start-sanitize-gxsim
|
||||
AC_ARG_ENABLE(sim-gx, [],
|
||||
[case "${enableval}" in
|
||||
yes)
|
||||
if test -d ${srcdir}/${sim_target}-gx ; then
|
||||
extra_subdirs="${sim_target}-gx"
|
||||
else
|
||||
AC_MSG_WARN(GX simulator not available for ${sim_target})
|
||||
fi ;;
|
||||
esac])dnl
|
||||
# end-sanitize-gxsim
|
||||
|
||||
|
||||
# Is there a testsuite directory for the target?
|
||||
testdir=`echo ${target} | sed -e 's/-.*-/-/'`
|
||||
if test -r ${srcdir}/testsuite/${testdir}/configure ; then
|
||||
|
|
46
sim/m32r-gx/.Sanitize
Normal file
46
sim/m32r-gx/.Sanitize
Normal file
|
@ -0,0 +1,46 @@
|
|||
# Sanitize.in for sim/m32r
|
||||
# $Id$
|
||||
|
||||
# Each directory to survive it's way into a release will need a file
|
||||
# like this one called "./.Sanitize". All keyword lines must exist,
|
||||
# and must exist in the order specified by this file. Each directory
|
||||
# in the tree will be processed, top down, in the following order.
|
||||
|
||||
# Hash started lines like this one are comments and will be deleted
|
||||
# before anything else is done. Blank lines will also be squashed
|
||||
# out.
|
||||
|
||||
# The lines between the "Do-first:" line and the "Things-to-keep:"
|
||||
# line are executed as a /bin/sh shell script before anything else is
|
||||
# done in this
|
||||
|
||||
Do-first:
|
||||
|
||||
# All files listed between the "Things-to-keep:" line and the
|
||||
# "Files-to-sed:" line will be kept. All other files will be removed.
|
||||
# Directories listed in this section will have their own Sanitize
|
||||
# called. Directories not listed will be removed in their entirety
|
||||
# with rm -rf.
|
||||
|
||||
Things-to-keep:
|
||||
|
||||
ChangeLog
|
||||
Makefile.in
|
||||
arch.h
|
||||
config.in
|
||||
configure
|
||||
configure.in
|
||||
cpuall.h
|
||||
gx-translate.c
|
||||
ltconfig
|
||||
ltmain.sh
|
||||
m32r-sim.h
|
||||
sim-if.c
|
||||
sim-main.h
|
||||
tconfig.in
|
||||
|
||||
Things-to-lose:
|
||||
|
||||
Do-last:
|
||||
|
||||
# End of file.
|
3
sim/m32r-gx/ChangeLog
Normal file
3
sim/m32r-gx/ChangeLog
Normal file
|
@ -0,0 +1,3 @@
|
|||
1998-11-13 Frank Ch. Eigler <fche@elastic.org>
|
||||
|
||||
* (*): New files: snapshot of gx simulator prototype.
|
104
sim/m32r-gx/Makefile.in
Normal file
104
sim/m32r-gx/Makefile.in
Normal file
|
@ -0,0 +1,104 @@
|
|||
# Makefile template for Configure for the m32r simulator
|
||||
# Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
# Contributed by Cygnus Support.
|
||||
#
|
||||
# This file is part of GDB, the GNU debugger.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
## COMMON_PRE_CONFIG_FRAG
|
||||
|
||||
M32R_OBJS = gx-translate.o
|
||||
|
||||
CONFIG_DEVICES = dv-sockser.o
|
||||
CONFIG_DEVICES =
|
||||
|
||||
SIM_OBJS = \
|
||||
sim-bits.o \
|
||||
sim-break.o \
|
||||
sim-config.o \
|
||||
sim-core.o \
|
||||
sim-endian.o \
|
||||
sim-events.o \
|
||||
sim-fpu.o \
|
||||
sim-io.o \
|
||||
sim-if.o \
|
||||
sim-info.o \
|
||||
sim-load.o \
|
||||
sim-memopt.o \
|
||||
sim-module.o \
|
||||
sim-options.o \
|
||||
sim-signal.o \
|
||||
sim-trace.o \
|
||||
sim-utils.o \
|
||||
sim-watch.o \
|
||||
sim-cpu.o \
|
||||
sim-engine.o \
|
||||
sim-core.o \
|
||||
sim-hload.o \
|
||||
sim-hrw.o \
|
||||
sim-reason.o \
|
||||
$(M32R_OBJS) \
|
||||
sim-gx.o \
|
||||
sim-gx-run.o \
|
||||
$(CONFIG_DEVICES)
|
||||
|
||||
# Extra headers included by sim-main.h.
|
||||
SIM_EXTRA_DEPS = \
|
||||
arch.h cpuall.h m32r-sim.h cpu-opc.h
|
||||
|
||||
SIM_EXTRA_CFLAGS = -DSIM_GX=1
|
||||
SIM_EXTRA_ALL = gxtool
|
||||
SIM_EXTRA_INSTALL = install-gxtool
|
||||
SIM_RUN_OBJS = nrun.o
|
||||
SIM_EXTRA_CLEAN = m32r-clean
|
||||
|
||||
# This selects the m32r newlib/libgloss syscall definitions.
|
||||
NL_TARGET = -DNL_TARGET_m32r
|
||||
|
||||
## COMMON_POST_CONFIG_FRAG
|
||||
|
||||
arch = m32r
|
||||
|
||||
MAIN_INCLUDE_DEPS = \
|
||||
sim-main.h \
|
||||
$(srcdir)/../common/sim-config.h \
|
||||
$(srcdir)/../common/sim-base.h \
|
||||
$(srcdir)/../common/sim-basics.h \
|
||||
$(srcdir)/../common/sim-module.h \
|
||||
$(srcdir)/../common/sim-trace.h \
|
||||
tconfig.h
|
||||
INCLUDE_DEPS = $(MAIN_INCLUDE_DEPS) $(SIM_EXTRA_DEPS) cpu-sim.h
|
||||
OPS_INCLUDE_DEPS = \
|
||||
$(srcdir)/../common/cgen-mem.h \
|
||||
$(srcdir)/../common/cgen-ops.h
|
||||
|
||||
sim-if.o: sim-if.c $(INCLUDE_DEPS) $(srcdir)/../common/sim-core.h
|
||||
|
||||
arch.o: arch.c $(INCLUDE_DEPS)
|
||||
|
||||
# M32R objs
|
||||
|
||||
m32r.o: m32r.c $(INCLUDE_DEPS) $(OPS_INCLUDE_DEPS) cpu.h
|
||||
|
||||
m32r-clean:
|
||||
rm -f mloop.c stamp-arch stamp-cpu stamp-decode
|
||||
rm -f tmp-*
|
||||
|
||||
gxtool: ltconfig ltmain.sh
|
||||
$(SHELL) $(srcdir)/ltconfig --disable-static -o $@ $(srcdir)/ltmain.sh
|
||||
|
||||
install-gxtool: gxtool
|
||||
$(INSTALL_PROGRAM) gxtool $(bindir)
|
52
sim/m32r-gx/arch.h
Normal file
52
sim/m32r-gx/arch.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/* Simulator header for m32r.
|
||||
|
||||
This file is machine generated with CGEN.
|
||||
|
||||
Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Simulators.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef M32R_ARCH_H
|
||||
#define M32R_ARCH_H
|
||||
|
||||
#include "m32r-opc.h"
|
||||
|
||||
#define TARGET_BIG_ENDIAN 1
|
||||
|
||||
/* Shorthand macro for fetching registers. */
|
||||
#define CPU(x) (CPU_CGEN_HW (current_cpu)->x)
|
||||
|
||||
typedef enum model_type {
|
||||
MODEL_M32R_D, MODEL_TEST
|
||||
, MODEL_MAX
|
||||
} MODEL_TYPE;
|
||||
|
||||
#define MAX_MODELS ((int) MODEL_MAX)
|
||||
|
||||
/* Enum declaration for unit types. */
|
||||
typedef enum unit_type {
|
||||
UNIT_NONE, UNIT_M32R_D_U_STORE, UNIT_M32R_D_U_LOAD, UNIT_M32R_D_U_EXEC
|
||||
, UNIT_TEST_U_EXEC
|
||||
, UNIT_MAX
|
||||
} UNIT_TYPE;
|
||||
|
||||
#define MAX_UNITS (1)
|
||||
|
||||
#endif /* M32R_ARCH_H */
|
||||
|
180
sim/m32r-gx/config.in
Normal file
180
sim/m32r-gx/config.in
Normal file
|
@ -0,0 +1,180 @@
|
|||
/* config.in. Generated automatically from configure.in by autoheader. */
|
||||
|
||||
/* Define if using alloca.c. */
|
||||
#undef C_ALLOCA
|
||||
|
||||
/* Define to empty if the keyword does not work. */
|
||||
#undef const
|
||||
|
||||
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
|
||||
This function is required for alloca.c support on those systems. */
|
||||
#undef CRAY_STACKSEG_END
|
||||
|
||||
/* Define if you have alloca, as a function or macro. */
|
||||
#undef HAVE_ALLOCA
|
||||
|
||||
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
|
||||
#undef HAVE_ALLOCA_H
|
||||
|
||||
/* Define if you have a working `mmap' system call. */
|
||||
#undef HAVE_MMAP
|
||||
|
||||
/* Define as __inline if that's what the C compiler calls it. */
|
||||
#undef inline
|
||||
|
||||
/* Define to `long' if <sys/types.h> doesn't define. */
|
||||
#undef off_t
|
||||
|
||||
/* Define if you need to in order for stat and other things to work. */
|
||||
#undef _POSIX_SOURCE
|
||||
|
||||
/* Define as the return type of signal handlers (int or void). */
|
||||
#undef RETSIGTYPE
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> doesn't define. */
|
||||
#undef size_t
|
||||
|
||||
/* If using the C implementation of alloca, define if you know the
|
||||
direction of stack growth for your system; otherwise it will be
|
||||
automatically deduced at run-time.
|
||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
STACK_DIRECTION = 0 => direction of growth unknown
|
||||
*/
|
||||
#undef STACK_DIRECTION
|
||||
|
||||
/* Define if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Define if your processor stores words with the most significant
|
||||
byte first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
#undef WORDS_BIGENDIAN
|
||||
|
||||
/* Define to 1 if NLS is requested. */
|
||||
#undef ENABLE_NLS
|
||||
|
||||
/* Define as 1 if you have gettext and don't want to use GNU gettext. */
|
||||
#undef HAVE_GETTEXT
|
||||
|
||||
/* Define as 1 if you have the stpcpy function. */
|
||||
#undef HAVE_STPCPY
|
||||
|
||||
/* Define if your locale.h file contains LC_MESSAGES. */
|
||||
#undef HAVE_LC_MESSAGES
|
||||
|
||||
/* Define if you have the __argz_count function. */
|
||||
#undef HAVE___ARGZ_COUNT
|
||||
|
||||
/* Define if you have the __argz_next function. */
|
||||
#undef HAVE___ARGZ_NEXT
|
||||
|
||||
/* Define if you have the __argz_stringify function. */
|
||||
#undef HAVE___ARGZ_STRINGIFY
|
||||
|
||||
/* Define if you have the __setfpucw function. */
|
||||
#undef HAVE___SETFPUCW
|
||||
|
||||
/* Define if you have the dcgettext function. */
|
||||
#undef HAVE_DCGETTEXT
|
||||
|
||||
/* Define if you have the getcwd function. */
|
||||
#undef HAVE_GETCWD
|
||||
|
||||
/* Define if you have the getpagesize function. */
|
||||
#undef HAVE_GETPAGESIZE
|
||||
|
||||
/* Define if you have the getrusage function. */
|
||||
#undef HAVE_GETRUSAGE
|
||||
|
||||
/* Define if you have the munmap function. */
|
||||
#undef HAVE_MUNMAP
|
||||
|
||||
/* Define if you have the putenv function. */
|
||||
#undef HAVE_PUTENV
|
||||
|
||||
/* Define if you have the setenv function. */
|
||||
#undef HAVE_SETENV
|
||||
|
||||
/* Define if you have the setlocale function. */
|
||||
#undef HAVE_SETLOCALE
|
||||
|
||||
/* Define if you have the sigaction function. */
|
||||
#undef HAVE_SIGACTION
|
||||
|
||||
/* Define if you have the stpcpy function. */
|
||||
#undef HAVE_STPCPY
|
||||
|
||||
/* Define if you have the strcasecmp function. */
|
||||
#undef HAVE_STRCASECMP
|
||||
|
||||
/* Define if you have the strchr function. */
|
||||
#undef HAVE_STRCHR
|
||||
|
||||
/* Define if you have the time function. */
|
||||
#undef HAVE_TIME
|
||||
|
||||
/* Define if you have the <argz.h> header file. */
|
||||
#undef HAVE_ARGZ_H
|
||||
|
||||
/* Define if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define if you have the <errno.h> header file. */
|
||||
#undef HAVE_ERRNO_H
|
||||
|
||||
/* Define if you have the <fcntl.h> header file. */
|
||||
#undef HAVE_FCNTL_H
|
||||
|
||||
/* Define if you have the <fpu_control.h> header file. */
|
||||
#undef HAVE_FPU_CONTROL_H
|
||||
|
||||
/* Define if you have the <limits.h> header file. */
|
||||
#undef HAVE_LIMITS_H
|
||||
|
||||
/* Define if you have the <locale.h> header file. */
|
||||
#undef HAVE_LOCALE_H
|
||||
|
||||
/* Define if you have the <malloc.h> header file. */
|
||||
#undef HAVE_MALLOC_H
|
||||
|
||||
/* Define if you have the <nl_types.h> header file. */
|
||||
#undef HAVE_NL_TYPES_H
|
||||
|
||||
/* Define if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define if you have the <sys/param.h> header file. */
|
||||
#undef HAVE_SYS_PARAM_H
|
||||
|
||||
/* Define if you have the <sys/resource.h> header file. */
|
||||
#undef HAVE_SYS_RESOURCE_H
|
||||
|
||||
/* Define if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define if you have the <sys/time.h> header file. */
|
||||
#undef HAVE_SYS_TIME_H
|
||||
|
||||
/* Define if you have the <time.h> header file. */
|
||||
#undef HAVE_TIME_H
|
||||
|
||||
/* Define if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define if you have the <values.h> header file. */
|
||||
#undef HAVE_VALUES_H
|
||||
|
||||
/* Define if you have the dl library (-ldl). */
|
||||
#undef HAVE_LIBDL
|
||||
|
||||
/* Define if you have the nsl library (-lnsl). */
|
||||
#undef HAVE_LIBNSL
|
||||
|
||||
/* Define if you have the socket library (-lsocket). */
|
||||
#undef HAVE_LIBSOCKET
|
4205
sim/m32r-gx/configure
vendored
Executable file
4205
sim/m32r-gx/configure
vendored
Executable file
File diff suppressed because it is too large
Load diff
26
sim/m32r-gx/configure.in
Normal file
26
sim/m32r-gx/configure.in
Normal file
|
@ -0,0 +1,26 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
sinclude(../common/aclocal.m4)
|
||||
AC_PREREQ(2.5)dnl
|
||||
AC_INIT(Makefile.in)
|
||||
|
||||
|
||||
SIM_AC_COMMON
|
||||
|
||||
program_transform_name="s,^,${program_prefix}gx-,"
|
||||
target_alias="${target_alias}-gx"
|
||||
|
||||
sim_link_files="${sim_link_files} m32r-sim.h ../../opcodes/m32r-opc.h"
|
||||
sim_link_links="${sim_link_links} cpu-sim.h cpu-opc.h"
|
||||
|
||||
SIM_AC_OPTION_ENDIAN(BIG_ENDIAN)
|
||||
SIM_AC_OPTION_ALIGNMENT(NONSTRICT_ALIGNMENT)
|
||||
SIM_AC_OPTION_HOSTENDIAN
|
||||
SIM_AC_OPTION_DEFAULT_MODEL(m32r/d)
|
||||
SIM_AC_OPTION_ENVIRONMENT
|
||||
|
||||
AC_CHECK_LIB(dl, dlopen)
|
||||
|
||||
SIM_AC_OUTPUT
|
||||
|
||||
|
||||
|
2
sim/m32r-gx/cpuall.h
Normal file
2
sim/m32r-gx/cpuall.h
Normal file
|
@ -0,0 +1,2 @@
|
|||
#include "sim-cpu.h"
|
||||
#include "sim-model.h"
|
1038
sim/m32r-gx/gx-translate.c
Normal file
1038
sim/m32r-gx/gx-translate.c
Normal file
File diff suppressed because it is too large
Load diff
1715
sim/m32r-gx/ltconfig
Executable file
1715
sim/m32r-gx/ltconfig
Executable file
File diff suppressed because it is too large
Load diff
2639
sim/m32r-gx/ltmain.sh
Normal file
2639
sim/m32r-gx/ltmain.sh
Normal file
File diff suppressed because it is too large
Load diff
0
sim/m32r-gx/m32r-sim.h
Normal file
0
sim/m32r-gx/m32r-sim.h
Normal file
250
sim/m32r-gx/sim-if.c
Normal file
250
sim/m32r-gx/sim-if.c
Normal file
|
@ -0,0 +1,250 @@
|
|||
/* Main simulator entry points for the M32R.
|
||||
Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "sim-main.h"
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include "sim-options.h"
|
||||
#include "libiberty.h"
|
||||
#include "bfd.h"
|
||||
#include "sim-assert.h"
|
||||
|
||||
|
||||
static void free_state (SIM_DESC);
|
||||
|
||||
/* Records simulator descriptor so utilities like m32r_dump_regs can be
|
||||
called from gdb. */
|
||||
SIM_DESC current_state;
|
||||
|
||||
/* Cover function of sim_state_free to free the cpu buffers as well. */
|
||||
|
||||
static void
|
||||
free_state (SIM_DESC sd)
|
||||
{
|
||||
if (STATE_MODULES (sd) != NULL)
|
||||
sim_module_uninstall (sd);
|
||||
sim_cpu_free_all (sd);
|
||||
sim_state_free (sd);
|
||||
}
|
||||
|
||||
/* Create an instance of the simulator. */
|
||||
|
||||
SIM_DESC
|
||||
sim_open (kind, callback, abfd, argv)
|
||||
SIM_OPEN_KIND kind;
|
||||
host_callback *callback;
|
||||
struct _bfd *abfd;
|
||||
char **argv;
|
||||
{
|
||||
SIM_DESC sd = sim_state_alloc (kind, callback);
|
||||
|
||||
sim_cpu_alloc_all (sd, 1, 0);
|
||||
|
||||
if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
|
||||
{
|
||||
free_state (sd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allocate core managed memory */
|
||||
sim_do_commandf (sd, "memory region 0,0x%lx", M32R_DEFAULT_MEM_SIZE);
|
||||
|
||||
/* getopt will print the error message so we just have to exit if this fails.
|
||||
FIXME: Hmmm... in the case of gdb we need getopt to call
|
||||
print_filtered. */
|
||||
if (sim_parse_args (sd, argv) != SIM_RC_OK)
|
||||
{
|
||||
free_state (sd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check for/establish the reference program image */
|
||||
if (sim_analyze_program (sd,
|
||||
(STATE_PROG_ARGV (sd) != NULL
|
||||
? *STATE_PROG_ARGV (sd)
|
||||
: NULL),
|
||||
abfd) != SIM_RC_OK)
|
||||
{
|
||||
free_state (sd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Establish any remaining configuration options. */
|
||||
if (sim_config (sd) != SIM_RC_OK)
|
||||
{
|
||||
free_state (sd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sim_post_argv_init (sd) != SIM_RC_OK)
|
||||
{
|
||||
free_state (sd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Store in a global so things like sparc32_dump_regs can be invoked
|
||||
from the gdb command line. */
|
||||
current_state = sd;
|
||||
sim_gx_read_block_list();
|
||||
return sd;
|
||||
}
|
||||
|
||||
void
|
||||
sim_close (sd, quitting)
|
||||
SIM_DESC sd;
|
||||
int quitting;
|
||||
{
|
||||
sim_gx_write_block_list();
|
||||
sim_module_uninstall (sd);
|
||||
}
|
||||
|
||||
|
||||
USI
|
||||
m32r_h_pc_get (SIM_CPU *current_cpu)
|
||||
{
|
||||
return current_cpu->regs.h_pc;
|
||||
}
|
||||
|
||||
/* Set a value for h-pc. */
|
||||
|
||||
void
|
||||
m32r_h_pc_set (SIM_CPU *current_cpu, USI newval)
|
||||
{
|
||||
current_cpu->regs.h_pc = newval;
|
||||
}
|
||||
|
||||
|
||||
SIM_RC
|
||||
sim_create_inferior (sd, abfd, argv, envp)
|
||||
SIM_DESC sd;
|
||||
struct _bfd *abfd;
|
||||
char **argv;
|
||||
char **envp;
|
||||
{
|
||||
SIM_CPU *current_cpu = STATE_CPU (sd, 0);
|
||||
SIM_ADDR addr;
|
||||
|
||||
CPU_PC_STORE (current_cpu) = m32r_h_pc_set;
|
||||
CPU_PC_FETCH (current_cpu) = m32r_h_pc_get;
|
||||
CPU_REG_STORE (current_cpu) = & abort;
|
||||
CPU_REG_FETCH (current_cpu) = & abort;
|
||||
|
||||
if (abfd != NULL)
|
||||
addr = bfd_get_start_address (abfd);
|
||||
else
|
||||
addr = 0;
|
||||
|
||||
sim_pc_set (current_cpu, addr);
|
||||
|
||||
#if 0
|
||||
STATE_ARGV (sd) = sim_copy_argv (argv);
|
||||
STATE_ENVP (sd) = sim_copy_argv (envp);
|
||||
#endif
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
int
|
||||
sim_stop (SIM_DESC sd)
|
||||
{
|
||||
sim_io_error(sd, "cannot sim_stop\n");
|
||||
}
|
||||
|
||||
/* This isn't part of the official interface.
|
||||
This is just a good place to put this for now. */
|
||||
|
||||
void
|
||||
sim_sync_stop (SIM_DESC sd, SIM_CPU *cpu, PCADDR pc, enum sim_stop reason, int sigrc)
|
||||
{
|
||||
sim_io_error(sd, "cannot sim_stop\n");
|
||||
}
|
||||
|
||||
void
|
||||
sim_resume (sd, step, siggnal)
|
||||
SIM_DESC sd;
|
||||
int step, siggnal;
|
||||
{
|
||||
sim_engine *engine = STATE_ENGINE (sd);
|
||||
jmp_buf buf;
|
||||
int jmpval;
|
||||
|
||||
sim_module_resume (sd);
|
||||
ASSERT(step == 0); /* XXX */
|
||||
|
||||
engine->jmpbuf = &buf;
|
||||
jmpval = setjmp (buf);
|
||||
if(jmpval == 0)
|
||||
sim_engine_run(sd, 0, 1, siggnal);
|
||||
engine->jmpbuf = NULL;
|
||||
|
||||
sim_module_suspend (sd);
|
||||
}
|
||||
|
||||
/* The contents of BUF are in target byte order. */
|
||||
|
||||
int
|
||||
sim_fetch_register (sd, rn, buf, length)
|
||||
SIM_DESC sd;
|
||||
int rn;
|
||||
unsigned char *buf;
|
||||
int length;
|
||||
{
|
||||
SIM_CPU *cpu = STATE_CPU (sd, 0);
|
||||
|
||||
return (* CPU_REG_FETCH (cpu)) (cpu, rn, buf, length);
|
||||
}
|
||||
|
||||
/* The contents of BUF are in target byte order. */
|
||||
|
||||
int
|
||||
sim_store_register (sd, rn, buf, length)
|
||||
SIM_DESC sd;
|
||||
int rn;
|
||||
unsigned char *buf;
|
||||
int length;
|
||||
{
|
||||
SIM_CPU *cpu = STATE_CPU (sd, 0);
|
||||
|
||||
return (* CPU_REG_STORE (cpu)) (cpu, rn, buf, length);
|
||||
}
|
||||
|
||||
void
|
||||
sim_do_command (sd, cmd)
|
||||
SIM_DESC sd;
|
||||
char *cmd;
|
||||
{
|
||||
if (sim_args_command (sd, cmd) != SIM_RC_OK)
|
||||
sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
|
||||
}
|
||||
|
||||
/* Utility fns to access registers, without knowing the current mach. */
|
||||
|
||||
SI
|
||||
h_gr_get (SIM_CPU *current_cpu, UINT regno)
|
||||
{
|
||||
SIM_DESC sd = CURRENT_STATE;
|
||||
sim_io_error(sd, "cannot h_gr_get\n");
|
||||
}
|
||||
|
||||
void
|
||||
h_gr_set (SIM_CPU *current_cpu, UINT regno, SI newval)
|
||||
{
|
||||
SIM_DESC sd = CURRENT_STATE;
|
||||
sim_io_error(sd, "cannot h_gr_set\n");
|
||||
}
|
94
sim/m32r-gx/sim-main.h
Normal file
94
sim/m32r-gx/sim-main.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/* Main header for the m32r. */
|
||||
|
||||
#define USING_SIM_BASE_H /* FIXME: quick hack */
|
||||
|
||||
struct _sim_cpu; /* FIXME: should be in sim-basics.h */
|
||||
typedef struct _sim_cpu SIM_CPU;
|
||||
|
||||
/* sim-basics.h includes config.h but cgen-types.h must be included before
|
||||
sim-basics.h and cgen-types.h needs config.h. */
|
||||
#include "config.h"
|
||||
|
||||
#include "ansidecl.h"
|
||||
#include "symcat.h"
|
||||
#include "cgen-types.h"
|
||||
#include "arch.h"
|
||||
#include "sim-basics.h"
|
||||
|
||||
/* These must be defined before sim-base.h. */
|
||||
typedef USI sim_cia;
|
||||
#define CIA_GET(cpu) (cpu)->regs.h_pc
|
||||
#define CIA_SET(cpu,val) (cpu)->regs.h_pc = (val)
|
||||
|
||||
#define TRAP_SYSCALL 0
|
||||
|
||||
#include "sim-base.h"
|
||||
#include "cpu-sim.h"
|
||||
|
||||
#ifdef WANT_CPU_M32R
|
||||
#include "cpu.h"
|
||||
#include "decode.h"
|
||||
#endif
|
||||
#include "cpuall.h"
|
||||
|
||||
|
||||
/* match with definition in gx-translate.c! */
|
||||
typedef struct tgx_cpu_regs
|
||||
{
|
||||
unsigned int h_pc; /* program counter */
|
||||
signed int h_gr[16]; /* general registers */
|
||||
unsigned int h_cr[16]; /* control registers */
|
||||
long long h_accum; /* accumulator */
|
||||
unsigned h_lock; /* lock */
|
||||
} tgx_cpu_regs;
|
||||
|
||||
/* match with definition in gx-translate.c! */
|
||||
typedef struct tgx_syscall_data
|
||||
{
|
||||
unsigned pc;
|
||||
unsigned func;
|
||||
unsigned arg1;
|
||||
unsigned arg2;
|
||||
unsigned arg3;
|
||||
unsigned errcode;
|
||||
unsigned result;
|
||||
unsigned result2;
|
||||
} tgx_syscall_data;
|
||||
|
||||
|
||||
/* match with definition in gx-translate.c! */
|
||||
typedef struct tgx_callbacks
|
||||
{
|
||||
unsigned (*load)(unsigned pc, unsigned addr);
|
||||
void (*store)(unsigned pc, unsigned addr, unsigned data);
|
||||
signed char (*load1)(unsigned pc, unsigned addr);
|
||||
void (*store1)(unsigned pc, unsigned addr, signed char data);
|
||||
signed short (*load2)(unsigned pc, unsigned addr);
|
||||
void (*store2)(unsigned pc, unsigned addr, signed short data);
|
||||
void (*syscall)(tgx_syscall_data* data);
|
||||
} tgx_callbacks;
|
||||
|
||||
|
||||
|
||||
struct _sim_cpu
|
||||
{
|
||||
sim_cpu_base base;
|
||||
tgx_cpu_regs regs;
|
||||
};
|
||||
|
||||
struct sim_state {
|
||||
sim_cpu *cpu;
|
||||
#define STATE_CPU(sd, n) (/*&*/ (sd)->cpu)
|
||||
sim_state_base base;
|
||||
};
|
||||
|
||||
|
||||
/* Default memory size. */
|
||||
#define M32R_DEFAULT_MEM_SIZE 0x800000 /* 8M */
|
||||
|
||||
|
||||
|
||||
/* Register access fns. These look up the current mach and call the
|
||||
appropriate handler. */
|
||||
SI h_gr_get (SIM_CPU *, UINT);
|
||||
void h_gr_set (SIM_CPU *, UINT, SI);
|
42
sim/m32r-gx/tconfig.in
Normal file
42
sim/m32r-gx/tconfig.in
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* M32R target configuration file. -*- C -*- */
|
||||
|
||||
/* Define this if the simulator can vary the size of memory.
|
||||
See the xxx simulator for an example.
|
||||
This enables the `-m size' option.
|
||||
The memory size is stored in STATE_MEM_SIZE. */
|
||||
/* Not used for M32R since we use the memory module. */
|
||||
/* #define SIM_HAVE_MEM_SIZE */
|
||||
|
||||
/* See sim-hload.c. We properly handle LMA. */
|
||||
#define SIM_HANDLES_LMA 1
|
||||
|
||||
/* FIXME: Revisit. */
|
||||
#ifdef HAVE_DV_SOCKSER
|
||||
MODULE_INSTALL_FN dv_sockser_install;
|
||||
#define MODULE_LIST dv_sockser_install,
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* Enable watchpoints. */
|
||||
#define WITH_WATCHPOINTS 1
|
||||
#endif
|
||||
|
||||
/* no profile */
|
||||
#define WITH_PROFILE 0
|
||||
|
||||
#if 0
|
||||
#define SIM_HAVE_BREAKPOINTS
|
||||
#define SIM_BREAKPOINT { 0x10, 0xf1 }
|
||||
#define SIM_BREAKPOINT_SIZE 2
|
||||
#endif
|
||||
|
||||
/* The semantic code should probably always use a switch().
|
||||
However, in case that's not possible in some circumstance, we allow
|
||||
the target to choose. Perhaps this can be autoconf'd on whether the
|
||||
switch is too big? I can't (yet) think of a reason for allowing the
|
||||
user to choose, though the developer may certainly wish to. */
|
||||
#ifdef WANT_CPU_M32R
|
||||
#define WITH_FAST 1
|
||||
#define WITH_SEM_SWITCH_FULL 0
|
||||
#define WITH_SEM_SWITCH_FAST 1
|
||||
#endif
|
Loading…
Reference in a new issue