daily update
[external/binutils.git] / sim / h8300 / compile.c
index f416695..7b4a5fa 100644 (file)
@@ -53,7 +53,7 @@ static void set_simcache_size (SIM_DESC, int);
 
 #define X(op, size)  (op * 4 + size)
 
-#define SP (h8300hmode ? SL : SW)
+#define SP (h8300hmode && !h8300_normal_mode ? SL : SW)
 
 #define h8_opcodes ops
 #define DEFINE_TABLE
@@ -510,6 +510,7 @@ enum { POLL_QUIT_INTERVAL = 0x80000 };
 
 int h8300hmode  = 0;
 int h8300smode  = 0;
+int h8300_normal_mode  = 0;
 int h8300sxmode = 0;
 
 static int memory_size;
@@ -539,7 +540,7 @@ bitfrom (int x)
     case L_32:
       return SL;
     case L_P:
-      return h8300hmode ? SL : SW;
+      return (h8300hmode && !h8300_normal_mode)? SL : SW;
     }
   return 0;
 }
@@ -575,9 +576,9 @@ lvalue (SIM_DESC sd, int x, int rn, unsigned int *val)
 static int
 cmdline_location()
 {
-  if (h8300smode)
+  if (h8300smode && !h8300_normal_mode)
     return 0xffff00L;
-  else if (h8300hmode)
+  else if (h8300hmode && !h8300_normal_mode)
     return 0x2ff00L;
   else
     return 0xff00L;
@@ -598,7 +599,7 @@ decode (SIM_DESC sd, int addr, unsigned char *data, decoded_inst *dst)
   /* Find the exact opcode/arg combo.  */
   for (q = h8_opcodes; q->name; q++)
     {
-      op_type *nib = q->data.nib;
+      const op_type *nib = q->data.nib;
       unsigned int len = 0;
 
       if ((q->available == AV_H8SX && !h8300sxmode) ||
@@ -606,6 +607,10 @@ decode (SIM_DESC sd, int addr, unsigned char *data, decoded_inst *dst)
          (q->available == AV_H8H  && !h8300hmode))
        continue;
 
+      cst[0]   = cst[1]   = cst[2]   = 0;
+      reg[0]   = reg[1]   = reg[2]   = 0;
+      rdisp[0] = rdisp[1] = rdisp[2] = 0;
+
       while (1)
        {
          op_type looking_for = *nib;
@@ -770,26 +775,11 @@ decode (SIM_DESC sd, int addr, unsigned char *data, decoded_inst *dst)
                       (looking_for & MODE) == INDEXB ||
                       (looking_for & MODE) == INDEXW ||
                       (looking_for & MODE) == INDEXL)
-
                {
                  switch (looking_for & SIZE)
                    {
                    case L_2:
                      cst[opnum] = thisnib & 3;
-
-                     /* DISP2 special treatment.  */
-                     if ((looking_for & MODE) == DISP)
-                       {
-                         switch (OP_SIZE (q->how)) {
-                         default: break;
-                         case SW:
-                           cst[opnum] *= 2;
-                           break;
-                         case SL:
-                           cst[opnum] *= 4;
-                           break;
-                         }
-                       }
                      break;
                    case L_8:
                      cst[opnum] = SEXTCHAR (data[len / 2]);
@@ -818,7 +808,9 @@ decode (SIM_DESC sd, int addr, unsigned char *data, decoded_inst *dst)
                       (looking_for & SIZE) == L_16U)
                {
                  cst[opnum] = (data[len / 2] << 8) + data[len / 2 + 1];
-                 if ((looking_for & SIZE) != L_16U)
+                 /* Immediates are always unsigned.  */
+                 if ((looking_for & SIZE) != L_16U &&
+                     (looking_for & MODE) != IMM)
                    cst[opnum] = (short) cst[opnum];    /* Sign extend.  */
                }
              else if (looking_for & ABSJMP)
@@ -846,8 +838,10 @@ decode (SIM_DESC sd, int addr, unsigned char *data, decoded_inst *dst)
                }
              else if ((looking_for & MODE) == VECIND)
                {
-                 /* FIXME: Multiplier should be 2 for "normal" mode.  */
-                 cst[opnum] = ((data[1] & 0x7f) + 0x80) * 4;
+                 if(h8300_normal_mode)
+                   cst[opnum] = ((data[1] & 0x7f) + 0x80) * 2;
+                 else
+                   cst[opnum] = ((data[1] & 0x7f) + 0x80) * 4;
                  cst[opnum] += h8_get_vbr (sd); /* Add vector base reg.  */
                }
              else if ((looking_for & SIZE) == L_32)
@@ -930,7 +924,7 @@ decode (SIM_DESC sd, int addr, unsigned char *data, decoded_inst *dst)
 #endif
                  /* Fill in the args.  */
                  {
-                   op_type *args = q->args.nib;
+                   const op_type *args = q->args.nib;
                    int hadone = 0;
                    int nargs;
 
@@ -1024,7 +1018,7 @@ decode (SIM_DESC sd, int addr, unsigned char *data, decoded_inst *dst)
                            p->literal = 0;
                            if (OP_KIND (q->how) == O_JSR ||
                                OP_KIND (q->how) == O_JMP)
-                             if (lvalue (sd, p->type, p->reg, &p->type))
+                             if (lvalue (sd, p->type, p->reg, (unsigned int *)&p->type))
                                goto end;
                          }
                        else if ((x & MODE) == ABS)
@@ -1056,7 +1050,7 @@ decode (SIM_DESC sd, int addr, unsigned char *data, decoded_inst *dst)
                            p->literal = cst[opnum];
                            if (OP_KIND (q->how) == O_JSR ||
                                OP_KIND (q->how) == O_JMP)
-                             if (lvalue (sd, p->type, p->reg, &p->type))
+                             if (lvalue (sd, p->type, p->reg, (unsigned int *)&p->type))
                                goto end;
                          }
                        else if ((x & MODE) == PCREL)
@@ -1070,31 +1064,64 @@ decode (SIM_DESC sd, int addr, unsigned char *data, decoded_inst *dst)
                            p->type = X (OP_IMM, SP);
                            p->literal = cst[opnum];
                          }
-                       else if ((x & MODE) == INDEXB ||
-                                (x & MODE) == INDEXW ||
-                                (x & MODE) == INDEXL ||
-                                (x & MODE) == DISP)
+                       else if ((x & MODE) == INDEXB)
                          {
-                           /* Use the instruction to determine 
-                              the operand size.  */
-                           switch (x & MODE) {
-                           case INDEXB:
-                             p->type = X (OP_INDEXB, OP_SIZE (q->how));
-                             break;
-                           case INDEXW:
-                             p->type = X (OP_INDEXW, OP_SIZE (q->how));
-                             break;
-                           case INDEXL:
-                             p->type = X (OP_INDEXL, OP_SIZE (q->how));
-                             break;
-                           case DISP:
-                             p->type = X (OP_DISP,   OP_SIZE (q->how));
-                             break;
-                           }
-
+                           p->type = X (OP_INDEXB, OP_SIZE (q->how));
+                           p->literal = cst[opnum];
+                           p->reg     = rdisp[opnum];
+                         }
+                       else if ((x & MODE) == INDEXW)
+                         {
+                           p->type = X (OP_INDEXW, OP_SIZE (q->how));
+                           p->literal = cst[opnum];
+                           p->reg     = rdisp[opnum];
+                         }
+                       else if ((x & MODE) == INDEXL)
+                         {
+                           p->type = X (OP_INDEXL, OP_SIZE (q->how));
                            p->literal = cst[opnum];
                            p->reg     = rdisp[opnum];
                          }
+                       else if ((x & MODE) == DISP)
+                         {
+                           /* Yuck -- special for mova args.  */
+                           if (strncmp (q->name, "mova", 4) == 0 &&
+                               (x & SIZE) == L_2)
+                             {
+                               /* Mova can have a DISP2 dest, with an
+                                  INDEXB or INDEXW src.  The multiplier
+                                  for the displacement value is determined
+                                  by the src operand, not by the insn.  */
+
+                               switch (OP_KIND (dst->src.type))
+                                 {
+                                 case OP_INDEXB:
+                                   p->type = X (OP_DISP, SB);
+                                   p->literal = cst[opnum];
+                                   break;
+                                 case OP_INDEXW:
+                                   p->type = X (OP_DISP, SW);
+                                   p->literal = cst[opnum] * 2;
+                                   break;
+                                 default:
+                                   goto fail;
+                                 }
+                             }
+                           else
+                             {
+                               p->type = X (OP_DISP,   OP_SIZE (q->how));
+                               p->literal = cst[opnum];
+                               /* DISP2 is special.  */
+                               if ((x & SIZE) == L_2)
+                                 switch (OP_SIZE (q->how))
+                                   {
+                                   case SB:                  break;
+                                   case SW: p->literal *= 2; break;
+                                   case SL: p->literal *= 4; break;
+                                   }
+                             }
+                           p->reg     = rdisp[opnum];
+                         }
                        else if (x & CTRL)
                          {
                            switch (reg[opnum])
@@ -1359,105 +1386,93 @@ fetch_1 (SIM_DESC sd, ea_type *arg, int *val, int twice)
       break;
     case X (OP_POSTINC, SB):   /* Register indirect w/post-incr: byte.  */
       t = GET_L_REG (rn);
-      t &= h8_get_mask (sd);
-      r = GET_MEMORY_B (t);
+      r = GET_MEMORY_B (t & h8_get_mask (sd));
       if (!twice)
        t += 1;
-      t = t & h8_get_mask (sd);
       SET_L_REG (rn, t);
       *val = r;
       break;
     case X (OP_POSTINC, SW):   /* Register indirect w/post-incr: word.  */
       t = GET_L_REG (rn);
-      t &= h8_get_mask (sd);
-      r = GET_MEMORY_W (t);
+      r = GET_MEMORY_W (t & h8_get_mask (sd));
       if (!twice)
        t += 2;
-      t = t & h8_get_mask (sd);
       SET_L_REG (rn, t);
       *val = r;
       break;
     case X (OP_POSTINC, SL):   /* Register indirect w/post-incr: long.  */
       t = GET_L_REG (rn);
-      t &= h8_get_mask (sd);
-      r = GET_MEMORY_L (t);
+      r = GET_MEMORY_L (t & h8_get_mask (sd));
       if (!twice)
        t += 4;
-      t = t & h8_get_mask (sd);
       SET_L_REG (rn, t);
       *val = r;
       break;
 
     case X (OP_POSTDEC, SB):   /* Register indirect w/post-decr: byte.  */
       t = GET_L_REG (rn);
-      t &= h8_get_mask (sd);
-      r = GET_MEMORY_B (t);
+      r = GET_MEMORY_B (t & h8_get_mask (sd));
       if (!twice)
        t -= 1;
-      t = t & h8_get_mask (sd);
       SET_L_REG (rn, t);
       *val = r;
       break;
     case X (OP_POSTDEC, SW):   /* Register indirect w/post-decr: word.  */
       t = GET_L_REG (rn);
-      t &= h8_get_mask (sd);
-      r = GET_MEMORY_W (t);
+      r = GET_MEMORY_W (t & h8_get_mask (sd));
       if (!twice)
        t -= 2;
-      t = t & h8_get_mask (sd);
       SET_L_REG (rn, t);
       *val = r;
       break;
     case X (OP_POSTDEC, SL):   /* Register indirect w/post-decr: long.  */
       t = GET_L_REG (rn);
-      t &= h8_get_mask (sd);
-      r = GET_MEMORY_L (t);
+      r = GET_MEMORY_L (t & h8_get_mask (sd));
       if (!twice)
        t -= 4;
-      t = t & h8_get_mask (sd);
       SET_L_REG (rn, t);
       *val = r;
       break;
 
     case X (OP_PREDEC, SB):    /* Register indirect w/pre-decr: byte.  */
       t = GET_L_REG (rn) - 1;
-      t &= h8_get_mask (sd);
       SET_L_REG (rn, t);
+      t &= h8_get_mask (sd);
       *val = GET_MEMORY_B (t);
       break;
       
     case X (OP_PREDEC, SW):    /* Register indirect w/pre-decr: word.  */
       t = GET_L_REG (rn) - 2;
-      t &= h8_get_mask (sd);
       SET_L_REG (rn, t);
+      t &= h8_get_mask (sd);
       *val = GET_MEMORY_W (t);
       break;
       
     case X (OP_PREDEC, SL):    /* Register indirect w/pre-decr: long.  */
       t = GET_L_REG (rn) - 4;
-      t &= h8_get_mask (sd);
       SET_L_REG (rn, t);
+      t &= h8_get_mask (sd);
       *val = GET_MEMORY_L (t);
       break;
       
     case X (OP_PREINC, SB):    /* Register indirect w/pre-incr: byte.  */
       t = GET_L_REG (rn) + 1;
-      t &= h8_get_mask (sd);
       SET_L_REG (rn, t);
+      t &= h8_get_mask (sd);
       *val = GET_MEMORY_B (t);
       break;
 
     case X (OP_PREINC, SW):    /* Register indirect w/pre-incr: long.  */
       t = GET_L_REG (rn) + 2;
-      t &= h8_get_mask (sd);
       SET_L_REG (rn, t);
+      t &= h8_get_mask (sd);
       *val = GET_MEMORY_W (t);
       break;
 
     case X (OP_PREINC, SL):    /* Register indirect w/pre-incr: long.  */
       t = GET_L_REG (rn) + 4;
-      t &= h8_get_mask (sd);
       SET_L_REG (rn, t);
+      t &= h8_get_mask (sd);
       *val = GET_MEMORY_L (t);
       break;
 
@@ -1594,8 +1609,8 @@ store_1 (SIM_DESC sd, ea_type *arg, int n, int twice)
       t = GET_L_REG (rn);
       if (!twice)
        t -= 1;
-      t &= h8_get_mask (sd);
       SET_L_REG (rn, t);
+      t &= h8_get_mask (sd);
       SET_MEMORY_B (t, n);
 
       break;
@@ -1603,8 +1618,8 @@ store_1 (SIM_DESC sd, ea_type *arg, int n, int twice)
       t = GET_L_REG (rn);
       if (!twice)
        t -= 2;
-      t &= h8_get_mask (sd);
       SET_L_REG (rn, t);
+      t &= h8_get_mask (sd);
       SET_MEMORY_W (t, n);
       break;
 
@@ -1612,8 +1627,8 @@ store_1 (SIM_DESC sd, ea_type *arg, int n, int twice)
       t = GET_L_REG (rn);
       if (!twice)
        t -= 4;
-      t &= h8_get_mask (sd);
       SET_L_REG (rn, t);
+      t &= h8_get_mask (sd);
       SET_MEMORY_L (t, n);
       break;
 
@@ -1621,8 +1636,8 @@ store_1 (SIM_DESC sd, ea_type *arg, int n, int twice)
       t = GET_L_REG (rn);
       if (!twice)
        t += 1;
-      t &= h8_get_mask (sd);
       SET_L_REG (rn, t);
+      t &= h8_get_mask (sd);
       SET_MEMORY_B (t, n);
 
       break;
@@ -1630,8 +1645,8 @@ store_1 (SIM_DESC sd, ea_type *arg, int n, int twice)
       t = GET_L_REG (rn);
       if (!twice)
        t += 2;
-      t &= h8_get_mask (sd);
       SET_L_REG (rn, t);
+      t &= h8_get_mask (sd);
       SET_MEMORY_W (t, n);
       break;
 
@@ -1639,45 +1654,51 @@ store_1 (SIM_DESC sd, ea_type *arg, int n, int twice)
       t = GET_L_REG (rn);
       if (!twice)
        t += 4;
-      t &= h8_get_mask (sd);
       SET_L_REG (rn, t);
+      t &= h8_get_mask (sd);
       SET_MEMORY_L (t, n);
       break;
 
     case X (OP_POSTDEC, SB):   /* Register indirect w/post-decr, byte.  */
-      t = GET_L_REG (rn) & h8_get_mask (sd);
-      SET_MEMORY_B (t, n);
+      t = GET_L_REG (rn);
       SET_L_REG (rn, t - 1);
+      t &= h8_get_mask (sd);
+      SET_MEMORY_B (t, n);
       break;
 
     case X (OP_POSTDEC, SW):   /* Register indirect w/post-decr, word.  */
-      t = GET_L_REG (rn) & h8_get_mask (sd);
-      SET_MEMORY_W (t, n);
+      t = GET_L_REG (rn);
       SET_L_REG (rn, t - 2);
+      t &= h8_get_mask (sd);
+      SET_MEMORY_W (t, n);
       break;
 
     case X (OP_POSTDEC, SL):   /* Register indirect w/post-decr, long.  */
-      t = GET_L_REG (rn) & h8_get_mask (sd);
-      SET_MEMORY_L (t, n);
+      t = GET_L_REG (rn);
       SET_L_REG (rn, t - 4);
+      t &= h8_get_mask (sd);
+      SET_MEMORY_L (t, n);
       break;
 
     case X (OP_POSTINC, SB):   /* Register indirect w/post-incr, byte.  */
-      t = GET_L_REG (rn) & h8_get_mask (sd);
-      SET_MEMORY_B (t, n);
+      t = GET_L_REG (rn);
       SET_L_REG (rn, t + 1);
+      t &= h8_get_mask (sd);
+      SET_MEMORY_B (t, n);
       break;
 
     case X (OP_POSTINC, SW):   /* Register indirect w/post-incr, word.  */
-      t = GET_L_REG (rn) & h8_get_mask (sd);
-      SET_MEMORY_W (t, n);
+      t = GET_L_REG (rn);
       SET_L_REG (rn, t + 2);
+      t &= h8_get_mask (sd);
+      SET_MEMORY_W (t, n);
       break;
 
     case X (OP_POSTINC, SL):   /* Register indirect w/post-incr, long.  */
-      t = GET_L_REG (rn) & h8_get_mask (sd);
-      SET_MEMORY_L (t, n);
+      t = GET_L_REG (rn);
       SET_L_REG (rn, t + 4);
+      t &= h8_get_mask (sd);
+      SET_MEMORY_L (t, n);
       break;
 
     case X (OP_DISP, SB):      /* Register indirect w/displacement, byte.  */
@@ -1750,9 +1771,9 @@ init_pointers (SIM_DESC sd)
 
       littleendian.i = 1;
 
-      if (h8300smode)
+      if (h8300smode && !h8300_normal_mode)
        memory_size = H8300S_MSIZE;
-      else if (h8300hmode)
+      else if (h8300hmode && !h8300_normal_mode)
        memory_size = H8300H_MSIZE;
       else
        memory_size = H8300_MSIZE;
@@ -1864,7 +1885,7 @@ case O (name, SB):                                \
       goto end;                                        \
   if (fetch (sd, &code->src, &tmp))            \
     goto end;                                  \
-  m = 1 << tmp;                                        \
+  m = 1 << (tmp & 7);                          \
   op;                                          \
   if (s)                                       \
     if (store (sd, &code->dst,ea))             \
@@ -1926,7 +1947,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
     }
 
   oldmask = h8_get_mask (sd);
-  if (!h8300hmode)
+  if (!h8300hmode || h8300_normal_mode)
     h8_set_mask (sd, 0xffff);
   do
     {
@@ -1977,8 +1998,47 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
                (mova/b, mova/w, mova/l).
             4) Add literal value of 1st argument (src).
             5) Store result in 3rd argument (op3).
+         */
+
+         /* Alas, since this is the only instruction with 3 arguments, 
+            decode doesn't handle them very well.  Some fix-up is required.
+
+            a) The size of dst is determined by whether src is 
+               INDEXB or INDEXW.  */
 
+         if (OP_KIND (code->src.type) == OP_INDEXB)
+           code->dst.type = X (OP_KIND (code->dst.type), SB);
+         else if (OP_KIND (code->src.type) == OP_INDEXW)
+           code->dst.type = X (OP_KIND (code->dst.type), SW);
+
+         /* b) If op3 == null, then this is the short form of the insn.
+               Dst is the dispreg of src, and op3 is the 32-bit form
+               of the same register.
          */
+
+         if (code->op3.type == 0)
+           {
+             /* Short form: src == INDEXB/INDEXW, dst == op3 == 0.
+                We get to compose dst and op3 as follows:
+
+                    op3 is a 32-bit register, ID == src.reg.
+                    dst is the same register, but 8 or 16 bits
+                    depending on whether src is INDEXB or INDEXW.
+             */
+
+             code->op3.type = X (OP_REG, SL);
+             code->op3.reg  = code->src.reg;
+             code->op3.literal = 0;
+
+             if (OP_KIND (code->src.type) == OP_INDEXB)
+               {
+                 code->dst.type = X (OP_REG, SB);
+                 code->dst.reg = code->op3.reg + 8;
+               }
+             else
+               code->dst.type = X (OP_REG, SW);
+           }
+
          if (fetch (sd, &code->dst, &ea))
            goto end;
 
@@ -2503,7 +2563,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
            {
              if (h8300smode)
                h8_set_exr (sd, (trace << 7) | intMask);
-             res = h8_get_exr (sd);
+             rd = h8_get_exr (sd);
            }
          else
            goto illegal;
@@ -2730,7 +2790,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
 
            /* Setting char_ptr_size to the sizeof (char *) on the different
               architectures.  */
-           if (h8300hmode || h8300smode)
+           if ((h8300hmode || h8300smode) && !h8300_normal_mode)
              {
                char_ptr_size = 4;
              }
@@ -2744,7 +2804,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
                ind_arg_len = 0;
 
                /* The size of the commandline argument.  */
-               ind_arg_len = strlen (h8_get_cmdline_arg (sd, i) + 1);
+               ind_arg_len = strlen (h8_get_cmdline_arg (sd, i)) + 1;
 
                /* The total size of the command line string.  */
                size_cmdline += ind_arg_len;
@@ -2799,7 +2859,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
            for (i = 0; i < no_of_args; i++)
              {
                /* Saving the argv pointer.  */
-               if (h8300hmode || h8300smode)
+               if ((h8300hmode || h8300smode) && !h8300_normal_mode)
                  {
                    SET_MEMORY_L (argv_ptrs_location, argv_ptrs[i]);
                  }
@@ -2815,7 +2875,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
 
            /* Required by POSIX, Setting 0x0 at the end of the list of argv
               pointers.  */
-           if (h8300hmode || h8300smode)
+           if ((h8300hmode || h8300smode) && !h8300_normal_mode)
              {
                SET_MEMORY_L (old_sp, 0x0);
              }
@@ -2854,7 +2914,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
 
            /* Setting filename_ptr to first argument of open,  */
            /* and trying to get mode.  */
-           if (h8300sxmode || h8300hmode || h8300smode)
+           if ((h8300sxmode || h8300hmode || h8300smode) && !h8300_normal_mode)
              {
                filename_ptr = GET_L_REG (0);
                mode = GET_MEMORY_L (h8_get_reg (sd, SP_REGNUM) + 4);
@@ -2905,8 +2965,8 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
            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);
+           fd = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (0) : GET_W_REG (0);
+           buf_size = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (2) : GET_W_REG (2);
 
            char_ptr = (char *) malloc (sizeof (char) * buf_size);
 
@@ -2940,9 +3000,9 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
            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);
+           fd = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (0) : GET_W_REG (0);
+           char_ptr = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (1) : GET_W_REG (1);
+           len = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (2) : GET_W_REG (2);
 
            /* Allocating space for the characters to be written.  */
            ptr = (char *) malloc (sizeof (char) * len);
@@ -2972,9 +3032,9 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
            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);
+           fd = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (0) : GET_W_REG (0);
+           offset = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (1) : GET_W_REG (1);
+           origin = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (2) : GET_W_REG (2);
 
            /* Callback lseek and return offset.  */
            lseek_return =
@@ -2990,7 +3050,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
            int fd;             /* File descriptor */
            int close_return;   /* Return value from callback to close.  */
 
-           fd = h8300hmode ? GET_L_REG (0) : GET_W_REG (0);
+           fd = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (0) : GET_W_REG (0);
 
            /* Callback close and return.  */
            close_return = sim_callback->close (sim_callback, fd);
@@ -3008,10 +3068,10 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
            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);
+           fd = (h8300hmode && !h8300_normal_mode) ? 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);
+           stat_ptr = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (1) : GET_W_REG (1);
 
            /* Callback stat and return.  */
            fstat_return = sim_callback->fstat (sim_callback, fd, &stat_rec);
@@ -3060,7 +3120,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
            int i = 0;          /* Loop Counter */
 
            /* Setting filename_ptr to first argument of open.  */
-           filename_ptr = h8300hmode ? GET_L_REG (0) : GET_W_REG (0);
+           filename_ptr = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (0) : GET_W_REG (0);
 
            /* Trying to find the length of the filename.  */
            temp_char = GET_MEMORY_B (h8_get_reg (sd, 0));
@@ -3084,7 +3144,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
 
            /* Setting stat_ptr to second argument of stat.  */
            /* stat_ptr = h8_get_reg (sd, 1); */
-           stat_ptr = h8300hmode ? GET_L_REG (1) : GET_W_REG (1);
+           stat_ptr = (h8300hmode && !h8300_normal_mode) ? GET_L_REG (1) : GET_W_REG (1);
 
            /* Callback stat and return.  */
            stat_return =
@@ -3151,10 +3211,10 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
          if (fetch2 (sd, &code->dst, &rd))
            goto end;
 
-         if (code->src.type == X (OP_IMM, SB))
+         if (memcmp (&code->src, &code->dst, sizeof (code->src)) == 0)
+           ea = 1;             /* unary  op */
+         else                  /* binary op */
            fetch (sd, &code->src, &ea);
-         else
-           ea = 1;
 
          if (code->opcode == O (O_SHLL, SB))
            {
@@ -3175,10 +3235,10 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
          if (fetch2 (sd, &code->dst, &rd))
            goto end;
 
-         if (code->src.type == X (OP_IMM, SW))
-           fetch (sd, &code->src, &ea);
+         if (memcmp (&code->src, &code->dst, sizeof (code->src)) == 0)
+           ea = 1;             /* unary  op */
          else
-           ea = 1;
+           fetch (sd, &code->src, &ea);
 
          if (code->opcode == O (O_SHLL, SW))
            {
@@ -3199,10 +3259,10 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
          if (fetch2 (sd, &code->dst, &rd))
            goto end;
 
-         if (code->src.type == X (OP_IMM, SL))
-           fetch (sd, &code->src, &ea);
+         if (memcmp (&code->src, &code->dst, sizeof (code->src)) == 0)
+           ea = 1;             /* unary  op */
          else
-           ea = 1;
+           fetch (sd, &code->src, &ea);
 
          if (code->opcode == O (O_SHLL, SL))
            {
@@ -3492,7 +3552,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
        call:
          tmp = h8_get_reg (sd, SP_REGNUM);
 
-         if (h8300hmode)
+         if (h8300hmode && !h8300_normal_mode)
            {
              tmp -= 4;
              SET_MEMORY_L (tmp, code->next_pc);
@@ -3524,7 +3584,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
              h8_set_exr (sd, GET_MEMORY_L (tmp));
              tmp += 4;
            }
-         if (h8300hmode)
+         if (h8300hmode && !h8300_normal_mode)
            {
              h8_set_ccr (sd, GET_MEMORY_L (tmp));
              tmp += 4;
@@ -3547,7 +3607,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
        rts:
          tmp = h8_get_reg (sd, SP_REGNUM);
 
-         if (h8300hmode)
+         if (h8300hmode && !h8300_normal_mode)
            {
              pc = GET_MEMORY_L (tmp);
              tmp += 4;
@@ -3575,6 +3635,17 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
              sim_engine_set_run_state (sd, sim_exited, 
                                        SIM_WEXITSTATUS (h8_get_reg (sd, 0)));
            }
+#if 0
+         /* Unfortunately this won't really work, because
+            when we take a breakpoint trap, R0 has a "random", 
+            user-defined value.  Don't see any immediate solution.  */
+         else if (SIM_WIFSTOPPED (h8_get_reg (sd, 0)))
+           {
+             /* Pass the stop signal up to gdb.  */
+             sim_engine_set_run_state (sd, sim_stopped, 
+                                       SIM_WSTOPSIG (h8_get_reg (sd, 0)));
+           }
+#endif
          else
            {
              /* Treat it as a sigtrap.  */
@@ -3584,16 +3655,26 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
 
        case O (O_TRAPA, SB):           /* trapa */
          if (fetch (sd, &code->src, &res))
-           goto end;                   /* res is vector number.  */
-
-         tmp = h8_get_reg (sd, SP_REGNUM);
-         tmp -= 4;
-         SET_MEMORY_L (tmp, code->next_pc);
-         tmp -= 4; 
-         SET_MEMORY_L (tmp, h8_get_ccr (sd));
-         intMaskBit = 1;
-         BUILDSR (sd);
-
+           goto end;                   /* res is vector number.  */
+  
+         tmp = h8_get_reg (sd, SP_REGNUM);
+         if(h8300_normal_mode)
+           {
+             tmp -= 2;
+             SET_MEMORY_W (tmp, code->next_pc);
+             tmp -= 2;
+             SET_MEMORY_W (tmp, h8_get_ccr (sd));
+           }
+         else
+           {
+             tmp -= 4;
+             SET_MEMORY_L (tmp, code->next_pc);
+             tmp -= 4;
+             SET_MEMORY_L (tmp, h8_get_ccr (sd));
+           }
+         intMaskBit = 1;
+         BUILDSR (sd);
          if (h8300smode)
            {
              tmp -= 4;
@@ -3602,8 +3683,10 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
 
          h8_set_reg (sd, SP_REGNUM, tmp);
 
-         /* FIXME: "normal" mode should use 2-byte ptrs.  */
-         pc = GET_MEMORY_L (0x20 + res * 4);
+         if(h8300_normal_mode)
+           pc = GET_MEMORY_L (0x10 + res * 2); /* Vector addresses are 0x10,0x12,0x14 and 0x16 */
+         else
+           pc = GET_MEMORY_L (0x20 + res * 4);
          goto end;
 
        case O (O_BPT, SN):
@@ -3800,13 +3883,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
              fetch (sd, &code->dst, &rd))
            goto end;
 
-         /* FIXME: is this the right place to be doing sign extend?  */
-         if (OP_KIND (code->src.type) == OP_IMM &&
-             (ea & 8) != 0)
-           ea |= 0xfff0;
-         else
-           ea = SEXTSHORT (ea);
-
+         ea = SEXTSHORT (ea);
          res = SEXTSHORT (ea * SEXTSHORT (rd));
 
          n  = res & 0x8000;
@@ -3821,11 +3898,6 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
              fetch (sd, &code->dst, &rd))
            goto end;
 
-         /* FIXME: is this the right place to be doing sign extend?  */
-         if (OP_KIND (code->src.type) == OP_IMM &&
-             (ea & 8) != 0)
-           ea |= 0xfffffff0;
-
          res = ea * rd;
 
          n  = res & 0x80000000;
@@ -3839,11 +3911,6 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
              fetch (sd, &code->dst, &rd))
            goto end;
 
-         /* FIXME: is this the right place to be doing sign extend?  */
-         if (OP_KIND (code->src.type) == OP_IMM &&
-             (ea & 8) != 0)
-           ea |= 0xfffffff0;
-
          /* Compute upper 32 bits of the 64-bit result.  */
          res = (((long long) ea) * ((long long) rd)) >> 32;
 
@@ -3899,13 +3966,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
              fetch (sd, &code->dst, &rd))
            goto end;
 
-         /* FIXME: is this the right place to be doing sign extend?  */
-         if (OP_KIND (code->src.type) == OP_IMM &&
-             (ea & 8) != 0)
-           ea |= 0xfffffff0;
-         else
-           ea = SEXTCHAR (ea);
-
+         ea = SEXTCHAR (ea);
          res = ea * SEXTCHAR (rd);
 
          n  = res & 0x8000;
@@ -3920,13 +3981,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
              fetch (sd, &code->dst, &rd))
            goto end;
 
-         /* FIXME: is this the right place to be doing sign extend?  */
-         if (OP_KIND (code->src.type) == OP_IMM &&
-             (ea & 8) != 0)
-           ea |= 0xfff0;
-         else
-           ea = SEXTSHORT (ea);
-
+         ea = SEXTSHORT (ea);
          res = ea * SEXTSHORT (rd & 0xffff);
 
          n  = res & 0x80000000;
@@ -4017,11 +4072,6 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
              fetch (sd, &code->dst, &rd))
            goto end;
 
-         /* FIXME: is this the right place to be doing sign extend?  */
-         if (OP_KIND (code->src.type) == OP_IMM &&
-             (ea & 8) != 0)
-           ea |= 0xfffffff0;
-
          if (ea)
            {
              res = SEXTSHORT (rd) / SEXTSHORT (ea);
@@ -4043,11 +4093,6 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
              fetch (sd, &code->dst, &rd))
            goto end;
 
-         /* FIXME: is this the right place to be doing sign extend?  */
-         if (OP_KIND (code->src.type) == OP_IMM &&
-             (ea & 8) != 0)
-           ea |= 0xfffffff0;
-
          if (ea)
            {
              res = rd / ea;
@@ -4119,13 +4164,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
            goto end;
 
          rd = SEXTSHORT (rd);
-
-         /* FIXME: is this the right place to be doing sign extend?  */
-         if (OP_KIND (code->src.type) == OP_IMM &&
-             (ea & 8) != 0)
-           ea |= 0xfffffff0;
-         else
-           ea = SEXTCHAR (ea);
+         ea = SEXTCHAR (ea);
 
          if (ea)
            {
@@ -4150,12 +4189,7 @@ sim_resume (SIM_DESC sd, int step, int siggnal)
              fetch (sd, &code->dst, &rd))
            goto end;
 
-         /* FIXME: is this the right place to be doing sign extend?  */
-         if (OP_KIND (code->src.type) == OP_IMM &&
-             (ea & 8) != 0)
-           ea |= 0xfffffff0;
-         else
-           ea = SEXTSHORT (ea);
+         ea = SEXTSHORT (ea);
 
          if (ea)
            {
@@ -4582,7 +4616,7 @@ sim_trace (SIM_DESC sd)
 }
 
 int
-sim_write (SIM_DESC sd, SIM_ADDR addr, unsigned char *buffer, int size)
+sim_write (SIM_DESC sd, SIM_ADDR addr, const unsigned char *buffer, int size)
 {
   int i;
 
@@ -4632,7 +4666,10 @@ sim_store_register (SIM_DESC sd, int rn, unsigned char *value, int length)
   switch (rn)
     {
     case PC_REGNUM:
-      h8_set_pc (sd, intval);
+      if(h8300_normal_mode)
+        h8_set_pc (sd, shortval); /* PC for Normal mode is 2 bytes */
+      else
+        h8_set_pc (sd, intval);
       break;
     default:
       (*sim_callback->printf_filtered) (sim_callback, 
@@ -4678,7 +4715,7 @@ sim_store_register (SIM_DESC sd, int rn, unsigned char *value, int length)
       h8_set_ticks (sd, longval);
       break;
     }
-  return -1;
+  return length;
 }
 
 int
@@ -4743,7 +4780,8 @@ sim_fetch_register (SIM_DESC sd, int rn, unsigned char *buf, int length)
       longreg = 1;
       break;
     }
-  if (h8300hmode || longreg)
+  /* In Normal mode PC is 2 byte, but other registers are 4 byte */
+  if ((h8300hmode || longreg) && !(rn == PC_REGNUM && h8300_normal_mode))
     {
       buf[0] = v >> 24;
       buf[1] = v >> 16;
@@ -4840,6 +4878,8 @@ set_h8300h (unsigned long machine)
      This function being replaced by a sim_open:ARGV configuration
      option.  */
 
+  h8300hmode = h8300smode = h8300sxmode = h8300_normal_mode = 0;
+
   if (machine == bfd_mach_h8300sx || machine == bfd_mach_h8300sxn)
     h8300sxmode = 1;
 
@@ -4848,6 +4888,9 @@ set_h8300h (unsigned long machine)
 
   if (machine == bfd_mach_h8300h || machine == bfd_mach_h8300hn || h8300smode)
     h8300hmode = 1;
+
+  if(machine == bfd_mach_h8300hn || machine == bfd_mach_h8300sn || machine == bfd_mach_h8300sxn)
+    h8300_normal_mode = 1;
 }
 
 /* Cover function of sim_state_free to free the cpu buffers as well.  */
@@ -4957,7 +5000,7 @@ sim_load (SIM_DESC sd, char *prog, bfd *abfd, int from_tty)
   if (abfd != NULL)
     prog_bfd = abfd;
   else
-    prog_bfd = bfd_openr (prog, "coff-h8300");
+    prog_bfd = bfd_openr (prog, NULL);
   if (prog_bfd != NULL)
     {
       /* Set the cpu type.  We ignore failure from bfd_check_format
@@ -4983,9 +5026,9 @@ sim_load (SIM_DESC sd, char *prog, bfd *abfd, int from_tty)
      switching between H8/300 and H8/300H programs without exiting
      gdb.  */
 
-  if (h8300smode)
+  if (h8300smode && !h8300_normal_mode)
     memory_size = H8300S_MSIZE;
-  else if (h8300hmode)
+  else if (h8300hmode && !h8300_normal_mode)
     memory_size = H8300H_MSIZE;
   else
     memory_size = H8300_MSIZE;
@@ -5001,6 +5044,7 @@ sim_load (SIM_DESC sd, char *prog, bfd *abfd, int from_tty)
                     calloc (sizeof (char), memory_size));
   h8_set_cache_idx_buf (sd, (unsigned short *) 
                        calloc (sizeof (short), memory_size));
+  sd->memory_size = memory_size;
   h8_set_eightbit_buf (sd, (unsigned char *) calloc (sizeof (char), 256));
 
   /* `msize' must be a power of two.  */
@@ -5064,13 +5108,6 @@ sim_create_inferior (SIM_DESC sd, struct bfd *abfd, char **argv, char **env)
 }
 
 void
-sim_do_command (SIM_DESC sd, char *cmd)
-{
-  (*sim_callback->printf_filtered) (sim_callback,
-                                   "This simulator does not accept any commands.\n");
-}
-
-void
 sim_set_callbacks (struct host_callback_struct *ptr)
 {
   sim_callback = ptr;