o Implement generic halt/restart/abort module.
authorAndrew Cagney <cagney@redhat.com>
Mon, 19 May 1997 03:42:33 +0000 (03:42 +0000)
committerAndrew Cagney <cagney@redhat.com>
Mon, 19 May 1997 03:42:33 +0000 (03:42 +0000)
Use in tic80 and d30v simulators.
o Add signal hook to sim-core module

18 files changed:
sim/common/.Sanitize
sim/common/ChangeLog
sim/common/Make-common.in
sim/common/sim-abort.c [new file with mode: 0644]
sim/common/sim-engine.c [new file with mode: 0644]
sim/common/sim-engine.h [new file with mode: 0644]
sim/common/sim-events.c
sim/common/sim-events.h
sim/common/sim-resume.c [new file with mode: 0644]
sim/common/sim-run.c [new file with mode: 0644]
sim/common/sim-stop.c [new file with mode: 0644]
sim/m32r/ChangeLog
sim/tic80/ChangeLog
sim/tic80/Makefile.in
sim/tic80/insns
sim/tic80/interp.c
sim/tic80/sim-calls.c
sim/tic80/sim-main.h

index 86daab6..c256e5c 100644 (file)
@@ -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
index cd79a60..c2cc924 100644 (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>
 
        * callback.c (os_open): Type of arg flags is int.
index c2b2fff..7db8ba7 100644 (file)
@@ -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 (file)
index 0000000..0a441e4
--- /dev/null
@@ -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 ();
+    }
+}
diff --git a/sim/common/sim-engine.c b/sim/common/sim-engine.c
new file mode 100644 (file)
index 0000000..46f69e5
--- /dev/null
@@ -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;
+}
diff --git a/sim/common/sim-engine.h b/sim/common/sim-engine.h
new file mode 100644 (file)
index 0000000..57c43e9
--- /dev/null
@@ -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
index 60927c0..00fac12 100644 (file)
 
 #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
    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 = &current->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);
index 05b28b5..8c41927 100644 (file)
    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 (file)
index 0000000..e1004b7
--- /dev/null
@@ -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;
+}
diff --git a/sim/common/sim-run.c b/sim/common/sim-run.c
new file mode 100644 (file)
index 0000000..82aee67
--- /dev/null
@@ -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 (file)
index 0000000..1a11bd5
--- /dev/null
@@ -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;
+}
index 4654296..55058dc 100644 (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>
 
        * sim-if.c (sim_open): Update to reflect changes to core in
index 81a7ad3..76952bc 100644 (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>
 
        * ic (compute): Drop check for REG == 0, now always forced to
index dbfb4b6..9075ac7 100644 (file)
@@ -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)
index 182fcbd..89502fc 100644 (file)
 
 // 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);
index 24cfad1..24c86f6 100644 (file)
 #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
+
index dd54184..5b580bd 100644 (file)
@@ -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)
 {
index be4e88d..bb7aad0 100644 (file)
@@ -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