diff --git a/sim/cr16/ChangeLog b/sim/cr16/ChangeLog
index 5d03dc3..0bf6e84 100644
--- a/sim/cr16/ChangeLog
+++ b/sim/cr16/ChangeLog
@@ -1,5 +1,27 @@
 2015-11-15  Mike Frysinger  <vapier@gentoo.org>
 
+	* Makefile.in (SIM_OBJS): Add sim-reason.o, sim-resume.o, and
+	sim-stop.o.
+	* cr16_sim.h (struct _state): Delete exe and exception.
+	* interp.c (lookup_hash): Call sim_engine_halt instead of setting
+	State.exception.
+	(do_run): Delete unused s and func variables.
+	(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_1_4, OP_18_8, OP_10_10, OP_C0_8, OP_102_14, OP_148_14, OP_D_C,
+	OP_14_D, OP_15_D, OP_2C00_10, OP_16_D, OP_17_D, OP_31E_10, OP_6_10):
+	Likewise.
+	(OP_C_C): Likewise.  Call sim_engine_halt instead of setting
+	State.exception.
+	(OP_0_20): Call sim_engine_halt instead of setting State.exception.
+
+2015-11-15  Mike Frysinger  <vapier@gentoo.org>
+
 	* Makefile.in (SIM_OBJS): Delete endian.o.
 	(INCLUDE): Delete endian.c.
 	* configure.ac (SIM_AC_OPTION_ENDIAN): Declare little endian.
diff --git a/sim/cr16/Makefile.in b/sim/cr16/Makefile.in
index f9b52ad..a3db8da 100644
--- a/sim/cr16/Makefile.in
+++ b/sim/cr16/Makefile.in
@@ -20,7 +20,10 @@
 SIM_OBJS = \
 	$(SIM_NEW_COMMON_OBJS) \
 	sim-hload.o \
+	sim-reason.o \
 	sim-reg.o \
+	sim-resume.o \
+	sim-stop.o \
 	interp.o \
 	table.o \
 	simops.o
diff --git a/sim/cr16/cr16_sim.h b/sim/cr16/cr16_sim.h
index d70ce14..bbba908 100644
--- a/sim/cr16/cr16_sim.h
+++ b/sim/cr16/cr16_sim.h
@@ -236,8 +236,6 @@ struct _state
     uint16 psw;
   } trace;
 
-  uint8 exe;
-  int	exception;
   int	pc_changed;
 
   /* NOTE: everything below this line is not reset by
diff --git a/sim/cr16/interp.c b/sim/cr16/interp.c
index 478cd9b..8925d85 100644
--- a/sim/cr16/interp.c
+++ b/sim/cr16/interp.c
@@ -91,11 +91,7 @@ lookup_hash (SIM_DESC sd, SIM_CPU *cpu, uint64 ins, int size)
   while ((ins & mask) != (BIN(h->opcode, h->mask)))
     {
       if (h->next == NULL)
-        {
-          State.exception = SIGILL;
-          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;
 
       mask = (((1 << (32 - h->mask)) -1) << h->mask);
@@ -331,9 +327,8 @@ static int
 do_run (SIM_DESC sd, SIM_CPU *cpu, uint64 mcode)
 {
   host_callback *cr16_callback = STATE_CALLBACK (sd);
-  struct simops *s= Simops;
   struct hash_entry *h;
-  char func[12]="\0";
+
 #ifdef DEBUG
   if ((cr16_debug & DEBUG_INSTRUCTION) != 0)
     (*cr16_callback->printf_filtered) (cr16_callback, "do_long 0x%x\n", mcode);
@@ -579,46 +574,64 @@ sim_open (SIM_OPEN_KIND kind, struct host_callback_struct *cb, struct bfd *abfd,
   return sd;
 }
 
-static int stop_simulator = 0;
-
-int
-sim_stop (SIM_DESC sd)
+static void
+step_once (SIM_DESC sd, SIM_CPU *cpu)
 {
-  stop_simulator = 1;
-  return 1;
-}
+  uint32 curr_ins_size = 0;
+  uint64 mcode = RLW (PC);
 
+  State.pc_changed = 0;
+
+  curr_ins_size = do_run (sd, cpu, mcode);
+
+#if CR16_DEBUG
+  (*cr16_callback->printf_filtered) (cr16_callback, "INS: PC=0x%X, mcode=0x%X\n", PC, mcode);
+#endif
+
+  if (curr_ins_size == 0)
+    sim_engine_halt (sd, cpu, NULL, PC, sim_exited, GPR (2));
+  else if (!State.pc_changed)
+    SET_PC (PC + (curr_ins_size * 2)); /* For word instructions.  */
+
+#if 0
+  /* Check for a breakpoint trap on this instruction.  This
+     overrides any pending branches or loops */
+  if (PSR_DB && PC == DBS)
+    {
+      SET_BPC (PC);
+      SET_BPSR (PSR);
+      SET_PC (SDBT_VECTOR_START);
+    }
+#endif
+
+  /* Writeback all the DATA / PC changes */
+  SLOT_FLUSH ();
+}
 
-/* Run (or resume) the program.  */
 void
-sim_resume (SIM_DESC sd, int step, int siggnal)
+sim_engine_run (SIM_DESC sd,
+		int next_cpu_nr,  /* ignore  */
+		int nr_cpus,      /* ignore  */
+		int siggnal)
 {
-  SIM_CPU *cpu = STATE_CPU (sd, 0);
-  uint32 curr_ins_size = 0;
-  uint64 mcode;
+  sim_cpu *cpu;
 
-#ifdef DEBUG
-//  (*cr16_callback->printf_filtered) (cr16_callback, "sim_resume (%d,%d)  PC=0x%x\n",step,siggnal,PC); 
-#endif
+  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
 
-  State.exception = 0;
-  if (step)
-    sim_stop (sd);
+  cpu = STATE_CPU (sd, 0);
 
   switch (siggnal)
     {
     case 0:
       break;
-#ifdef SIGBUS
-    case SIGBUS:
-#endif
-    case SIGSEGV:
+    case GDB_SIGNAL_BUS:
+    case GDB_SIGNAL_SEGV:
       SET_PC (PC);
       SET_PSR (PSR);
       JMP (AE_VECTOR_START);
       SLOT_FLUSH ();
       break;
-    case SIGILL:
+    case GDB_SIGNAL_ILL:
       SET_PC (PC);
       SET_PSR (PSR);
       SET_HW_PSR ((PSR & (PSR_C_BIT)));
@@ -630,47 +643,12 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
       break;
     }
 
-  do
+  while (1)
     {
-      mcode = RLW (PC);
-
-      State.pc_changed = 0;
-      
-      curr_ins_size = do_run (sd, cpu, mcode);
-
-#if CR16_DEBUG
- (*cr16_callback->printf_filtered) (cr16_callback, "INS: PC=0x%X, mcode=0x%X\n",PC,mcode); 
-#endif
-
-      if (!State.pc_changed)
-        {
-          if (curr_ins_size == 0) 
-           {
-             State.exception = SIG_CR16_EXIT; /* exit trap */
-             break;
-           }
-          else
-           SET_PC (PC + (curr_ins_size * 2)); /* For word instructions.  */
-        }
-
-#if 0
-      /* Check for a breakpoint trap on this instruction.  This
-         overrides any pending branches or loops */
-      if (PSR_DB && PC == DBS)
-        {
-          SET_BPC (PC);
-          SET_BPSR (PSR);
-          SET_PC (SDBT_VECTOR_START);
-        }
-#endif
-
-      /* Writeback all the DATA / PC changes */
-      SLOT_FLUSH ();
+      step_once (sd, cpu);
+      if (sim_events_tick (sd))
+	sim_events_process (sd);
     }
-  while ( !State.exception && !stop_simulator);
-  
-  if (step && !State.exception)
-    State.exception = SIGTRAP;
 }
 
 SIM_RC
@@ -707,45 +685,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)
-{
-/*   (*cr16_callback->printf_filtered) (cr16_callback, "sim_stop_reason:  PC=0x%x\n",PC<<2); */
-
-  switch (State.exception)
-    {
-    case SIG_CR16_STOP:                        /* stop instruction */
-      *reason = sim_stopped;
-      *sigrc = 0;
-      break;
-
-    case SIG_CR16_EXIT:                        /* exit trap */
-      *reason = sim_exited;
-      *sigrc = GPR (2);
-      break;
-
-    case SIG_CR16_BUS:
-      *reason = sim_stopped;
-      *sigrc = GDB_SIGNAL_BUS;
-      break;
-//
-//    case SIG_CR16_IAD:
-//      *reason = sim_stopped;
-//      *sigrc = GDB_SIGNAL_IAD;
-//      break;
-
-    default:                                /* some signal */
-      *reason = sim_stopped;
-      if (stop_simulator && !State.exception)
-        *sigrc = GDB_SIGNAL_INT;
-      else
-        *sigrc = State.exception;
-      break;
-    }
-
-  stop_simulator = 0;
-}
-
 static uint32
 cr16_extract_unsigned_integer (unsigned char *addr, int len)
 {
diff --git a/sim/cr16/simops.c b/sim/cr16/simops.c
index db595f1..9186c7f 100644
--- a/sim/cr16/simops.c
+++ b/sim/cr16/simops.c
@@ -48,6 +48,8 @@
 #include <sys/wait.h>
 #endif
 
+#define EXCEPTION(sig) sim_engine_halt (sd, cpu, NULL, PC, sim_stopped, sig)
+
 enum op_types {
   OP_VOID,
   OP_CONSTANT3,
@@ -184,7 +186,7 @@ move_to_cr (SIM_DESC sd, SIM_CPU *cpu, int cr, creg_t mask, creg_t val, int psw_
 	      (*cr16_callback->printf_filtered)
 		(cr16_callback,
 		 "ERROR at PC 0x%x: ST can only be set when FX is set.\n", PC);
-	      State.exception = SIGILL;
+	  EXCEPTION (SIM_SIGILL);
 #endif
       /* keep an up-to-date psw around for tracing.  */
       State.trace.psw = (State.trace.psw & mask) | val;
@@ -999,10 +1001,8 @@ OP_1_4 (SIM_DESC sd, SIM_CPU *cpu)
 
       if ((tmp < 0x000000) || (tmp > 0xFFFFFF))
         {
-          State.exception = SIG_CR16_BUS;
-          State.pc_changed = 1; /* Don't increment the PC. */
           trace_output_void (sd);
-          return;
+          EXCEPTION (SIM_SIGBUS);
         }
       else
         JMP (tmp);
@@ -1028,10 +1028,8 @@ OP_18_8 (SIM_DESC sd, SIM_CPU *cpu)
 
       if ((tmp < 0x000000) || (tmp > 0xFFFFFF))
         {
-          State.exception = SIG_CR16_BUS;
-          State.pc_changed = 1; /* Don't increment the PC. */
           trace_output_void (sd);
-          return;
+          EXCEPTION (SIM_SIGBUS);
         }
       else
         JMP (tmp);
@@ -1057,10 +1055,8 @@ OP_10_10 (SIM_DESC sd, SIM_CPU *cpu)
 
       if ((tmp < 0x000000) || (tmp > 0xFFFFFF))
         {
-          State.exception = SIG_CR16_BUS;
-          State.pc_changed = 1; /* Don't increment the PC. */
           trace_output_void (sd);
-          return;
+          EXCEPTION (SIM_SIGBUS);
         }
       else
         JMP (tmp);
@@ -1087,10 +1083,8 @@ OP_C0_8 (SIM_DESC sd, SIM_CPU *cpu)
 
   if ((tmp < 0x000000) || (tmp > 0xFFFFFF))
     {
-      State.exception = SIG_CR16_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   else
     JMP (tmp);
@@ -1116,10 +1110,8 @@ OP_102_14 (SIM_DESC sd, SIM_CPU *cpu)
 
   if ((tmp < 0x000000) || (tmp > 0xFFFFFF))
     {
-      State.exception = SIG_CR16_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   else
     JMP (tmp);
@@ -1141,10 +1133,8 @@ OP_148_14 (SIM_DESC sd, SIM_CPU *cpu)
 
   if ((tmp < 0x0) || (tmp > 0xFFFFFF))
     {
-      State.exception = SIG_CR16_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   else
     JMP (tmp);
@@ -1167,10 +1157,8 @@ OP_D_C (SIM_DESC sd, SIM_CPU *cpu)
 
   if ((tmp < 0x0) || (tmp > 0xFFFFFF))
     {
-      State.exception = SIG_CR16_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   else
     JMP (tmp);
@@ -2722,10 +2710,8 @@ OP_14_D (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("loadm", OP_CONSTANT4, OP_VOID, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_CR16_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
 
   while (count)
@@ -2752,10 +2738,8 @@ OP_15_D (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("loadm", OP_CONSTANT4, OP_VOID, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_CR16_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
 
   while (count)
@@ -4359,7 +4343,6 @@ OP_2C00_10 (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("nop", OP_VOID, OP_VOID, OP_VOID);
 
 #if 0
-  State.exception = SIGTRAP;
   ins_type_counters[ (int)State.ins_type ]--;	/* don't count nops as normal instructions */
   switch (State.ins_type)
     {
@@ -4368,7 +4351,7 @@ OP_2C00_10 (SIM_DESC sd, SIM_CPU *cpu)
       break;
 
     }
-
+  EXCEPTION (SIM_SIGTRAP);
 #endif
   trace_output_void (sd);
 }
@@ -4789,10 +4772,8 @@ OP_16_D (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("storm", OP_CONSTANT4, OP_VOID, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_CR16_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
 
   while (count)
@@ -4819,10 +4800,8 @@ OP_17_D (SIM_DESC sd, SIM_CPU *cpu)
   trace_input ("stormp", OP_CONSTANT4, OP_VOID, OP_VOID);
   if ((addr & 1))
     {
-      State.exception = SIG_CR16_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
 
   while (count)
@@ -5168,7 +5147,7 @@ OP_C_C (SIM_DESC sd, SIM_CPU *cpu)
 	    if (PARM1 == getpid ())
 	      {
 		trace_output_void (sd);
-		State.exception = PARM2;
+		EXCEPTION (PARM2);
 	      }
 	    else
 	      {
@@ -5281,7 +5260,7 @@ OP_C_C (SIM_DESC sd, SIM_CPU *cpu)
 		    trace_output_void (sd);
 		    (*cr16_callback->printf_filtered) (cr16_callback, "Unknown signal %d\n", PARM2);
 		    (*cr16_callback->flush_stdout) (cr16_callback);
-		    State.exception = SIGILL;
+		    EXCEPTION (SIM_SIGILL);
 		  }
 		else
 		  {
@@ -5347,7 +5326,7 @@ OP_C_C (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;
+	    EXCEPTION (PARM2);
 	    break;
 #endif
 
@@ -5406,8 +5385,8 @@ OP_C_C (SIM_DESC sd, SIM_CPU *cpu)
 
 	  case TARGET_SYS_exit:
 	    trace_input ("<exit>", OP_VOID, OP_VOID, OP_VOID);
-	    State.exception = SIG_CR16_EXIT;
 	    trace_output_void (sd);
+	    sim_engine_halt (sd, cpu, NULL, PC, sim_exited, GPR (2));
 	    break;
 
 	  case TARGET_SYS_unlink:
@@ -5486,14 +5465,14 @@ OP_C_C (SIM_DESC sd, SIM_CPU *cpu)
 	    switch (a)
 	    {
 	      case TRAP_BREAKPOINT:
-		State.exception = SIGTRAP;
 		tmp = (PC);
 		JMP(tmp);
 		trace_output_void (sd);
+		EXCEPTION (SIM_SIGTRAP);
 		break;
 	      case SIGTRAP:  /* supervisor call ?  */
-		State.exception = SIG_CR16_EXIT;
 		trace_output_void (sd);
+		sim_engine_halt (sd, cpu, NULL, PC, sim_exited, GPR (2));
 		break;
 	      default:
 		cr16_callback->error (cr16_callback, "Unknown syscall %d", FUNC);
@@ -5789,10 +5768,8 @@ OP_31E_10 (SIM_DESC sd, SIM_CPU *cpu)
 
   if ((tmp < 0x0) || (tmp > 0xFFFFFF))
     {
-      State.exception = SIG_CR16_BUS;
-      State.pc_changed = 1; /* Don't increment the PC. */
       trace_output_void (sd);
-      return;
+      EXCEPTION (SIM_SIGBUS);
     }
   else
     JMP (tmp);
@@ -5887,8 +5864,8 @@ void
 OP_6_10 (SIM_DESC sd, SIM_CPU *cpu)
 {
   trace_input ("wait", OP_VOID, OP_VOID, OP_VOID);
-  State.exception = SIGTRAP;
   trace_output_void (sd);
+  EXCEPTION (SIM_SIGTRAP);
 }
 
 /* ewait.  */
@@ -6013,5 +5990,5 @@ void
 OP_0_20 (SIM_DESC sd, SIM_CPU *cpu)
 {
   trace_input ("null", OP_VOID, OP_VOID, OP_VOID);
-  State.exception = SIG_CR16_STOP;
+  sim_engine_halt (sd, cpu, NULL, PC, sim_exited, 0);
 }
