2003-04-13 Michael Snyder <msnyder@redhat.com>
[binutils-gdb.git] / sim / h8300 / compile.c
index 5290b4c92b1ccd60527435a89ffe81a1714ee2b2..0e4b6d2b2912e952771c75a601b391b1ccddb36c 100644 (file)
  * AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+#include "config.h"
+
+#include <stdio.h>
 #include <signal.h>
-#include <sys/times.h>
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
 #include <sys/param.h>
+#endif
 #include "ansidecl.h"
-#include "sysdep.h"
-#include "remote-sim.h"
+#include "bfd.h"
+#include "gdb/callback.h"
+#include "gdb/remote-sim.h"
+#include "gdb/sim-h8300.h"
+#include "sys/stat.h"
+#include "sys/types.h"
+
+#ifndef SIGTRAP
+# define SIGTRAP 5
+#endif
 
 int debug;
 
+host_callback *sim_callback;
+
+static SIM_OPEN_KIND sim_kind;
+static char *myname;
+
+/* FIXME: Needs to live in header file.
+   This header should also include the things in remote-sim.h.
+   One could move this to remote-sim.h but this function isn't needed
+   by gdb.  */
+void sim_set_simcache_size PARAMS ((int));
 
-#define X(op, size)  op*4+size
+#define X(op, size)  op * 4 + size
 
-#define SP (h8300hmode ? SL:SW)
+#define SP (h8300hmode ? SL : SW)
 #define SB 0
 #define SW 1
 #define SL 2
@@ -42,62 +70,78 @@ int debug;
 #define OP_CCR 7
 #define OP_IMM 8
 #define OP_ABS 10
+#define OP_EXR 11
 #define h8_opcodes ops
 #define DEFINE_TABLE
 #include "opcode/h8300.h"
 
 #include "inst.h"
 
+/* The rate at which to call the host's poll_quit callback.  */
+
+#define POLL_QUIT_INTERVAL 0x80000
+
 #define LOW_BYTE(x) ((x) & 0xff)
-#define HIGH_BYTE(x) (((x)>>8) & 0xff)
-#define P(X,Y) ((X<<8) | Y)
+#define HIGH_BYTE(x) (((x) >> 8) & 0xff)
+#define P(X,Y) ((X << 8) | Y)
+
+#define BUILDSR()                                      \
+  cpu.ccr = ((I << 7) | (UI << 6) | (H << 5) | (U << 4)        \
+            | (N << 3) | (Z << 2) | (V << 1) | C);
 
-#define BUILDSR()   cpu.ccr = (N << 3) | (Z << 2) | (V<<1) | C;
+#define BUILDEXR()         \
+  if (h8300smode) cpu.exr = (trace<<7) | intMask;
 
 #define GETSR()                    \
   c = (cpu.ccr >> 0) & 1;\
   v = (cpu.ccr >> 1) & 1;\
   nz = !((cpu.ccr >> 2) & 1);\
-  n = (cpu.ccr >> 3) & 1;
+  n = (cpu.ccr >> 3) & 1;\
+  u = (cpu.ccr >> 4) & 1;\
+  h = (cpu.ccr >> 5) & 1;\
+  ui = ((cpu.ccr >> 6) & 1);\
+  intMaskBit = (cpu.ccr >> 7) & 1;
+
+#define GETEXR()                               \
+  if (h8300smode)                              \
+    {                                          \
+      trace = (cpu.exr >> 7) & 1;              \
+      intMask = cpu.exr & 7;                   \
+    }
 
 #ifdef __CHAR_IS_SIGNED__
-#define SEXTCHAR(x) ((char)(x))
+#define SEXTCHAR(x) ((char) (x))
 #endif
 
 #ifndef SEXTCHAR
-#define SEXTCHAR(x) ((x & 0x80) ? (x | ~0xff):x)
+#define SEXTCHAR(x) ((x & 0x80) ? (x | ~0xff) : x & 0xff)
 #endif
 
 #define UEXTCHAR(x) ((x) & 0xff)
 #define UEXTSHORT(x) ((x) & 0xffff)
-#define SEXTSHORT(x) ((short)(x))
+#define SEXTSHORT(x) ((short) (x))
 
 static cpu_state_type cpu;
 
 int h8300hmode = 0;
+int h8300smode = 0;
 
+static int memory_size;
 
 static int
-get_now ()
+get_now (void)
 {
-  struct tms b;
-
-  return time (0);
-#if 0
-  times (&b);
-  return b.tms_utime + b.tms_stime;
-#endif
+  return time (0);     /* WinXX HAS UNIX like 'time', so why not using it? */
 }
 
 static int
-now_persec ()
+now_persec (void)
 {
   return 1;
 }
 
-
 static int
-bitfrom (x)
+bitfrom (int x)
 {
   switch (x & SIZE)
     {
@@ -112,9 +156,8 @@ bitfrom (x)
     }
 }
 
-static
-unsigned int
-lvalue (x, rn)
+static unsigned int
+lvalue (int x, int rn)
 {
   switch (x / 4)
     {
@@ -126,38 +169,45 @@ lvalue (x, rn)
       return X (OP_REG, SP);
 
     case OP_MEM:
-
       return X (OP_MEM, SP);
+
     default:
-      abort ();
+      abort (); /* ?? May be something more usefull? */
     }
 }
 
-static unsigned int
-decode (addr, data, dst)
-     int addr;
-     unsigned char *data;
-     decoded_inst *dst;
+static int
+cmdline_location()
+{
+  if (h8300smode)
+    return 0xffff00L;
+  else if (h8300hmode)
+    return 0x2ff00L;
+  else
+    return 0xff00L;
+}
 
+static unsigned int
+decode (int addr, unsigned char *data, decoded_inst *dst)
 {
   int rs = 0;
   int rd = 0;
   int rdisp = 0;
   int abs = 0;
+  int bit = 0;
   int plen = 0;
-
-  struct h8_opcode *q = h8_opcodes;
+  struct h8_opcode *q;
   int size = 0;
+
   dst->dst.type = -1;
   dst->src.type = -1;
-  /* Find the exact opcode/arg combo */
-  while (q->name)
+
+  /* Find the exact opcode/arg combo.  */
+  for (q = h8_opcodes; q->name; q++)
     {
-      op_type *nib;
+      op_type *nib = q->data.nib;
       unsigned int len = 0;
 
-      nib = q->data.nib;
-
       while (1)
        {
          op_type looking_for = *nib;
@@ -176,40 +226,40 @@ decode (addr, data, dst)
                {
                  if (!(((int) thisnib & 0x8) != 0))
                    goto fail;
-                 looking_for = (op_type) ((int) looking_for & ~(int)
-                                          B31);
+
+                 looking_for = (op_type) ((int) looking_for & ~(int) B31);
                  thisnib &= 0x7;
                }
+
              if ((int) looking_for & (int) B30)
                {
                  if (!(((int) thisnib & 0x8) == 0))
                    goto fail;
+
                  looking_for = (op_type) ((int) looking_for & ~(int) B30);
                }
+
              if (looking_for & DBIT)
                {
-                 if ((looking_for & 5) != (thisnib & 5))
+                 /* Exclude adds/subs by looking at bit 0 and 2, and
+                     make sure the operand size, either w or l,
+                     matches by looking at bit 1.  */
+                 if ((looking_for & 7) != (thisnib & 7))
                    goto fail;
+
                  abs = (thisnib & 0x8) ? 2 : 1;
                }
              else if (looking_for & (REG | IND | INC | DEC))
                {
                  if (looking_for & REG)
                    {
-                     /*
-                      * Can work out size from the
-                      * register
-                      */
+                     /* Can work out size from the register.  */
                      size = bitfrom (looking_for);
                    }
                  if (looking_for & SRC)
-                   {
-                     rs = thisnib;
-                   }
+                   rs = thisnib;
                  else
-                   {
-                     rd = thisnib;
-                   }
+                   rd = thisnib;
                }
              else if (looking_for & L_16)
                {
@@ -222,10 +272,7 @@ decode (addr, data, dst)
                }
              else if (looking_for & ABSJMP)
                {
-                 abs =
-                   (data[1] << 16)
-                   | (data[2] << 8)
-                   | (data[3]);
+                 abs = (data[1] << 16) | (data[2] << 8) | (data[3]);
                }
              else if (looking_for & MEMIND)
                {
@@ -234,6 +281,7 @@ decode (addr, data, dst)
              else if (looking_for & L_32)
                {
                  int i = len >> 1;
+
                  abs = (data[i] << 24)
                    | (data[i + 1] << 16)
                    | (data[i + 2] << 8)
@@ -244,12 +292,13 @@ decode (addr, data, dst)
              else if (looking_for & L_24)
                {
                  int i = len >> 1;
+
                  abs = (data[i] << 16) | (data[i + 1] << 8) | (data[i + 2]);
                  plen = 24;
                }
              else if (looking_for & IGNORE)
                {
-                 /* nothing to do */
+                 ;
                }
              else if (looking_for & DISPREG)
                {
@@ -268,6 +317,8 @@ decode (addr, data, dst)
                    case 0:
                      abs = 1;
                      break;
+                   default:
+                     goto fail;
                    }
                }
              else if (looking_for & L_8)
@@ -278,6 +329,12 @@ decode (addr, data, dst)
                    {
                      abs = SEXTCHAR (data[len >> 1]);
                    }
+                 else if (looking_for & ABS8MEM)
+                   {
+                     plen = 8;
+                     abs = h8300hmode ? ~0xff0000ff : ~0xffff00ff;
+                     abs |= data[len >> 1] & 0xff;
+                   }
                  else
                    {
                      abs = data[len >> 1] & 0xff;
@@ -287,13 +344,13 @@ decode (addr, data, dst)
                {
                  plen = 3;
 
-                 abs = thisnib;
+                 bit = thisnib;
                }
              else if (looking_for == E)
                {
                  dst->op = q;
 
-                 /* Fill in the args */
+                 /* Fill in the args */
                  {
                    op_type *args = q->args.nib;
                    int hadone = 0;
@@ -305,23 +362,24 @@ decode (addr, data, dst)
                        ea_type *p;
 
                        if (x & DST)
-                         {
-                           p = &(dst->dst);
-                         }
+                         p = &(dst->dst);
                        else
+                         p = &(dst->src);
+
+                       if (x & L_3)
                          {
-                           p = &(dst->src);
+                           p->type = X (OP_IMM, size);
+                           p->literal = bit;
                          }
-
-                       if (x & (IMM | KBIT | DBIT))
+                       else if (x & (IMM | KBIT | DBIT))
                          {
                            p->type = X (OP_IMM, size);
                            p->literal = abs;
                          }
                        else if (x & REG)
                          {
-                           /* Reset the size, some
-                              ops (like mul) have two sizes */
+                           /* Reset the size.
+                              Some ops (like mul) have two sizes.  */
 
                            size = bitfrom (x);
                            p->type = X (OP_REG, size);
@@ -343,7 +401,7 @@ decode (addr, data, dst)
                            p->reg = rn & 0x7;
                            p->literal = 0;
                          }
-                       else if (x & (ABS | ABSJMP | ABSMOV))
+                       else if (x & (ABS | ABSJMP | ABS8MEM))
                          {
                            p->type = X (OP_DISP, size);
                            p->literal = abs;
@@ -376,6 +434,10 @@ decode (addr, data, dst)
                          {
                            p->type = OP_CCR;
                          }
+                       else if (x & EXR)
+                         {
+                           p->type = OP_EXR;
+                         }
                        else
                          printf ("Hmmmm %x", x);
 
@@ -383,12 +445,9 @@ decode (addr, data, dst)
                      }
                  }
 
-                 /*
-                    * But a jmp or a jsr gets
-                    * automagically lvalued, since we
-                    * branch to their address not their
-                    * contents
-                  */
+                 /* But a jmp or a jsr gets automagically lvalued,
+                    since we branch to their address not their
+                    contents.  */
                  if (q->how == O (O_JSR, SB)
                      || q->how == O (O_JMP, SB))
                    {
@@ -401,23 +460,46 @@ decode (addr, data, dst)
                  dst->opcode = q->how;
                  dst->cycles = q->time;
 
-                 /* And a jsr to 0xc4 is turned into a magic trap */
+                 /* And a jsr to these locations are turned into magic
+                    traps.  */
 
                  if (dst->opcode == O (O_JSR, SB))
                    {
-                     if (dst->src.literal == 0xc4)
+                     switch (dst->src.literal)
                        {
-                         dst->opcode = O (O_SYSCALL, SB);
+                       case 0xc5:
+                         dst->opcode = O (O_SYS_OPEN, SB);
+                         break;
+                       case 0xc6:
+                         dst->opcode = O (O_SYS_READ, SB);
+                         break;
+                       case 0xc7:
+                         dst->opcode = O (O_SYS_WRITE, SB);
+                         break;
+                       case 0xc8:
+                         dst->opcode = O (O_SYS_LSEEK, SB);
+                         break;
+                       case 0xc9:
+                         dst->opcode = O (O_SYS_CLOSE, SB);
+                         break;
+                       case 0xca:
+                         dst->opcode = O (O_SYS_STAT, SB);
+                         break;
+                       case 0xcb:
+                         dst->opcode = O (O_SYS_FSTAT, SB);
+                         break;
+                       case 0xcc:
+                         dst->opcode = O (O_SYS_CMDLINE, SB);
+                         break;
                        }
+                     /* End of Processing for system calls.  */
                    }
 
                  dst->next_pc = addr + len / 2;
                  return;
                }
              else
-               {
-                 printf ("Dont understand %x \n", looking_for);
-               }
+               printf ("Don't understand %x \n", looking_for);
            }
 
          len++;
@@ -425,20 +507,19 @@ decode (addr, data, dst)
        }
 
     fail:
-      q++;
+      ;
     }
 
+  /* Fell off the end.  */
   dst->opcode = O (O_ILL, SB);
 }
 
-
 static void
-compile (pc)
+compile (int pc)
 {
   int idx;
 
-  /* find the next cache entry to use */
-
+  /* Find the next cache entry to use.  */
   idx = cpu.cache_top + 1;
   cpu.compiles++;
   if (idx >= cpu.csize)
@@ -447,16 +528,16 @@ compile (pc)
     }
   cpu.cache_top = idx;
 
-  /* Throw away its old meaning */
+  /* Throw away its old meaning */
   cpu.cache_idx[cpu.cache[idx].oldpc] = 0;
 
-  /* set to new address */
+  /* Set to new address.  */
   cpu.cache[idx].oldpc = pc;
 
-  /* fill in instruction info */
+  /* Fill in instruction info.  */
   decode (pc, cpu.memory + pc, cpu.cache + idx);
 
-  /* point to new cache entry */
+  /* Point to new cache entry.  */
   cpu.cache_idx[pc] = idx;
 }
 
@@ -474,30 +555,37 @@ static unsigned int *lreg[18];
 #define SET_L_REG(x,y) (*(lreg[x])) = (y)
 
 #define GET_MEMORY_L(x) \
-  ((cpu.memory[x+0] << 24) | (cpu.memory[x+1] << 16) | (cpu.memory[x+2] << 8) | cpu.memory[x+3])
+  (x < memory_size \
+   ? ((cpu.memory[x+0] << 24) | (cpu.memory[x+1] << 16) \
+      | (cpu.memory[x+2] << 8) | cpu.memory[x+3]) \
+   : ((cpu.eightbit[(x+0) & 0xff] << 24) | (cpu.eightbit[(x+1) & 0xff] << 16) \
+      | (cpu.eightbit[(x+2) & 0xff] << 8) | cpu.eightbit[(x+3) & 0xff]))
 
 #define GET_MEMORY_W(x) \
-  ((cpu.memory[x+0] << 8) | (cpu.memory[x+1] << 0))
+  (x < memory_size \
+   ? ((cpu.memory[x+0] << 8) | (cpu.memory[x+1] << 0)) \
+   : ((cpu.eightbit[(x+0) & 0xff] << 8) | (cpu.eightbit[(x+1) & 0xff] << 0)))
 
 
-#define SET_MEMORY_B(x,y) \
-  (cpu.memory[(x)] = y)
-
-#define SET_MEMORY_W(x,y) \
-{register unsigned char *_p = cpu.memory+x;\
-   register int __y = y;\
-     _p[0] = (__y)>>8;\
-       _p[1] =(__y);     }
+#define GET_MEMORY_B(x) \
+  (x < memory_size ? (cpu.memory[x]) : (cpu.eightbit[x & 0xff]))
 
 #define SET_MEMORY_L(x,y)  \
-{register unsigned char *_p = cpu.memory+x;register int __y = y;\
-   _p[0] = (__y)>>24;   _p[1] = (__y)>>16;      _p[2] = (__y)>>8;       _p[3] = (__y)>>0;}
+{  register unsigned char *_p; register int __y = y; \
+   _p = (x < memory_size ? cpu.memory+x : cpu.eightbit + (x & 0xff)); \
+   _p[0] = (__y)>>24; _p[1] = (__y)>>16; \
+   _p[2] = (__y)>>8; _p[3] = (__y)>>0;}
 
-#define GET_MEMORY_B(x)  (cpu.memory[x])
+#define SET_MEMORY_W(x,y) \
+{  register unsigned char *_p; register int __y = y; \
+   _p = (x < memory_size ? cpu.memory+x : cpu.eightbit + (x & 0xff)); \
+   _p[0] = (__y)>>8; _p[1] =(__y);}
 
-int
-fetch (arg, n)
-     ea_type *arg;
+#define SET_MEMORY_B(x,y) \
+  (x < memory_size ? (cpu.memory[(x)] = y) : (cpu.eightbit[x & 0xff] = y))
+
+static int
+fetch (ea_type *arg)
 {
   int rn = arg->reg;
   int abs = arg->literal;
@@ -566,18 +654,20 @@ fetch (arg, n)
       t &= cpu.mask;
       return t;
 
+    case X (OP_MEM, SW):
+      t = GET_MEMORY_W (abs);
+      t &= cpu.mask;
+      return t;
+
     default:
-      abort ();
+      abort (); /* ?? May be something more usefull? */
 
     }
 }
 
 
-static
-void
-store (arg, n)
-     ea_type *arg;
-     int n;
+static void
+store (ea_type *arg, int n)
 {
   int rn = arg->reg;
   int abs = arg->literal;
@@ -650,9 +740,8 @@ static union
 
 littleendian;
 
-static
-void
-init_pointers ()
+static void
+init_pointers (void)
 {
   static int init;
 
@@ -663,9 +752,20 @@ init_pointers ()
       init = 1;
       littleendian.i = 1;
 
-      cpu.memory = (unsigned char *) calloc (sizeof (char), MSIZE);
-      cpu.cache_idx = (unsigned short *) calloc (sizeof (short), MSIZE);
-      cpu.mask = (1 << MPOWER) - 1;
+      if (h8300smode)
+       memory_size = H8300S_MSIZE;
+      else if (h8300hmode)
+       memory_size = H8300H_MSIZE;
+      else
+       memory_size = H8300_MSIZE;
+      cpu.memory = (unsigned char *) calloc (sizeof (char), memory_size);
+      cpu.cache_idx = (unsigned short *) calloc (sizeof (short), memory_size);
+      cpu.eightbit = (unsigned char *) calloc (sizeof (char), 256);
+
+      /* `msize' must be a power of two.  */
+      if ((memory_size & (memory_size - 1)) != 0)
+       abort ();
+      cpu.mask = memory_size - 1;
 
       for (i = 0; i < 9; i++)
        {
@@ -691,6 +791,7 @@ init_pointers ()
                }
              p++;
            }
+         wreg[i] = wreg[i + 8] = 0;
          while (q < u)
            {
              if (*q == 0x2233)
@@ -703,25 +804,24 @@ init_pointers ()
                }
              q++;
            }
+         if (wreg[i] == 0 || wreg[i + 8] == 0)
+           abort ();
          cpu.regs[i] = 0;
          lreg[i] = &cpu.regs[i];
        }
 
       lreg[8] = &cpu.regs[8];
 
-      /* initialize the seg registers */
+      /* Initialize the seg registers.  */
       if (!cpu.cache)
-       sim_csize (CSIZE);
+       sim_set_simcache_size (CSIZE);
     }
 }
 
 static void
-control_c (sig, code, scp, addr)
-     int sig;
-     int code;
-     char *scp;
-     char *addr;
+control_c (int sig)
 {
+  cpu.state = SIM_STATE_STOPPED;
   cpu.exception = SIGINT;
 }
 
@@ -729,12 +829,13 @@ control_c (sig, code, scp, addr)
 #define Z (nz == 0)
 #define V (v != 0)
 #define N (n != 0)
+#define U (u != 0)
+#define H (h != 0)
+#define UI (ui != 0)
+#define I (intMaskBit != 0)
 
 static int
-mop (code, bsize, sign)
-     decoded_inst *code;
-     int bsize;
-     int sign;
+mop (decoded_inst *code, int bsize, int sign)
 {
   int multiplier;
   int multiplicand;
@@ -774,12 +875,13 @@ mop (code, bsize, sign)
     {
       SET_L_REG (code->dst.reg, result);
     }
-/*  return ((n==1) << 1) | (nz==1); */
-
+#if 0
+  return ((n == 1) << 1) | (nz == 1);
+#endif
 }
 
-#define OSHIFTS(name, how) \
-case O(name, SB):                              \
+#define ONOT(name, how) \
+case O (name, SB):                             \
 {                                              \
   int t;                                       \
   int hm = 0x80;                               \
@@ -787,7 +889,7 @@ case O(name, SB):                           \
   how;                                                 \
   goto shift8;                                 \
 }                                              \
-case O(name, SW):                              \
+case O (name, SW):                             \
 {                                              \
   int t;                                       \
   int hm = 0x8000;                             \
@@ -795,7 +897,7 @@ case O(name, SW):                           \
   how;                                                 \
   goto shift16;                                        \
 }                                              \
-case O(name, SL):                              \
+case O (name, SL):                             \
 {                                              \
   int t;                                       \
   int hm = 0x80000000;                                 \
@@ -804,19 +906,96 @@ case O(name, SL):                         \
   goto shift32;                                        \
 }
 
+#define OSHIFTS(name, how1, how2) \
+case O (name, SB):                             \
+{                                              \
+  int t;                                       \
+  int hm = 0x80;                               \
+  rd = GET_B_REG (code->src.reg);              \
+  if ((GET_MEMORY_B (pc + 1) & 0x40) == 0)     \
+    {                                          \
+      how1;                                    \
+    }                                          \
+  else                                         \
+    {                                          \
+      how2;                                    \
+    }                                          \
+  goto shift8;                                 \
+}                                              \
+case O (name, SW):                             \
+{                                              \
+  int t;                                       \
+  int hm = 0x8000;                             \
+  rd = GET_W_REG (code->src.reg);              \
+  if ((GET_MEMORY_B (pc + 1) & 0x40) == 0)     \
+    {                                          \
+      how1;                                    \
+    }                                          \
+  else                                         \
+    {                                          \
+      how2;                                    \
+    }                                          \
+  goto shift16;                                        \
+}                                              \
+case O (name, SL):                             \
+{                                              \
+  int t;                                       \
+  int hm = 0x80000000;                                 \
+  rd = GET_L_REG (code->src.reg);              \
+  if ((GET_MEMORY_B (pc + 1) & 0x40) == 0)     \
+    {                                          \
+      how1;                                    \
+    }                                          \
+  else                                         \
+    {                                          \
+      how2;                                    \
+    }                                          \
+  goto shift32;                                        \
+}
+
 #define OBITOP(name,f, s, op)                  \
-case  O(name, SB):                             \
+case (name, SB):                             \
 {                                              \
   int m;                                       \
   int b;                                       \
   if (f) ea = fetch (&code->dst);              \
-  m=1<< fetch(&code->src);                     \
+  m=1<< fetch (&code->src);                    \
   op;                                          \
-  if(s) store (&code->dst,ea); goto next;      \
+  if (s) store (&code->dst,ea); goto next;     \
 }
 
 int
-sim_resume (step, siggnal)
+sim_stop (SIM_DESC sd)
+{
+  cpu.state = SIM_STATE_STOPPED;
+  cpu.exception = SIGINT;
+  return 1;
+}
+
+#define R0_REGNUM      0
+#define R1_REGNUM      1
+#define R2_REGNUM      2
+#define R3_REGNUM      3
+#define R4_REGNUM      4
+#define R5_REGNUM      5
+#define R6_REGNUM      6
+#define R7_REGNUM      7
+
+#define SP_REGNUM       R7_REGNUM      /* Contains address of top of stack */
+#define FP_REGNUM       R6_REGNUM      /* Contains address of executing
+                                        * stack frame */
+
+#define CCR_REGNUM      8      /* Contains processor status */
+#define PC_REGNUM       9      /* Contains program counter */
+
+#define CYCLE_REGNUM    10
+
+#define EXR_REGNUM     11
+#define INST_REGNUM     12
+#define TICK_REGNUM     13
+
+void
+sim_resume (SIM_DESC sd, int step, int siggnal)
 {
   static int init1;
   int cycles = 0;
@@ -830,25 +1009,36 @@ sim_resume (step, siggnal)
   int ea;
   int bit;
   int pc;
-  int c, nz, v, n;
-
+  int c, nz, v, n, u, h, ui, intMaskBit;
+  int trace, intMask;
+  int oldmask;
   init_pointers ();
 
   prev = signal (SIGINT, control_c);
 
   if (step)
     {
+      cpu.state = SIM_STATE_STOPPED;
       cpu.exception = SIGTRAP;
     }
   else
     {
+      cpu.state = SIM_STATE_RUNNING;
       cpu.exception = 0;
     }
 
   pc = cpu.pc;
 
+  /* The PC should never be odd.  */
+  if (pc & 0x1)
+    abort ();
+
   GETSR ();
+  GETEXR ();
 
+  oldmask = cpu.mask;
+  if (!h8300hmode)
+    cpu.mask = 0xffff;
   do
     {
       int cidx;
@@ -860,15 +1050,15 @@ sim_resume (step, siggnal)
 
 
 #define ALUOP(STORE, NAME, HOW) \
-    case O(NAME,SB):  HOW; if(STORE)goto alu8;else goto just_flags_alu8;  \
-    case O(NAME, SW): HOW; if(STORE)goto alu16;else goto just_flags_alu16; \
-    case O(NAME,SL):  HOW; if(STORE)goto alu32;else goto just_flags_alu32;
+    case O (NAME, SB): HOW; if (STORE) goto alu8;  else goto just_flags_alu8;  \
+    case O (NAME, SW): HOW; if (STORE) goto alu16; else goto just_flags_alu16; \
+    case O (NAME, SL): HOW; if (STORE) goto alu32; else goto just_flags_alu32;
 
 
-#define LOGOP(NAME, HOW) \
-    case O(NAME,SB): HOW; goto log8;\
-    case O(NAME, SW): HOW; goto log16;\
-    case O(NAME,SL): HOW; goto log32;
+#define LOGOP(NAME, HOW)                       \
+    case O (NAME, SB): HOW; goto log8;         \
+    case O (NAME, SW): HOW; goto log16;                \
+    case O (NAME, SL): HOW; goto log32;
 
 
 
@@ -882,8 +1072,12 @@ sim_resume (step, siggnal)
 
 #endif
 
-      cycles += code->cycles;
-      insts++;
+      if (code->opcode)
+       {
+         cycles += code->cycles;
+         insts++;
+       }
+
       switch (code->opcode)
        {
        case 0:
@@ -910,8 +1104,8 @@ sim_resume (step, siggnal)
          res = rd + ea;
          goto alu8;
 
-#define EA    ea = fetch(&code->src);
-#define RD_EA ea = fetch(&code->src); rd = fetch(&code->dst);
+#define EA    ea = fetch (&code->src);
+#define RD_EA ea = fetch (&code->src); rd = fetch (&code->dst);
 
          ALUOP (1, O_SUB, RD_EA;
                 ea = -ea;
@@ -972,6 +1166,41 @@ sim_resume (step, siggnal)
          SET_L_REG (code->dst.reg, res);
          goto just_flags_log32;
 
+       case O (O_EEPMOV, SB):
+       case O (O_EEPMOV, SW):
+         if (h8300hmode || h8300smode)
+           {
+             register unsigned char *_src, *_dst;
+             unsigned int count = ((code->opcode == O (O_EEPMOV, SW))
+                                   ? cpu.regs[R4_REGNUM] & 0xffff
+                                   : cpu.regs[R4_REGNUM] & 0xff);
+
+             _src = (cpu.regs[R5_REGNUM] < memory_size
+                     ? cpu.memory + cpu.regs[R5_REGNUM]
+                     : cpu.eightbit + (cpu.regs[R5_REGNUM] & 0xff));
+             if ((_src + count) >= (cpu.memory + memory_size))
+               {
+                 if ((_src + count) >= (cpu.eightbit + 0x100))
+                   goto illegal;
+               }
+             _dst = (cpu.regs[R6_REGNUM] < memory_size
+                     ? cpu.memory + cpu.regs[R6_REGNUM]
+                     : cpu.eightbit + (cpu.regs[R6_REGNUM] & 0xff));
+             if ((_dst + count) >= (cpu.memory + memory_size))
+               {
+                 if ((_dst + count) >= (cpu.eightbit + 0x100))
+                   goto illegal;
+               }
+             memcpy (_dst, _src, count);
+
+             cpu.regs[R5_REGNUM] += count;
+             cpu.regs[R6_REGNUM] += count;
+             cpu.regs[R4_REGNUM] &= ((code->opcode == O (O_EEPMOV, SW))
+                                     ? (~0xffff) : (~0xff));
+             cycles += 2 * count;
+             goto next;
+           }
+         goto illegal;
 
        case O (O_ADDS, SL):
          SET_L_REG (code->dst.reg,
@@ -1051,23 +1280,69 @@ sim_resume (step, siggnal)
          SET_L_REG (code->dst.reg, res);
          goto just_flags_inc32;
 
-
 #define GET_CCR(x) BUILDSR();x = cpu.ccr
+#define GET_EXR(x) BUILDEXR ();x = cpu.exr
+
+       case O (O_LDC, SB):
+       case O (O_LDC, SW):
+         res = fetch (&code->src);
+         goto setc;
+       case O (O_STC, SB):
+       case O (O_STC, SW):
+         if (code->src.type == OP_CCR)
+           {
+             GET_CCR (res);
+           }
+         else if (code->src.type == OP_EXR && h8300smode)
+           {
+             GET_EXR (res);
+           }
+         else
+           goto illegal;
+         store (&code->dst, res);
+         goto next;
 
        case O (O_ANDC, SB):
-         GET_CCR (rd);
+         if (code->dst.type == OP_CCR)
+           {
+             GET_CCR (rd);
+           }
+         else if (code->dst.type == OP_EXR && h8300smode)
+           {
+             GET_EXR (rd);
+           }
+         else
+           goto illegal;
          ea = code->src.literal;
          res = rd & ea;
          goto setc;
 
        case O (O_ORC, SB):
-         GET_CCR (rd);
+         if (code->dst.type == OP_CCR)
+           {
+             GET_CCR (rd);
+           }
+         else if (code->dst.type == OP_EXR && h8300smode)
+           {
+             GET_EXR (rd);
+           }
+         else
+           goto illegal;
          ea = code->src.literal;
          res = rd | ea;
          goto setc;
 
        case O (O_XORC, SB):
-         GET_CCR (rd);
+         if (code->dst.type == OP_CCR)
+           {
+             GET_CCR (rd);
+           }
+         else if (code->dst.type == OP_EXR && h8300smode)
+           {
+             GET_EXR (rd);
+           }
+         else
+           goto illegal;
          ea = code->src.literal;
          res = rd ^ ea;
          goto setc;
@@ -1149,36 +1424,472 @@ sim_resume (step, siggnal)
            goto condtrue;
          goto next;
 
-       case O (O_SYSCALL, SB):
-         printf ("%c", cpu.regs[2]);
+       /* Trap for Command Line setup.  */
+       case O (O_SYS_CMDLINE, SB):
+         {
+           int i = 0;          /* Loop counter.  */
+           int j = 0;          /* Loop counter.  */
+           int ind_arg_len = 0;        /* Length of each argument.  */
+           int no_of_args = 0; /* The no. or cmdline args.  */
+           int current_location = 0;   /* Location of string.  */
+           int old_sp = 0;     /* The Initial Stack Pointer.  */
+           int no_of_slots = 0;        /* No. of slots required on the stack
+                                          for storing cmdline args.  */
+           int sp_move = 0;    /* No. of locations by which the stack needs
+                                  to grow.  */
+           int new_sp = 0;     /* The final stack pointer location passed
+                                  back.  */
+           int *argv_ptrs;     /* Pointers of argv strings to be stored.  */
+           int argv_ptrs_location = 0; /* Location of pointers to cmdline
+                                          args on the stack.  */
+           int char_ptr_size = 0;      /* Size of a character pointer on
+                                          target machine.  */
+           int addr_cmdline = 0;       /* Memory location where cmdline has
+                                          to be stored.  */
+           int size_cmdline = 0;       /* Size of cmdline.  */
+
+           /* Set the address of 256 free locations where command line is
+              stored.  */
+           addr_cmdline = cmdline_location();
+           cpu.regs[0] = addr_cmdline;
+
+           /* Counting the no. of commandline arguments.  */
+           for (i = 0; ptr_command_line[i] != NULL; i++)
+             continue;
+
+           /* No. of arguments in the command line.  */
+           no_of_args = i;
+
+           /* Current location is just a temporary variable,which we are
+              setting to the point to the start of our commandline string.  */
+           current_location = addr_cmdline;
+
+           /* Allocating space for storing pointers of the command line
+              arguments.  */
+           argv_ptrs = (int *) malloc (sizeof (int) * no_of_args);
+
+           /* Setting char_ptr_size to the sizeof (char *) on the different
+              architectures.  */
+           if (h8300hmode || h8300smode)
+             {
+               char_ptr_size = 4;
+             }
+           else
+             {
+               char_ptr_size = 2;
+             }
+
+           for (i = 0; i < no_of_args; i++)
+             {
+               ind_arg_len = 0;
+
+               /* The size of the commandline argument.  */
+               ind_arg_len = (strlen (ptr_command_line[i]) + 1);
+
+               /* The total size of the command line string.  */
+               size_cmdline += ind_arg_len;
+
+               /* As we have only 256 bytes, we need to provide a graceful
+                  exit. Anyways, a program using command line arguments 
+                  where we cannot store all the command line arguments
+                  given may behave unpredictably.  */
+               if (size_cmdline >= 256)
+                 {
+                   cpu.regs[0] = 0;
+                   goto next;
+                 }
+               else
+                 {
+                   /* current_location points to the memory where the next
+                      commandline argument is stored.  */
+                   argv_ptrs[i] = current_location;
+                   for (j = 0; j < ind_arg_len; j++)
+                     {
+                       SET_MEMORY_B ((current_location +
+                                      (sizeof (char) * j)),
+                                     *(ptr_command_line[i] + 
+                                      sizeof (char) * j));
+                     }
+
+                   /* Setting current_location to the starting of next
+                      argument.  */
+                   current_location += ind_arg_len;
+                 }
+             }
+
+           /* This is the original position of the stack pointer.  */
+           old_sp = cpu.regs[7];
+
+           /* We need space from the stack to store the pointers to argvs.  */
+           /* As we will infringe on the stack, we need to shift the stack
+              pointer so that the data is not overwritten. We calculate how
+              much space is required.  */
+           sp_move = (no_of_args) * (char_ptr_size);
+
+           /* The final position of stack pointer, we have thus taken some
+              space from the stack.  */
+           new_sp = old_sp - sp_move;
+
+           /* Temporary variable holding value where the argv pointers need
+              to be stored.  */
+           argv_ptrs_location = new_sp;
+
+           /* The argv pointers are stored at sequential locations. As per
+              the H8300 ABI.  */
+           for (i = 0; i < no_of_args; i++)
+             {
+               /* Saving the argv pointer.  */
+               if (h8300hmode || h8300smode)
+                 {
+                   SET_MEMORY_L (argv_ptrs_location, argv_ptrs[i]);
+                 }
+               else
+                 {
+                   SET_MEMORY_W (argv_ptrs_location, argv_ptrs[i]);
+                 }
+       
+               /* The next location where the pointer to the next argv
+                  string has to be stored.  */    
+               argv_ptrs_location += char_ptr_size;
+             }
+
+           /* Required by POSIX, Setting 0x0 at the end of the list of argv
+              pointers.  */
+           if (h8300hmode || h8300smode)
+             {
+               SET_MEMORY_L (old_sp, 0x0);
+             }
+           else
+             {
+               SET_MEMORY_W (old_sp, 0x0);
+             }
+
+           /* Freeing allocated memory.  */
+           free (argv_ptrs);
+           for (i = 0; i <= no_of_args; i++)
+             {
+               free (ptr_command_line[i]);
+             }
+           free (ptr_command_line);
+
+           /* The no. of argv arguments are returned in Reg 0.  */
+           cpu.regs[0] = no_of_args;
+           /* The Pointer to argv in Register 1.  */
+           cpu.regs[1] = new_sp;
+           /* Setting the stack pointer to the new value.  */
+           cpu.regs[7] = new_sp;
+         }
+         goto next;
+
+         /* System call processing starts.  */
+       case O (O_SYS_OPEN, SB):
+         {
+           int len = 0;        /* Length of filename.  */
+           char *filename;     /* Filename would go here.  */
+           char temp_char;     /* Temporary character */
+           int mode = 0;       /* Mode bits for the file.  */
+           int open_return;    /* Return value of open, file descriptor.  */
+           int i;              /* Loop counter */
+           int filename_ptr;   /* Pointer to filename in cpu memory.  */
+
+           /* Setting filename_ptr to first argument of open.  */
+           filename_ptr = h8300hmode ? GET_L_REG (0) : GET_W_REG (0);
+
+           /* Trying to get mode.  */
+           if (h8300hmode || h8300smode)
+             {
+               mode = GET_MEMORY_L (cpu.regs[7] + 4);
+             }
+           else
+             {
+               mode = GET_MEMORY_W (cpu.regs[7] + 2);
+             }
+
+           /* Trying to find the length of the filename.  */
+           temp_char = GET_MEMORY_B (cpu.regs[0]);
+
+           len = 1;
+           while (temp_char != '\0')
+             {
+               temp_char = GET_MEMORY_B (filename_ptr + len);
+               len++;
+             }
+
+           /* Allocating space for the filename.  */
+           filename = (char *) malloc (sizeof (char) * len);
+
+           /* String copying the filename from memory.  */
+           for (i = 0; i < len; i++)
+             {
+               temp_char = GET_MEMORY_B (filename_ptr + i);
+               filename[i] = temp_char;
+             }
+
+           /* Callback to open and return the file descriptor.  */
+           open_return = sim_callback->open (sim_callback, filename, mode);
+
+           /* Return value in register 0.  */
+           cpu.regs[0] = open_return;
+
+           /* Freeing memory used for filename. */
+           free (filename);
+         }
+         goto next;
+
+       case O (O_SYS_READ, SB):
+         {
+           char *char_ptr;     /* Where characters read would be stored.  */
+           int fd;             /* File descriptor */
+           int buf_size;       /* BUF_SIZE parameter in read.  */
+           int i = 0;          /* Temporary Loop counter */
+           int read_return = 0;        /* Return value from callback to
+                                          read.  */
+
+           fd = h8300hmode ? GET_L_REG (0) : GET_W_REG (0);
+           buf_size = h8300hmode ? GET_L_REG (2) : GET_W_REG (2);
+
+           char_ptr = (char *) malloc (sizeof (char) * buf_size);
+
+           /* Callback to read and return the no. of characters read.  */
+           read_return =
+             sim_callback->read (sim_callback, fd, char_ptr, buf_size);
+
+           /* The characters read are stored in cpu memory.  */
+           for (i = 0; i < buf_size; i++)
+             {
+               SET_MEMORY_B ((cpu.regs[1] + (sizeof (char) * i)),
+                             *(char_ptr + (sizeof (char) * i)));
+             }
+
+           /* Return value in Register 0.  */
+           cpu.regs[0] = read_return;
+
+           /* Freeing memory used as buffer.  */
+           free (char_ptr);
+         }
+         goto next;
+
+       case O (O_SYS_WRITE, SB):
+         {
+           int fd;             /* File descriptor */
+           char temp_char;     /* Temporary character */
+           int len;            /* Length of write, Parameter II to write.  */
+           int char_ptr;       /* Character Pointer, Parameter I of write.  */
+           char *ptr;          /* Where characters to be written are stored. 
+                                */
+           int write_return;   /* Return value from callback to write.  */
+           int i = 0;          /* Loop counter */
+
+           fd = h8300hmode ? GET_L_REG (0) : GET_W_REG (0);
+           char_ptr = h8300hmode ? GET_L_REG (1) : GET_W_REG (1);
+           len = h8300hmode ? GET_L_REG (2) : GET_W_REG (2);
+
+           /* Allocating space for the characters to be written.  */
+           ptr = (char *) malloc (sizeof (char) * len);
+
+           /* Fetching the characters from cpu memory.  */
+           for (i = 0; i < len; i++)
+             {
+               temp_char = GET_MEMORY_B (char_ptr + i);
+               ptr[i] = temp_char;
+             }
+
+           /* Callback write and return the no. of characters written.  */
+           write_return = sim_callback->write (sim_callback, fd, ptr, len);
+
+           /* Return value in Register 0.  */
+           cpu.regs[0] = write_return;
+
+           /* Freeing memory used as buffer.  */
+           free (ptr);
+         }
+         goto next;
+
+       case O (O_SYS_LSEEK, SB):
+         {
+           int fd;             /* File descriptor */
+           int offset;         /* Offset */
+           int origin;         /* Origin */
+           int lseek_return;   /* Return value from callback to lseek.  */
+
+           fd = h8300hmode ? GET_L_REG (0) : GET_W_REG (0);
+           offset = h8300hmode ? GET_L_REG (1) : GET_W_REG (1);
+           origin = h8300hmode ? GET_L_REG (2) : GET_W_REG (2);
+
+           /* Callback lseek and return offset.  */
+           lseek_return =
+             sim_callback->lseek (sim_callback, fd, offset, origin);
+
+           /* Return value in register 0.  */
+           cpu.regs[0] = lseek_return;
+         }
+         goto next;
+
+       case O (O_SYS_CLOSE, SB):
+         {
+           int fd;             /* File descriptor */
+           int close_return;   /* Return value from callback to close.  */
+
+           fd = h8300hmode ? GET_L_REG (0) : GET_W_REG (0);
+
+           /* Callback close and return.  */
+           close_return = sim_callback->close (sim_callback, fd);
+
+           /* Return value in register 0.  */
+           cpu.regs[0] = close_return;
+         }
+         goto next;
+
+       case O (O_SYS_FSTAT, SB):
+         {
+           int fd;             /* File descriptor */
+           struct stat stat_rec;       /* Stat record */
+           int fstat_return;   /* Return value from callback to stat.  */
+           int stat_ptr;       /* Pointer to stat record.  */
+           char *temp_stat_ptr;        /* Temporary stat_rec pointer.  */
+
+           fd = h8300hmode ? GET_L_REG (0) : GET_W_REG (0);
+
+           /* Setting stat_ptr to second argument of stat.  */
+           stat_ptr = h8300hmode ? GET_L_REG (1) : GET_W_REG (1);
+
+           /* Callback stat and return.  */
+           fstat_return = sim_callback->fstat (sim_callback, fd, &stat_rec);
+
+           /* Have stat_ptr point to starting of stat_rec.  */
+           temp_stat_ptr = (char *) (&stat_rec);
+
+           /* Setting up the stat structure returned.  */
+           SET_MEMORY_W (stat_ptr, stat_rec.st_dev);
+           stat_ptr += 2;
+           SET_MEMORY_W (stat_ptr, stat_rec.st_ino);
+           stat_ptr += 2;
+           SET_MEMORY_L (stat_ptr, stat_rec.st_mode);
+           stat_ptr += 4;
+           SET_MEMORY_W (stat_ptr, stat_rec.st_nlink);
+           stat_ptr += 2;
+           SET_MEMORY_W (stat_ptr, stat_rec.st_uid);
+           stat_ptr += 2;
+           SET_MEMORY_W (stat_ptr, stat_rec.st_gid);
+           stat_ptr += 2;
+           SET_MEMORY_W (stat_ptr, stat_rec.st_rdev);
+           stat_ptr += 2;
+           SET_MEMORY_L (stat_ptr, stat_rec.st_size);
+           stat_ptr += 4;
+           SET_MEMORY_L (stat_ptr, stat_rec.st_atime);
+           stat_ptr += 8;
+           SET_MEMORY_L (stat_ptr, stat_rec.st_mtime);
+           stat_ptr += 8;
+           SET_MEMORY_L (stat_ptr, stat_rec.st_ctime);
+
+           /* Return value in register 0.  */
+           cpu.regs[0] = fstat_return;
+         }
          goto next;
 
-         OSHIFTS (O_NOT, rd = ~rd);
-         OSHIFTS (O_SHLL, c = rd & hm;
-                  rd <<= 1);
-         OSHIFTS (O_SHLR, c = rd & 1;
-                  rd = (unsigned int) rd >> 1);
-         OSHIFTS (O_SHAL, c = rd & hm;
-                  rd <<= 1);
-         OSHIFTS (O_SHAR, t = rd & hm;
-                  c = rd & 1;
-                  rd >>= 1;
-                  rd |= t;
-           );
-         OSHIFTS (O_ROTL, c = rd & hm;
-                  rd <<= 1;
-                  rd |= C);
-         OSHIFTS (O_ROTR, c = rd & 1;
-                  rd = (unsigned int) rd >> 1;
-                  if (c) rd |= hm;);
-         OSHIFTS (O_ROTXL, t = rd & hm;
-                  rd <<= 1;
-                  rd |= C;
-                  c = t;
-           );
-         OSHIFTS (O_ROTXR, t = rd & 1;
-                  rd = (unsigned int) rd >> 1;
-                  if (C) rd |= hm; c = t;);
+       case O (O_SYS_STAT, SB):
+         {
+           int len = 0;        /* Length of filename.  */
+           char *filename;     /* Filename would go here.  */
+           char temp_char;     /* Temporary character */
+           int filename_ptr;   /* Pointer to filename in cpu memory.  */
+           struct stat stat_rec;       /* Stat record */
+           int stat_return;    /* Return value from callback to stat */
+           int stat_ptr;       /* Pointer to stat record.  */
+           char *temp_stat_ptr;        /* Temporary stat_rec pointer.  */
+           int i = 0;          /* Loop Counter */
+
+           /* Setting filename_ptr to first argument of open.  */
+           filename_ptr = h8300hmode ? GET_L_REG (0) : GET_W_REG (0);
+
+           /* Trying to find the length of the filename.  */
+           temp_char = GET_MEMORY_B (cpu.regs[0]);
+
+           len = 1;
+           while (temp_char != '\0')
+             {
+               temp_char = GET_MEMORY_B (filename_ptr + len);
+               len++;
+             }
+
+           /* Allocating space for the filename.  */
+           filename = (char *) malloc (sizeof (char) * len);
+
+           /* String copying the filename from memory.  */
+           for (i = 0; i < len; i++)
+             {
+               temp_char = GET_MEMORY_B (filename_ptr + i);
+               filename[i] = temp_char;
+             }
+
+           /* Setting stat_ptr to second argument of stat.  */
+           /* stat_ptr = cpu.regs[1]; */
+           stat_ptr = h8300hmode ? GET_L_REG (1) : GET_W_REG (1);
+
+           /* Callback stat and return.  */
+           stat_return =
+             sim_callback->stat (sim_callback, filename, &stat_rec);
+
+           /* Have stat_ptr point to starting of stat_rec.  */
+           temp_stat_ptr = (char *) (&stat_rec);
+
+           /* Freeing memory used for filename.  */
+           free (filename);
+
+           /* Setting up the stat structure returned.  */
+           SET_MEMORY_W (stat_ptr, stat_rec.st_dev);
+           stat_ptr += 2;
+           SET_MEMORY_W (stat_ptr, stat_rec.st_ino);
+           stat_ptr += 2;
+           SET_MEMORY_L (stat_ptr, stat_rec.st_mode);
+           stat_ptr += 4;
+           SET_MEMORY_W (stat_ptr, stat_rec.st_nlink);
+           stat_ptr += 2;
+           SET_MEMORY_W (stat_ptr, stat_rec.st_uid);
+           stat_ptr += 2;
+           SET_MEMORY_W (stat_ptr, stat_rec.st_gid);
+           stat_ptr += 2;
+           SET_MEMORY_W (stat_ptr, stat_rec.st_rdev);
+           stat_ptr += 2;
+           SET_MEMORY_L (stat_ptr, stat_rec.st_size);
+           stat_ptr += 4;
+           SET_MEMORY_L (stat_ptr, stat_rec.st_atime);
+           stat_ptr += 8;
+           SET_MEMORY_L (stat_ptr, stat_rec.st_mtime);
+           stat_ptr += 8;
+           SET_MEMORY_L (stat_ptr, stat_rec.st_ctime);
+
+           /* Return value in register 0.  */
+           cpu.regs[0] = stat_return;
+         }
+         goto next;
+         /* End of system call processing.  */
+
+         ONOT (O_NOT, rd = ~rd; v = 0;);
+         OSHIFTS (O_SHLL,
+                  c = rd & hm; v = 0; rd <<= 1,
+                  c = rd & (hm >> 1); v = 0; rd <<= 2);
+         OSHIFTS (O_SHLR,
+                  c = rd & 1; v = 0; rd = (unsigned int) rd >> 1,
+                  c = rd & 2; v = 0; rd = (unsigned int) rd >> 2);
+         OSHIFTS (O_SHAL,
+                  c = rd & hm; v = (rd & hm) != ((rd & (hm >> 1)) << 1); rd <<= 1,
+                  c = rd & (hm >> 1); v = (rd & (hm >> 1)) != ((rd & (hm >> 2)) << 2); rd <<= 2);
+         OSHIFTS (O_SHAR,
+                  t = rd & hm; c = rd & 1; v = 0; rd >>= 1; rd |= t,
+                  t = rd & hm; c = rd & 2; v = 0; rd >>= 2; rd |= t | t >> 1);
+         OSHIFTS (O_ROTL,
+                  c = rd & hm; v = 0; rd <<= 1; rd |= C,
+                  c = rd & hm; v = 0; rd <<= 1; rd |= C; c = rd & hm; rd <<= 1; rd |= C);
+         OSHIFTS (O_ROTR,
+                  c = rd & 1; v = 0; rd = (unsigned int) rd >> 1; if (c) rd |= hm,
+                  c = rd & 1; v = 0; rd = (unsigned int) rd >> 1; if (c) rd |= hm; c = rd & 1; rd = (unsigned int) rd >> 1; if (c) rd |= hm);
+         OSHIFTS (O_ROTXL,
+                  t = rd & hm; rd <<= 1; rd |= C; c = t; v = 0,
+                  t = rd & hm; rd <<= 1; rd |= C; c = t; v = 0; t = rd & hm; rd <<= 1; rd |= C; c = t);
+         OSHIFTS (O_ROTXR,
+                  t = rd & 1; rd = (unsigned int) rd >> 1; if (C) rd |= hm; c = t; v = 0,
+                  t = rd & 1; rd = (unsigned int) rd >> 1; if (C) rd |= hm; c = t; v = 0; t = rd & 1; rd = (unsigned int) rd >> 1; if (C) rd |= hm; c = t);
 
        case O (O_JMP, SB):
          {
@@ -1212,7 +1923,7 @@ sim_resume (step, siggnal)
          pc = code->src.literal;
          goto call;
 
-       case O (O_RTS, SB):
+       case O (O_RTS, SN):
          {
            int tmp;
 
@@ -1234,17 +1945,31 @@ sim_resume (step, siggnal)
          }
 
        case O (O_ILL, SB):
+         cpu.state = SIM_STATE_STOPPED;
          cpu.exception = SIGILL;
          goto end;
-       case O (O_SLEEP, SB):
-       case O (O_BPT, SB):
+       case O (O_SLEEP, SN):
+         /* FIXME: Doesn't this break for breakpoints when r0
+            contains just the right (er, wrong) value?  */
+         cpu.state = SIM_STATE_STOPPED;
+         /* The format of r0 is defined by target newlib.  Expand
+             the macros here instead of looking for .../sys/wait.h.  */
+#define SIM_WIFEXITED(v) (((v) & 0xff) == 0)
+#define SIM_WIFSIGNALED(v) (((v) & 0x7f) > 0 && (((v) & 0x7f) < 0x7f))
+         if (! SIM_WIFEXITED (cpu.regs[0]) && SIM_WIFSIGNALED (cpu.regs[0]))
+           cpu.exception = SIGILL;
+         else
+           cpu.exception = SIGTRAP;
+         goto end;
+       case O (O_BPT, SN):
+         cpu.state = SIM_STATE_STOPPED;
          cpu.exception = SIGTRAP;
          goto end;
 
          OBITOP (O_BNOT, 1, 1, ea ^= m);
          OBITOP (O_BTST, 1, 0, nz = ea & m);
          OBITOP (O_BCLR, 1, 1, ea &= ~m);
-         OBITOP (O_BSET, 1, 1, ea |= m);       
+         OBITOP (O_BSET, 1, 1, ea |= m);
          OBITOP (O_BLD, 1, 0, c = ea & m);
          OBITOP (O_BILD, 1, 0, c = !(ea & m));
          OBITOP (O_BST, 1, 1, ea &= ~m;
@@ -1255,11 +1980,12 @@ sim_resume (step, siggnal)
          OBITOP (O_BIAND, 1, 0, c = !(ea & m) && C);
          OBITOP (O_BOR, 1, 0, c = (ea & m) || C);
          OBITOP (O_BIOR, 1, 0, c = !(ea & m) || C);
-         OBITOP (O_BXOR, 1, 0, c = (ea & m) != C);
+         OBITOP (O_BXOR, 1, 0, c = ((ea & m) != 0) != C);
          OBITOP (O_BIXOR, 1, 0, c = !(ea & m) != C);
 
-
-#define MOP(bsize, signed) mop(code, bsize,signed); goto next;
+#define MOP(bsize, signed)                     \
+  mop (code, bsize, signed);                   \
+  goto next;
 
        case O (O_MULS, SB):
          MOP (1, 1);
@@ -1274,6 +2000,22 @@ sim_resume (step, siggnal)
          MOP (0, 0);
          break;
 
+       case O (O_TAS, SB):
+         if (!h8300smode || code->src.type != X (OP_REG, SL))
+           goto illegal;
+         switch (code->src.reg)
+           {
+           case R0_REGNUM:
+           case R1_REGNUM:
+           case R4_REGNUM:
+           case R5_REGNUM:
+             break;
+           default:
+             goto illegal;
+           }
+         res = fetch (&code->src);
+         store (&code->src, res | 0x80);
+         goto just_flags_log8;
 
        case O (O_DIVU, SB):
          {
@@ -1281,8 +2023,8 @@ sim_resume (step, siggnal)
            ea = GET_B_REG (code->src.reg);
            if (ea)
              {
-               tmp = rd % ea;
-               rd = rd / ea;
+               tmp = (unsigned) rd % ea;
+               rd = (unsigned) rd / ea;
              }
            SET_W_REG (code->dst.reg, (rd & 0xff) | (tmp << 8));
            n = ea & 0x80;
@@ -1298,8 +2040,8 @@ sim_resume (step, siggnal)
            nz = ea & 0xffff;
            if (ea)
              {
-               tmp = rd % ea;
-               rd = rd / ea;
+               tmp = (unsigned) rd % ea;
+               rd = (unsigned) rd / ea;
              }
            SET_L_REG (code->dst.reg, (rd & 0xffff) | (tmp << 16));
            goto next;
@@ -1339,7 +2081,7 @@ sim_resume (step, siggnal)
            goto next;
          }
        case O (O_EXTS, SW):
-         rd = GET_B_REG (code->src.reg + 8) & 0xff;    /* Yes, src, not dst.  */
+         rd = GET_W_REG (code->src.reg) & 0xff; /* Yes, src, not dst.  */
          ea = rd & 0x80 ? -256 : 0;
          res = rd + ea;
          goto log16;
@@ -1349,7 +2091,7 @@ sim_resume (step, siggnal)
          res = rd + ea;
          goto log32;
        case O (O_EXTU, SW):
-         rd = GET_B_REG (code->src.reg + 8) & 0xff;
+         rd = GET_W_REG (code->src.reg) & 0xff;
          ea = 0;
          res = rd + ea;
          goto log16;
@@ -1359,19 +2101,117 @@ sim_resume (step, siggnal)
          res = rd + ea;
          goto log32;
 
-       case O (O_NOP, SB):
+       case O (O_NOP, SN):
+         goto next;
+
+       case O (O_STM, SL):
+         {
+           int nregs, firstreg, i;
+
+           nregs = GET_MEMORY_B (pc + 1);
+           nregs >>= 4;
+           nregs &= 0xf;
+           firstreg = GET_MEMORY_B (pc + 3);
+           firstreg &= 0xf;
+           for (i = firstreg; i <= firstreg + nregs; i++)
+             {
+               cpu.regs[7] -= 4;
+               SET_MEMORY_L (cpu.regs[7], cpu.regs[i]);
+             }
+         }
+         goto next;
+
+       case O (O_LDM, SL):
+         {
+           int nregs, firstreg, i;
+
+           nregs = GET_MEMORY_B (pc + 1);
+           nregs >>= 4;
+           nregs &= 0xf;
+           firstreg = GET_MEMORY_B (pc + 3);
+           firstreg &= 0xf;
+           for (i = firstreg; i >= firstreg - nregs; i--)
+             {
+               cpu.regs[i] = GET_MEMORY_L (cpu.regs[7]);
+               cpu.regs[7] += 4;
+             }
+         }
          goto next;
 
+       case O (O_DAA, SB):
+         /* Decimal Adjust Addition.  This is for BCD arithmetic.  */
+         res = GET_B_REG (code->src.reg);
+         if (!c && (0 <= (res >>  4) && (res >>  4) <= 9) 
+             && !h && (0 <= (res & 0xf) && (res & 0xf) <= 9))
+           res = res;          /* Value added == 0.  */
+         else if (!c && (0  <= (res >>  4) && (res >>  4) <=  8) 
+                  && !h && (10 <= (res & 0xf) && (res & 0xf) <= 15))
+           res = res + 0x6;            /* Value added == 6.  */
+         else if (!c && (0 <= (res >>  4) && (res >>  4) <= 9) 
+                  && h && (0 <= (res & 0xf) && (res & 0xf) <= 3))
+           res = res + 0x6;            /* Value added == 6.  */
+         else if (!c && (10 <= (res >>  4) && (res >>  4) <= 15) 
+                  && !h && (0  <= (res & 0xf) && (res & 0xf) <=  9))
+           res = res + 0x60;           /* Value added == 60.  */
+         else if (!c && (9  <= (res >>  4) && (res >>  4) <= 15) 
+                  && !h && (10 <= (res & 0xf) && (res & 0xf) <= 15))
+           res = res + 0x66;           /* Value added == 66.  */
+         else if (!c && (10 <= (res >>  4) && (res >>  4) <= 15) 
+                  && h && (0  <= (res & 0xf) && (res & 0xf) <=  3))
+           res = res + 0x66;           /* Value added == 66.  */
+         else if (c && (1 <= (res >>  4) && (res >>  4) <= 2) 
+                  && !h && (0 <= (res & 0xf) && (res & 0xf) <= 9))
+           res = res + 0x160;          /* Value added == 60, plus 'carry'.  */
+         else if (c && (1  <= (res >>  4) && (res >>  4) <=  2) 
+                  && !h && (10 <= (res & 0xf) && (res & 0xf) <= 15))
+           res = res + 0x166;          /* Value added == 66, plus 'carry'.  */
+         else if (c && (1 <= (res >>  4) && (res >>  4) <= 3) 
+                  && h && (0 <= (res & 0xf) && (res & 0xf) <= 3))
+           res = res + 0x166;          /* Value added == 66, plus 'carry'.  */
+
+         goto alu8;
+
+       case O (O_DAS, SB):
+         /* Decimal Adjust Subtraction.  This is for BCD arithmetic.  */
+         res = GET_B_REG (code->src.reg); /* FIXME fetch, fetch2... */
+         if (!c && (0 <= (res >>  4) && (res >>  4) <= 9) 
+             && !h && (0 <= (res & 0xf) && (res & 0xf) <= 9))
+           res = res;          /* Value added == 0.  */
+         else if (!c && (0 <= (res >>  4) && (res >>  4) <=  8) 
+                  && h && (6 <= (res & 0xf) && (res & 0xf) <= 15))
+           res = res + 0xfa;           /* Value added == 0xfa.  */
+         else if (c && (7 <= (res >>  4) && (res >>  4) <= 15) 
+                  && !h && (0 <= (res & 0xf) && (res & 0xf) <=  9))
+           res = res + 0xa0;           /* Value added == 0xa0.  */
+         else if (c && (6 <= (res >>  4) && (res >>  4) <= 15) 
+                  && h && (6 <= (res & 0xf) && (res & 0xf) <= 15))
+           res = res + 0x9a;           /* Value added == 0x9a.  */
+
+         goto alu8;
+
        default:
-         cpu.exception = 123;
+       illegal:
+         cpu.state = SIM_STATE_STOPPED;
+         cpu.exception = SIGILL;
          goto end;
 
        }
       abort ();
 
     setc:
-      cpu.ccr = res;
-      GETSR ();
+      if (code->dst.type == OP_CCR)
+       {
+         cpu.ccr = res;
+         GETSR ();
+       }
+      else if (code->dst.type == OP_EXR && h8300smode)
+       {
+         cpu.exr = res;
+         GETEXR ();
+       }
+      else
+       goto illegal;
+
       goto next;
 
     condtrue:
@@ -1407,27 +2247,22 @@ sim_resume (step, siggnal)
 
 
     shift8:
-      /* Set flags after an 8 bit shift op, carry set in insn */
+      /* Set flags after an 8 bit shift op, carry,overflow set in insn */
       n = (rd & 0x80);
-      v = 0;
       nz = rd & 0xff;
       SET_B_REG (code->src.reg, rd);
       goto next;
 
-
     shift16:
-      /* Set flags after an 16 bit shift op, carry set in insn */
+      /* Set flags after an 16 bit shift op, carry,overflow set in insn */
       n = (rd & 0x8000);
-      v = 0;
       nz = rd & 0xffff;
-
       SET_W_REG (code->src.reg, rd);
       goto next;
 
     shift32:
-      /* Set flags after an 32 bit shift op, carry set in insn */
+      /* Set flags after an 32 bit shift op, carry,overflow set in insn */
       n = (rd & 0x80000000);
-      v = 0;
       nz = rd & 0xffffffff;
       SET_L_REG (code->src.reg, rd);
       goto next;
@@ -1464,8 +2299,22 @@ sim_resume (step, siggnal)
     just_flags_alu8:
       n = res & 0x80;
       nz = res & 0xff;
-      v = ((ea & 0x80) == (rd & 0x80)) && ((ea & 0x80) != (res & 0x80));
       c = (res & 0x100);
+      switch (code->opcode / 4)
+       {
+       case O_ADD:
+         v = ((rd & 0x80) == (ea & 0x80)
+              && (rd & 0x80) != (res & 0x80));
+         break;
+       case O_SUB:
+       case O_CMP:
+         v = ((rd & 0x80) != (-ea & 0x80)
+              && (rd & 0x80) != (res & 0x80));
+         break;
+       case O_NEG:
+         v = (rd == 0x80);
+         break;
+       }
       goto next;
 
     alu16:
@@ -1473,8 +2322,22 @@ sim_resume (step, siggnal)
     just_flags_alu16:
       n = res & 0x8000;
       nz = res & 0xffff;
-      v = ((ea & 0x8000) == (rd & 0x8000)) && ((ea & 0x8000) != (res & 0x8000));
       c = (res & 0x10000);
+      switch (code->opcode / 4)
+       {
+       case O_ADD:
+         v = ((rd & 0x8000) == (ea & 0x8000)
+              && (rd & 0x8000) != (res & 0x8000));
+         break;
+       case O_SUB:
+       case O_CMP:
+         v = ((rd & 0x8000) != (-ea & 0x8000)
+              && (rd & 0x8000) != (res & 0x8000));
+         break;
+       case O_NEG:
+         v = (rd == 0x8000);
+         break;
+       }
       goto next;
 
     alu32:
@@ -1482,18 +2345,21 @@ sim_resume (step, siggnal)
     just_flags_alu32:
       n = res & 0x80000000;
       nz = res & 0xffffffff;
-      v = ((ea & 0x80000000) == (rd & 0x80000000))
-       && ((ea & 0x80000000) != (res & 0x80000000));
       switch (code->opcode / 4)
        {
        case O_ADD:
+         v = ((rd & 0x80000000) == (ea & 0x80000000)
+              && (rd & 0x80000000) != (res & 0x80000000));
          c = ((unsigned) res < (unsigned) rd) || ((unsigned) res < (unsigned) ea);
          break;
        case O_SUB:
        case O_CMP:
+         v = ((rd & 0x80000000) != (-ea & 0x80000000)
+              && (rd & 0x80000000) != (res & 0x80000000));
          c = (unsigned) rd < (unsigned) -ea;
          break;
        case O_NEG:
+         v = (rd == 0x80000000);
          c = res != 0;
          break;
        }
@@ -1504,92 +2370,76 @@ sim_resume (step, siggnal)
 
     end:
       ;
-      /*      if (cpu.regs[8] ) abort(); */
+#if 0
+      if (cpu.regs[8])
+       abort ();
+#endif
 
-#ifdef __GO32__
-      /* Poll after every 100th insn, */
-      if (poll_count++ > 100)
+      if (--poll_count < 0)
        {
-         poll_count = 0;
-         if (kbhit ())
-           {
-             int c = getkey ();
-             control_c ();
-           }
+         poll_count = POLL_QUIT_INTERVAL;
+         if ((*sim_callback->poll_quit) != NULL
+             && (*sim_callback->poll_quit) (sim_callback))
+           sim_stop (sd);
        }
-#endif
 
     }
-  while (!cpu.exception);
+  while (cpu.state == SIM_STATE_RUNNING);
   cpu.ticks += get_now () - tick_start;
   cpu.cycles += cycles;
   cpu.insts += insts;
 
   cpu.pc = pc;
   BUILDSR ();
-
+  BUILDEXR ();
+  cpu.mask = oldmask;
   signal (SIGINT, prev);
 }
 
+int
+sim_trace (SIM_DESC sd)
+{
+  /* FIXME: Unfinished.  */
+  abort ();
+}
 
 int
-sim_write (addr, buffer, size)
-     SIM_ADDR addr;
-     unsigned char *buffer;
-     int size;
+sim_write (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
 {
   int i;
 
   init_pointers ();
-  if (addr < 0 || addr + size > MSIZE)
+  if (addr < 0)
     return 0;
   for (i = 0; i < size; i++)
     {
-      cpu.memory[addr + i] = buffer[i];
-      cpu.cache_idx[addr + i] = 0;
+      if (addr < memory_size)
+       {
+         cpu.memory[addr + i] = buffer[i];
+         cpu.cache_idx[addr + i] = 0;
+       }
+      else
+       cpu.eightbit[(addr + i) & 0xff] = buffer[i];
     }
   return size;
 }
 
 int
-sim_read (addr, buffer, size)
-     SIM_ADDR addr;
-     unsigned char *buffer;
-     int size;
+sim_read (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
 {
   init_pointers ();
-  if (addr < 0 || addr + size > MSIZE)
+  if (addr < 0)
     return 0;
-  memcpy (buffer, cpu.memory + addr, size);
+  if (addr < memory_size)
+    memcpy (buffer, cpu.memory + addr, size);
+  else
+    memcpy (buffer, cpu.eightbit + (addr & 0xff), size);
   return size;
 }
 
 
-#define R0_REGNUM      0
-#define R1_REGNUM      1
-#define R2_REGNUM      2
-#define R3_REGNUM      3
-#define R4_REGNUM      4
-#define R5_REGNUM      5
-#define R6_REGNUM      6
-#define R7_REGNUM      7
-
-#define SP_REGNUM       R7_REGNUM      /* Contains address of top of stack */
-#define FP_REGNUM       R6_REGNUM      /* Contains address of executing
-                                          * stack frame */
-
-#define CCR_REGNUM      8      /* Contains processor status */
-#define PC_REGNUM       9      /* Contains program counter */
-
-#define CYCLE_REGNUM    10
-#define INST_REGNUM     11
-#define TICK_REGNUM     12
-
-
 int
-sim_store_register (rn, value)
-     int rn;
-     unsigned char *value;
+sim_store_register (SIM_DESC sd, int rn, unsigned char *value, int length)
 {
   int longval;
   int shortval;
@@ -1619,6 +2469,9 @@ sim_store_register (rn, value)
     case CCR_REGNUM:
       cpu.ccr = intval;
       break;
+    case EXR_REGNUM:
+      cpu.exr = intval;
+      break;
     case CYCLE_REGNUM:
       cpu.cycles = longval;
       break;
@@ -1631,27 +2484,30 @@ sim_store_register (rn, value)
       cpu.ticks = longval;
       break;
     }
-  return 0;
+  return -1;
 }
 
 int
-sim_fetch_register (rn, buf)
-     int rn;
-     unsigned char *buf;
+sim_fetch_register (SIM_DESC sd, int rn, unsigned char *buf, int length)
 {
   int v;
   int longreg = 0;
 
   init_pointers ();
 
+  if (!h8300smode && rn >= EXR_REGNUM)
+    rn++;
   switch (rn)
     {
     default:
       abort ();
-    case 8:
+    case CCR_REGNUM:
       v = cpu.ccr;
       break;
-    case 9:
+    case EXR_REGNUM:
+      v = cpu.exr;
+      break;
+    case PC_REGNUM:
       v = cpu.pc;
       break;
     case R0_REGNUM:
@@ -1664,15 +2520,15 @@ sim_fetch_register (rn, buf)
     case R7_REGNUM:
       v = cpu.regs[rn];
       break;
-    case 10:
+    case CYCLE_REGNUM:
       v = cpu.cycles;
       longreg = 1;
       break;
-    case 11:
+    case TICK_REGNUM:
       v = cpu.ticks;
       longreg = 1;
       break;
-    case 12:
+    case INST_REGNUM:
       v = cpu.insts;
       longreg = 1;
       break;
@@ -1689,35 +2545,37 @@ sim_fetch_register (rn, buf)
       buf[0] = v >> 8;
       buf[1] = v;
     }
-  return 0;
+  return -1;
 }
 
-int
-sim_trace ()
-{
-  return 0;
-}
-
-int
-sim_stop_reason (reason, sigrc)
-     enum sim_stop *reason;
-     int *sigrc;
+void
+sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc)
 {
+#if 0 /* FIXME: This should work but we can't use it.
+        grep for SLEEP above.  */
+  switch (cpu.state)
+    {
+    case SIM_STATE_EXITED : *reason = sim_exited; break;
+    case SIM_STATE_SIGNALLED : *reason = sim_signalled; break;
+    case SIM_STATE_STOPPED : *reason = sim_stopped; break;
+    default : abort ();
+    }
+#else
   *reason = sim_stopped;
+#endif
   *sigrc = cpu.exception;
-  return 0;
 }
 
-int
-sim_set_pc (n)
-     SIM_ADDR n;
+/* FIXME: Rename to sim_set_mem_size.  */
+
+void
+sim_size (int n)
 {
-  cpu.pc = n;
-  return 0;
+  /* Memory size is fixed.  */
 }
 
-
-sim_csize (n)
+void
+sim_set_simcache_size (int n)
 {
   if (cpu.cache)
     free (cpu.cache);
@@ -1729,61 +2587,215 @@ sim_csize (n)
 }
 
 
-int
-sim_info (printf_fn, verbose)
-     void (*printf_fn) ();
-     int verbose;
-
+void
+sim_info (SIM_DESC sd, int verbose)
 {
   double timetaken = (double) cpu.ticks / (double) now_persec ();
   double virttime = cpu.cycles / 10.0e6;
 
-  printf ("\n\n#instructions executed  %10d\n", cpu.insts);
-  printf ("#cycles (v approximate) %10d\n", cpu.cycles);
-  printf ("#real time taken        %10.4f\n", timetaken);
-  printf ("#virtual time taked     %10.4f\n", virttime);
+  (*sim_callback->printf_filtered) (sim_callback,
+                                   "\n\n#instructions executed  %10d\n",
+                                   cpu.insts);
+  (*sim_callback->printf_filtered) (sim_callback,
+                                   "#cycles (v approximate) %10d\n",
+                                   cpu.cycles);
+  (*sim_callback->printf_filtered) (sim_callback,
+                                   "#real time taken        %10.4f\n",
+                                   timetaken);
+  (*sim_callback->printf_filtered) (sim_callback,
+                                   "#virtual time taked     %10.4f\n",
+                                   virttime);
   if (timetaken != 0.0)
-    printf ("#simulation ratio       %10.4f\n", virttime / timetaken);
-  printf ("#compiles               %10d\n", cpu.compiles);
-  printf ("#cache size             %10d\n", cpu.csize);
-
+    (*sim_callback->printf_filtered) (sim_callback,
+                                     "#simulation ratio       %10.4f\n",
+                                     virttime / timetaken);
+  (*sim_callback->printf_filtered) (sim_callback,
+                                   "#compiles               %10d\n",
+                                   cpu.compiles);
+  (*sim_callback->printf_filtered) (sim_callback,
+                                   "#cache size             %10d\n",
+                                   cpu.csize);
 
 #ifdef ADEBUG
-  if (verbose)
+  /* This to be conditional on `what' (aka `verbose'),
+     however it was never passed as non-zero.  */
+  if (1)
     {
       int i;
       for (i = 0; i < O_LAST; i++)
        {
          if (cpu.stats[i])
-           printf ("%d: %d\n", i, cpu.stats[i]);
+           (*sim_callback->printf_filtered) (sim_callback,
+                                             "%d: %d\n", i, cpu.stats[i]);
        }
     }
 #endif
+}
 
-  return 0;
+/* Indicate whether the cpu is an H8/300 or H8/300H.
+   FLAG is non-zero for the H8/300H.  */
+
+void
+set_h8300h (int h_flag, int s_flag)
+{
+  /* FIXME: Much of the code in sim_load can be moved to sim_open.
+     This function being replaced by a sim_open:ARGV configuration
+     option.  */
+  h8300hmode = h_flag;
+  h8300smode = s_flag;
+}
+
+SIM_DESC
+sim_open (SIM_OPEN_KIND kind, 
+         struct host_callback_struct *ptr, 
+         struct bfd *abfd, 
+         char **argv)
+{
+  /* FIXME: Much of the code in sim_load can be moved here.  */
+
+  sim_kind = kind;
+  myname = argv[0];
+  sim_callback = ptr;
+  /* Fudge our descriptor.  */
+  return (SIM_DESC) 1;
 }
 
 void
-set_h8300h ()
+sim_close (SIM_DESC sd, int quitting)
 {
-  h8300hmode = 1;
+  /* Nothing to do.  */
 }
 
-int
-sim_kill ()
+/* Called by gdb to load a program into memory.  */
+
+SIM_RC
+sim_load (SIM_DESC sd, char *prog, bfd *abfd, int from_tty)
 {
-  return 0;
+  bfd *prog_bfd;
+
+  /* FIXME: The code below that sets a specific variant of the H8/300
+     being simulated should be moved to sim_open().  */
+
+  /* See if the file is for the H8/300 or H8/300H.  */
+  /* ??? This may not be the most efficient way.  The z8k simulator
+     does this via a different mechanism (INIT_EXTRA_SYMTAB_INFO).  */
+  if (abfd != NULL)
+    prog_bfd = abfd;
+  else
+    prog_bfd = bfd_openr (prog, "coff-h8300");
+  if (prog_bfd != NULL)
+    {
+      /* Set the cpu type.  We ignore failure from bfd_check_format
+        and bfd_openr as sim_load_file checks too.  */
+      if (bfd_check_format (prog_bfd, bfd_object))
+       {
+         unsigned long mach = bfd_get_mach (prog_bfd);
+         set_h8300h (mach == bfd_mach_h8300h || mach == bfd_mach_h8300s,
+                     mach == bfd_mach_h8300s);
+       }
+    }
+
+  /* If we're using gdb attached to the simulator, then we have to
+     reallocate memory for the simulator.
+
+     When gdb first starts, it calls fetch_registers (among other
+     functions), which in turn calls init_pointers, which allocates
+     simulator memory.
+
+     The problem is when we do that, we don't know whether we're
+     debugging an H8/300 or H8/300H program.
+
+     This is the first point at which we can make that determination,
+     so we just reallocate memory now; this will also allow us to handle
+     switching between H8/300 and H8/300H programs without exiting
+     gdb.  */
+
+  if (h8300smode)
+    memory_size = H8300S_MSIZE;
+  else if (h8300hmode)
+    memory_size = H8300H_MSIZE;
+  else
+    memory_size = H8300_MSIZE;
+
+  if (cpu.memory)
+    free (cpu.memory);
+  if (cpu.cache_idx)
+    free (cpu.cache_idx);
+  if (cpu.eightbit)
+    free (cpu.eightbit);
+
+  cpu.memory = (unsigned char *) calloc (sizeof (char), memory_size);
+  cpu.cache_idx = (unsigned short *) calloc (sizeof (short), memory_size);
+  cpu.eightbit = (unsigned char *) calloc (sizeof (char), 256);
+
+  /* `msize' must be a power of two.  */
+  if ((memory_size & (memory_size - 1)) != 0)
+    abort ();
+  cpu.mask = memory_size - 1;
+
+  if (sim_load_file (sd, myname, sim_callback, prog, prog_bfd,
+                    sim_kind == SIM_OPEN_DEBUG,
+                    0, sim_write)
+      == NULL)
+    {
+      /* Close the bfd if we opened it.  */
+      if (abfd == NULL && prog_bfd != NULL)
+       bfd_close (prog_bfd);
+      return SIM_RC_FAIL;
+    }
+
+  /* Close the bfd if we opened it.  */
+  if (abfd == NULL && prog_bfd != NULL)
+    bfd_close (prog_bfd);
+  return SIM_RC_OK;
 }
 
-sim_open (name)
-     char *name;
+SIM_RC
+sim_create_inferior (SIM_DESC sd, struct bfd *abfd, char **argv, char **env)
 {
-  return 0;
+  int i = 0;
+  int len_arg = 0;
+  int no_of_args = 0;
+  
+  if (abfd != NULL)
+    cpu.pc = bfd_get_start_address (abfd);
+  else
+    cpu.pc = 0;
+
+  /* Command Line support.  */
+  if (argv != NULL)
+    {
+      /* Counting the no. of commandline arguments.  */
+      for (no_of_args = 0; argv[no_of_args] != NULL; no_of_args++)
+        continue;
+
+      /* Allocating memory for the argv pointers.  */
+      ptr_command_line = (char **) malloc ((sizeof (char *))
+                        * (no_of_args + 1));
+
+      for (i = 0; i < no_of_args; i++)
+       {
+         /* Calculating the length of argument for allocating memory.  */
+         len_arg = strlen (argv[i] + 1);
+         ptr_command_line[i] = (char *) malloc (sizeof (char) * len_arg);
+         /* Copying the argument string.  */
+         ptr_command_line[i] = (char *) strdup (argv[i]);
+       }
+      ptr_command_line[i] = NULL;
+    }
+  
+  return SIM_RC_OK;
+}
+
+void
+sim_do_command (SIM_DESC sd, char *cmd)
+{
+  (*sim_callback->printf_filtered) (sim_callback,
+                                   "This simulator does not accept any commands.\n");
 }
 
-sim_set_args (argv, env)
-     char **argv;
-     char **env;
+void
+sim_set_callbacks (struct host_callback_struct *ptr)
 {
-  return 0;
+  sim_callback = ptr;
 }