o Implement generic halt/restart/abort module.

Use in tic80 and d30v simulators.
o	Add signal hook to sim-core module
This commit is contained in:
Andrew Cagney
1997-05-19 03:42:33 +00:00
parent 11ab132f16
commit f03b093cd3
18 changed files with 1415 additions and 377 deletions

View File

@ -61,6 +61,8 @@ sim-events.c
sim-events.h sim-events.h
sim-fpu.c sim-fpu.c
sim-fpu.h sim-fpu.h
sim-halt.c
sim-halt.h
sim-inline.c sim-inline.c
sim-inline.h sim-inline.h
sim-io.c sim-io.c

View File

@ -1,3 +1,68 @@
Mon May 19 12:07:22 1997 Andrew Cagney <cagney@b1.cygnus.com>
* sim-basics.h (transfer_type): New type.
* sim-core.c (sim_core_signal): New function. Print core signal
information.
(sim_core_find_mapping): Add transfer argument.
* sim-n-core.h (sim_core_{write,write}_unaligned_N): Call
SIM_CORE_SIGNAL if a recoverable abort.
* sim-core.c (sim_core_find_mapping): Ditto.
Fri May 16 15:13:21 1997 Andrew Cagney <cagney@b1.cygnus.com>
* sim-core.c (sim_core_find_mapping): Replace calls to
sim_io_error to more resiliant sim_engine_abort.
* sim-n-core.h (sim_core_read_unaligned_N): Ditto.
(sim_core_write_unaligned_N): Ditto.
Tue May 13 13:50:06 1997 Andrew Cagney <cagney@b1.cygnus.com>
* sim-module.c: Add sim_events_install to list.
* sim-events.c (sim_events_install, sim_events_uninstall): Clonse
from sim_core_*.
(sim_events_init): Now returns SIG_RC.
* sim-run.c: New file. Generic sim_engine_run.
* sim-reason.c: New file. Generic sim_stop_reason.
* sim-stop.c: New file. Generic sim_stop.
* sim-resume.c: New file. Generic sim_resume.
* Make-common.in (sim-engine.o): Add rule.
(sim-run.o, sim-reason.o, sim-stop.o, sim-resume.o): Ditto.
* sim-engine.h, sim-engine.c: New file. Provide generic
implementation of sim_engine_halt, sim_engine_error. et.al.
* sim-base.h (sim_state_base): Add member halt.
(sim-engine.h): Include.
* sim-events.h (sim_event_handler): Always pass SIM_DESC to event
handlers.
* sim-events.c (sim_events_poll): Update event handler.
Tue May 13 09:57:49 1997 Andrew Cagney <cagney@b2.cygnus.com>
* sim-events.h, sim-events.c (sim_events_watch_clock): New
function.
(sim_events_watch_sim): New function.
(sim_events_watch_core): New function.
(sim_watch_valid): New function.
(sim_events_preprocess): New function.
(sim_events_process): Process the watchpoints as well as the timer
queue.
(sim_events_tick): Check WORK_PENDING instead of the hold queue.
(sim_events_deschedule): Check all the queues when removing an
event.
(sim_events_init): Ditto for cleaning.
Mon May 19 12:07:22 1997 Andrew Cagney <cagney@b1.cygnus.com>
* sim-fpu.c (is_ufpu_number): Comment out - currently unused.
Mon May 19 11:23:03 1997 Andrew Cagney <cagney@b1.cygnus.com> Mon May 19 11:23:03 1997 Andrew Cagney <cagney@b1.cygnus.com>
* callback.c (os_open): Type of arg flags is int. * callback.c (os_open): Type of arg flags is int.

View File

@ -180,6 +180,7 @@ sim_main_headers = \
$(srcdir)/../common/sim-module.h \ $(srcdir)/../common/sim-module.h \
$(srcdir)/../common/sim-trace.h \ $(srcdir)/../common/sim-trace.h \
$(srcdir)/../common/sim-profile.h \ $(srcdir)/../common/sim-profile.h \
$(srcdir)/../common/sim-engine.h \
tconfig.h tconfig.h
sim-assert_h = $(srcdir)/../common/sim-assert.h sim-assert_h = $(srcdir)/../common/sim-assert.h
@ -190,6 +191,7 @@ sim-config_h = $(srcdir)/../common/sim-config.h
sim-n-bits_h = $(srcdir)/../common/sim-n-bits.h sim-n-bits_h = $(srcdir)/../common/sim-n-bits.h
sim-core_h = $(srcdir)/../common/sim-core.h sim-core_h = $(srcdir)/../common/sim-core.h
sim-n-core_h = $(srcdir)/../common/sim-n-core.h sim-n-core_h = $(srcdir)/../common/sim-n-core.h
sim-engine_h = $(srcdir)/../common/sim-engine.h
sim-events_h = $(srcdir)/../common/sim-events.h sim-events_h = $(srcdir)/../common/sim-events.h
sim-fpu_h = $(srcdir)/../common/sim-fpu.h sim-fpu_h = $(srcdir)/../common/sim-fpu.h
sim-io_h = $(srcdir)/../common/sim-io.h sim-io_h = $(srcdir)/../common/sim-io.h
@ -207,6 +209,14 @@ BUILT_SRC_FROM_COMMON= \
sim-config.c \ sim-config.c \
sim-io.c sim-io.c
sim-abort.o: sim-abort.c \
$(SIM_EXTRA_DEPS)
sim-abort.c: $(srcdir)/../common/sim-abort.c
rm -f $@ tmp-$@
echo "# 1 \"$(srcdir)/../common/$@\"" > tmp-$@
cat $(srcdir)/../common/$@ >> tmp-$@
$(srcdir)/../../move-if-change tmp-$@ $@
sim-bits.o: sim-bits.c $(sim-bits_h) $(sim-n-bits_h) $(sim-assert_h) \ sim-bits.o: sim-bits.c $(sim-bits_h) $(sim-n-bits_h) $(sim-assert_h) \
$(SIM_EXTRA_DEPS) $(SIM_EXTRA_DEPS)
sim-bits.c: $(srcdir)/../common/sim-bits.c sim-bits.c: $(srcdir)/../common/sim-bits.c
@ -239,6 +249,14 @@ sim-endian.c: $(srcdir)/../common/sim-endian.c
cat $(srcdir)/../common/$@ >> tmp-$@ cat $(srcdir)/../common/$@ >> tmp-$@
$(srcdir)/../../move-if-change tmp-$@ $@ $(srcdir)/../../move-if-change tmp-$@ $@
sim-engine.o: sim-engine.c $(sim_main_headers) $(sim-engine_h) $(sim-assert_h) \
$(SIM_EXTRA_DEPS)
sim-engine.c: $(srcdir)/../common/sim-engine.c
rm -f $@ tmp-$@
echo "# 1 \"$(srcdir)/../common/$@\"" > tmp-$@
cat $(srcdir)/../common/$@ >> tmp-$@
$(srcdir)/../../move-if-change tmp-$@ $@
sim-events.o: sim-events.c $(sim-events_h) $(sim-assert_h) \ sim-events.o: sim-events.c $(sim-events_h) $(sim-assert_h) \
$(SIM_EXTRA_DEPS) $(SIM_EXTRA_DEPS)
sim-events.c: $(srcdir)/../common/sim-events.c sim-events.c: $(srcdir)/../common/sim-events.c
@ -277,6 +295,38 @@ sim-options.o: $(srcdir)/../common/sim-options.c $(sim_main_headers) \
$(sim-options_h) $(sim-io_h) $(SIM_EXTRA_DEPS) $(sim-options_h) $(sim-io_h) $(SIM_EXTRA_DEPS)
$(CC) -c $(srcdir)/../common/sim-options.c $(ALL_CFLAGS) $(CC) -c $(srcdir)/../common/sim-options.c $(ALL_CFLAGS)
sim-reason.o: sim-reason.c $(sim_main_headers) $(sim-assert_h) \
$(SIM_EXTRA_DEPS)
sim-reason.c: $(srcdir)/../common/sim-reason.c
rm -f $@ tmp-$@
echo "# 1 \"$(srcdir)/../common/$@\"" > tmp-$@
cat $(srcdir)/../common/$@ >> tmp-$@
$(srcdir)/../../move-if-change tmp-$@ $@
sim-resume.o: sim-resume.c $(sim_main_headers) $(sim-assert_h) \
$(SIM_EXTRA_DEPS)
sim-resume.c: $(srcdir)/../common/sim-resume.c
rm -f $@ tmp-$@
echo "# 1 \"$(srcdir)/../common/$@\"" > tmp-$@
cat $(srcdir)/../common/$@ >> tmp-$@
$(srcdir)/../../move-if-change tmp-$@ $@
sim-run.o: sim-run.c $(sim_main_headers) $(sim-assert_h) \
$(SIM_EXTRA_DEPS)
sim-run.c: $(srcdir)/../common/sim-run.c
rm -f $@ tmp-$@
echo "# 1 \"$(srcdir)/../common/$@\"" > tmp-$@
cat $(srcdir)/../common/$@ >> tmp-$@
$(srcdir)/../../move-if-change tmp-$@ $@
sim-stop.o: sim-stop.c $(sim_main_headers) $(sim-assert_h) \
$(SIM_EXTRA_DEPS)
sim-stop.c: $(srcdir)/../common/sim-stop.c
rm -f $@ tmp-$@
echo "# 1 \"$(srcdir)/../common/$@\"" > tmp-$@
cat $(srcdir)/../common/$@ >> tmp-$@
$(srcdir)/../../move-if-change tmp-$@ $@
sim-trace.o: $(srcdir)/../common/sim-trace.c $(sim_main_headers) \ sim-trace.o: $(srcdir)/../common/sim-trace.c $(sim_main_headers) \
$(sim-options_h) $(sim-io_h) $(SIM_EXTRA_DEPS) $(sim-options_h) $(sim-io_h) $(SIM_EXTRA_DEPS)
$(CC) -c $(srcdir)/../common/sim-trace.c $(ALL_CFLAGS) $(CC) -c $(srcdir)/../common/sim-trace.c $(ALL_CFLAGS)

60
sim/common/sim-abort.c Normal file
View File

@ -0,0 +1,60 @@
/* Generic simulator abort.
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. */
#include "sim-main.h"
#include <signal.h>
#include <stdio.h>
/* This is an implementation of sim_engine_abort that does not use
longjmp, instead it just calls sim_io_error. sim_io_error will
jump right out of the simulator.
It is intended as a holder for simulators that have started to use
sim-core et.al. but are not yet in a position to use sim-engine
(the setjmp/longjmp code). */
void
sim_engine_abort (SIM_DESC sd,
sim_cpu *cpu,
sim_cia cia,
const char *fmt,
...)
{
if (sd != NULL)
{
va_list ap;
va_start(ap, fmt);
sim_io_evprintf (sd, fmt, ap);
va_end(ap);
sim_io_error (sd, "\n");
}
else
{
va_list ap;
va_start(ap, fmt);
vfprintf (stderr, fmt, ap);
va_end(ap);
fprintf (stderr, "\n");
abort ();
}
}

134
sim/common/sim-engine.c Normal file
View File

@ -0,0 +1,134 @@
/* Generic simulator halt/restart.
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. */
#include "sim-main.h"
#include <stdio.h>
#include <signal.h>
/* Generic halt */
void
sim_engine_halt (SIM_DESC sd,
sim_cpu *last_cpu,
sim_cpu *next_cpu, /* NULL - use default */
sim_cia cia,
enum sim_stop reason,
int sigrc)
{
sim_engine *engine = STATE_ENGINE (sd);
if (engine->jmpbuf != NULL)
{
jmp_buf *halt_buf = engine->jmpbuf;
engine->last_cpu = last_cpu;
engine->next_cpu = next_cpu;
engine->reason = reason;
engine->sigrc = sigrc;
SIM_ENGINE_HALT_HOOK (sd, last_cpu, cia);
longjmp(*halt_buf, 1);
}
else
sim_io_error (sd, "sim_halt - bad long jump");
}
/* Generic restart */
void
sim_engine_restart (SIM_DESC sd,
sim_cpu *last_cpu,
sim_cpu *next_cpu,
sim_cia cia)
{
sim_engine *engine = STATE_ENGINE (sd);
if (engine->jmpbuf != NULL)
{
jmp_buf *halt_buf = engine->jmpbuf;
engine->last_cpu = last_cpu;
engine->next_cpu = next_cpu;
SIM_ENGINE_RESTART_HOOK (sd, last_cpu, cia);
longjmp(*halt_buf, 0);
}
else
sim_io_error (sd, "sim_restart - bad long jump");
}
/* Generic error code */
void
sim_engine_abort (SIM_DESC sd,
sim_cpu *cpu,
sim_cia cia,
const char *fmt,
...)
{
if (sd == NULL)
{
va_list ap;
va_start(ap, fmt);
vfprintf (stderr, fmt, ap);
va_end(ap);
fprintf (stderr, "\nQuit\n");
abort ();
}
else if (STATE_ENGINE (sd)->jmpbuf == NULL)
{
va_list ap;
va_start(ap, fmt);
sim_io_evprintf (sd, fmt, ap);
va_end(ap);
sim_io_eprintf (sd, "\n");
sim_io_error (sd, "Quit Simulator");
}
else
{
va_list ap;
va_start(ap, fmt);
sim_io_evprintf (sd, fmt, ap);
va_end(ap);
sim_io_eprintf (sd, "\n");
sim_engine_halt (sd, cpu, NULL, cia, sim_stopped, SIGABRT);
}
}
/* Generic next/last cpu */
int
sim_engine_last_cpu_nr (SIM_DESC sd)
{
sim_engine *engine = STATE_ENGINE (sd);
if (engine->last_cpu != NULL)
return engine->last_cpu - STATE_CPU (sd, 0);
else
return MAX_NR_PROCESSORS;
}
int
sim_engine_next_cpu_nr (SIM_DESC sd)
{
sim_engine *engine = STATE_ENGINE (sd);
if (engine->next_cpu != NULL)
return engine->next_cpu - STATE_CPU (sd, 0);
else
return sim_engine_last_cpu_nr (sd) + 1;
}

122
sim/common/sim-engine.h Normal file
View File

@ -0,0 +1,122 @@
/* Generic simulator halt/resume.
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. */
#ifndef SIM_ENGINE_H
#define SIM_ENGINE_H
typedef struct _sim_engine sim_engine;
struct _sim_engine
{
void *jmpbuf;
sim_cpu *last_cpu;
sim_cpu *next_cpu;
enum sim_stop reason;
sim_event *stepper;
int sigrc;
};
/* Halt the simulator *now* */
extern void sim_engine_halt
(SIM_DESC sd,
sim_cpu *last_cpu,
sim_cpu *next_cpu, /* NULL -> succ (last_cpu) or event-mgr */
sim_cia cia,
enum sim_stop reason,
int sigrc);
/* Halt hook - allow target specific operation when halting a
simulator */
#if !defined (SIM_ENGINE_HALT_HOOK)
#define SIM_ENGINE_HALT_HOOK(SD, LAST_CPU, CIA) if ((LAST_CPU) != NULL) (LAST_CPU)->cia = cia
#endif
/* restart the simulator *now* */
extern void sim_engine_restart
(SIM_DESC sd,
sim_cpu *last_cpu,
sim_cpu *next_cpu,
sim_cia cia);
/* Restart hook - allow target specific operation when restarting a
simulator */
#if !defined (SIM_ENGINE_RESTART_HOOK)
#define SIM_ENGINE_RESTART_HOOK(SD, LAST_CPU, CIA) SIM_ENGINE_HALT_HOOK(SD, LAST_CPU, CIA)
#endif
/* Abort the simulator *now*.
This function is NULL safe. It can be called when either of SD or
CIA are NULL.
This function is setjmp/longjmp safe. It can be called when of
the sim_engine setjmp/longjmp buffer has not been established.
Simulators that are using components such as sim-core but are not
yet using this sim-engine module should link in file sim-abort.o
which implements a non setjmp/longjmp version of
sim_engine_abort. */
extern void sim_engine_abort
(SIM_DESC sd,
sim_cpu *cpu,
sim_cia cia,
const char *fmt,
...);
/* No abort hook - when possible this function exits using the
engine_halt function (and SIM_ENGINE_HALT_HOOK). */
/* Called by the generic sim_resume to run the simulation within the
above safty net.
An example implementation of sim_engine_run can be found in the
file sim-run.c */
extern void sim_engine_run
(SIM_DESC sd,
int next_cpu_nr,
int siggnal); /* most simulators ignore siggnal */
/* Determine the state of next/last cpu when the simulator was last
halted - a value >= nr-cpus indicates that the event-queue was
next/last. */
extern int sim_engine_next_cpu_nr (SIM_DESC sd);
extern int sim_engine_last_cpu_nr (SIM_DESC sd);
#endif

View File

@ -27,6 +27,71 @@
#include <signal.h> #include <signal.h>
typedef enum {
watch_invalid,
/* core - target byte order */
watch_core_targ_1,
watch_core_targ_2,
watch_core_targ_4,
watch_core_targ_8,
/* core - big-endian */
watch_core_be_1,
watch_core_be_2,
watch_core_be_4,
watch_core_be_8,
/* core - little-endian */
watch_core_le_1,
watch_core_le_2,
watch_core_le_4,
watch_core_le_8,
/* sim - host byte order */
watch_sim_host_1,
watch_sim_host_2,
watch_sim_host_4,
watch_sim_host_8,
/* sim - big-endian */
watch_sim_be_1,
watch_sim_be_2,
watch_sim_be_4,
watch_sim_be_8,
/* sim - little-endian */
watch_sim_le_1,
watch_sim_le_2,
watch_sim_le_4,
watch_sim_le_8,
/* wallclock */
watch_clock,
/* timer */
watch_timer,
} sim_watchpoints;
struct _sim_event {
sim_watchpoints watching;
void *data;
sim_event_handler *handler;
/* timer event */
signed64 time_of_event;
/* watch wallclock event */
unsigned wallclock;
/* watch core address */
address_word core_addr;
sim_core_maps core_map;
/* watch sim addr */
void *host_addr;
/* watch core/sim range */
unsigned ub;
unsigned lb;
unsigned64 ub64;
unsigned64 lb64;
/* list */
sim_event *next;
};
/* The event queue maintains a single absolute time using two /* The event queue maintains a single absolute time using two
variables. variables.
@ -65,10 +130,10 @@ do \
{ \ { \
if (WITH_TRACE) \ if (WITH_TRACE) \
{ \ { \
if (sd->events.trace) \ if (STATE_EVENTS (sd)->trace) \
{ \ { \
const char *file; \ const char *file; \
SIM_FILTER_PATH(file, __FILE__); \ SIM_FILTER_PATH (file, __FILE__); \
sim_io_printf (sd, "%s:%d: ", file, __LINE__); \ sim_io_printf (sd, "%s:%d: ", file, __LINE__); \
sim_io_printf ARGS; \ sim_io_printf ARGS; \
} \ } \
@ -77,26 +142,72 @@ do \
while (0) while (0)
/* event queue iterator */
STATIC_INLINE_SIM_EVENTS\
(sim_event **)
next_event_queue (SIM_DESC sd,
sim_event **queue)
{
if (queue == NULL)
return &STATE_EVENTS (sd)->queue;
else if (queue == &STATE_EVENTS (sd)->queue)
return &STATE_EVENTS (sd)->watchpoints;
else if (queue == &STATE_EVENTS (sd)->watchpoints)
return &STATE_EVENTS (sd)->watchedpoints;
else if (queue == &STATE_EVENTS (sd)->watchedpoints)
return NULL;
else
sim_io_error (sd, "next_event_queue - bad queue");
return NULL;
}
STATIC_INLINE_SIM_EVENTS\ STATIC_INLINE_SIM_EVENTS\
(void) (void)
sim_events_poll (void *data) sim_events_poll (SIM_DESC sd,
void *data)
{ {
/* just re-schedule in 1000 million ticks time */ /* just re-schedule in 1000 million ticks time */
SIM_DESC sd = data; sim_events_schedule (sd, SIM_EVENTS_POLL_RATE, sim_events_poll, sd);
sim_events_schedule(sd, SIM_EVENTS_POLL_RATE, sim_events_poll, sd);
sim_io_poll_quit (sd); sim_io_poll_quit (sd);
} }
INLINE_SIM_EVENTS\ /* "events" module install handler.
(void) This is called via sim_module_install to install the "events" subsystem
sim_events_init(SIM_DESC sd) into the simulator. */
EXTERN_SIM_EVENTS\
(SIM_RC)
sim_events_install (SIM_DESC sd)
{ {
sim_events *events = &sd->events; sim_module_add_uninstall_fn (sd, sim_events_uninstall);
sim_event *event; sim_module_add_init_fn (sd, sim_events_init);
return SIM_RC_OK;
}
/* Uninstall the "events" subsystem from the simulator. */
EXTERN_SIM_EVENTS\
(void)
sim_events_uninstall (SIM_DESC sd)
{
/* FIXME: free buffers, etc. */
}
/* Initialize the simulator event manager */
EXTERN_SIM_EVENTS\
(SIM_RC)
sim_events_init (SIM_DESC sd)
{
sim_events *events = STATE_EVENTS (sd);
/* drain the interrupt queue */ /* drain the interrupt queue */
{ {
sim_event *event;
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK) #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
sigset_t old_mask; sigset_t old_mask;
sigset_t new_mask; sigset_t new_mask;
@ -111,86 +222,103 @@ sim_events_init(SIM_DESC sd)
} }
events->held = NULL; events->held = NULL;
events->held_end = &events->held; events->held_end = &events->held;
events->work_pending = 0;
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK) #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
/*-UNLOCK-*/ sigprocmask(SIG_SETMASK, &old_mask, NULL); /*-UNLOCK-*/ sigprocmask(SIG_SETMASK, &old_mask, NULL);
#endif #endif
} }
/* drain the normal queue */ /* drain the normal queues */
event = events->queue; {
while (event != NULL) { sim_event **queue = NULL;
sim_event *dead = event; while ((queue = next_event_queue (sd, queue)) != NULL)
event = event->next; {
zfree(dead); if (queue == NULL) break;
while (*queue != NULL)
{
sim_event *dead = *queue;
*queue = dead->next;
zfree (dead);
}
*queue = NULL;
}
} }
events->queue = NULL;
/* wind time back to zero */ /* wind time back to zero */
events->processing = 0; events->processing = 1; /* start by doing queue */
events->time_of_event = 0; events->time_of_event = 0;
events->time_from_event = 0; events->time_from_event = 0;
events->initial_wallclock = sim_elapsed_time_get ();
/* schedule our initial counter event */ /* schedule our initial counter event */
sim_events_schedule(sd, 0, sim_events_poll, sd); sim_events_schedule (sd, 0, sim_events_poll, sd);
/* from now on, except when the large-int event is being processed /* from now on, except when the large-int event is being processed
the event queue is non empty */ the event queue is non empty */
SIM_ASSERT(events->queue != NULL); SIM_ASSERT (events->queue != NULL);
return SIM_RC_OK;
} }
INLINE_SIM_EVENTS\ INLINE_SIM_EVENTS\
(signed64) (signed64)
sim_events_time(SIM_DESC sd) sim_events_time (SIM_DESC sd)
{ {
sim_events *events = &sd->events; sim_events *events = STATE_EVENTS (sd);
return events->time_of_event - events->time_from_event; return events->time_of_event - events->time_from_event;
} }
STATIC_INLINE_SIM_EVENTS\
(void)
update_time_from_event(SIM_DESC sd)
{
sim_events *events = &sd->events;
signed64 current_time = sim_events_time(sd);
if (events->queue != NULL) {
events->time_from_event = (events->queue->time_of_event - current_time);
events->time_of_event = events->queue->time_of_event;
}
else {
events->time_of_event = current_time - 1;
events->time_from_event = -1;
}
SIM_ASSERT(current_time == sim_events_time (sd));
SIM_ASSERT((events->time_from_event >= 0) == (events->queue != NULL));
}
STATIC_INLINE_SIM_EVENTS\ STATIC_INLINE_SIM_EVENTS\
(void) (void)
insert_sim_event(SIM_DESC sd, update_time_from_event (SIM_DESC sd)
sim_event *new_event,
signed64 delta)
{ {
sim_events *events = &sd->events; sim_events *events = STATE_EVENTS (sd);
signed64 current_time = sim_events_time (sd);
if (events->queue != NULL)
{
events->time_from_event = (events->queue->time_of_event - current_time);
events->time_of_event = events->queue->time_of_event;
}
else
{
events->time_of_event = current_time - 1;
events->time_from_event = -1;
}
SIM_ASSERT (current_time == sim_events_time (sd));
SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
}
STATIC_INLINE_SIM_EVENTS\
(void)
insert_sim_event (SIM_DESC sd,
sim_event *new_event,
signed64 delta)
{
sim_events *events = STATE_EVENTS (sd);
sim_event *curr; sim_event *curr;
sim_event **prev; sim_event **prev;
signed64 time_of_event; signed64 time_of_event;
if (delta < 0) if (delta < 0)
engine_error (sd, "what is past is past!\n"); sim_io_error (sd, "what is past is past!\n");
/* compute when the event should occure */ /* compute when the event should occure */
time_of_event = sim_events_time(sd) + delta; time_of_event = sim_events_time (sd) + delta;
/* find the queue insertion point - things are time ordered */ /* find the queue insertion point - things are time ordered */
prev = &events->queue; prev = &events->queue;
curr = events->queue; curr = events->queue;
while (curr != NULL && time_of_event >= curr->time_of_event) { while (curr != NULL && time_of_event >= curr->time_of_event)
SIM_ASSERT(curr->next == NULL {
|| curr->time_of_event <= curr->next->time_of_event); SIM_ASSERT (curr->next == NULL
prev = &curr->next; || curr->time_of_event <= curr->next->time_of_event);
curr = curr->next; prev = &curr->next;
} curr = curr->next;
SIM_ASSERT(curr == NULL || time_of_event < curr->time_of_event); }
SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event);
/* insert it */ /* insert it */
new_event->next = curr; new_event->next = curr;
@ -198,19 +326,21 @@ insert_sim_event(SIM_DESC sd,
new_event->time_of_event = time_of_event; new_event->time_of_event = time_of_event;
/* adjust the time until the first event */ /* adjust the time until the first event */
update_time_from_event(sd); update_time_from_event (sd);
} }
INLINE_SIM_EVENTS\
EXTERN_SIM_EVENTS\
(sim_event *) (sim_event *)
sim_events_schedule(SIM_DESC sd, sim_events_schedule (SIM_DESC sd,
signed64 delta_time, signed64 delta_time,
sim_event_handler *handler, sim_event_handler *handler,
void *data) void *data)
{ {
sim_event *new_event = ZALLOC(sim_event); sim_event *new_event = ZALLOC(sim_event);
new_event->data = data; new_event->data = data;
new_event->handler = handler; new_event->handler = handler;
new_event->watching = watch_timer;
insert_sim_event(sd, new_event, delta_time); insert_sim_event(sd, new_event, delta_time);
ETRACE((_ETRACE, ETRACE((_ETRACE,
"event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n", "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
@ -223,15 +353,15 @@ sim_events_schedule(SIM_DESC sd,
} }
INLINE_SIM_EVENTS\ EXTERN_SIM_EVENTS\
(sim_event *) (sim_event *)
sim_events_schedule_after_signal(SIM_DESC sd, sim_events_schedule_after_signal(SIM_DESC sd,
signed64 delta_time, signed64 delta_time,
sim_event_handler *handler, sim_event_handler *handler,
void *data) void *data)
{ {
sim_events *events = &sd->events; sim_events *events = STATE_EVENTS (sd);
sim_event *new_event = ZALLOC(sim_event); sim_event *new_event = ZALLOC (sim_event);
new_event->data = data; new_event->data = data;
new_event->handler = handler; new_event->handler = handler;
@ -239,11 +369,12 @@ sim_events_schedule_after_signal(SIM_DESC sd,
new_event->next = NULL; new_event->next = NULL;
{ {
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK) #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
/*-LOCK-*/
sigset_t old_mask; sigset_t old_mask;
sigset_t new_mask; sigset_t new_mask;
sigfillset(&new_mask); sigfillset(&new_mask);
/*-LOCK-*/ sigprocmask(SIG_SETMASK, &new_mask, &old_mask); sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
#endif #endif
if (events->held == NULL) { if (events->held == NULL) {
events->held = new_event; events->held = new_event;
@ -252,77 +383,337 @@ sim_events_schedule_after_signal(SIM_DESC sd,
*events->held_end = new_event; *events->held_end = new_event;
} }
events->held_end = &new_event->next; events->held_end = &new_event->next;
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK) events->work_pending = 1; /* notify main process */
/*-UNLOCK-*/ sigprocmask(SIG_SETMASK, &old_mask, NULL); #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
/*-UNLOCK-*/
sigprocmask (SIG_SETMASK, &old_mask, NULL);
#endif #endif
} }
ETRACE((_ETRACE, ETRACE ((_ETRACE,
"event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n", "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
(long)sim_events_time(sd), (long)sim_events_time(sd),
(long)new_event, (long)new_event,
(long)new_event->time_of_event, (long)new_event->time_of_event,
(long)new_event->handler, (long)new_event->handler,
(long)new_event->data)); (long)new_event->data));
return new_event; return new_event;
} }
INLINE_SIM_EVENTS\ EXTERN_SIM_EVENTS\
(void) (sim_event *)
sim_events_deschedule(SIM_DESC sd, sim_events_watch_clock (SIM_DESC sd,
sim_event *event_to_remove) unsigned wallclock_ms_time,
sim_event_handler *handler,
void *data)
{ {
sim_events *events = &sd->events; sim_events *events = STATE_EVENTS (sd);
sim_event *to_remove = (sim_event*)event_to_remove; sim_event *new_event = ZALLOC (sim_event);
SIM_ASSERT((events->time_from_event >= 0) == (events->queue != NULL)); /* type */
if (event_to_remove != NULL) { new_event->watching = watch_clock;
sim_event *current; /* handler */
sim_event **ptr_to_current; new_event->data = data;
for (ptr_to_current = &events->queue, current = *ptr_to_current; new_event->handler = handler;
current != NULL && current != to_remove; /* data */
ptr_to_current = &current->next, current = *ptr_to_current); new_event->wallclock = wallclock_ms_time;
if (current == to_remove) { /* insert */
*ptr_to_current = current->next; new_event->next = events->watchpoints;
ETRACE((_ETRACE, events->watchpoints = new_event;
"event descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n", events->work_pending = 1;
(long)sim_events_time(sd), ETRACE ((_ETRACE,
(long)event_to_remove, "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
(long)current->time_of_event, (long)sim_events_time (sd),
(long)current->handler, (long)new_event,
(long)current->data)); (long)new_event->wallclock,
zfree(current); (long)new_event->handler,
update_time_from_event(sd); (long)new_event->data));
} return new_event;
else {
ETRACE((_ETRACE,
"event descheduled at %ld - tag 0x%lx - not found\n",
(long)sim_events_time(sd),
(long)event_to_remove));
}
}
SIM_ASSERT((events->time_from_event >= 0) == (events->queue != NULL));
} }
EXTERN_SIM_EVENTS\
(sim_event *)
sim_events_watch_sim (SIM_DESC sd,
void *host_addr,
int nr_bytes,
int byte_order,
unsigned64 lb,
unsigned64 ub,
sim_event_handler *handler,
void *data)
{
sim_events *events = STATE_EVENTS (sd);
sim_event *new_event = ZALLOC (sim_event);
/* type */
switch (byte_order)
{
case 0:
switch (nr_bytes)
{
case 1: new_event->watching = watch_sim_host_1; break;
case 2: new_event->watching = watch_sim_host_2; break;
case 4: new_event->watching = watch_sim_host_4; break;
case 8: new_event->watching = watch_sim_host_8; break;
default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
}
break;
case BIG_ENDIAN:
switch (nr_bytes)
{
case 1: new_event->watching = watch_sim_be_1; break;
case 2: new_event->watching = watch_sim_be_2; break;
case 4: new_event->watching = watch_sim_be_4; break;
case 8: new_event->watching = watch_sim_be_8; break;
default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
}
break;
case LITTLE_ENDIAN:
switch (nr_bytes)
{
case 1: new_event->watching = watch_sim_le_1; break;
case 2: new_event->watching = watch_sim_le_2; break;
case 4: new_event->watching = watch_sim_le_4; break;
case 8: new_event->watching = watch_sim_le_8; break;
default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
}
break;
default:
sim_io_error (sd, "sim_events_watch_sim - invalid byte order");
}
/* handler */
new_event->data = data;
new_event->handler = handler;
/* data */
new_event->host_addr = host_addr;
new_event->lb = lb;
new_event->lb64 = lb;
new_event->ub = ub;
new_event->ub64 = ub;
/* insert */
new_event->next = events->watchpoints;
events->watchpoints = new_event;
events->work_pending = 1;
ETRACE ((_ETRACE,
"event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
(long)sim_events_time (sd),
(long)new_event,
(long)new_event->host_addr,
(long)new_event->lb,
(long)new_event->ub,
(long)new_event->handler,
(long)new_event->data));
return new_event;
}
EXTERN_SIM_EVENTS\
(sim_event *)
sim_events_watch_core (SIM_DESC sd,
address_word core_addr,
sim_core_maps core_map,
int nr_bytes,
int byte_order,
unsigned64 lb,
unsigned64 ub,
sim_event_handler *handler,
void *data)
{
sim_events *events = STATE_EVENTS (sd);
sim_event *new_event = ZALLOC (sim_event);
/* type */
switch (byte_order)
{
case 0:
switch (nr_bytes)
{
case 1: new_event->watching = watch_core_targ_1; break;
case 2: new_event->watching = watch_core_targ_2; break;
case 4: new_event->watching = watch_core_targ_4; break;
case 8: new_event->watching = watch_core_targ_8; break;
default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
}
break;
case BIG_ENDIAN:
switch (nr_bytes)
{
case 1: new_event->watching = watch_core_be_1; break;
case 2: new_event->watching = watch_core_be_2; break;
case 4: new_event->watching = watch_core_be_4; break;
case 8: new_event->watching = watch_core_be_8; break;
default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
}
break;
case LITTLE_ENDIAN:
switch (nr_bytes)
{
case 1: new_event->watching = watch_core_le_1; break;
case 2: new_event->watching = watch_core_le_2; break;
case 4: new_event->watching = watch_core_le_4; break;
case 8: new_event->watching = watch_core_le_8; break;
default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
}
break;
default:
sim_io_error (sd, "sim_events_watch_core - invalid byte order");
}
/* handler */
new_event->data = data;
new_event->handler = handler;
/* data */
new_event->core_addr = core_addr;
new_event->core_map = core_map;
new_event->lb = lb;
new_event->lb64 = lb;
new_event->ub = ub;
new_event->ub64 = ub;
/* insert */
new_event->next = events->watchpoints;
events->watchpoints = new_event;
events->work_pending = 1;
ETRACE ((_ETRACE,
"event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
(long)sim_events_time (sd),
(long)new_event,
(long)new_event->host_addr,
(long)new_event->lb,
(long)new_event->ub,
(long)new_event->handler,
(long)new_event->data));
return new_event;
}
EXTERN_SIM_EVENTS\
(void)
sim_events_deschedule (SIM_DESC sd,
sim_event *event_to_remove)
{
sim_events *events = STATE_EVENTS (sd);
sim_event *to_remove = (sim_event*)event_to_remove;
SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
if (event_to_remove != NULL)
{
sim_event **queue = NULL;
while ((queue = next_event_queue (sd, queue)) != NULL)
{
sim_event **ptr_to_current;
for (ptr_to_current = queue;
*ptr_to_current != NULL && *ptr_to_current != to_remove;
ptr_to_current = &(*ptr_to_current)->next);
if (*ptr_to_current == to_remove)
{
sim_event *dead = *ptr_to_current;
*ptr_to_current = dead->next;
ETRACE ((_ETRACE,
"event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
(long) sim_events_time (sd),
(long) event_to_remove,
(long) dead->time_of_event,
(long) dead->handler,
(long) dead->data));
zfree (dead);
update_time_from_event (sd);
SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
return;
}
}
}
ETRACE ((_ETRACE,
"event/watch descheduled at %ld - tag 0x%lx - not found\n",
(long) sim_events_time (sd),
(long) event_to_remove));
}
STATIC_INLINE_SIM_EVENTS\
(int)
sim_watch_valid (SIM_DESC sd,
sim_event *to_do)
{
switch (to_do->watching)
{
#define WATCH_CORE(N,OP) \
{ \
unsigned_##N word; \
sim_core_read_buffer (sd, to_do->core_map, &word, to_do->core_addr, sizeof (word)); \
OP (word); \
return (word >= to_do->lb && word <= to_do->ub); \
}
case watch_core_targ_1: WATCH_CORE (1, T2H);
case watch_core_targ_2: WATCH_CORE (2, T2H);
case watch_core_targ_4: WATCH_CORE (4, T2H);
case watch_core_targ_8: WATCH_CORE (8, T2H);
case watch_core_be_1: WATCH_CORE (1, BE2H);
case watch_core_be_2: WATCH_CORE (2, BE2H);
case watch_core_be_4: WATCH_CORE (4, BE2H);
case watch_core_be_8: WATCH_CORE (8, BE2H);
case watch_core_le_1: WATCH_CORE (1, LE2H);
case watch_core_le_2: WATCH_CORE (2, LE2H);
case watch_core_le_4: WATCH_CORE (4, LE2H);
case watch_core_le_8: WATCH_CORE (8, LE2H);
#undef WATCH_CORE
#define WATCH_SIM(N,OP) \
{ \
unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
OP (word); \
return (word >= to_do->lb && word <= to_do->ub); \
}
case watch_sim_host_1: WATCH_SIM (1, word = );
case watch_sim_host_2: WATCH_SIM (2, word = );
case watch_sim_host_4: WATCH_SIM (4, word = );
case watch_sim_host_8: WATCH_SIM (8, word = );
case watch_sim_be_1: WATCH_SIM (1, BE2H);
case watch_sim_be_2: WATCH_SIM (2, BE2H);
case watch_sim_be_4: WATCH_SIM (4, BE2H);
case watch_sim_be_8: WATCH_SIM (8, BE2H);
case watch_sim_le_1: WATCH_SIM (1, LE2H);
case watch_sim_le_2: WATCH_SIM (1, LE2H);
case watch_sim_le_4: WATCH_SIM (1, LE2H);
case watch_sim_le_8: WATCH_SIM (1, LE2H);
#undef WATCH_SIM
case watch_clock: /* wallclock */
return (sim_elapsed_time_since (STATE_EVENTS (sd)->initial_wallclock)
< to_do->wallclock);
case watch_timer:
case watch_invalid:
sim_io_error (sd, "sim_watch_valid - bad switch");
break;
}
return 1;
}
INLINE_SIM_EVENTS\ INLINE_SIM_EVENTS\
(int) (int)
sim_events_tick(SIM_DESC sd) sim_events_tick (SIM_DESC sd)
{ {
sim_events *events = &sd->events; sim_events *events = STATE_EVENTS (sd);
/* we should only be here when the previous tick has been fully /* this should only be called after the previous tick has been fully
processed */ processed */
SIM_ASSERT(!events->processing && events->queue != NULL); SIM_ASSERT (!events->processing);
/* Advance the time but *only* if there is nothing to process */ /* Advance the time but *only* if there is nothing to process */
if (events->time_from_event == 0) if (events->work_pending
return 1; || events->time_from_event == 0)
else if (events->held != NULL) {
return 1; events->processing = 1;
return 1;
}
else { else {
events->time_from_event -= 1; events->time_from_event -= 1;
return 0; return 0;
@ -330,65 +721,129 @@ sim_events_tick(SIM_DESC sd)
} }
INLINE_SIM_EVENTS\
(void)
sim_events_preprocess (SIM_DESC sd,
int events_were_last,
int events_were_next)
{
sim_events *events = STATE_EVENTS(sd);
if (events->processing)
{
/* Halted midway through event processing */
ASSERT (events_were_last && events_were_next);
sim_events_process (sd);
}
else if (events_were_next)
{
/* Halted by the last processor */
ASSERT (!events->processing && !events_were_last);
if (sim_events_tick (sd))
sim_events_process (sd);
}
}
INLINE_SIM_EVENTS\ INLINE_SIM_EVENTS\
(void) (void)
sim_events_process(SIM_DESC sd) sim_events_process (SIM_DESC sd)
{ {
sim_events *events = &sd->events; sim_events *events = STATE_EVENTS(sd);
signed64 event_time = sim_events_time(sd); signed64 event_time = sim_events_time(sd);
/* something to do */ ASSERT (events->processing);
SIM_ASSERT(events->time_from_event == 0 || events->held != NULL);
SIM_ASSERT(events->queue != NULL);
/* move any events that were queued by any signal handlers onto the /* move any events that were queued by any signal handlers onto
real event queue. */ the real event queue. */
if (events->held != NULL) { if (events->held != NULL)
sim_event *held_events; {
sim_event *curr_event; sim_event *held_events;
sim_event *curr_event;
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK) #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
/*-LOCK-*/ /*-LOCK-*/
sigset_t old_mask; sigset_t old_mask;
sigset_t new_mask; sigset_t new_mask;
sigfillset(&new_mask); sigfillset(&new_mask);
sigprocmask(SIG_SETMASK, &new_mask, &old_mask); sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
#endif #endif
held_events = events->held; held_events = events->held;
events->held = NULL; events->held = NULL;
events->held_end = &events->held; events->held_end = &events->held;
events->work_pending = 0;
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK) #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
/*-UNLOCK-*/ /*-UNLOCK-*/
sigprocmask(SIG_SETMASK, &old_mask, NULL); sigprocmask(SIG_SETMASK, &old_mask, NULL);
#endif #endif
do { do
curr_event = held_events; {
held_events = curr_event->next; curr_event = held_events;
insert_sim_event(sd, curr_event, curr_event->time_of_event); held_events = curr_event->next;
} while (held_events != NULL); insert_sim_event (sd, curr_event,
} curr_event->time_of_event);
}
while (held_events != NULL);
}
/* Process any watchpoints. Be careful to allow a watchpoint to
appear/disappear under our feet.
To ensure that watchpoints are processed only once per cycle,
they are moved onto a watched queue, this returned to the
watchpoint queue when all queue processing has been
completed. */
while (events->watchpoints != NULL)
{
sim_event *to_do = events->watchpoints;
events->watchpoints = to_do->next;
if (sim_watch_valid (sd, to_do))
{
sim_event_handler *handler = to_do->handler;
void *data = to_do->data;
events->queue = to_do->next;
ETRACE((_ETRACE,
"event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
(long) event_time,
(long) to_do,
(long) handler,
(long) data));
zfree (to_do);
handler (sd, data);
}
else
{
to_do->next = events->watchedpoints;
events->watchedpoints = to_do;
}
}
/* consume all events for this or earlier times. Be careful to /* consume all events for this or earlier times. Be careful to
allow a new event to appear under our feet */ allow an event to appear/disappear under our feet */
events->processing = 1; while (events->queue->time_of_event <= event_time)
while (events->queue->time_of_event <= event_time) { {
sim_event *to_do = events->queue; sim_event *to_do = events->queue;
sim_event_handler *handler = to_do->handler; sim_event_handler *handler = to_do->handler;
void *data = to_do->data; void *data = to_do->data;
events->queue = to_do->next; events->queue = to_do->next;
ETRACE((_ETRACE, ETRACE((_ETRACE,
"event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n", "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
(long)event_time, (long) event_time,
(long)to_do, (long) to_do,
(long)handler, (long) handler,
(long)data)); (long) data));
zfree (to_do); zfree (to_do);
handler (data); handler (sd, data);
} }
/* put things back where they belong ready for the next iteration */
events->watchpoints = events->watchedpoints;
events->watchedpoints = NULL;
if (events->watchpoints != NULL)
events->work_pending = 1;
/* this round of processing complete */
events->processing = 0; events->processing = 0;
/* re-caculate time for new events - advance the time */ /* re-caculate time for new events - advance the time */

View File

@ -38,49 +38,84 @@
illustrated above, the event queue should be processed before the illustrated above, the event queue should be processed before the
first instruction. That instruction being executed during tick 1. first instruction. That instruction being executed during tick 1.
The event queue is processed using: The simulator main loop may take a form similar to:
if (sim_events_tick (sd)) { if (halt-/restart-setjmp)
sim_events_process (sd); {
}
*/ .... // Determine who should go next
last-cpu-nr = get-last-cpu-nr (sd);
next-cpu-nr = get-next-cpu-nr (sd);
events-were-last? = (last-cpu-nr >= nr-cpus);
events-were-next? = (next-cpu-nr >= nr-cpus);
.... // process any outstanding events
sim_events_preprocess (sd, events-were-last?, events-were-next?);
if (events-were-next)
next-cpu-nr = 0;
.... // prime main loop
while (1)
{
.... // model one insn of next-cpu-nr .. nr-cpus
if (sim_events_tick (sd))
sim_events_process (sd);
next-cpu-nr = 0
}
}
NB. In the above pseudo code it is assumed that any cpu-nr >=
nr-cpus is a marker for the event queue. */
typedef void sim_event_handler(void *data); typedef void sim_event_handler(SIM_DESC sd, void *data);
typedef struct _sim_event sim_event; typedef struct _sim_event sim_event;
struct _sim_event {
void *data;
sim_event_handler *handler;
signed64 time_of_event;
sim_event *next;
};
typedef struct _sim_events sim_events; typedef struct _sim_events sim_events;
struct _sim_events { struct _sim_events {
int processing; int processing;
sim_event *queue; sim_event *queue;
sim_event *watchpoints;
sim_event *watchedpoints;
/* flag additional work needed */
volatile int work_pending;
/* the asynchronous event queue */
sim_event *volatile held; sim_event *volatile held;
sim_event *volatile *volatile held_end; sim_event *volatile *volatile held_end;
/* timekeeping */
SIM_ELAPSED_TIME initial_wallclock;
signed64 time_of_event; signed64 time_of_event;
int time_from_event; int time_from_event;
void *path_to_halt_or_restart;
int trace; int trace;
}; };
/* Install the "events" module. */
EXTERN_SIM_EVENTS\
(SIM_RC) sim_events_install (SIM_DESC sd);
/* Uninstall the "events" subsystem. */
EXTERN_SIM_EVENTS\
(void)
sim_events_uninstall (SIM_DESC sd);
/* Initialization */ /* Initialization */
INLINE_SIM_EVENTS\ EXTERN_SIM_EVENTS\
(void) sim_events_init (SIM_RC) sim_events_init (SIM_DESC sd);
(SIM_DESC sd);
/* Set Tracing Level */ /* Set Tracing Level */
INLINE_SIM_EVENTS\ EXTERN_SIM_EVENTS\
(void) sim_events_set_trace (void) sim_events_set_trace
(SIM_DESC sd, (SIM_DESC sd,
int level); int level);
@ -88,14 +123,14 @@ INLINE_SIM_EVENTS\
/* Schedule an event DELTA_TIME ticks into the future */ /* Schedule an event DELTA_TIME ticks into the future */
INLINE_SIM_EVENTS\ EXTERN_SIM_EVENTS\
(sim_event *) sim_events_schedule (sim_event *) sim_events_schedule
(SIM_DESC sd, (SIM_DESC sd,
signed64 delta_time, signed64 delta_time,
sim_event_handler *handler, sim_event_handler *handler,
void *data); void *data);
INLINE_SIM_EVENTS\ EXTERN_SIM_EVENTS\
(sim_event *) sim_events_schedule_after_signal (sim_event *) sim_events_schedule_after_signal
(SIM_DESC sd, (SIM_DESC sd,
signed64 delta_time, signed64 delta_time,
@ -107,79 +142,77 @@ INLINE_SIM_EVENTS\
simulation. The exact interpretation of wallclock is host simulation. The exact interpretation of wallclock is host
dependant. */ dependant. */
INLINE_SIM_EVENTS\ EXTERN_SIM_EVENTS\
(void) sim_events_wallclock_schedule (sim_event *) sim_events_watch_clock
(SIM_DESC sd, (SIM_DESC sd,
signed64 wallclock_ms_time, unsigned wallclock_ms_time,
sim_event_handler *handler, sim_event_handler *handler,
void *data); void *data);
#if 0 /* Schedule an event when the NR_BYTES value at HOST_ADDR with
/* Schedule an event when the value at ADDR lies between LB..UB */ BYTE_ORDER lies within LB..UB (unsigned).
typedef enum { HOST_ADDR: pointer into the host address space.
/* value host byte ordered */ BYTE_ORDER: 0 - host endian; BIG_ENDIAN; LITTLE_ENDIAN */
watch_host_1,
watch_host_2,
watch_host_4,
watch_host_8,
/* value target byte ordered */
watch_targ_1,
watch_targ_2,
watch_targ_4,
watch_targ_8,
/* value big-endian */
watch_bend_1,
watch_bend_2,
watch_bend_4,
watch_bend_8,
/* value little-endian */
watch_lend_1,
watch_lend_2,
watch_lend_4,
watch_lend_8,
} sim_watchpoint;
INLINE_SIM_EVENTS\ EXTERN_SIM_EVENTS\
(void) sim_events_watchpoint_schedule (sim_event*) sim_events_watch_sim
(SIM_DESC sd, (SIM_DESC sd,
sim_watchpoint type, void *host_addr,
void *addr, int nr_bytes,
int byte_order,
unsigned64 lb, unsigned64 lb,
unsigned64 ub, unsigned64 ub,
sim_event_handler *handler, sim_event_handler *handler,
void *data); void *data);
#endif
#if 0 /* Schedule an event when the NR_BYTES value at CORE_ADDR with BYTE_ORDER
/* Schedule an event when the value in CORE lies between LB..UB */ lies between LB..UB.
INLINE_SIM_EVENTS\ CORE_ADDR/MAP: pointer into the target address space.
(void) sim_events_watchcore_schedule BYTE_ORDER: 0 - current target endian; BIG_ENDIAN; LITTLE_ENDIAN */
EXTERN_SIM_EVENTS\
(sim_event*) sim_events_watch_core
(SIM_DESC sd, (SIM_DESC sd,
sim_watchpoint type, address_word core_addr,
address_word addr, sim_core_maps core_map,
sim_core_maps map, int nr_bytes,
int byte_order,
unsigned64 lb, unsigned64 lb,
unsigned64 ub, unsigned64 ub,
sim_event_handler *handler, sim_event_handler *handler,
void *data); void *data);
#endif
/* Deschedule the specified event */ /* Deschedule the specified event */
INLINE_SIM_EVENTS\ EXTERN_SIM_EVENTS\
(void) sim_events_deschedule (void) sim_events_deschedule
(SIM_DESC sd, (SIM_DESC sd,
sim_event *event_to_remove); sim_event *event_to_remove);
/* Prepare for main simulator loop. Ensure that the next thing to do
is not event processing.
/* progress time. Broken into two parts so that if something is If the simulator halted part way through event processing then both
pending, the caller has a chance to save any cached state */ EVENTS_WERE_LAST and EVENTS_WERE_FIRST shall be true.
If the simulator halted after processing the last cpu, then only
EVENTS_WERE_NEXT shall be true. */
INLINE_SIM_EVENTS\
(void) sim_events_preprocess
(SIM_DESC sd,
int events_were_last,
int events_were_next);
/* Progress time - separated into two parts so that the main loop can
save its context before the event queue is processed */
INLINE_SIM_EVENTS\ INLINE_SIM_EVENTS\
(int) sim_events_tick (int) sim_events_tick
@ -190,6 +223,7 @@ INLINE_SIM_EVENTS\
(SIM_DESC sd); (SIM_DESC sd);
/* local concept of time */ /* local concept of time */
INLINE_SIM_EVENTS\ INLINE_SIM_EVENTS\

67
sim/common/sim-resume.c Normal file
View File

@ -0,0 +1,67 @@
/* Generic simulator resume.
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. */
#include "sim-main.h"
#include <signal.h>
/* Halt the simulator after just one instruction */
static void
has_stepped (SIM_DESC sd,
void *data)
{
sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIGTRAP);
}
/* Generic resume - assumes the existance of sim_engine_run */
void
sim_resume (SIM_DESC sd,
int step,
int siggnal)
{
sim_engine *engine = STATE_ENGINE (sd);
jmp_buf buf;
/* we only want to be single stepping the simulator once */
if (engine->stepper != NULL)
{
sim_events_deschedule (sd, engine->stepper);
engine->stepper = NULL;
}
if (step)
engine->stepper = sim_events_schedule (sd, 1, has_stepped, sd);
/* run/resume the simulator */
engine->jmpbuf = &buf;
if (! setjmp (buf))
{
int last_cpu_nr = sim_engine_last_cpu_nr (sd);
int next_cpu_nr = sim_engine_next_cpu_nr (sd);
int nr_cpus = MAX_NR_PROCESSORS; /* FIXME */
sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus);
if (next_cpu_nr >= nr_cpus)
next_cpu_nr = 0;
sim_engine_run (sd, next_cpu_nr, siggnal);
}
engine->jmpbuf = NULL;
}

45
sim/common/sim-run.c Normal file
View File

@ -0,0 +1,45 @@
/* Generic simulator run.
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. */
#include "sim-main.h"
/* Generic 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, /* ignore */
int siggnal) /* ignore */
{
sim_cia cia;
sim_cpu *cpu = STATE_CPU (sd, 0);
cia = cpu->cia;
while (1)
{
instruction_word insn = IMEM (cia);
cia = idecode_issue (sd, insn, cia);
/* process any events */
if (sim_events_tick (sd))
{
cpu->cia = cia;
sim_events_process (sd);
}
}
}

43
sim/common/sim-stop.c Normal file
View File

@ -0,0 +1,43 @@
/* Generic simulator stop.
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. */
#include "sim-main.h"
#include <signal.h>
/* Generic implementation if sim_stop */
static void
control_c_simulation (SIM_DESC sd,
void *data)
{
sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIGINT);
}
int
sim_stop (SIM_DESC sd)
{
sim_events_schedule_after_signal(sd,
0 /*NOW*/,
control_c_simulation,
sd /*data*/);
return 1;
}

View File

@ -1,3 +1,8 @@
Mon May 19 12:55:42 1997 Andrew Cagney <cagney@b1.cygnus.com>
* Makefile.in (SIM_OBJS): Link in sim-abort.o as a stub for
sim_engine_abort.
Mon May 5 12:45:28 1997 Andrew Cagney <cagney@b1.cygnus.com> Mon May 5 12:45:28 1997 Andrew Cagney <cagney@b1.cygnus.com>
* sim-if.c (sim_open): Update to reflect changes to core in * sim-if.c (sim_open): Update to reflect changes to core in

View File

@ -1,3 +1,28 @@
Fri May 16 14:35:30 1997 Andrew Cagney <cagney@b1.cygnus.com>
* insns (illegal, fp_unavailable): Halt instead of abort the
simulator.
* insns: Replace calls to engine_error with sim_engine_abort.
Ditto for engine_halt V sim_engine_halt.
Tue May 13 15:24:12 1997 Andrew Cagney <cagney@b2.cygnus.com>
* interp.c (engine_run_until_stop): Delete. Moved to common.
(engine_step): Ditto.
(engine_step): Ditto.
(engine_halt): Ditto.
(engine_restart): Ditto.
(engine_halt): Ditto.
(engine_error): Ditto.
* sim-calls.c (sim_stop): Delete. Moved to common.
(sim_stop_reason): Ditto.
(sim_resume): Ditto.
* Makefile.in (SIM_OBJS): Link in generic sim-engine, sim-run,
sim-resume, sim-reason, sim-stop modules.
Fri May 16 11:57:49 1997 Andrew Cagney <cagney@b1.cygnus.com> Fri May 16 11:57:49 1997 Andrew Cagney <cagney@b1.cygnus.com>
* ic (compute): Drop check for REG == 0, now always forced to * ic (compute): Drop check for REG == 0, now always forced to

View File

@ -10,7 +10,7 @@
# Not all of these need to be mentioned, only the necessary ones. # Not all of these need to be mentioned, only the necessary ones.
# List of object files, less common parts. # List of object files, less common parts.
SIM_OBJS = sim-endian.o sim-bits.o sim-config.o interp.o \ SIM_OBJS = sim-endian.o sim-bits.o sim-config.o \
support.o idecode.o semantics.o itable.o misc.o \ support.o idecode.o semantics.o itable.o misc.o \
sim-calls.o \ sim-calls.o \
sim-events.o \ sim-events.o \
@ -22,7 +22,12 @@ SIM_OBJS = sim-endian.o sim-bits.o sim-config.o interp.o \
sim-options.o \ sim-options.o \
sim-trace.o \ sim-trace.o \
sim-profile.o \ sim-profile.o \
sim-fpu.o sim-fpu.o \
sim-engine.o \
sim-run.o \
sim-resume.o \
sim-stop.o \
sim-reason.o
# List of extra dependencies. # List of extra dependencies.
# Generally this consists of simulator specific files included by sim-main.h. # Generally this consists of simulator specific files included by sim-main.h.
@ -142,6 +147,7 @@ ENGINE_H = \
$(srcdir)/../common/sim-core.h \ $(srcdir)/../common/sim-core.h \
$(srcdir)/../common/sim-events.h \ $(srcdir)/../common/sim-events.h \
$(srcdir)/../common/sim-fpu.h \ $(srcdir)/../common/sim-fpu.h \
$(srcdir)/../common/sim-engine.h \
idecode.o: $(ENGINE_H) idecode.o: $(ENGINE_H)
semantics.o: $(ENGINE_H) semantics.o: $(ENGINE_H)

View File

@ -21,12 +21,13 @@
// The following is called when ever an illegal instruction is encountered. // The following is called when ever an illegal instruction is encountered.
::internal::illegal ::internal::illegal
engine_error (SD, CPU, cia, sim_io_eprintf (SD, "0x%lx: illegal instruction\n", (unsigned long) cia.ip);
"illegal instruction at 0x%lx", cia.ip); sim_engine_halt (SD, CPU, NULL, cia, sim_signalled, SIGILL);
// The following is called when ever an FP op is attempted with FPU disabled. // The following is called when ever an FP op is attempted with FPU disabled.
::internal::fp_unavailable ::internal::fp_unavailable
engine_error (SD, CPU, cia, sim_io_eprintf (SD, "0x%lx: floating-point unavailable\n", (unsigned long) cia.ip);
"floating-point unavailable at 0x%lx", cia.ip); sim_engine_halt (SD, CPU, NULL, cia, sim_signalled, SIGFPE);
// Handle a branch instruction // Handle a branch instruction
instruction_address::function::do_branch:int annul, address_word target, int rLink_p, unsigned32 *rLink instruction_address::function::do_branch:int annul, address_word target, int rLink_p, unsigned32 *rLink
@ -184,7 +185,7 @@ instruction_address::function::do_bcnd:instruction_address nia, int Cond, unsign
case 0: val = SEXT32 (source, 7); break; case 0: val = SEXT32 (source, 7); break;
case 1: val = SEXT32 (source, 15); break; case 1: val = SEXT32 (source, 15); break;
case 2: val = source; break; case 2: val = source; break;
default: engine_error (SD, CPU, cia, "bcnd - reserved size"); default: sim_engine_abort (SD, CPU, cia, "bcnd - reserved size");
} }
switch (code) switch (code)
{ {
@ -271,28 +272,28 @@ void::function::do_cmnd:signed32 source
int PP = EXTRACTED32 (source, 3, 0); int PP = EXTRACTED32 (source, 3, 0);
/* what is implemented? */ /* what is implemented? */
if (PP != 0) if (PP != 0)
engine_error (SD, CPU, cia, "0x%lx: cmnd - PPs not supported", sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - PPs not supported",
(unsigned long) cia.ip); (unsigned long) cia.ip);
if (VC != 0) if (VC != 0)
engine_error (SD, CPU, cia, "0x%lx: cmnd - VC not supported", sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - VC not supported",
(unsigned long) cia.ip); (unsigned long) cia.ip);
if (TC != 0) if (TC != 0)
engine_error (SD, CPU, cia, "0x%lx: cmnd - TC not supported", sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - TC not supported",
(unsigned long) cia.ip); (unsigned long) cia.ip);
if (MP) if (MP)
{ {
if (Reset || Halt) if (Reset || Halt)
engine_halt (SD, CPU, cia, sim_exited, 0); sim_engine_halt (SD, CPU, NULL, cia, sim_exited, 0);
if (Unhalt) if (Unhalt)
engine_error (SD, CPU, cia, "0x%lx: cmnd - Can not unhalt the MP", sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - Can not unhalt the MP",
(unsigned long) cia.ip); (unsigned long) cia.ip);
/* if (ICR || DCR); */ /* if (ICR || DCR); */
if (Task) if (Task)
engine_error (SD, CPU, cia, "0x%lx: cmnd - Can not Task the MP", sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - Can not Task the MP",
(unsigned long) cia.ip); (unsigned long) cia.ip);
if (Msg) if (Msg)
engine_error (SD, CPU, cia, "0x%lx: cmnd - Msg to MP not suported", sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - Msg to MP not suported",
(unsigned long) cia.ip); (unsigned long) cia.ip);
} }
TRACE_SINK1 (MY_INDEX, source); TRACE_SINK1 (MY_INDEX, source);
31./,21.0b0000010,14.UI::::cmnd i 31./,21.0b0000010,14.UI::::cmnd i
@ -401,11 +402,11 @@ sim_fpu::function::get_fp_reg:int reg, unsigned32 val, int precision
return sim_fpu_32to (val); return sim_fpu_32to (val);
case 1: /* double */ case 1: /* double */
if (reg < 0) if (reg < 0)
engine_error (SD, CPU, cia, "DP immediate invalid"); sim_engine_abort (SD, CPU, cia, "DP immediate invalid");
if (reg & 1) if (reg & 1)
engine_error (SD, CPU, cia, "DP FP register must be even"); sim_engine_abort (SD, CPU, cia, "DP FP register must be even");
if (reg <= 1) if (reg <= 1)
engine_error (SD, CPU, cia, "DP FP register must be >= 2"); sim_engine_abort (SD, CPU, cia, "DP FP register must be >= 2");
return sim_fpu_64to (INSERTED64 (GPR (reg + 1), 63, 32) return sim_fpu_64to (INSERTED64 (GPR (reg + 1), 63, 32)
| INSERTED64 (GPR (reg), 31, 0)); | INSERTED64 (GPR (reg), 31, 0));
case 2: /* 32 bit signed integer */ case 2: /* 32 bit signed integer */
@ -413,7 +414,7 @@ sim_fpu::function::get_fp_reg:int reg, unsigned32 val, int precision
case 3: /* 32 bit unsigned integer */ case 3: /* 32 bit unsigned integer */
return sim_fpu_u32to (val); return sim_fpu_u32to (val);
default: default:
engine_error (SD, CPU, cia, "Unsupported FP precision"); sim_engine_abort (SD, CPU, cia, "Unsupported FP precision");
} }
return sim_fpu_i32to (0); return sim_fpu_i32to (0);
void::function::set_fp_reg:int Dest, sim_fpu val, int PD void::function::set_fp_reg:int Dest, sim_fpu val, int PD
@ -428,9 +429,9 @@ void::function::set_fp_reg:int Dest, sim_fpu val, int PD
{ {
unsigned64 v = sim_fpu_to64 (val); unsigned64 v = sim_fpu_to64 (val);
if (Dest & 1) if (Dest & 1)
engine_error (SD, CPU, cia, "DP FP Dest register must be even"); sim_engine_abort (SD, CPU, cia, "DP FP Dest register must be even");
if (Dest <= 1) if (Dest <= 1)
engine_error (SD, CPU, cia, "DP FP Dest register must be >= 2"); sim_engine_abort (SD, CPU, cia, "DP FP Dest register must be >= 2");
GPR (Dest + 0) = VL4_8 (v); GPR (Dest + 0) = VL4_8 (v);
GPR (Dest + 1) = VH4_8 (v); GPR (Dest + 1) = VH4_8 (v);
break; break;
@ -446,7 +447,7 @@ void::function::set_fp_reg:int Dest, sim_fpu val, int PD
break; break;
} }
default: default:
engine_error (SD, CPU, cia, "Unsupported FP precision"); sim_engine_abort (SD, CPU, cia, "Unsupported FP precision");
} }
// fadd.{s|d}{s|d}{s|d} // fadd.{s|d}{s|d}{s|d}
@ -634,10 +635,10 @@ instruction_address::function::do_jsr:instruction_address nia, signed32 *rLink,
TRACE_UCOND_BR (MY_INDEX, target); TRACE_UCOND_BR (MY_INDEX, target);
nia = do_branch (_SD, annul, target, 1, rLink); nia = do_branch (_SD, annul, target, 1, rLink);
if (nia.dp & 0x3) if (nia.dp & 0x3)
engine_error (SD, CPU, cia, sim_engine_abort (SD, CPU, cia,
"0x%lx: destination address 0x%lx misaligned", "0x%lx: destination address 0x%lx misaligned",
(unsigned long) cia.ip, (unsigned long) cia.ip,
(unsigned long) nia.dp); (unsigned long) nia.dp);
return nia; return nia;
31.Link,26.Base,21.0b100010,15.A,14.SignedOffset::::jsr i 31.Link,26.Base,21.0b100010,15.A,14.SignedOffset::::jsr i
nia = do_jsr (_SD, nia, rLink, A, vSignedOffset, vBase); nia = do_jsr (_SD, nia, rLink, A, vSignedOffset, vBase);
@ -675,8 +676,8 @@ void::function::do_ld:int Dest, unsigned32 base, unsigned32 *rBase, int m , int
{ {
signed64 val; signed64 val;
if (Dest & 0x1) if (Dest & 0x1)
engine_error (SD, CPU, cia, "0x%lx: ld.d to odd register %d", sim_engine_abort (SD, CPU, cia, "0x%lx: ld.d to odd register %d",
cia.ip, Dest); cia.ip, Dest);
addr = base + (S ? (offset << 3) : offset); addr = base + (S ? (offset << 3) : offset);
if (m) if (m)
*rBase = addr; *rBase = addr;
@ -687,7 +688,7 @@ void::function::do_ld:int Dest, unsigned32 base, unsigned32 *rBase, int m , int
break; break;
default: default:
addr = -1; addr = -1;
engine_error (SD, CPU, cia, "ld - invalid sz %d", sz); sim_engine_abort (SD, CPU, cia, "ld - invalid sz %d", sz);
} }
TRACE_LD (MY_INDEX, GPR(Dest), m, S, base, offset); TRACE_LD (MY_INDEX, GPR(Dest), m, S, base, offset);
31.Dest,26.Base,21.0b0100,17.m,16.sz,14.SignedOffset::::ld i 31.Dest,26.Base,21.0b0100,17.m,16.sz,14.SignedOffset::::ld i
@ -714,7 +715,7 @@ void::function::do_ld_u:unsigned32 *rDest, unsigned32 base, unsigned32 *rBase, i
break; break;
default: default:
addr = -1; addr = -1;
engine_error (SD, CPU, cia, "ld.u - invalid sz %d", sz); sim_engine_abort (SD, CPU, cia, "ld.u - invalid sz %d", sz);
} }
if (m) if (m)
*rBase = addr; *rBase = addr;
@ -867,9 +868,9 @@ void::function::do_shift:int Dest, unsigned32 source, int Merge, int i, int n, i
shiftmask = ~((1 << nRotate) - 1); /* inverted */ shiftmask = ~((1 << nRotate) - 1); /* inverted */
break; break;
default: default:
engine_error (SD, CPU, cia, sim_engine_abort (SD, CPU, cia,
"0x%lx: Invalid merge (%d) for shift", "0x%lx: Invalid merge (%d) for shift",
cia.ip, source); cia.ip, source);
shiftmask = 0; shiftmask = 0;
} }
/* and the composite mask */ /* and the composite mask */
@ -894,9 +895,9 @@ void::function::do_shift:int Dest, unsigned32 source, int Merge, int i, int n, i
} }
break; break;
default: default:
engine_error (SD, CPU, cia, sim_engine_abort (SD, CPU, cia,
"0x%lx: Invalid merge (%d)", "0x%lx: Invalid merge (%d)",
cia.ip, source); cia.ip, source);
} }
TRACE_SHIFT (MY_INDEX, GPR (Dest), input, i, n, Merge, EndMask, Rotate); TRACE_SHIFT (MY_INDEX, GPR (Dest), input, i, n, Merge, EndMask, Rotate);
@ -942,9 +943,9 @@ void::function::do_st:int Source, unsigned32 base, unsigned32 *rBase, int m , in
{ {
signed64 val; signed64 val;
if (Source & 0x1) if (Source & 0x1)
engine_error (SD, CPU, cia, sim_engine_abort (SD, CPU, cia,
"0x%lx: st.d with odd source register %d", "0x%lx: st.d with odd source register %d",
cia.ip, Source); cia.ip, Source);
addr = base + (S ? (offset << 3) : offset); addr = base + (S ? (offset << 3) : offset);
val = (V4_H8 (GPR(Source + 1)) | V4_L8 (GPR(Source))); val = (V4_H8 (GPR(Source + 1)) | V4_L8 (GPR(Source)));
STORE (addr, 8, val); STORE (addr, 8, val);
@ -952,7 +953,7 @@ void::function::do_st:int Source, unsigned32 base, unsigned32 *rBase, int m , in
break; break;
default: default:
addr = -1; addr = -1;
engine_error (SD, CPU, cia, "st - invalid sz %d", sz); sim_engine_abort (SD, CPU, cia, "st - invalid sz %d", sz);
} }
if (m) if (m)
*rBase = addr; *rBase = addr;
@ -1035,7 +1036,7 @@ void::function::do_trap:unsigned32 trap_number
{ {
case 1: /* EXIT */ case 1: /* EXIT */
{ {
engine_halt (SD, CPU, cia, sim_exited, GPR(2)); sim_engine_halt (SD, CPU, NULL, cia, sim_exited, GPR(2));
break; break;
} }
case 4: /* WRITE */ case 4: /* WRITE */
@ -1056,9 +1057,9 @@ void::function::do_trap:unsigned32 trap_number
sim_io_write_stderr (SD, &c, 1); sim_io_write_stderr (SD, &c, 1);
} }
else else
engine_error (SD, CPU, cia, sim_engine_abort (SD, CPU, cia,
"0x%lx: write to invalid fid %d", "0x%lx: write to invalid fid %d",
(unsigned long) cia.ip, GPR(2)); (unsigned long) cia.ip, GPR(2));
GPR(2) = GPR(6); GPR(2) = GPR(6);
break; break;
} }
@ -1069,13 +1070,13 @@ void::function::do_trap:unsigned32 trap_number
GPR(2) = -22; /* -EINVAL */ GPR(2) = -22; /* -EINVAL */
break; break;
} }
engine_error (SD, CPU, cia, sim_engine_abort (SD, CPU, cia,
"0x%lx: unknown syscall %d", "0x%lx: unknown syscall %d",
(unsigned long) cia.ip, GPR(15)); (unsigned long) cia.ip, GPR(15));
} }
break; break;
case 73: case 73:
engine_halt (SD, CPU, cia, sim_stopped, SIGTRAP); sim_engine_halt (SD, CPU, NULL, cia, sim_stopped, SIGTRAP);
/* Add a few traps for now to print the register state */ /* Add a few traps for now to print the register state */
case 74: case 74:
@ -1096,9 +1097,9 @@ void::function::do_trap:unsigned32 trap_number
break; break;
default: default:
engine_error (SD, CPU, cia, sim_engine_abort (SD, CPU, cia,
"0x%lx: unsupported trap %d", "0x%lx: unsupported trap %d",
(unsigned long) cia.ip, trap_number); (unsigned long) cia.ip, trap_number);
} }
31./,27.0,26./,21.0b0000001,14.UTN::::trap i 31./,27.0,26./,21.0b0000001,14.UTN::::trap i
do_trap (_SD, UTN); do_trap (_SD, UTN);

View File

@ -36,16 +36,8 @@
#endif #endif
#endif #endif
void
engine_init (SIM_DESC sd)
{
memset (&STATE_CPU (sd, 0)->reg, 0, sizeof STATE_CPU (sd, 0)->reg);
memset (&STATE_CPU (sd, 0)->cia, 0, sizeof STATE_CPU (sd, 0)->cia);
CPU_STATE (STATE_CPU (sd, 0)) = sd;
}
#if 0
/* Mechanisms for stopping/restarting the simulation */
void void
engine_error (SIM_DESC sd, engine_error (SIM_DESC sd,
@ -59,13 +51,7 @@ engine_error (SIM_DESC sd,
sim_io_evprintf (sd, fmt, ap); sim_io_evprintf (sd, fmt, ap);
va_end (ap); va_end (ap);
if (sd->halt_ok) sim_halt (sd, cpu, NULL, cia, sim_stopped, SIGABRT);
{
sim_io_eprintf (sd, "\n");
engine_halt (sd, cpu, cia, sim_stopped, SIGABRT);
}
else
sim_io_error (sd, " - aborting simulation");
} }
void void
@ -139,3 +125,6 @@ engine_step (SIM_DESC sd)
engine_halt (sd, cpu, cia, sim_stopped, SIGTRAP); engine_halt (sd, cpu, cia, sim_stopped, SIGTRAP);
} }
} }
#endif

View File

@ -80,7 +80,13 @@ sim_open (SIM_OPEN_KIND kind, char **argv)
return 0; return 0;
} }
engine_init(&simulation); /* Initialize the main processor */
memset (&STATE_CPU (&simulation, 0)->reg, 0, sizeof STATE_CPU (&simulation, 0)->reg);
memset (&STATE_CPU (&simulation, 0)->acc, 0, sizeof STATE_CPU (&simulation, 0)->acc);
memset (&STATE_CPU (&simulation, 0)->cr, 0, sizeof STATE_CPU (&simulation, 0)->cr);
STATE_CPU (&simulation, 0)->is_user_mode = 0;
memset (&STATE_CPU (&simulation, 0)->cia, 0, sizeof STATE_CPU (&simulation, 0)->cia);
CPU_STATE (STATE_CPU (&simulation, 0)) = &simulation;
#define TIC80_MEM_START 0x2000000 #define TIC80_MEM_START 0x2000000
#define TIC80_MEM_SIZE 0x100000 #define TIC80_MEM_SIZE 0x100000
@ -230,42 +236,6 @@ sim_create_inferior (SIM_DESC sd,
} }
volatile int keep_running = 1;
void
sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc)
{
if (!keep_running)
{
*reason = sim_stopped;
*sigrc = SIGINT;
keep_running = 1;
}
else
{
*reason = simulation.reason;
*sigrc = simulation.siggnal;
}
}
int
sim_stop (SIM_DESC sd)
{
keep_running = 0;
return 1;
}
void
sim_resume (SIM_DESC sd, int step, int siggnal)
{
/* keep_running = 1 - in sim_stop_reason */
if (step)
engine_step (sd);
else
engine_run_until_stop (sd, &keep_running);
}
void void
sim_do_command (SIM_DESC sd, char *cmd) sim_do_command (SIM_DESC sd, char *cmd)
{ {

View File

@ -69,39 +69,4 @@ extern void engine_init
(SIM_DESC sd); (SIM_DESC sd);
/* Mechanisms for stopping/restarting the simulation.
A non NULL CPU argument designates the processor that is initiating
the halt. After the simulation has stopped that processor should
be marked as the last one active */
extern void engine_error
(SIM_DESC sd,
sim_cpu *cpu,
instruction_address cia,
const char *fmt,
...);
extern void engine_halt
(SIM_DESC sd,
sim_cpu *cpu,
instruction_address cia,
enum sim_stop reason,
int siggnal);
extern void engine_restart
(SIM_DESC sd,
sim_cpu *cpu,
instruction_address cia);
/* SIMULATE INSTRUCTIONS, various different ways of achieving the same
thing (others later) */
extern void engine_run_until_stop
(SIM_DESC sd,
volatile int *keep_running);
extern void engine_step
(SIM_DESC sd);
#endif #endif