sim: d10v: convert to common sim engine logic
authorMike Frysinger <vapier@gentoo.org>
Sun, 15 Nov 2015 11:07:06 +0000 (03:07 -0800)
committerMike Frysinger <vapier@gentoo.org>
Mon, 16 Nov 2015 01:47:17 +0000 (20:47 -0500)
Now that we have access to the sim state everywhere, we can convert to
the common engine logic for overall processing.  This frees us up from
tracking exception state ourselves.

sim/d10v/ChangeLog
sim/d10v/Makefile.in
sim/d10v/d10v_sim.h
sim/d10v/interp.c
sim/d10v/simops.c

index 2db4312a359c9a244a30d38a559b57b2133ae9e0..e26ef6cb86567418db8646ae2a1f3b5d628a2bc8 100644 (file)
@@ -1,3 +1,33 @@
+2015-11-15  Mike Frysinger  <vapier@gentoo.org>
+
+       * Makefile.in (SIM_OBJS): Add sim-reason.o, sim-resume.o, and
+       sim-stop.o.
+       * d10v_sim.h (struct d10v_memory): Delete fault member.
+       (struct _state): Delete exception member.
+       * interp.c (lookup_hash): Call sim_engine_halt instead of setting
+       State.exception.
+       (do_2_short, do_parallel): Delete State.exception checks.
+       (sim_size): Mark static.
+       (map_memory): Call sim_engine_halt instead of returning fault.
+       Call xcalloc instead of calloc and checking the return.
+       (dmem_addr): Call sim_engine_halt when phys_size is 0.
+       (imem_addr): Likewise.
+       (stop_simulator, sim_stop, sim_stop_reason): Delete.
+       (sim_resume): Rename to ...
+       (step_once): ... this.  Delete State.exception code and move
+       siggnal checking to sim_engine_run.
+       (sim_engine_run): New function.
+       * simops.c (EXCEPTION): Define.
+       (move_to_cr): Call EXCEPTION instead of setting State.exception.
+       (OP_30000000, OP_6401, OP_6001, OP_6000, OP_32010000, OP_31000000,
+       OP_6601, OP_6201, OP_6200, OP_33010000, OP_5201, OP_27000000,
+       OP_2F000000, OP_3220, OP_3200, OP_3400, OP_3000, OP_34000000,
+       OP_6800, OP_6C1F, OP_6801, OP_6C01, OP_36010000, OP_35000000,
+       OP_6A00, OP_6E1F, OP_6A01, OP_6E01, OP_37010000, OP_5FE0): Likewise.
+       (OP_5F20): Call sim_engine_halt instead of setting State.exception.
+       (OP_5F00): Call sim_engine_halt and EXCEPTION instead of setting
+       State.exception.
+
 2015-11-15  Mike Frysinger  <vapier@gentoo.org>
 
        * d10v_sim.h (struct simops): Add SIM_DESC and SIM_CPU to func args.
index 27b0008d12aad5b8d66b862f2fb1903bb00bc124..a6100dec4c4b32867a3a885890ba4e3bb8ed20e8 100644 (file)
@@ -21,6 +21,9 @@ SIM_OBJS = \
        interp.o \
        $(SIM_NEW_COMMON_OBJS) \
        sim-hload.o \
+       sim-reason.o \
+       sim-resume.o \
+       sim-stop.o \
        table.o \
        simops.o \
        endian.o
index ed2bbbb16d9001defb73382e6898d7ca4b2ce77e..e2d21112e4051ce7842bf2d0fecf1f6f29bf17b2 100644 (file)
@@ -226,7 +226,6 @@ struct d10v_memory
   uint8 *insn[IMEM_SEGMENTS];
   uint8 *data[DMEM_SEGMENTS];
   uint8 *unif[UMEM_SEGMENTS];
-  uint8 fault[16];
 };
 
 struct _state
@@ -262,7 +261,6 @@ struct _state
   } trace;
 
   uint8 exe;
-  int  exception;
   int  pc_changed;
 
   /* NOTE: everything below this line is not reset by
index df8b9290a4119037bcb82b00071d8b8ddb8bf8f8..263156e2f20dcc1b316af549a4804f96c6924298 100644 (file)
@@ -79,11 +79,7 @@ lookup_hash (SIM_DESC sd, SIM_CPU *cpu, uint32 ins, int size)
   while ((ins & h->mask) != h->opcode || h->size != size)
     {
       if (h->next == NULL)
-       {
-         State.exception = GDB_SIGNAL_ILL;
-         State.pc_changed = 1; /* Don't increment the PC. */
-         return NULL;
-       }
+       sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, SIM_SIGILL);
       h = h->next;
     }
   return (h);
@@ -159,7 +155,7 @@ do_2_short (SIM_DESC sd, SIM_CPU *cpu, uint16 ins1, uint16 ins2, enum _leftright
   (h->ops->func) (sd, cpu);
 
   /* Issue the second instruction (if the PC hasn't changed) */
-  if (!State.pc_changed && !State.exception)
+  if (!State.pc_changed)
     {
       /* finish any existing instructions */
       SLOT_FLUSH ();
@@ -172,7 +168,7 @@ do_2_short (SIM_DESC sd, SIM_CPU *cpu, uint16 ins1, uint16 ins2, enum _leftright
       ins_type_counters[ (int)INS_CYCLES ]++;
       (h->ops->func) (sd, cpu);
     }
-  else if (!State.exception)
+  else
     ins_type_counters[ (int)INS_COND_JUMP ]++;
 }
 
@@ -232,13 +228,10 @@ do_parallel (SIM_DESC sd, SIM_CPU *cpu, uint16 ins1, uint16 ins2)
       State.ins_type = INS_LEFT_PARALLEL;
       ins_type_counters[ (int)State.ins_type ]++;
       (h1->ops->func) (sd, cpu);
-      if (!State.exception)
-       {
-         get_operands (h2->ops, ins2);
-         State.ins_type = INS_RIGHT_PARALLEL;
-         ins_type_counters[ (int)State.ins_type ]++;
-         (h2->ops->func) (sd, cpu);
-       }
+      get_operands (h2->ops, ins2);
+      State.ins_type = INS_RIGHT_PARALLEL;
+      ins_type_counters[ (int)State.ins_type ]++;
+      (h2->ops->func) (sd, cpu);
     }
 }
  
@@ -262,7 +255,7 @@ add_commas (char *buf, int sizeof_buf, unsigned long value)
   return endbuf;
 }
 
-void
+static void
 sim_size (int power)
 {
   int i;
@@ -655,18 +648,11 @@ map_memory (SIM_DESC sd, SIM_CPU *cpu, unsigned phys_addr)
     default:
       /* OOPS! */
       last_segname = "scrap";
-      return State.mem.fault;
+      sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, SIM_SIGBUS);
     }
   
   if (*memory == NULL)
-    {
-      *memory = calloc (1, SEGMENT_SIZE);
-      if (*memory == NULL)
-       {
-         (*d10v_callback->printf_filtered) (d10v_callback, "Malloc failed.\n");
-         return State.mem.fault;
-       }
-    }
+    *memory = xcalloc (1, SEGMENT_SIZE);
   
   offset = (phys_addr % SEGMENT_SIZE);
   raw = *memory + offset;
@@ -893,11 +879,8 @@ dmem_addr (SIM_DESC sd, SIM_CPU *cpu, uint16 offset)
   phys_size = sim_d10v_translate_dmap_addr (sd, cpu, offset, 1, &phys, NULL,
                                            dmap_register);
   if (phys_size == 0)
-    {
-      mem = State.mem.fault;
-    }
-  else
-    mem = map_memory (sd, cpu, phys);
+    sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, SIM_SIGBUS);
+  mem = map_memory (sd, cpu, phys);
 #ifdef DEBUG
   if ((d10v_debug & DEBUG_MEMORY))
     {
@@ -920,9 +903,7 @@ imem_addr (SIM_DESC sd, SIM_CPU *cpu, uint32 offset)
   int phys_size = sim_d10v_translate_imap_addr (sd, cpu, offset, 1, &phys, NULL,
                                                imap_register);
   if (phys_size == 0)
-    {
-      return State.mem.fault;
-    }
+    sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, SIM_SIGBUS);
   mem = map_memory (sd, cpu, phys);
 #ifdef DEBUG
   if ((d10v_debug & DEBUG_MEMORY))
@@ -938,60 +919,15 @@ imem_addr (SIM_DESC sd, SIM_CPU *cpu, uint32 offset)
   return mem;
 }
 
-static int stop_simulator = 0;
-
-int
-sim_stop (SIM_DESC sd)
-{
-  stop_simulator = 1;
-  return 1;
-}
-
-
-/* Run (or resume) the program.  */
-void
-sim_resume (SIM_DESC sd, int step, int siggnal)
+static void
+step_once (SIM_DESC sd, SIM_CPU *cpu)
 {
-  SIM_CPU *cpu = STATE_CPU (sd, 0);
   uint32 inst;
   uint8 *iaddr;
 
-/*   (*d10v_callback->printf_filtered) (d10v_callback, "sim_resume (%d,%d)  PC=0x%x\n",step,siggnal,PC); */
-  State.exception = 0;
-  if (step)
-    sim_stop (sd);
-
-  switch (siggnal)
-    {
-    case 0:
-      break;
-    case GDB_SIGNAL_BUS:
-      SET_BPC (PC);
-      SET_BPSW (PSW);
-      SET_HW_PSW ((PSW & (PSW_F0_BIT | PSW_F1_BIT | PSW_C_BIT)));
-      JMP (AE_VECTOR_START);
-      SLOT_FLUSH ();
-      break;
-    case GDB_SIGNAL_ILL:
-      SET_BPC (PC);
-      SET_BPSW (PSW);
-      SET_HW_PSW ((PSW & (PSW_F0_BIT | PSW_F1_BIT | PSW_C_BIT)));
-      JMP (RIE_VECTOR_START);
-      SLOT_FLUSH ();
-      break;
-    default:
-      /* just ignore it */
-      break;
-    }
-
-  do
+  /* TODO: Unindent this block.  */
     {
       iaddr = imem_addr (sd, cpu, (uint32)PC << 2);
-      if (iaddr == State.mem.fault)
-       {
-         State.exception = GDB_SIGNAL_BUS;
-         break;
-       }
  
       inst = get_longword( iaddr ); 
  
@@ -1058,10 +994,49 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
       /* Writeback all the DATA / PC changes */
       SLOT_FLUSH ();
     }
-  while ( !State.exception && !stop_simulator);
-  
-  if (step && !State.exception)
-    State.exception = GDB_SIGNAL_TRAP;
+}
+
+void
+sim_engine_run (SIM_DESC sd,
+               int next_cpu_nr,  /* ignore  */
+               int nr_cpus,      /* ignore  */
+               int siggnal)
+{
+  sim_cpu *cpu;
+
+  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
+
+  cpu = STATE_CPU (sd, 0);
+
+  switch (siggnal)
+    {
+    case 0:
+      break;
+    case GDB_SIGNAL_BUS:
+      SET_BPC (PC);
+      SET_BPSW (PSW);
+      SET_HW_PSW ((PSW & (PSW_F0_BIT | PSW_F1_BIT | PSW_C_BIT)));
+      JMP (AE_VECTOR_START);
+      SLOT_FLUSH ();
+      break;
+    case GDB_SIGNAL_ILL:
+      SET_BPC (PC);
+      SET_BPSW (PSW);
+      SET_HW_PSW ((PSW & (PSW_F0_BIT | PSW_F1_BIT | PSW_C_BIT)));
+      JMP (RIE_VECTOR_START);
+      SLOT_FLUSH ();
+      break;
+    default:
+      /* just ignore it */
+      break;
+    }
+
+  while (1)
+    {
+      step_once (sd, cpu);
+      if (sim_events_tick (sd))
+       sim_events_process (sd);
+    }
 }
 
 void
@@ -1226,40 +1201,6 @@ sim_create_inferior (SIM_DESC sd, struct bfd *abfd, char **argv, char **env)
   return SIM_RC_OK;
 }
 
-void
-sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc)
-{
-/*   (*d10v_callback->printf_filtered) (d10v_callback, "sim_stop_reason:  PC=0x%x\n",PC<<2); */
-
-  switch (State.exception)
-    {
-    case SIG_D10V_STOP:                        /* stop instruction */
-      *reason = sim_exited;
-      *sigrc = 0;
-      break;
-
-    case SIG_D10V_EXIT:                        /* exit trap */
-      *reason = sim_exited;
-      *sigrc = GPR (0);
-      break;
-
-    case SIG_D10V_BUS:
-      *reason = sim_stopped;
-      *sigrc = GDB_SIGNAL_BUS;
-      break;
-
-    default:                           /* some signal */
-      *reason = sim_stopped;
-      if (stop_simulator && !State.exception)
-       *sigrc = GDB_SIGNAL_INT;
-      else
-       *sigrc = State.exception;
-      break;
-    }
-
-  stop_simulator = 0;
-}
-
 int
 sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
 {
index 28044f6eb7541658cb4454ccc6a0028809b5266d..6eb1a209ad6cb044829f48f51787028ea5ca1d41 100644 (file)
@@ -15,6 +15,8 @@
 #include "simops.h"
 #include "targ-vals.h"
 
+#define EXCEPTION(sig) sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, sig)
+
 enum op_types {
   OP_VOID,
   OP_REG,
@@ -92,7 +94,7 @@ move_to_cr (SIM_DESC sd, SIM_CPU *cpu, int cr, reg_t mask, reg_t val, int psw_hw
                (d10v_callback,
                 "ERROR at PC 0x%x: ST can only be set when FX is set.\n",
                 PC<<2);
-             State.exception = SIGILL;
+             EXCEPTION (SIM_SIGILL);
            }
        }
       /* keep an up-to-date psw around for tracing */
@@ -1138,9 +1140,7 @@ OP_5F20 (SIM_DESC sd, SIM_CPU *cpu)
       trace_output_void (sd);
     }
   else
-    {
-      State.exception = SIGTRAP;
-    }
+    sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, SIM_SIGTRAP);
 }
 
 /* divs */
@@ -1320,10 +1320,8 @@ OP_30000000 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("ld", OP_REG_OUTPUT, OP_MEMREF2, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   tmp = RW (addr);
   SET_GPR (OP[0], tmp);
@@ -1339,10 +1337,8 @@ OP_6401 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("ld", OP_REG_OUTPUT, OP_POSTDEC, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   tmp = RW (addr);
   SET_GPR (OP[0], tmp);
@@ -1360,10 +1356,8 @@ OP_6001 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("ld", OP_REG_OUTPUT, OP_POSTINC, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   tmp = RW (addr);
   SET_GPR (OP[0], tmp);
@@ -1381,10 +1375,8 @@ OP_6000 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("ld", OP_REG_OUTPUT, OP_MEMREF, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   tmp = RW (addr);
   SET_GPR (OP[0], tmp);
@@ -1400,10 +1392,8 @@ OP_32010000 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("ld", OP_REG_OUTPUT, OP_MEMREF3, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   tmp = RW (addr);
   SET_GPR (OP[0], tmp);
@@ -1419,10 +1409,8 @@ OP_31000000 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF2, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   tmp = RLW (addr);
   SET_GPR32 (OP[0], tmp);
@@ -1438,10 +1426,8 @@ OP_6601 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("ld2w", OP_REG_OUTPUT, OP_POSTDEC, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   tmp = RLW (addr);
   SET_GPR32 (OP[0], tmp);
@@ -1459,10 +1445,8 @@ OP_6201 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("ld2w", OP_REG_OUTPUT, OP_POSTINC, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   tmp = RLW (addr);
   SET_GPR32 (OP[0], tmp);
@@ -1480,10 +1464,8 @@ OP_6200 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   tmp = RLW (addr);
   SET_GPR32 (OP[0], tmp);
@@ -1499,10 +1481,8 @@ OP_33010000 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF3, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   tmp = RLW (addr);
   SET_GPR32 (OP[0], tmp);
@@ -2225,7 +2205,7 @@ OP_5201 (SIM_DESC sd, SIM_CPU *cpu)
       (*d10v_callback->printf_filtered) (d10v_callback,
                                         "ERROR at PC 0x%x: instruction only valid for A0\n",
                                         PC<<2);
-      State.exception = SIGILL;
+      EXCEPTION (SIM_SIGILL);
     }
 
   SET_PSW_F1 (PSW_F0);
@@ -2300,12 +2280,12 @@ OP_27000000 (SIM_DESC sd, SIM_CPU *cpu)
   if (GPR (OP[0]) == 0)
     {
       (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: rep with count=0 is illegal.\n");
-      State.exception = SIGILL;
+      EXCEPTION (SIM_SIGILL);
     }
   if (OP[1] < 4)
     {
       (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: rep must include at least 4 instructions.\n");
-      State.exception = SIGILL;
+      EXCEPTION (SIM_SIGILL);
     }
   trace_output_void (sd);
 }
@@ -2322,12 +2302,12 @@ OP_2F000000 (SIM_DESC sd, SIM_CPU *cpu)
   if (OP[0] == 0)
     {
       (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: repi with count=0 is illegal.\n");
-      State.exception = SIGILL;
+      EXCEPTION (SIM_SIGILL);
     }
   if (OP[1] < 4)
     {
       (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: repi must include at least 4 instructions.\n");
-      State.exception = SIGILL;
+      EXCEPTION (SIM_SIGILL);
     }
   trace_output_void (sd);
 }
@@ -2476,8 +2456,7 @@ OP_3220 (SIM_DESC sd, SIM_CPU *cpu)
   if (reg >= 17 || reg <= -17)
     {
       (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: shift value %d too large.\n", reg);
-      State.exception = SIGILL;
-      return;
+      EXCEPTION (SIM_SIGILL);
     }
 
   tmp = SEXT40 (ACC (OP[0]));
@@ -2485,8 +2464,7 @@ OP_3220 (SIM_DESC sd, SIM_CPU *cpu)
   if (PSW_ST && (tmp < SEXT40 (MIN32) || tmp > SEXT40 (MAX32)))
     {
       (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: accumulator value 0x%.2x%.8lx out of range\n", ((int)(tmp >> 32) & 0xff), ((unsigned long) tmp) & 0xffffffff);
-      State.exception = SIGILL;
-      return;
+      EXCEPTION (SIM_SIGILL);
     }
 
   if (reg >= 0 && reg <= 16)
@@ -2545,8 +2523,7 @@ OP_3200 (SIM_DESC sd, SIM_CPU *cpu)
   else
     {
       (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: shift value %d too large.\n", GPR (OP[1]) & 31);
-      State.exception = SIGILL;
-      return;
+      EXCEPTION (SIM_SIGILL);
     }
 
   if (PSW_ST)
@@ -2638,8 +2615,7 @@ OP_3400 (SIM_DESC sd, SIM_CPU *cpu)
   else
     {
       (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: shift value %d too large.\n", GPR (OP[1]) & 31);
-      State.exception = SIGILL;
-      return;
+      EXCEPTION (SIM_SIGILL);
     }
 }
 
@@ -2693,8 +2669,7 @@ OP_3000 (SIM_DESC sd, SIM_CPU *cpu)
   else
     {
       (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: shift value %d too large.\n", GPR (OP[1]) & 31);
-      State.exception = SIGILL;
-      return;
+      EXCEPTION (SIM_SIGILL);
     }
 
 }
@@ -2744,10 +2719,8 @@ OP_34000000 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("st", OP_REG, OP_MEMREF2, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   SW (addr, GPR (OP[0]));
   trace_output_void (sd);
@@ -2761,10 +2734,8 @@ OP_6800 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("st", OP_REG, OP_MEMREF, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   SW (addr, GPR (OP[0]));
   trace_output_void (sd);
@@ -2780,15 +2751,12 @@ OP_6C1F (SIM_DESC sd, SIM_CPU *cpu)
   if (OP[1] != 15)
     {
       (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot pre-decrement any registers but r15 (SP).\n");
-      State.exception = SIGILL;
-      return;
+      EXCEPTION (SIM_SIGILL);
     }
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   SW (addr, GPR (OP[0]));
   SET_GPR (OP[1], addr);
@@ -2803,10 +2771,8 @@ OP_6801 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("st", OP_REG, OP_POSTINC, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   SW (addr, GPR (OP[0]));
   INC_ADDR (OP[1], 2);
@@ -2822,15 +2788,12 @@ OP_6C01 (SIM_DESC sd, SIM_CPU *cpu)
   if ( OP[1] == 15 )
     {
       (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot post-decrement register r15 (SP).\n");
-      State.exception = SIGILL;
-      return;
+      EXCEPTION (SIM_SIGILL);
     }
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   SW (addr, GPR (OP[0]));
   INC_ADDR (OP[1], -2);
@@ -2845,10 +2808,8 @@ OP_36010000 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("st", OP_REG, OP_MEMREF3, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   SW (addr, GPR (OP[0]));
   trace_output_void (sd);
@@ -2862,10 +2823,8 @@ OP_35000000 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("st2w", OP_DREG, OP_MEMREF2, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   SW (addr + 0, GPR (OP[0] + 0));
   SW (addr + 2, GPR (OP[0] + 1));
@@ -2880,10 +2839,8 @@ OP_6A00 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("st2w", OP_DREG, OP_MEMREF, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   SW (addr + 0, GPR (OP[0] + 0));
   SW (addr + 2, GPR (OP[0] + 1));
@@ -2899,15 +2856,12 @@ OP_6E1F (SIM_DESC sd, SIM_CPU *cpu)
   if ( OP[1] != 15 )
     {
       (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot pre-decrement any registers but r15 (SP).\n");
-      State.exception = SIGILL;
-      return;
+      EXCEPTION (SIM_SIGILL);
     }
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   SW (addr + 0, GPR (OP[0] + 0));
   SW (addr + 2, GPR (OP[0] + 1));
@@ -2923,10 +2877,8 @@ OP_6A01 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("st2w", OP_DREG, OP_POSTINC, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   SW (addr + 0, GPR (OP[0] + 0));
   SW (addr + 2, GPR (OP[0] + 1));
@@ -2943,15 +2895,12 @@ OP_6E01 (SIM_DESC sd, SIM_CPU *cpu)
   if ( OP[1] == 15 )
     {
       (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot post-decrement register r15 (SP).\n");
-      State.exception = SIGILL;
-      return;
+      EXCEPTION (SIM_SIGILL);
     }
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   SW (addr + 0, GPR (OP[0] + 0));
   SW (addr + 2, GPR (OP[0] + 1));
@@ -2967,10 +2916,8 @@ OP_37010000 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("st2w", OP_DREG, OP_MEMREF3, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_D10V_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   SW (addr + 0, GPR (OP[0] + 0));
   SW (addr + 2, GPR (OP[0] + 1));
@@ -3000,8 +2947,8 @@ void
 OP_5FE0 (SIM_DESC sd, SIM_CPU *cpu)
 {
   trace_input ("stop", OP_VOID, OP_VOID, OP_VOID);
-  State.exception = SIG_D10V_STOP;
   trace_output_void (sd);
+  sim_engine_halt (sd, cpu, NULL, PC, sim_exited, 0);
 }
 
 /* sub */
@@ -3276,7 +3223,7 @@ OP_5F00 (SIM_DESC sd, SIM_CPU *cpu)
            if (PARM1 == getpid ())
              {
                trace_output_void (sd);
-               State.exception = PARM2;
+               sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, PARM2);
              }
            else
              {
@@ -3389,7 +3336,7 @@ OP_5F00 (SIM_DESC sd, SIM_CPU *cpu)
                    trace_output_void (sd);
                    (*d10v_callback->printf_filtered) (d10v_callback, "Unknown signal %d\n", PARM2);
                    (*d10v_callback->flush_stdout) (d10v_callback);
-                   State.exception = SIGILL;
+                   EXCEPTION (SIM_SIGILL);
                  }
                else
                  {
@@ -3453,7 +3400,7 @@ OP_5F00 (SIM_DESC sd, SIM_CPU *cpu)
          case TARGET_SYS_kill:
            trace_input ("<kill>", OP_REG, OP_REG, OP_VOID);
            trace_output_void (sd);
-           State.exception = PARM2;
+           sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, PARM2);
            break;
 #endif
 
@@ -3498,8 +3445,8 @@ OP_5F00 (SIM_DESC sd, SIM_CPU *cpu)
 
          case TARGET_SYS_exit:
            trace_input ("<exit>", OP_R0, OP_VOID, OP_VOID);
-           State.exception = SIG_D10V_EXIT;
            trace_output_void (sd);
+           sim_engine_halt (sd, cpu, NULL, PC, sim_exited, GPR (0));
            break;
 
 #ifdef TARGET_SYS_stat