From: Andrew Cagney Date: Mon, 19 May 1997 03:42:33 +0000 (+0000) Subject: o Implement generic halt/restart/abort module. X-Git-Tag: gdb-4_18~5503 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f03b093cd34bc352ad89334a43a34b00a5e5c60c;p=platform%2Fupstream%2Fbinutils.git o Implement generic halt/restart/abort module. Use in tic80 and d30v simulators. o Add signal hook to sim-core module --- diff --git a/sim/common/.Sanitize b/sim/common/.Sanitize index 86daab6..c256e5c 100644 --- a/sim/common/.Sanitize +++ b/sim/common/.Sanitize @@ -61,6 +61,8 @@ sim-events.c sim-events.h sim-fpu.c sim-fpu.h +sim-halt.c +sim-halt.h sim-inline.c sim-inline.h sim-io.c diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog index cd79a60..c2cc924 100644 --- a/sim/common/ChangeLog +++ b/sim/common/ChangeLog @@ -1,3 +1,68 @@ +Mon May 19 12:07:22 1997 Andrew Cagney + + * 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 + + * 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 + + * 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 + + * 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 + + * sim-fpu.c (is_ufpu_number): Comment out - currently unused. + Mon May 19 11:23:03 1997 Andrew Cagney * callback.c (os_open): Type of arg flags is int. diff --git a/sim/common/Make-common.in b/sim/common/Make-common.in index c2b2fff..7db8ba7 100644 --- a/sim/common/Make-common.in +++ b/sim/common/Make-common.in @@ -180,6 +180,7 @@ sim_main_headers = \ $(srcdir)/../common/sim-module.h \ $(srcdir)/../common/sim-trace.h \ $(srcdir)/../common/sim-profile.h \ + $(srcdir)/../common/sim-engine.h \ tconfig.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-core_h = $(srcdir)/../common/sim-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-fpu_h = $(srcdir)/../common/sim-fpu.h sim-io_h = $(srcdir)/../common/sim-io.h @@ -207,6 +209,14 @@ BUILT_SRC_FROM_COMMON= \ sim-config.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_EXTRA_DEPS) sim-bits.c: $(srcdir)/../common/sim-bits.c @@ -239,6 +249,14 @@ sim-endian.c: $(srcdir)/../common/sim-endian.c cat $(srcdir)/../common/$@ >> 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_EXTRA_DEPS) 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) $(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-options_h) $(sim-io_h) $(SIM_EXTRA_DEPS) $(CC) -c $(srcdir)/../common/sim-trace.c $(ALL_CFLAGS) diff --git a/sim/common/sim-abort.c b/sim/common/sim-abort.c new file mode 100644 index 0000000..0a441e4 --- /dev/null +++ b/sim/common/sim-abort.c @@ -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 +#include + + +/* 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 (); + } +} diff --git a/sim/common/sim-engine.c b/sim/common/sim-engine.c new file mode 100644 index 0000000..46f69e5 --- /dev/null +++ b/sim/common/sim-engine.c @@ -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 +#include + + +/* 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; +} diff --git a/sim/common/sim-engine.h b/sim/common/sim-engine.h new file mode 100644 index 0000000..57c43e9 --- /dev/null +++ b/sim/common/sim-engine.h @@ -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 diff --git a/sim/common/sim-events.c b/sim/common/sim-events.c index 60927c0..00fac12 100644 --- a/sim/common/sim-events.c +++ b/sim/common/sim-events.c @@ -27,6 +27,71 @@ #include +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 variables. @@ -65,10 +130,10 @@ do \ { \ if (WITH_TRACE) \ { \ - if (sd->events.trace) \ + if (STATE_EVENTS (sd)->trace) \ { \ const char *file; \ - SIM_FILTER_PATH(file, __FILE__); \ + SIM_FILTER_PATH (file, __FILE__); \ sim_io_printf (sd, "%s:%d: ", file, __LINE__); \ sim_io_printf ARGS; \ } \ @@ -77,26 +142,72 @@ do \ 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\ (void) -sim_events_poll (void *data) +sim_events_poll (SIM_DESC sd, + void *data) { /* 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); } -INLINE_SIM_EVENTS\ +/* "events" module install handler. + This is called via sim_module_install to install the "events" subsystem + into the simulator. */ + +EXTERN_SIM_EVENTS\ +(SIM_RC) +sim_events_install (SIM_DESC sd) +{ + sim_module_add_uninstall_fn (sd, sim_events_uninstall); + 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_init(SIM_DESC sd) +sim_events_uninstall (SIM_DESC sd) { - sim_events *events = &sd->events; - sim_event *event; + /* 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 */ { + sim_event *event; #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK) sigset_t old_mask; sigset_t new_mask; @@ -111,106 +222,125 @@ sim_events_init(SIM_DESC sd) } events->held = NULL; events->held_end = &events->held; + events->work_pending = 0; #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK) /*-UNLOCK-*/ sigprocmask(SIG_SETMASK, &old_mask, NULL); #endif } - /* drain the normal queue */ - event = events->queue; - while (event != NULL) { - sim_event *dead = event; - event = event->next; - zfree(dead); + /* drain the normal queues */ + { + sim_event **queue = NULL; + while ((queue = next_event_queue (sd, queue)) != NULL) + { + 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 */ - events->processing = 0; + events->processing = 1; /* start by doing queue */ events->time_of_event = 0; events->time_from_event = 0; + events->initial_wallclock = sim_elapsed_time_get (); /* 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 the event queue is non empty */ - SIM_ASSERT(events->queue != NULL); + SIM_ASSERT (events->queue != NULL); + + return SIM_RC_OK; } + INLINE_SIM_EVENTS\ (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; } + STATIC_INLINE_SIM_EVENTS\ (void) -update_time_from_event(SIM_DESC sd) +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)); + 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) +insert_sim_event (SIM_DESC sd, + sim_event *new_event, + signed64 delta) { - sim_events *events = &sd->events; + sim_events *events = STATE_EVENTS (sd); sim_event *curr; sim_event **prev; signed64 time_of_event; 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 */ - 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 */ prev = &events->queue; curr = events->queue; - while (curr != NULL && time_of_event >= curr->time_of_event) { - SIM_ASSERT(curr->next == NULL - || curr->time_of_event <= curr->next->time_of_event); - prev = &curr->next; - curr = curr->next; - } - SIM_ASSERT(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); + prev = &curr->next; + curr = curr->next; + } + SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event); + /* insert it */ new_event->next = curr; *prev = new_event; new_event->time_of_event = time_of_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_events_schedule(SIM_DESC sd, - signed64 delta_time, - sim_event_handler *handler, - void *data) +sim_events_schedule (SIM_DESC sd, + signed64 delta_time, + sim_event_handler *handler, + void *data) { sim_event *new_event = ZALLOC(sim_event); new_event->data = data; new_event->handler = handler; + new_event->watching = watch_timer; insert_sim_event(sd, new_event, delta_time); ETRACE((_ETRACE, "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n", @@ -223,27 +353,28 @@ sim_events_schedule(SIM_DESC sd, } -INLINE_SIM_EVENTS\ +EXTERN_SIM_EVENTS\ (sim_event *) sim_events_schedule_after_signal(SIM_DESC sd, signed64 delta_time, sim_event_handler *handler, void *data) { - sim_events *events = &sd->events; - sim_event *new_event = ZALLOC(sim_event); - + sim_events *events = STATE_EVENTS (sd); + sim_event *new_event = ZALLOC (sim_event); + new_event->data = data; new_event->handler = handler; new_event->time_of_event = delta_time; /* work it out later */ 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 new_mask; sigfillset(&new_mask); - /*-LOCK-*/ sigprocmask(SIG_SETMASK, &new_mask, &old_mask); + sigprocmask (SIG_SETMASK, &new_mask, &old_mask); #endif if (events->held == NULL) { 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->next; -#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK) - /*-UNLOCK-*/ sigprocmask(SIG_SETMASK, &old_mask, NULL); + events->work_pending = 1; /* notify main process */ +#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK) + /*-UNLOCK-*/ + sigprocmask (SIG_SETMASK, &old_mask, NULL); #endif } + + ETRACE ((_ETRACE, + "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n", + (long)sim_events_time(sd), + (long)new_event, + (long)new_event->time_of_event, + (long)new_event->handler, + (long)new_event->data)); + + return new_event; +} - ETRACE((_ETRACE, - "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n", - (long)sim_events_time(sd), - (long)new_event, - (long)new_event->time_of_event, - (long)new_event->handler, - (long)new_event->data)); +EXTERN_SIM_EVENTS\ +(sim_event *) +sim_events_watch_clock (SIM_DESC sd, + unsigned wallclock_ms_time, + sim_event_handler *handler, + void *data) +{ + sim_events *events = STATE_EVENTS (sd); + sim_event *new_event = ZALLOC (sim_event); + /* type */ + new_event->watching = watch_clock; + /* handler */ + new_event->data = data; + new_event->handler = handler; + /* data */ + new_event->wallclock = wallclock_ms_time; + /* insert */ + new_event->next = events->watchpoints; + events->watchpoints = new_event; + events->work_pending = 1; + ETRACE ((_ETRACE, + "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n", + (long)sim_events_time (sd), + (long)new_event, + (long)new_event->wallclock, + (long)new_event->handler, + (long)new_event->data)); return new_event; } -INLINE_SIM_EVENTS\ +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_deschedule (SIM_DESC sd, + sim_event *event_to_remove) { - sim_events *events = &sd->events; + 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 *current; - sim_event **ptr_to_current; - for (ptr_to_current = &events->queue, current = *ptr_to_current; - current != NULL && current != to_remove; - ptr_to_current = ¤t->next, current = *ptr_to_current); - if (current == to_remove) { - *ptr_to_current = current->next; - ETRACE((_ETRACE, - "event 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)current->time_of_event, - (long)current->handler, - (long)current->data)); - zfree(current); - update_time_from_event(sd); - } - 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)); + 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; + } + } } - } - SIM_ASSERT((events->time_from_event >= 0) == (events->queue != NULL)); + 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\ (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 */ - SIM_ASSERT(!events->processing && events->queue != NULL); + SIM_ASSERT (!events->processing); /* Advance the time but *only* if there is nothing to process */ - if (events->time_from_event == 0) - return 1; - else if (events->held != NULL) - return 1; + if (events->work_pending + || events->time_from_event == 0) + { + events->processing = 1; + return 1; + } else { events->time_from_event -= 1; return 0; @@ -330,67 +721,131 @@ 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\ (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); - /* something to do */ - 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 - real event queue. */ - if (events->held != NULL) { - sim_event *held_events; - sim_event *curr_event; + ASSERT (events->processing); + /* move any events that were queued by any signal handlers onto + the real event queue. */ + if (events->held != NULL) + { + sim_event *held_events; + sim_event *curr_event; + #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK) - /*-LOCK-*/ - sigset_t old_mask; - sigset_t new_mask; - sigfillset(&new_mask); - sigprocmask(SIG_SETMASK, &new_mask, &old_mask); + /*-LOCK-*/ + sigset_t old_mask; + sigset_t new_mask; + sigfillset(&new_mask); + sigprocmask(SIG_SETMASK, &new_mask, &old_mask); #endif - - held_events = events->held; - events->held = NULL; - events->held_end = &events->held; - + + held_events = events->held; + events->held = NULL; + events->held_end = &events->held; + events->work_pending = 0; + #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK) - /*-UNLOCK-*/ - sigprocmask(SIG_SETMASK, &old_mask, NULL); + /*-UNLOCK-*/ + sigprocmask(SIG_SETMASK, &old_mask, NULL); #endif - - do { - curr_event = held_events; - held_events = curr_event->next; - insert_sim_event(sd, curr_event, curr_event->time_of_event); - } while (held_events != NULL); - } - + + do + { + curr_event = held_events; + held_events = curr_event->next; + 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 - allow a new event to appear under our feet */ - events->processing = 1; - while (events->queue->time_of_event <= event_time) { - sim_event *to_do = events->queue; - 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 (data); - } + allow an event to appear/disappear under our feet */ + while (events->queue->time_of_event <= event_time) + { + sim_event *to_do = events->queue; + 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); + } + + /* 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; - + /* re-caculate time for new events - advance the time */ update_time_from_event(sd); SIM_ASSERT(events->time_from_event > 0 && events->queue != NULL); diff --git a/sim/common/sim-events.h b/sim/common/sim-events.h index 05b28b5..8c41927 100644 --- a/sim/common/sim-events.h +++ b/sim/common/sim-events.h @@ -38,49 +38,84 @@ illustrated above, the event queue should be processed before the 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)) { - sim_events_process (sd); - } + if (halt-/restart-setjmp) + { - */ - + .... // 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); -typedef void sim_event_handler(void *data); + .... // 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(SIM_DESC sd, void *data); 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; struct _sim_events { int processing; 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 *volatile held_end; + /* timekeeping */ + SIM_ELAPSED_TIME initial_wallclock; signed64 time_of_event; int time_from_event; - void *path_to_halt_or_restart; 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 */ -INLINE_SIM_EVENTS\ -(void) sim_events_init -(SIM_DESC sd); +EXTERN_SIM_EVENTS\ +(SIM_RC) sim_events_init (SIM_DESC sd); /* Set Tracing Level */ -INLINE_SIM_EVENTS\ +EXTERN_SIM_EVENTS\ (void) sim_events_set_trace (SIM_DESC sd, int level); @@ -88,14 +123,14 @@ INLINE_SIM_EVENTS\ /* Schedule an event DELTA_TIME ticks into the future */ -INLINE_SIM_EVENTS\ +EXTERN_SIM_EVENTS\ (sim_event *) sim_events_schedule (SIM_DESC sd, signed64 delta_time, sim_event_handler *handler, void *data); -INLINE_SIM_EVENTS\ +EXTERN_SIM_EVENTS\ (sim_event *) sim_events_schedule_after_signal (SIM_DESC sd, signed64 delta_time, @@ -107,79 +142,77 @@ INLINE_SIM_EVENTS\ simulation. The exact interpretation of wallclock is host dependant. */ -INLINE_SIM_EVENTS\ -(void) sim_events_wallclock_schedule +EXTERN_SIM_EVENTS\ +(sim_event *) sim_events_watch_clock (SIM_DESC sd, - signed64 wallclock_ms_time, + unsigned wallclock_ms_time, sim_event_handler *handler, void *data); -#if 0 -/* Schedule an event when the value at ADDR lies between LB..UB */ - -typedef enum { - /* value host byte ordered */ - 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; +/* Schedule an event when the NR_BYTES value at HOST_ADDR with + BYTE_ORDER lies within LB..UB (unsigned). -INLINE_SIM_EVENTS\ -(void) sim_events_watchpoint_schedule + HOST_ADDR: pointer into the host address space. + BYTE_ORDER: 0 - host endian; BIG_ENDIAN; LITTLE_ENDIAN */ + +EXTERN_SIM_EVENTS\ +(sim_event*) sim_events_watch_sim (SIM_DESC sd, - sim_watchpoint type, - void *addr, + void *host_addr, + int nr_bytes, + int byte_order, unsigned64 lb, unsigned64 ub, sim_event_handler *handler, void *data); -#endif -#if 0 -/* Schedule an event when the value in CORE lies between LB..UB */ +/* Schedule an event when the NR_BYTES value at CORE_ADDR with BYTE_ORDER + lies between LB..UB. -INLINE_SIM_EVENTS\ -(void) sim_events_watchcore_schedule + CORE_ADDR/MAP: pointer into the target address space. + BYTE_ORDER: 0 - current target endian; BIG_ENDIAN; LITTLE_ENDIAN */ + +EXTERN_SIM_EVENTS\ +(sim_event*) sim_events_watch_core (SIM_DESC sd, - sim_watchpoint type, - address_word addr, - sim_core_maps map, + 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); -#endif /* Deschedule the specified event */ -INLINE_SIM_EVENTS\ +EXTERN_SIM_EVENTS\ (void) sim_events_deschedule (SIM_DESC sd, sim_event *event_to_remove); +/* Prepare for main simulator loop. Ensure that the next thing to do + is not event processing. + + If the simulator halted part way through event processing then both + 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. Broken into two parts so that if something is - pending, the caller has a chance to save any cached state */ + +/* Progress time - separated into two parts so that the main loop can + save its context before the event queue is processed */ INLINE_SIM_EVENTS\ (int) sim_events_tick @@ -190,6 +223,7 @@ INLINE_SIM_EVENTS\ (SIM_DESC sd); + /* local concept of time */ INLINE_SIM_EVENTS\ diff --git a/sim/common/sim-resume.c b/sim/common/sim-resume.c new file mode 100644 index 0000000..e1004b7 --- /dev/null +++ b/sim/common/sim-resume.c @@ -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 + +/* 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; +} diff --git a/sim/common/sim-run.c b/sim/common/sim-run.c new file mode 100644 index 0000000..82aee67 --- /dev/null +++ b/sim/common/sim-run.c @@ -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); + } + } +} diff --git a/sim/common/sim-stop.c b/sim/common/sim-stop.c new file mode 100644 index 0000000..1a11bd5 --- /dev/null +++ b/sim/common/sim-stop.c @@ -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 + + +/* 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; +} diff --git a/sim/m32r/ChangeLog b/sim/m32r/ChangeLog index 4654296..55058dc 100644 --- a/sim/m32r/ChangeLog +++ b/sim/m32r/ChangeLog @@ -1,3 +1,8 @@ +Mon May 19 12:55:42 1997 Andrew Cagney + + * 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 * sim-if.c (sim_open): Update to reflect changes to core in diff --git a/sim/tic80/ChangeLog b/sim/tic80/ChangeLog index 81a7ad3..76952bc 100644 --- a/sim/tic80/ChangeLog +++ b/sim/tic80/ChangeLog @@ -1,3 +1,28 @@ +Fri May 16 14:35:30 1997 Andrew Cagney + + * 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 + + * 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 * ic (compute): Drop check for REG == 0, now always forced to diff --git a/sim/tic80/Makefile.in b/sim/tic80/Makefile.in index dbfb4b6..9075ac7 100644 --- a/sim/tic80/Makefile.in +++ b/sim/tic80/Makefile.in @@ -10,7 +10,7 @@ # Not all of these need to be mentioned, only the necessary ones. # 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 \ sim-calls.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-trace.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. # 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-events.h \ $(srcdir)/../common/sim-fpu.h \ + $(srcdir)/../common/sim-engine.h \ idecode.o: $(ENGINE_H) semantics.o: $(ENGINE_H) diff --git a/sim/tic80/insns b/sim/tic80/insns index 182fcbd..89502fc 100644 --- a/sim/tic80/insns +++ b/sim/tic80/insns @@ -21,12 +21,13 @@ // The following is called when ever an illegal instruction is encountered. ::internal::illegal - engine_error (SD, CPU, cia, - "illegal instruction at 0x%lx", cia.ip); + sim_io_eprintf (SD, "0x%lx: illegal instruction\n", (unsigned long) 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. ::internal::fp_unavailable - engine_error (SD, CPU, cia, - "floating-point unavailable at 0x%lx", cia.ip); + sim_io_eprintf (SD, "0x%lx: floating-point unavailable\n", (unsigned long) cia.ip); + sim_engine_halt (SD, CPU, NULL, cia, sim_signalled, SIGFPE); // Handle a branch instruction 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 1: val = SEXT32 (source, 15); 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) { @@ -271,28 +272,28 @@ void::function::do_cmnd:signed32 source int PP = EXTRACTED32 (source, 3, 0); /* what is implemented? */ if (PP != 0) - engine_error (SD, CPU, cia, "0x%lx: cmnd - PPs not supported", - (unsigned long) cia.ip); + sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - PPs not supported", + (unsigned long) cia.ip); if (VC != 0) - engine_error (SD, CPU, cia, "0x%lx: cmnd - VC not supported", - (unsigned long) cia.ip); + sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - VC not supported", + (unsigned long) cia.ip); if (TC != 0) - engine_error (SD, CPU, cia, "0x%lx: cmnd - TC not supported", - (unsigned long) cia.ip); + sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - TC not supported", + (unsigned long) cia.ip); if (MP) { if (Reset || Halt) - engine_halt (SD, CPU, cia, sim_exited, 0); + sim_engine_halt (SD, CPU, NULL, cia, sim_exited, 0); if (Unhalt) - engine_error (SD, CPU, cia, "0x%lx: cmnd - Can not unhalt the MP", - (unsigned long) cia.ip); + sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - Can not unhalt the MP", + (unsigned long) cia.ip); /* if (ICR || DCR); */ if (Task) - engine_error (SD, CPU, cia, "0x%lx: cmnd - Can not Task the MP", - (unsigned long) cia.ip); + sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - Can not Task the MP", + (unsigned long) cia.ip); if (Msg) - engine_error (SD, CPU, cia, "0x%lx: cmnd - Msg to MP not suported", - (unsigned long) cia.ip); + sim_engine_abort (SD, CPU, cia, "0x%lx: cmnd - Msg to MP not suported", + (unsigned long) cia.ip); } TRACE_SINK1 (MY_INDEX, source); 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); case 1: /* double */ if (reg < 0) - engine_error (SD, CPU, cia, "DP immediate invalid"); + sim_engine_abort (SD, CPU, cia, "DP immediate invalid"); 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) - 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) | INSERTED64 (GPR (reg), 31, 0)); 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 */ return sim_fpu_u32to (val); default: - engine_error (SD, CPU, cia, "Unsupported FP precision"); + sim_engine_abort (SD, CPU, cia, "Unsupported FP precision"); } return sim_fpu_i32to (0); 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); 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) - 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 + 1) = VH4_8 (v); break; @@ -446,7 +447,7 @@ void::function::set_fp_reg:int Dest, sim_fpu val, int PD break; } 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} @@ -634,10 +635,10 @@ instruction_address::function::do_jsr:instruction_address nia, signed32 *rLink, TRACE_UCOND_BR (MY_INDEX, target); nia = do_branch (_SD, annul, target, 1, rLink); if (nia.dp & 0x3) - engine_error (SD, CPU, cia, - "0x%lx: destination address 0x%lx misaligned", - (unsigned long) cia.ip, - (unsigned long) nia.dp); + sim_engine_abort (SD, CPU, cia, + "0x%lx: destination address 0x%lx misaligned", + (unsigned long) cia.ip, + (unsigned long) nia.dp); return nia; 31.Link,26.Base,21.0b100010,15.A,14.SignedOffset::::jsr i 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; if (Dest & 0x1) - engine_error (SD, CPU, cia, "0x%lx: ld.d to odd register %d", - cia.ip, Dest); + sim_engine_abort (SD, CPU, cia, "0x%lx: ld.d to odd register %d", + cia.ip, Dest); addr = base + (S ? (offset << 3) : offset); if (m) *rBase = addr; @@ -687,7 +688,7 @@ void::function::do_ld:int Dest, unsigned32 base, unsigned32 *rBase, int m , int break; default: 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); 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; default: 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) *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 */ break; default: - engine_error (SD, CPU, cia, - "0x%lx: Invalid merge (%d) for shift", - cia.ip, source); + sim_engine_abort (SD, CPU, cia, + "0x%lx: Invalid merge (%d) for shift", + cia.ip, source); shiftmask = 0; } /* and the composite mask */ @@ -894,9 +895,9 @@ void::function::do_shift:int Dest, unsigned32 source, int Merge, int i, int n, i } break; default: - engine_error (SD, CPU, cia, - "0x%lx: Invalid merge (%d)", - cia.ip, source); + sim_engine_abort (SD, CPU, cia, + "0x%lx: Invalid merge (%d)", + cia.ip, source); } 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; if (Source & 0x1) - engine_error (SD, CPU, cia, - "0x%lx: st.d with odd source register %d", - cia.ip, Source); + sim_engine_abort (SD, CPU, cia, + "0x%lx: st.d with odd source register %d", + cia.ip, Source); addr = base + (S ? (offset << 3) : offset); val = (V4_H8 (GPR(Source + 1)) | V4_L8 (GPR(Source))); STORE (addr, 8, val); @@ -952,7 +953,7 @@ void::function::do_st:int Source, unsigned32 base, unsigned32 *rBase, int m , in break; default: 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) *rBase = addr; @@ -1035,7 +1036,7 @@ void::function::do_trap:unsigned32 trap_number { case 1: /* EXIT */ { - engine_halt (SD, CPU, cia, sim_exited, GPR(2)); + sim_engine_halt (SD, CPU, NULL, cia, sim_exited, GPR(2)); break; } case 4: /* WRITE */ @@ -1056,9 +1057,9 @@ void::function::do_trap:unsigned32 trap_number sim_io_write_stderr (SD, &c, 1); } else - engine_error (SD, CPU, cia, - "0x%lx: write to invalid fid %d", - (unsigned long) cia.ip, GPR(2)); + sim_engine_abort (SD, CPU, cia, + "0x%lx: write to invalid fid %d", + (unsigned long) cia.ip, GPR(2)); GPR(2) = GPR(6); break; } @@ -1069,13 +1070,13 @@ void::function::do_trap:unsigned32 trap_number GPR(2) = -22; /* -EINVAL */ break; } - engine_error (SD, CPU, cia, - "0x%lx: unknown syscall %d", - (unsigned long) cia.ip, GPR(15)); + sim_engine_abort (SD, CPU, cia, + "0x%lx: unknown syscall %d", + (unsigned long) cia.ip, GPR(15)); } break; 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 */ case 74: @@ -1096,9 +1097,9 @@ void::function::do_trap:unsigned32 trap_number break; default: - engine_error (SD, CPU, cia, - "0x%lx: unsupported trap %d", - (unsigned long) cia.ip, trap_number); + sim_engine_abort (SD, CPU, cia, + "0x%lx: unsupported trap %d", + (unsigned long) cia.ip, trap_number); } 31./,27.0,26./,21.0b0000001,14.UTN::::trap i do_trap (_SD, UTN); diff --git a/sim/tic80/interp.c b/sim/tic80/interp.c index 24cfad1..24c86f6 100644 --- a/sim/tic80/interp.c +++ b/sim/tic80/interp.c @@ -36,16 +36,8 @@ #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; -} - -/* Mechanisms for stopping/restarting the simulation */ +#if 0 void engine_error (SIM_DESC sd, @@ -59,13 +51,7 @@ engine_error (SIM_DESC sd, sim_io_evprintf (sd, fmt, ap); va_end (ap); - if (sd->halt_ok) - { - sim_io_eprintf (sd, "\n"); - engine_halt (sd, cpu, cia, sim_stopped, SIGABRT); - } - else - sim_io_error (sd, " - aborting simulation"); + sim_halt (sd, cpu, NULL, cia, sim_stopped, SIGABRT); } void @@ -139,3 +125,6 @@ engine_step (SIM_DESC sd) engine_halt (sd, cpu, cia, sim_stopped, SIGTRAP); } } + +#endif + diff --git a/sim/tic80/sim-calls.c b/sim/tic80/sim-calls.c index dd54184..5b580bd 100644 --- a/sim/tic80/sim-calls.c +++ b/sim/tic80/sim-calls.c @@ -80,7 +80,13 @@ sim_open (SIM_OPEN_KIND kind, char **argv) 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_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 sim_do_command (SIM_DESC sd, char *cmd) { diff --git a/sim/tic80/sim-main.h b/sim/tic80/sim-main.h index be4e88d..bb7aad0 100644 --- a/sim/tic80/sim-main.h +++ b/sim/tic80/sim-main.h @@ -69,39 +69,4 @@ extern void engine_init (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