* Make-common.in (sim-options.o, sim-load.o): Add rules for.

(sim_main_headers): Add sim-trace.h.
	* run.c (exec_bfd, target_byte_order): Delete.
	(main): Pass -E <endian> to sim_open.  Delete code to load sections,
	call sim_load instead.  Check return code of sim_create_inferior.
	* sim-base.h (CURRENT_STATE): Define.
	(sim_state_base): Make typedef.  New members options, prog_argv,
	prog_bfd, text_{section,start,end}, start_addr, simcache_size,
	mem_size, memory [+ corresponding access macros].
	(sim_cpu_base): New typedef.
	* sim-trace.h: New file.
	* sim-basics.h: #include it.
	* sim-load.c: New file.
This commit is contained in:
David Edelsohn 1997-04-17 09:37:02 +00:00
parent 22003c917e
commit 0f2811d1c5
7 changed files with 542 additions and 52 deletions

View File

@ -1,3 +1,18 @@
Thu Apr 17 02:25:11 1997 Doug Evans <dje@canuck.cygnus.com>
* Make-common.in (sim-options.o, sim-load.o): Add rules for.
(sim_main_headers): Add sim-trace.h.
* run.c (exec_bfd, target_byte_order): Delete.
(main): Pass -E <endian> to sim_open. Delete code to load sections,
call sim_load instead. Check return code of sim_create_inferior.
* sim-base.h (CURRENT_STATE): Define.
(sim_state_base): Make typedef. New members options, prog_argv,
prog_bfd, text_{section,start,end}, start_addr, simcache_size,
mem_size, memory [+ corresponding access macros].
(sim_cpu_base): New typedef.
* sim-trace.h: New file.
* sim-basics.h: #include it.
Tue Apr 15 15:10:13 1997 Ian Lance Taylor <ian@cygnus.com>
* Make-common.in (INSTALL): Set to @INSTALL@.

View File

@ -80,7 +80,9 @@ RANLIB = @RANLIB@
MAKEINFO = makeinfo
# Each simulator's Makefile.in defines one or more of these variables
# to override our settings as necessary.
# to override our settings as necessary. There is no need to define these
# in the simulator's Makefile.in if one is using the default value. In fact
# it's preferable not to.
# List of object files, less common parts.
SIM_OBJS =
@ -174,6 +176,7 @@ sim_main_headers = \
$(srcdir)/../common/sim-config.h \
$(srcdir)/../common/sim-base.h \
$(srcdir)/../common/sim-basics.h \
$(srcdir)/../common/sim-trace.h \
tconfig.h
sim-assert_h = $(srcdir)/../common/sim-assert.h
@ -254,10 +257,17 @@ sim-io.c: $(srcdir)/../common/sim-io.c
cat $(srcdir)/../common/$@ >> tmp-$@
$(srcdir)/../../move-if-change tmp-$@ $@
sim-options.o: $(srcdir)/../common/sim-options.c $(sim_headers) \
$(srcdir)/../common/sim-options.h
$(CC) -c $(srcdir)/../common/sim-options.c $(ALL_CFLAGS)
sim-utils.o: $(srcdir)/../common/sim-utils.c $(sim_main_headers) \
$(SIM_EXTRA_DEPS)
$(CC) -c $(srcdir)/../common/sim-utils.c $(ALL_CFLAGS)
sim-load.o: $(srcdir)/../common/sim-load.c
$(CC) -c $(srcdir)/../common/sim-load.c $(ALL_CFLAGS)
install: install-common $(SIM_EXTRA_INSTALL)

View File

@ -1,5 +1,5 @@
/* run front end support for all the simulators.
Copyright (C) 1992, 1993 1994, 1995, 1996 Free Software Foundation, Inc.
Copyright (C) 1992, 93-96, 1997 Free Software Foundation, Inc.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -52,10 +52,6 @@ static void usage PARAMS ((void));
extern int optind;
extern char *optarg;
bfd *exec_bfd;
int target_byte_order;
extern host_callback default_callback;
static char *myname;
@ -74,13 +70,12 @@ main (ac, av)
char **av;
{
bfd *abfd;
bfd_vma start_address;
asection *s;
int i;
int verbose = 0;
int trace = 0;
char *name;
static char *no_args[2];
static char *no_args[4];
char **sim_argv = &no_args[0];
char **prog_args;
enum sim_stop reason;
@ -93,6 +88,8 @@ main (ac, av)
/* The first element of sim_open's argv is the program name. */
no_args[0] = av[0];
no_args[1] = "-E";
no_args[2] = "set-later";
/* FIXME: This is currently being rewritten to have each simulator
do all argv processing. */
@ -108,8 +105,11 @@ main (ac, av)
/* FIXME: Temporary hack. */
{
int len = strlen (av[0]) + strlen (optarg);
char *argbuf = (char *) alloca (len + 2);
sprintf (argbuf, "%s %s", av[0], optarg);
char *argbuf = (char *) alloca (len + 2 + 50);
/* The desired endianness must be passed to sim_open.
The value for "set-later" is set when we know what it is.
-e support isn't yet part of the published interface. */
sprintf (argbuf, "%s %s -E set-later", av[0], optarg);
sim_argv = buildargv (argbuf);
}
break;
@ -154,16 +154,21 @@ main (ac, av)
ac -= optind;
av += optind;
if (ac <= 0)
usage ();
name = *av;
prog_args = av + 1;
prog_args = av;
if (verbose)
{
printf ("%s %s\n", myname, name);
}
exec_bfd = abfd = bfd_openr (name, 0);
sim_set_callbacks (NULL, &default_callback);
default_callback.init (&default_callback);
abfd = bfd_openr (name, 0);
if (!abfd)
{
fprintf (stderr, "%s: can't open %s: %s\n",
@ -178,43 +183,27 @@ main (ac, av)
exit (1);
}
/* This must be set before sim_open is called, because gdb assumes that
the simulator endianness is known immediately after the sim_open call. */
target_byte_order = bfd_big_endian (abfd) ? 4321 : 1234;
sim_set_callbacks (NULL, &default_callback);
default_callback.init (&default_callback);
/* The endianness must be passed to sim_open because one may wish to
examine/set registers before calling sim_load [which is the other
place where one can determine endianness]. We previously passed the
endianness via global `target_byte_order' but that's not a clean
interface. */
for (i = 1; sim_argv[i + 1] != NULL; ++i)
continue;
if (bfd_big_endian (abfd))
sim_argv[i] = "big";
else
sim_argv[i] = "little";
/* Ensure that any run-time initialisation that needs to be
performed by the simulator can occur. */
sd = sim_open (SIM_OPEN_STANDALONE, sim_argv);
for (s = abfd->sections; s; s = s->next)
{
if (s->flags & SEC_LOAD)
{
unsigned char *buffer = (unsigned char *)malloc ((size_t)(bfd_section_size (abfd, s)));
if (buffer != NULL)
{
bfd_get_section_contents (abfd,
s,
buffer,
0,
bfd_section_size (abfd, s));
sim_write (sd, s->vma, buffer, bfd_section_size (abfd, s));
/* FIXME: How come we don't free buffer? */
}
else
{
fprintf (stderr, "%s: failed to allocate section buffer: %s\n",
myname, bfd_errmsg (bfd_get_error ()));
exit (1);
}
}
}
if (sim_load (sd, name, abfd, 0) == SIM_RC_FAIL)
exit (1);
start_address = bfd_get_start_address (abfd);
sim_create_inferior (sd, start_address, prog_args, NULL);
if (sim_create_inferior (sd, prog_args, NULL) == SIM_RC_FAIL)
exit (1);
if (trace)
{
@ -228,6 +217,7 @@ main (ac, av)
{
sim_resume (sd, 0, 0);
}
if (verbose)
sim_info (sd, 0);

View File

@ -38,22 +38,44 @@ with this program; if not, write to the Free Software Foundation, Inc.,
extern struct sim_state *current_state;
#endif
/* Simulator state pseudo base-class.
/* The simulator may provide different (and faster) definition. */
#ifndef CURRENT_STATE
#define CURRENT_STATE current_state
#endif
/* Simulator state pseudo baseclass.
Each simulator is required to have a sim-main.h file that includes
sim-basics.h and defines struct sim_state to be:
struct sim_state {
struct sim_state_base base;
sim_cpu cpu;
#define STATE_CPU(sd,n) (&(sd)->cpu)
... simulator specific members ...
sim_state_base base;
};
for a single processor or
struct sim_state {
sim_cpu cpu[MAX_CPUS]; -- could be also be array of pointers
#define STATE_CPU(sd,n) (&(sd)->cpu[n])
... simulator specific members ...
sim_state_base base;
};
for multiprocessors.
Note that `base' appears last. This makes `base.magic' appear last
in the entire struct and helps catch miscompilation errors.
sim_cpu is defined to be:
typedef struct {
... simulator specific members ...
sim_cpu_base base;
} sim_cpu;
*/
struct sim_state_base {
/* Marker for those wanting to do sanity checks. */
int magic;
#define SIM_MAGIC_NUMBER 0x4242
#define STATE_MAGIC(sd) ((sd)->base.magic)
typedef struct {
/* Simulator's argv[0]. */
const char *my_name;
#define STATE_MY_NAME(sd) ((sd)->base.my_name)
@ -71,7 +93,138 @@ struct sim_state_base {
struct sim_config config;
#define STATE_CONFIG(sd) ((sd)->base.config)
#endif
};
/* Supported options. */
struct option_list *options;
#define STATE_OPTIONS(sd) ((sd)->base.options)
/* Non-zero if -v specified. */
int verbose_p;
#define STATE_VERBOSE_P(sd) ((sd)->base.verbose_p)
/* In standalone simulator, this is the program's arguments passed
on the command line. */
char **prog_argv;
#define STATE_PROG_ARGV(sd) ((sd)->base.prog_argv)
/* The program's bfd. */
struct _bfd *prog_bfd;
#define STATE_PROG_BFD(sd) ((sd)->base.prog_bfd)
/* The program's text section. */
struct sec *text_section;
/* Starting and ending text section addresses from the bfd. */
SIM_ADDR text_start, text_end;
#define STATE_TEXT_SECTION(sd) ((sd)->base.text_section)
#define STATE_TEXT_START(sd) ((sd)->base.text_start)
#define STATE_TEXT_END(sd) ((sd)->base.text_end)
/* Start address, set when the program is loaded from the bfd. */
SIM_ADDR start_addr;
#define STATE_START_ADDR(sd) ((sd)->base.start_addr)
/* Size of the simulator's cache, if any.
This is not the target's cache. It is the cache the simulator uses
to process instructions. */
unsigned int simcache_size;
#define STATE_SIMCACHE_SIZE(sd) ((sd)->base.simcache_size)
/* FIXME: Move to top level sim_state struct (as some struct)? */
#ifdef SIM_HAVE_FLATMEM
unsigned int mem_size;
#define STATE_MEM_SIZE(sd) ((sd)->base.mem_size)
unsigned char *memory;
#define STATE_MEMORY(sd) ((sd)->base.memory)
#endif
/* Marker for those wanting to do sanity checks.
This should remain the last member of this struct to help catch
miscompilation errors. */
int magic;
#define SIM_MAGIC_NUMBER 0x4242
#define STATE_MAGIC(sd) ((sd)->base.magic)
} sim_state_base;
/* Pseudo baseclass for each cpu. */
typedef struct {
/* Backlink to main state struct. */
SIM_DESC sd;
/* Maximum number of traceable entities. */
#ifndef MAX_TRACE_VALUES
#define MAX_TRACE_VALUES 12
#endif
/* Boolean array of specified tracing flags. */
/* ??? It's not clear that using an array vs a bit mask is faster.
Consider the case where one wants to test whether any of several bits
are set. */
char trace_flags[MAX_TRACE_VALUES];
#define CPU_TRACE_FLAGS(cpu) ((cpu)->base.trace_flags)
/* Standard values. */
#define TRACE_INSN_IDX 0
#define TRACE_DECODE_IDX 1
#define TRACE_EXTRACT_IDX 2
#define TRACE_LINENUM_IDX 3
#define TRACE_MEMORY_IDX 4
#define TRACE_MODEL_IDX 5
#define TRACE_ALU_IDX 6
#define TRACE_NEXT_IDX 8 /* simulator specific trace bits begin here */
/* Tracing output goes to this or stdout if NULL.
We can't store `stdout' here as stdout goes through a callback. */
FILE *trace_file;
/* Maximum number of debuggable entities.
This debugging is not intended for normal use.
It is only enabled when the simulator is configured with --with-debug
which shouldn't normally be specified. */
#ifndef MAX_DEBUG_VALUES
#define MAX_DEBUG_VALUES 4
#endif
/* Boolean array of specified debugging flags. */
char debug_flags[MAX_DEBUG_VALUES];
#define CPU_DEBUG_FLAGS(cpu) ((cpu)->base.debug_flags)
/* Standard values. */
#define DEBUG_INSN_IDX 0
#define DEBUG_NEXT_IDX 2 /* simulator specific debug bits begin here */
/* Debugging output goes to this or stderr if NULL.
We can't store `stderr' here as stderr goes through a callback. */
FILE *debug_file;
#ifdef SIM_HAVE_PROFILE
/* Maximum number of profilable entities. */
#ifndef MAX_PROFILE_VALUES
#define MAX_PROFILE_VALUES 8
#endif
/* Boolean array of specified profiling flags. */
char profile_flags[MAX_PROFILE_VALUES];
#define CPU_PROFILE_FLAGS(cpu) ((cpu)->base.profile_flags)
/* Standard masks. */
#define PROFILE_INSN_MASK 0
#define PROFILE_MEMORY_MASK 1
#define PROFILE_MODEL_MASK 2
#define PROFILE_SIMCACHE_MASK 3
#define PROFILE_NEXT_MASK 6 /* simulator specific profile bits begin here */
/* PC profiling attempts to determine function usage by sampling the PC
every so many instructions. */
#ifdef SIM_HAVE_PROFILE_PC
unsigned int profile_pc_freq;
#define STATE_PROFILE_PC_FREQ(sd) ((sd)->base.profile_pc_freq)
unsigned int profile_pc_size;
#define STATE_PROFILE_PC_SIZE(sd) ((sd)->base.profile_pc_size)
#endif
/* Profile output goes to this or stdout if NULL.
We can't store `stderr' here as stdout goes through a callback. */
FILE *profile_file;
#endif /* SIM_HAVE_PROFILE */
} sim_cpu_base;
/* Functions for allocating/freeing a sim_state. */
SIM_DESC sim_state_alloc PARAMS ((void));

View File

@ -107,6 +107,7 @@ typedef enum _attach_type {
#include "sim-config.h"
#include "sim-base.h"
#include "sim-trace.h"
#include "sim-inline.h"

209
sim/common/sim-load.c Normal file
View File

@ -0,0 +1,209 @@
/* Utility to load a file into the simulator.
Copyright (C) 1997 Free Software Foundation, Inc.
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 "config.h"
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <time.h>
#include "ansidecl.h"
#include "bfd.h"
#include "callback.h"
#include "remote-sim.h"
static void eprintf PARAMS ((host_callback *, const char *, ...));
static void xprintf PARAMS ((host_callback *, const char *, ...));
static void report_transfer_performance
PARAMS ((host_callback *, unsigned long, time_t, time_t));
static void xprintf_bfd_vma PARAMS ((host_callback *, bfd_vma));
/* Load program PROG into the simulator.
If PROG_BFD is non-NULL, the file has already been opened.
If VERBOSE_P is non-zero statistics are printed of each loaded section
and the transfer rate (for consistency with gdb).
If this fails an error message is printed and NULL is returned.
If it succeeds the bfd is returned. */
/* FIXME: Where can we put a prototype for this? */
bfd *
sim_load_file (sd, myname, callback, prog, prog_bfd, verbose_p)
SIM_DESC sd;
char *myname;
host_callback *callback;
char *prog;
bfd *prog_bfd;
{
asection *s;
/* Record separately as we don't want to close PROG_BFD if it was passed. */
bfd *result_bfd;
time_t start_time, end_time; /* Start and end times of download */
unsigned long data_count = 0; /* Number of bytes transferred to memory */
if (prog_bfd != NULL)
result_bfd = prog_bfd;
else
{
result_bfd = bfd_openr (prog, 0);
if (result_bfd == NULL)
{
eprintf (callback, "%s: can't open \"%s\": %s\n",
myname, prog, bfd_errmsg (bfd_get_error ()));
return NULL;
}
}
if (!bfd_check_format (result_bfd, bfd_object))
{
eprintf (callback, "%s: \"%s\" is not an object file: %s\n",
myname, prog, bfd_errmsg (bfd_get_error ()));
/* Only close if we opened it. */
if (prog_bfd == NULL)
bfd_close (result_bfd);
return NULL;
}
if (verbose_p)
start_time = time (NULL);
for (s = result_bfd->sections; s; s = s->next)
{
if (s->flags & SEC_LOAD)
{
bfd_size_type size;
size = bfd_get_section_size_before_reloc (s);
if (size > 0)
{
char *buffer;
bfd_vma lma;
buffer = malloc (size);
if (buffer == NULL)
{
eprintf (callback,
"%s: insufficient memory to load \"%s\"\n",
myname, prog);
/* Only close if we opened it. */
if (prog_bfd == NULL)
bfd_close (result_bfd);
return NULL;
}
/* Before you change this to bfd_section_lma, make sure
the arm-pe simulator still works. */
lma = bfd_section_vma (result_bfd, s);
if (verbose_p)
{
xprintf (callback, "Loading section %s, size 0x%lx lma ",
bfd_get_section_name (result_bfd, s),
(unsigned long) size);
xprintf_bfd_vma (callback, lma);
xprintf (callback, "\n");
}
data_count += size;
bfd_get_section_contents (result_bfd, s, buffer, 0, size);
sim_write (sd, lma, buffer, size);
free (buffer);
}
}
}
if (verbose_p)
{
end_time = time (NULL);
xprintf (callback, "Start address ");
xprintf_bfd_vma (callback, bfd_get_start_address (result_bfd));
xprintf (callback, "\n");
report_transfer_performance (callback, data_count, start_time, end_time);
}
return result_bfd;
}
static void
xprintf VPARAMS ((host_callback *callback, const char *fmt, ...))
{
#ifndef __STDC__
host_callback *callback;
char *fmt;
#endif
va_list ap;
VA_START (ap, fmt);
#ifndef __STDC__
callback = va_arg (ap, host_callback *);
fmt = va_arg (ap, char *);
#endif
(*callback->vprintf_filtered) (callback, fmt, ap);
va_end (ap);
}
static void
eprintf VPARAMS ((host_callback *callback, const char *fmt, ...))
{
#ifndef __STDC__
host_callback *callback;
char *fmt;
#endif
va_list ap;
VA_START (ap, fmt);
#ifndef __STDC__
callback = va_arg (ap, host_callback *);
fmt = va_arg (ap, char *);
#endif
(*callback->evprintf_filtered) (callback, fmt, ap);
va_end (ap);
}
/* Report how fast the transfer went. */
static void
report_transfer_performance (callback, data_count, start_time, end_time)
host_callback *callback;
unsigned long data_count;
time_t start_time, end_time;
{
xprintf (callback, "Transfer rate: ");
if (end_time != start_time)
xprintf (callback, "%ld bits/sec",
(data_count * 8) / (end_time - start_time));
else
xprintf (callback, "%ld bits in <1 sec", (data_count * 8));
xprintf (callback, ".\n");
}
/* Print a bfd_vma.
This is intended to handle the vagaries of 32 vs 64 bits, etc. */
static void
xprintf_bfd_vma (callback, vma)
host_callback *callback;
bfd_vma vma;
{
/* FIXME: for now */
xprintf (callback, "0x%lx", (unsigned long) vma);
}

112
sim/common/sim-trace.h Normal file
View File

@ -0,0 +1,112 @@
/* Simulator tracing/debugging support.
Copyright (C) 1997 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, 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. */
/* This file is meant to be included by sim-basics.h. */
#ifndef SIM_TRACE_H
#define SIM_TRACE_H
/* Tracing support. */
#ifdef MAX_CPUS
/* Return non-zero if tracing of IDX is enabled for CPU. */
#define TRACE_P(cpu,idx) \
((WITH_TRACE & (1 << (idx))) != 0 \
&& CPU_TRACE_FLAGS (cpu)[idx] != 0)
/* Non-zero if "--trace-insn" specified for CPU. */
#define TRACE_INSN_P(cpu) TRACE_P (cpu, TRACE_INSN_IDX)
#define TRACE_PRINTF(cpu, idx, args) \
do { \
if ((WITH_TRACE & (1 << (idx))) != 0 \
&& CPU_TRACE_FLAGS (cpu)[idx] != 0) \
trace_printf args; \
} while (0)
#else
/* Fetch current tracing flags. */
#define CURRENT_TRACE_FLAGS CPU_TRACE_FLAGS (& CURRENT_STATE->cpu)
/* Return non-zero if tracing of IDX is enabled. */
#define TRACE_P(idx) \
((WITH_TRACE & (1 << (idx))) != 0 \
&& CURRENT_TRACE_FLAGS[idx] != 0)
/* Non-zero if "--trace-insn" specified. */
#define TRACE_INSN_P TRACE_P (TRACE_INSN_IDX)
#define TRACE_PRINTF(idx, args) \
do { \
if ((WITH_TRACE & (1 << (idx))) != 0 \
&& CURRENT_TRACE_FLAGS[idx] != 0) \
trace_printf args; \
} while (0)
#endif /* MAX_CPUS */
extern void trace_printf PARAMS ((char *, ...));
/* Debug support. */
#ifdef MAX_CPUS
/* Return non-zero if debugging of IDX for CPU is enabled. */
#define DEBUG_P(cpu, idx) \
((WITH_DEBUG & (1 << (idx))) != 0 \
&& CPU_DEBUG_FLAGS (cpu)[idx] != 0)
/* Non-zero if "--debug-insn" specified. */
#define DEBUG_INSN_P(cpu) DEBUG_P (cpu, DEBUG_INSN_IDX)
#define DEBUG_PRINTF(cpu, idx, args) \
do { \
if ((WITH_DEBUG & (1 << (idx))) != 0 \
&& CPU_DEBUG_FLAGS (cpu)[idx] != 0) \
debug_printf args; \
} while (0)
#else
/* Fetch current debugging flags. */
#define CURRENT_DEBUG_FLAGS CPU_DEBUG_FLAGS (& CURRENT_STATE->cpu)
/* Return non-zero if debugging of IDX is enabled. */
#define DEBUG_P(idx) \
((WITH_DEBUG & (1 << (idx))) != 0 \
&& CURRENT_DEBUG_FLAGS[idx] != 0)
/* Non-zero if "--debug-insn" specified. */
#define DEBUG_INSN_P DEBUG_P (DEBUG_INSN_IDX)
#define DEBUG_PRINTF(idx, args) \
do { \
if ((WITH_DEBUG & (1 << (idx))) != 0 \
&& CURRENT_DEBUG_FLAGS[idx] != 0) \
debug_printf args; \
} while (0)
#endif /* MAX_CPUS */
extern void debug_printf PARAMS ((char *, ...));
#endif /* SIM_TRACE_H */