* 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:
Frank Ch. Eigler 1998-11-14 04:35:47 +00:00
parent fca5abc13a
commit 92fa45795d
23 changed files with 11603 additions and 0 deletions

View file

@ -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

View file

@ -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.

View 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.

View file

@ -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
View 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
View 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
View 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 */

View file

@ -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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

26
sim/m32r-gx/configure.in Normal file
View 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
View file

@ -0,0 +1,2 @@
#include "sim-cpu.h"
#include "sim-model.h"

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

File diff suppressed because it is too large Load diff

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
View file

250
sim/m32r-gx/sim-if.c Normal file
View 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
View 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
View 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