Browse Source
[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.gdb-4_18-branch
23 changed files with 11603 additions and 0 deletions
@ -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); |
|||
} |
|||
} |
|||
@ -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); */ |
|||
} |
|||
|
|||
@ -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 */ |
|||
@ -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. |
|||
@ -0,0 +1,3 @@ |
|||
1998-11-13 Frank Ch. Eigler <fche@elastic.org> |
|||
|
|||
* (*): New files: snapshot of gx simulator prototype. |
|||
@ -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) |
|||
@ -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 */ |
|||
|
|||
@ -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 |
|||
File diff suppressed because it is too large
@ -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 |
|||
|
|||
|
|||
|
|||
@ -0,0 +1,2 @@ |
|||
#include "sim-cpu.h" |
|||
#include "sim-model.h" |
|||
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -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"); |
|||
} |
|||
@ -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); |
|||
@ -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 new issue