]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - sim/v850/simops.c
Replace memory model with one from sim/common directory.
[thirdparty/binutils-gdb.git] / sim / v850 / simops.c
index 4ffe78a06e8ac43aa84c70bbc9e63c44256ea685..4926910b8b763684ac3fcad3c8cd4a65231f6f0f 100644 (file)
@@ -1,8 +1,27 @@
 #include <signal.h>
+#include "sim-main.h"
 #include "v850_sim.h"
 #include "simops.h"
-#include "sys/syscall.h"
+
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+ /* FIXME - should be including a version of syscall.h that does not
+    pollute the name space */
+#include "../../libgloss/v850/sys/syscall.h"
+
 #include "bfd.h"
+#include "libiberty.h"
+
 #include <errno.h>
 #if !defined(__GO32__) && !defined(_WIN32)
 #include <sys/stat.h>
@@ -504,7 +523,6 @@ condition_met (unsigned code)
   return 1;
 }
 
-/* start-sanitize-v850e */
 static unsigned long
 Add32 (unsigned long a1, unsigned long a2, int * carry)
 {
@@ -576,7 +594,50 @@ Multiply64 (boolean sign, unsigned long op0)
 
   return;
 }
-/* end-sanitize-v850e */
+
+\f
+/* Read a null terminated string from memory, return in a buffer */
+static char *
+fetch_str (sd, addr)
+     SIM_DESC sd;
+     address_word addr;
+{
+  char *buf;
+  int nr = 0;
+  while (sim_core_read_1 (STATE_CPU (sd, 0),
+                         PC, sim_core_read_map, addr + nr) != 0)
+    nr++;
+  buf = NZALLOC (char, nr + 1);
+  sim_read (simulator, addr, buf, nr);
+  return buf;
+}
+
+/* Read a null terminated argument vector from memory, return in a
+   buffer */
+static char **
+fetch_argv (sd, addr)
+     SIM_DESC sd;
+     address_word addr;
+{
+  int max_nr = 64;
+  int nr = 0;
+  char **buf = xmalloc (max_nr * sizeof (char*));
+  while (1)
+    {
+      unsigned32 a = sim_core_read_4 (STATE_CPU (sd, 0),
+                                     PC, sim_core_read_map, addr + nr * 4);
+      if (a == 0) break;
+      buf[nr] = fetch_str (sd, a);
+      nr ++;
+      if (nr == max_nr - 1)
+       {
+         max_nr += 50;
+         buf = xrealloc (buf, max_nr * sizeof (char*));
+       }
+    }
+  buf[nr] = 0;
+  return buf;
+}
 
 \f
 /* sld.b */
@@ -790,9 +851,6 @@ OP_10760 ()
 static int
 branch (int code)
 {
-  unsigned int psw;
-  int op0;
-
   trace_input ("Bcond", OP_COND_BR, 0);
   trace_output (OP_COND_BR);
 
@@ -1671,8 +1729,8 @@ OP_640 ()
 
       SP += (OP[3] & 0x3e) << 1;
 
-      /* Load the registers with lower number registers being retrieved from lower addresses.  */
-      for (i = 0; i < 12; i++)
+      /* Load the registers with lower number registers being retrieved from higher addresses.  */
+      for (i = 12; i--;)
        if ((OP[3] & (1 << type1_regs[ i ])))
          {
            State.regs[ 20 + i ] = load_mem (SP, 4);
@@ -1692,7 +1750,7 @@ OP_640 ()
     {
       trace_input ("movhi", OP_UIMM_REG_REG, 16);
       
-      State.regs[ OP[1] ] = State.regs[ OP[0] ] + OP[2] << 16;
+      State.regs[ OP[1] ] = State.regs[ OP[0] ] + (OP[2] << 16);
       
       trace_output (OP_UIMM_REG_REG);
     }
@@ -2217,20 +2275,47 @@ OP_10007E0 ()
 
       switch (FUNC)
        {
-#if !defined(__GO32__) && !defined(_WIN32)
+
+#ifdef HAVE_FORK
+#ifdef SYS_fork
        case SYS_fork:
          RETVAL = fork ();
          break;
+#endif
+#endif
+
+#ifdef HAVE_EXECVE
+#ifdef SYS_execv
        case SYS_execve:
-         RETVAL = execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2),
-                          (char **)MEMPTR (PARM3));
-         break;
+         {
+           char *path = fetch_str (simulator, PARM1);
+           char **argv = fetch_argv (simulator, PARM2);
+           char **envp = fetch_argv (simulator, PARM3);
+           RETVAL = execve (path, argv, envp);
+           zfree (path);
+           freeargv (argv);
+           freeargv (envp);
+           break;
+         }
+#endif
+#endif
+
+#if HAVE_EXECV
 #ifdef SYS_execv
        case SYS_execv:
-         RETVAL = execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2), NULL);
-         break;
+         {
+           char *path = fetch_str (simulator, PARM1);
+           char **argv = fetch_argv (simulator, PARM2);
+           RETVAL = execv (path, argv);
+           zfree (path);
+           freeargv (argv);
+           break;
+         }
+#endif
 #endif
+
 #if 0
+#ifdef SYS_pipe
        case SYS_pipe:
          {
            reg_t buf;
@@ -2243,7 +2328,11 @@ OP_10007E0 ()
            SW (buf, host_fd[1]);
          }
          break;
+#endif
+#endif
 
+#if 0
+#ifdef SYS_wait
        case SYS_wait:
          {
            int status;
@@ -2255,27 +2344,54 @@ OP_10007E0 ()
 #endif
 #endif
 
+#ifdef SYS_read
        case SYS_read:
-         RETVAL = v850_callback->read (v850_callback, PARM1, MEMPTR (PARM2),
-                                       PARM3);
-         break;
+         {
+           char *buf = zalloc (PARM3);
+           RETVAL = sim_io_read (simulator, PARM1, buf, PARM3);
+           sim_write (simulator, PARM2, buf, PARM3);
+           zfree (buf);
+           break;
+         }
+#endif
+
+#ifdef SYS_write
        case SYS_write:
-         if (PARM1 == 1)
-           RETVAL = (int)v850_callback->write_stdout (v850_callback,
-                                                      MEMPTR (PARM2), PARM3);
-         else
-           RETVAL = (int)v850_callback->write (v850_callback, PARM1,
-                                               MEMPTR (PARM2), PARM3);
-         break;
+         {
+           char *buf = zalloc (PARM3);
+           sim_read (simulator, PARM2, buf, PARM3);
+           if (PARM1 == 1)
+             RETVAL = sim_io_write_stdout (simulator, buf, PARM3);
+           else
+             RETVAL = sim_io_write (simulator, PARM1, buf, PARM3);
+           zfree (buf);
+           break;
+         }
+#endif
+
+#ifdef SYS_lseek
        case SYS_lseek:
-         RETVAL = v850_callback->lseek (v850_callback, PARM1, PARM2, PARM3);
+         RETVAL = sim_io_lseek (simulator, PARM1, PARM2, PARM3);
          break;
+#endif
+
+#ifdef SYS_close
        case SYS_close:
-         RETVAL = v850_callback->close (v850_callback, PARM1);
+         RETVAL = sim_io_close (simulator, PARM1);
          break;
+#endif
+
+#ifdef SYS_open
        case SYS_open:
-         RETVAL = v850_callback->open (v850_callback, MEMPTR (PARM1), PARM2);
-         break;
+         {
+           char *buf = fetch_str (simulator, PARM1);
+           RETVAL = sim_io_open (simulator, buf, PARM2);
+           zfree (buf);
+           break;
+         }
+#endif
+
+#ifdef SYS_exit
        case SYS_exit:
          if ((PARM1 & 0xffff0000) == 0xdead0000 && (PARM1 & 0xffff) != 0)
            State.exception = PARM1 & 0xffff;   /* get signal encoded by kill */
@@ -2284,16 +2400,20 @@ OP_10007E0 ()
          else
            State.exception = SIG_V850_EXIT;    /* PARM1 has exit status encoded */
          break;
+#endif
 
 #if !defined(__GO32__) && !defined(_WIN32)
+#ifdef SYS_stat
        case SYS_stat:  /* added at hmsi */
          /* stat system call */
          {
            struct stat host_stat;
            reg_t buf;
+           char *path = fetch_str (simulator, PARM1);
 
-           RETVAL = stat (MEMPTR (PARM1), &host_stat);
+           RETVAL = stat (path, &host_stat);
 
+           zfree (path);
            buf = PARM2;
 
            /* Just wild-assed guesses.  */
@@ -2310,14 +2430,35 @@ OP_10007E0 ()
            store_mem (buf + 36, 4, host_stat.st_ctime);
          }
          break;
+#endif
+#endif
 
+#ifdef HAVE_CHOWN
+#ifdef SYS_chown
        case SYS_chown:
-         RETVAL = chown (MEMPTR (PARM1), PARM2, PARM3);
+         {
+           char *path = fetch_str (simulator, PARM1);
+           RETVAL = chown (path, PARM2, PARM3);
+           zfree (path);
+         }
          break;
+#endif
+#endif
+
+#if HAVE_CHMOD
+#ifdef SYS_chmod
        case SYS_chmod:
-         RETVAL = chmod (MEMPTR (PARM1), PARM2);
+         {
+           char *path = fetch_str (simulator, PARM1);
+           RETVAL = chmod (path, PARM2);
+           zfree (path);
+         }
          break;
+#endif
+#endif
+
 #ifdef SYS_time
+#if HAVE_TIME
        case SYS_time:
          {
            time_t now;
@@ -2326,6 +2467,9 @@ OP_10007E0 ()
          }
          break;
 #endif
+#endif
+
+#if !defined(__GO32__) && !defined(_WIN32)
 #ifdef SYS_times
        case SYS_times:
          {
@@ -2338,6 +2482,10 @@ OP_10007E0 ()
            break;
          }
 #endif
+#endif
+
+#ifdef SYS_gettimeofday
+#if !defined(__GO32__) && !defined(_WIN32)
        case SYS_gettimeofday:
          {
            struct timeval t;
@@ -2349,14 +2497,22 @@ OP_10007E0 ()
            store_mem (PARM2 + 4, 4, tz.tz_dsttime);
            break;
          }
+#endif
+#endif
+
 #ifdef SYS_utime
+#if HAVE_UTIME
        case SYS_utime:
-         /* Cast the second argument to void *, to avoid type mismatch
-            if a prototype is present.  */
-         RETVAL = utime (MEMPTR (PARM1), (void *) MEMPTR (PARM2));
+         {
+           /* Cast the second argument to void *, to avoid type mismatch
+              if a prototype is present.  */
+           sim_io_error (simulator, "Utime not supported");
+           /* RETVAL = utime (path, (void *) MEMPTR (PARM2)); */
+         }
          break;
 #endif
 #endif
+
        default:
          abort ();
        }
@@ -2397,8 +2553,6 @@ OP_2007E0 ()
 int
 OP_4007E0 ()
 {
-  unsigned int op0;
-
   trace_input ("stsr", OP_STSR, 0);
   
   State.regs[ OP[1] ] = State.sregs[ OP[0] ];
@@ -2427,6 +2581,19 @@ OP_E607E0 (void)
   return 4;
 }
 
+/* mulu reg1, reg2, reg3 */
+int
+OP_22207E0 (void)
+{
+  trace_input ("mulu", OP_REG_REG_REG, 0);
+
+  Multiply64 (false, State.regs[ OP[0] ]);
+
+  trace_output (OP_REG_REG_REG);
+
+  return 4;
+}
+
 /* start-sanitize-v850e */
 
 #define BIT_CHANGE_OP( name, binop )           \
@@ -2485,38 +2652,209 @@ OP_20007E0 (void)
 /* end-sanitize-v850e */
 
 /* start-sanitize-v850eq */
+/* This function is courtesy of Sugimoto at NEC, via Seow Tan (Soew_Tan@el.nec.com) */
+static void
+divun
+(
+  unsigned int       N,
+  unsigned long int  als,
+  unsigned long int  sfi,
+  unsigned long int *  quotient_ptr,
+  unsigned long int *  remainder_ptr,
+  boolean *          overflow_ptr
+)
+{
+  unsigned long   ald = sfi >> (N - 1);
+  unsigned long   alo = als;
+  unsigned int    Q   = 1;
+  unsigned int    C;
+  unsigned int    S   = 0;
+  unsigned int    i;
+  unsigned int    R1  = 1;
+  unsigned int    DBZ = (als == 0) ? 1 : 0;
+  unsigned long   alt = Q ? ~als : als;
+
+  /* 1st Loop */
+  alo = ald + alt + Q;
+  C   = (((alt >> 31) & (ald >> 31))
+        | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31)));
+  C   = C ^ Q;
+  Q   = ~(C ^ S) & 1;
+  R1  = (alo == 0) ? 0 : (R1 & Q);
+  if ((S ^ (alo>>31)) && !C)
+    {
+      DBZ = 1;
+    }
+  S   = alo >> 31;
+  sfi = (sfi << (32-N+1)) | Q;
+  ald = (alo << 1) | (sfi >> 31);
+
+  /* 2nd - N-1th Loop */
+  for (i = 2; i < N; i++)
+    {
+      alt = Q ? ~als : als;
+      alo = ald + alt + Q;
+      C   = (((alt >> 31) & (ald >> 31))
+            | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31)));
+      C   = C ^ Q;
+      Q   = ~(C ^ S) & 1;
+      R1  = (alo == 0) ? 0 : (R1 & Q);
+      if ((S ^ (alo>>31)) && !C && !DBZ)
+       {
+         DBZ = 1;
+       }
+      S   = alo >> 31;
+      sfi = (sfi << 1) | Q;
+      ald = (alo << 1) | (sfi >> 31);
+    }
+  
+  /* Nth Loop */
+  alt = Q ? ~als : als;
+  alo = ald + alt + Q;
+  C   = (((alt >> 31) & (ald >> 31))
+        | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31)));
+  C   = C ^ Q;
+  Q   = ~(C ^ S) & 1;
+  R1  = (alo == 0) ? 0 : (R1 & Q);
+  if ((S ^ (alo>>31)) && !C)
+    {
+      DBZ = 1;
+    }
+  
+  * quotient_ptr  = (sfi << 1) | Q;
+  * remainder_ptr = Q ? alo : (alo + als);
+  * overflow_ptr  = DBZ | R1;
+}
+
+/* This function is courtesy of Sugimoto at NEC, via Seow Tan (Soew_Tan@el.nec.com) */
+static void
+divn
+(
+  unsigned int       N,
+  unsigned long int  als,
+  unsigned long int  sfi,
+  signed long int *  quotient_ptr,
+  signed long int *  remainder_ptr,
+  boolean *          overflow_ptr
+)
+{
+  unsigned long          ald = (signed long) sfi >> (N - 1);
+  unsigned long   alo = als;
+  unsigned int    SS  = als >> 31;
+  unsigned int   SD  = sfi >> 31;
+  unsigned int    R1  = 1;
+  unsigned int    OV;
+  unsigned int    DBZ = als == 0 ? 1 : 0;
+  unsigned int    Q   = ~(SS ^ SD) & 1;
+  unsigned int    C;
+  unsigned int    S;
+  unsigned int    i;
+  unsigned long   alt = Q ? ~als : als;
+
+
+  /* 1st Loop */
+  
+  alo = ald + alt + Q;
+  C   = (((alt >> 31) & (ald >> 31))
+        | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31)));
+  Q   = C ^ SS;
+  R1  = (alo == 0) ? 0 : (R1 & (Q ^ (SS ^ SD)));
+  S   = alo >> 31;
+  sfi = (sfi << (32-N+1)) | Q;
+  ald = (alo << 1) | (sfi >> 31);
+  if ((alo >> 31) ^ (ald >> 31))
+    {
+      DBZ = 1;
+    }
+
+  /* 2nd - N-1th Loop */
+  
+  for (i = 2; i < N; i++)
+    {
+      alt = Q ? ~als : als;
+      alo = ald + alt + Q;
+      C   = (((alt >> 31) & (ald >> 31))
+            | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31)));
+      Q   = C ^ SS;
+      R1  = (alo == 0) ? 0 : (R1 & (Q ^ (SS ^ SD)));
+      S   = alo >> 31;
+      sfi = (sfi << 1) | Q;
+      ald = (alo << 1) | (sfi >> 31);
+      if ((alo >> 31) ^ (ald >> 31))
+       {
+         DBZ = 1;
+       }
+    }
+
+  /* Nth Loop */
+  alt = Q ? ~als : als;
+  alo = ald + alt + Q;
+  C   = (((alt >> 31) & (ald >> 31))
+        | (((alt >> 31) ^ (ald >> 31)) & (~alo >> 31)));
+  Q   = C ^ SS;
+  R1  = (alo == 0) ? 0 : (R1 & (Q ^ (SS ^ SD)));
+  sfi = (sfi << (32-N+1));
+  ald = alo;
+
+  /* End */
+  if (alo != 0)
+    {
+      alt = Q ? ~als : als;
+      alo = ald + alt + Q;
+    }
+  R1  = R1 & ((~alo >> 31) ^ SD);
+  if ((alo != 0) && ((Q ^ (SS ^ SD)) ^ R1)) alo = ald;
+  if (N != 32)
+    ald = sfi = (long) ((sfi >> 1) | (SS ^ SD) << 31) >> (32-N-1) | Q;
+  else
+    ald = sfi = sfi | Q;
+  
+  OV = DBZ | ((alo == 0) ? 0 : R1);
+  
+  * remainder_ptr = alo;
+
+  /* Adj */
+  if (((alo != 0) && ((SS ^ SD) ^ R1))
+      || ((alo == 0) && (SS ^ R1)))
+    alo = ald + 1;
+  else
+    alo = ald;
+  
+  OV  = (DBZ | R1) ? OV : ((alo >> 31) & (~ald >> 31));
+
+  * quotient_ptr  = alo;
+  * overflow_ptr  = OV;
+}
+
 /* sdivun imm5, reg1, reg2, reg3 */
 int
 OP_1C207E0 (void)
 {
-  unsigned long long int quotient;
-  unsigned long long int remainder;
-  unsigned long long int divisor;
-  unsigned long long int dividend;
-  boolean                overflow = false;
-  unsigned int           imm5;
+  unsigned long int  quotient;
+  unsigned long int  remainder;
+  unsigned long int  divide_by;
+  unsigned long int  divide_this;
+  boolean            overflow = false;
+  unsigned int       imm5;
       
   trace_input ("sdivun", OP_IMM_REG_REG_REG, 0);
 
   imm5 = 32 - ((OP[3] & 0x3c0000) >> 17);
 
-  divisor  = State.regs[ OP[0] ] << imm5;
-  dividend = State.regs[ OP[1] ];
+  divide_by   = State.regs[ OP[0] ];
+  divide_this = State.regs[ OP[1] ] << imm5;
 
-  State.regs[ OP[1]       ] = quotient  = dividend / divisor;
-  State.regs[ OP[2] >> 11 ] = remainder = dividend % divisor;
+  divun (imm5, divide_by, divide_this, & quotient, & remainder, & overflow);
   
-  if (divisor == 0)
-    {
-      overflow = true;
-      quotient = dividend;
-    }
+  State.regs[ OP[1]       ] = quotient;
+  State.regs[ OP[2] >> 11 ] = remainder;
   
   /* Set condition codes.  */
   PSW &= ~(PSW_Z | PSW_S | PSW_OV);
   
   if (overflow)      PSW |= PSW_OV;
   if (quotient == 0) PSW |= PSW_Z;
+  if (quotient & 0x80000000) PSW |= PSW_S;
   
   trace_output (OP_IMM_REG_REG_REG);
 
@@ -2527,28 +2865,24 @@ OP_1C207E0 (void)
 int
 OP_1C007E0 (void)
 {
-  signed long long int quotient;
-  signed long long int remainder;
-  signed long long int divisor;
-  signed long long int dividend;
-  boolean              overflow = false;
-  unsigned int         imm5;
+  signed long int  quotient;
+  signed long int  remainder;
+  signed long int  divide_by;
+  signed long int  divide_this;
+  boolean          overflow = false;
+  unsigned int     imm5;
       
   trace_input ("sdivn", OP_IMM_REG_REG_REG, 0);
 
   imm5 = 32 - ((OP[3] & 0x3c0000) >> 17);
 
-  divisor  = State.regs[ OP[0] ] << imm5;
-  dividend = State.regs[ OP[1] ];
+  divide_by   = State.regs[ OP[0] ];
+  divide_this = State.regs[ OP[1] ] << imm5;
 
-  State.regs[ OP[1]       ] = quotient  = dividend / divisor;
-  State.regs[ OP[2] >> 11 ] = remainder = dividend % divisor;
+  divn (imm5, divide_by, divide_this, & quotient, & remainder, & overflow);
   
-  if (divisor == 0)
-    {
-      overflow = true;
-      quotient = dividend;
-    }
+  State.regs[ OP[1]       ] = quotient;
+  State.regs[ OP[2] >> 11 ] = remainder;
   
   /* Set condition codes.  */
   PSW &= ~(PSW_Z | PSW_S | PSW_OV);
@@ -2566,34 +2900,31 @@ OP_1C007E0 (void)
 int
 OP_18207E0 (void)
 {
-  unsigned long long int quotient;
-  unsigned long long int remainder;
-  unsigned long long int divisor;
-  unsigned long long int dividend;
-  boolean                overflow = false;
-  unsigned int           imm5;
+  unsigned long int  quotient;
+  unsigned long int  remainder;
+  unsigned long int  divide_by;
+  unsigned long int  divide_this;
+  boolean            overflow = false;
+  unsigned int       imm5;
       
   trace_input ("sdivhun", OP_IMM_REG_REG_REG, 0);
 
   imm5 = 32 - ((OP[3] & 0x3c0000) >> 17);
 
-  divisor  = State.regs[ OP[0] ] << imm5;
-  dividend = State.regs[ OP[1] ] & 0xffff;
+  divide_by   = State.regs[ OP[0] ] & 0xffff;
+  divide_this = State.regs[ OP[1] ] << imm5;
 
-  State.regs[ OP[1]       ] = quotient  = dividend / divisor;
-  State.regs[ OP[2] >> 11 ] = remainder = dividend % divisor;
+  divun (imm5, divide_by, divide_this, & quotient, & remainder, & overflow);
   
-  if (divisor == 0)
-    {
-      overflow = true;
-      quotient = dividend;
-    }
+  State.regs[ OP[1]       ] = quotient;
+  State.regs[ OP[2] >> 11 ] = remainder;
   
   /* Set condition codes.  */
   PSW &= ~(PSW_Z | PSW_S | PSW_OV);
   
   if (overflow)      PSW |= PSW_OV;
   if (quotient == 0) PSW |= PSW_Z;
+  if (quotient & 0x80000000) PSW |= PSW_S;
   
   trace_output (OP_IMM_REG_REG_REG);
 
@@ -2604,28 +2935,24 @@ OP_18207E0 (void)
 int
 OP_18007E0 (void)
 {
-  signed long long int quotient;
-  signed long long int remainder;
-  signed long long int divisor;
-  signed long long int dividend;
-  boolean              overflow = false;
-  unsigned int         imm5;
+  signed long int  quotient;
+  signed long int  remainder;
+  signed long int  divide_by;
+  signed long int  divide_this;
+  boolean          overflow = false;
+  unsigned int     imm5;
       
   trace_input ("sdivhn", OP_IMM_REG_REG_REG, 0);
 
   imm5 = 32 - ((OP[3] & 0x3c0000) >> 17);
 
-  divisor  = State.regs[ OP[0] ] << imm5;
-  dividend = SEXT16 (State.regs[ OP[1] ]);
+  divide_by   = SEXT16 (State.regs[ OP[0] ]);
+  divide_this = State.regs[ OP[1] ] << imm5;
 
-  State.regs[ OP[1]       ] = quotient  = dividend / divisor;
-  State.regs[ OP[2] >> 11 ] = remainder = dividend % divisor;
+  divn (imm5, divide_by, divide_this, & quotient, & remainder, & overflow);
   
-  if (divisor == 0)
-    {
-      overflow = true;
-      quotient = dividend;
-    }
+  State.regs[ OP[1]       ] = quotient;
+  State.regs[ OP[2] >> 11 ] = remainder;
   
   /* Set condition codes.  */
   PSW &= ~(PSW_Z | PSW_S | PSW_OV);
@@ -2642,14 +2969,13 @@ OP_18007E0 (void)
 
 /* start-sanitize-v850e */
 /* divu  reg1, reg2, reg3 */
-/* divun imm5, reg1, reg2, reg3 */
 int
 OP_2C207E0 (void)
 {
   unsigned long int quotient;
   unsigned long int remainder;
-  unsigned long int divisor;
-  unsigned long int dividend;
+  unsigned long int divide_by;
+  unsigned long int divide_this;
   boolean           overflow = false;
   
   if ((OP[3] & 0x3c0000) == 0)
@@ -2658,27 +2984,29 @@ OP_2C207E0 (void)
 
       /* Compute the result.  */
 
-      divisor  = State.regs[ OP[0] ];
-      dividend = State.regs[ OP[1] ];
+      divide_by   = State.regs[ OP[0] ];
+      divide_this = State.regs[ OP[1] ];
 
-      if (divisor == 0)
+      if (divide_by == 0)
        {
          overflow = true;
-         divisor  = 1;
+         divide_by  = 1;
        }
            
-      State.regs[ OP[1]       ] = quotient  = dividend / divisor;
-      State.regs[ OP[2] >> 11 ] = remainder = dividend % divisor;
+      State.regs[ OP[1]       ] = quotient  = divide_this / divide_by;
+      State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
 
       /* Set condition codes.  */
       PSW &= ~(PSW_Z | PSW_S | PSW_OV);
       
       if (overflow)      PSW |= PSW_OV;
       if (quotient == 0) PSW |= PSW_Z;
+      if (quotient & 0x80000000) PSW |= PSW_S;
 
       trace_output (OP_REG_REG_REG);
     }
 /* start-sanitize-v850eq */
+/* divun imm5, reg1, reg2, reg3 */
   else
     {
       unsigned int imm5;
@@ -2687,25 +3015,20 @@ OP_2C207E0 (void)
 
       imm5 = 32 - ((OP[3] & 0x3c0000) >> 17);
 
-      divisor  = State.regs[ OP[0] ];
-      dividend = State.regs[ OP[1] ];
+      divide_by   = State.regs[ OP[0] ];
+      divide_this = State.regs[ OP[1] ];
 
-      State.regs[ OP[1]       ] = quotient  = dividend / divisor;
-      State.regs[ OP[2] >> 11 ] = remainder = dividend % divisor;
+      divun (imm5, divide_by, divide_this, & quotient, & remainder, & overflow);
       
-      if ((divisor == 0)
-         || (quotient > (1 << imm5))
-         || (quotient < (((imm5 & 1) ? 1 : -1) << imm5)))
-       {
-         overflow = true;
-         quotient = dividend;
-       }
+      State.regs[ OP[1]       ] = quotient;
+      State.regs[ OP[2] >> 11 ] = remainder;
       
       /* Set condition codes.  */
       PSW &= ~(PSW_Z | PSW_S | PSW_OV);
       
       if (overflow)      PSW |= PSW_OV;
       if (quotient == 0) PSW |= PSW_Z;
+      if (quotient & 0x80000000) PSW |= PSW_S;
 
       trace_output (OP_IMM_REG_REG_REG);
     }
@@ -2715,14 +3038,13 @@ OP_2C207E0 (void)
 }
 
 /* div  reg1, reg2, reg3 */
-/* divn imm5, reg1, reg2, reg3 */
 int
 OP_2C007E0 (void)
 {
   signed long int quotient;
   signed long int remainder;
-  signed long int divisor;
-  signed long int dividend;
+  signed long int divide_by;
+  signed long int divide_this;
   boolean         overflow = false;
   
   if ((OP[3] & 0x3c0000) == 0)
@@ -2731,17 +3053,17 @@ OP_2C007E0 (void)
 
       /* Compute the result.  */
 
-      divisor  = State.regs[ OP[0] ];
-      dividend = State.regs[ OP[1] ];
+      divide_by   = State.regs[ OP[0] ];
+      divide_this = State.regs[ OP[1] ];
 
-      if (divisor == 0 || (divisor == -1 && dividend == (1 << 31)))
+      if (divide_by == 0 || (divide_by == -1 && divide_this == (1 << 31)))
        {
-         overflow = true;
-         divisor  = 1;
+         overflow  = true;
+         divide_by = 1;
        }
            
-      State.regs[ OP[1]       ] = quotient  = dividend / divisor;
-      State.regs[ OP[2] >> 11 ] = remainder = dividend % divisor;
+      State.regs[ OP[1]       ] = quotient  = divide_this / divide_by;
+      State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
 
       /* Set condition codes.  */
       PSW &= ~(PSW_Z | PSW_S | PSW_OV);
@@ -2753,6 +3075,7 @@ OP_2C007E0 (void)
       trace_output (OP_REG_REG_REG);
     }
 /* start-sanitize-v850eq */
+/* divn imm5, reg1, reg2, reg3 */
   else
     {
       unsigned int imm5;
@@ -2761,20 +3084,13 @@ OP_2C007E0 (void)
 
       imm5 = 32 - ((OP[3] & 0x3c0000) >> 17);
 
-      divisor  = State.regs[ OP[0] ];
-      dividend = State.regs[ OP[1] ];
+      divide_by   = State.regs[ OP[0] ];
+      divide_this = State.regs[ OP[1] ];
 
-      State.regs[ OP[1]       ] = quotient  = dividend / divisor;
-      State.regs[ OP[2] >> 11 ] = remainder = dividend % divisor;
+      divn (imm5, divide_by, divide_this, & quotient, & remainder, & overflow);
       
-      if ((divisor == 0)
-         || (quotient > (1 << imm5))
-         || (divisor == -1 && dividend == (1 << 31))
-         || (quotient < (((imm5 & 1) ? 1 : -1) << imm5)))
-       {
-         overflow = true;
-         quotient = dividend;
-       }
+      State.regs[ OP[1]       ] = quotient;
+      State.regs[ OP[2] >> 11 ] = remainder;
       
       /* Set condition codes.  */
       PSW &= ~(PSW_Z | PSW_S | PSW_OV);
@@ -2791,14 +3107,13 @@ OP_2C007E0 (void)
 }
 
 /* divhu  reg1, reg2, reg3 */
-/* divhun imm5, reg1, reg2, reg3 */
 int
 OP_28207E0 (void)
 {
   unsigned long int quotient;
   unsigned long int remainder;
-  unsigned long int divisor;
-  unsigned long int dividend;
+  unsigned long int divide_by;
+  unsigned long int divide_this;
   boolean           overflow = false;
   
   if ((OP[3] & 0x3c0000) == 0)
@@ -2807,27 +3122,29 @@ OP_28207E0 (void)
 
       /* Compute the result.  */
 
-      divisor  = State.regs[ OP[0] ];
-      dividend = State.regs[ OP[1] ] & 0xffff;
+      divide_by   = State.regs[ OP[0] ] & 0xffff;
+      divide_this = State.regs[ OP[1] ];
 
-      if (divisor == 0)
+      if (divide_by == 0)
        {
          overflow = true;
-         divisor  = 1;
+         divide_by  = 1;
        }
            
-      State.regs[ OP[1]       ] = quotient  = dividend / divisor;
-      State.regs[ OP[2] >> 11 ] = remainder = dividend % divisor;
+      State.regs[ OP[1]       ] = quotient  = divide_this / divide_by;
+      State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
 
       /* Set condition codes.  */
       PSW &= ~(PSW_Z | PSW_S | PSW_OV);
       
       if (overflow)      PSW |= PSW_OV;
       if (quotient == 0) PSW |= PSW_Z;
+      if (quotient & 0x80000000) PSW |= PSW_S;
 
       trace_output (OP_REG_REG_REG);
     }
 /* start-sanitize-v850eq */
+/* divhun imm5, reg1, reg2, reg3 */
   else
     {
       unsigned int imm5;
@@ -2836,25 +3153,20 @@ OP_28207E0 (void)
 
       imm5 = 32 - ((OP[3] & 0x3c0000) >> 17);
 
-      divisor  = State.regs[ OP[0] ];
-      dividend = State.regs[ OP[1] ] & 0xffff;
+      divide_by   = State.regs[ OP[0] ] & 0xffff;
+      divide_this = State.regs[ OP[1] ];
 
-      State.regs[ OP[1]       ] = quotient  = dividend / divisor;
-      State.regs[ OP[2] >> 11 ] = remainder = dividend % divisor;
+      divun (imm5, divide_by, divide_this, & quotient, & remainder, & overflow);
       
-      if ((divisor == 0)
-         || (quotient > (1 << imm5))
-         || (quotient < (((imm5 & 1) ? 1 : -1) << imm5)))
-       {
-         overflow = true;
-         quotient = dividend;
-       }
+      State.regs[ OP[1]       ] = quotient;
+      State.regs[ OP[2] >> 11 ] = remainder;
       
       /* Set condition codes.  */
       PSW &= ~(PSW_Z | PSW_S | PSW_OV);
       
       if (overflow)      PSW |= PSW_OV;
       if (quotient == 0) PSW |= PSW_Z;
+      if (quotient & 0x80000000) PSW |= PSW_S;
 
       trace_output (OP_IMM_REG_REG_REG);
     }
@@ -2864,14 +3176,13 @@ OP_28207E0 (void)
 }
 
 /* divh  reg1, reg2, reg3 */
-/* divhn imm5, reg1, reg2, reg3 */
 int
 OP_28007E0 (void)
 {
   signed long int quotient;
   signed long int remainder;
-  signed long int divisor;
-  signed long int dividend;
+  signed long int divide_by;
+  signed long int divide_this;
   boolean         overflow = false;
   
   if ((OP[3] & 0x3c0000) == 0)
@@ -2880,17 +3191,17 @@ OP_28007E0 (void)
 
       /* Compute the result.  */
 
-      divisor  = State.regs[ OP[0] ];
-      dividend = SEXT16 (State.regs[ OP[1] ]);
+      divide_by  = State.regs[ OP[0] ];
+      divide_this = SEXT16 (State.regs[ OP[1] ]);
 
-      if (divisor == 0 || (divisor == -1 && dividend == (1 << 31)))
+      if (divide_by == 0 || (divide_by == -1 && divide_this == (1 << 31)))
        {
          overflow = true;
-         divisor  = 1;
+         divide_by  = 1;
        }
            
-      State.regs[ OP[1]       ] = quotient  = dividend / divisor;
-      State.regs[ OP[2] >> 11 ] = remainder = dividend % divisor;
+      State.regs[ OP[1]       ] = quotient  = divide_this / divide_by;
+      State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
 
       /* Set condition codes.  */
       PSW &= ~(PSW_Z | PSW_S | PSW_OV);
@@ -2902,6 +3213,7 @@ OP_28007E0 (void)
       trace_output (OP_REG_REG_REG);
     }
 /* start-sanitize-v850eq */
+/* divhn imm5, reg1, reg2, reg3 */
   else
     {
       unsigned int imm5;
@@ -2910,20 +3222,13 @@ OP_28007E0 (void)
 
       imm5 = 32 - ((OP[3] & 0x3c0000) >> 17);
 
-      divisor  = State.regs[ OP[0] ];
-      dividend = SEXT16 (State.regs[ OP[1] ]);
+      divide_by   = SEXT16 (State.regs[ OP[0] ]);
+      divide_this = State.regs[ OP[1] ];
 
-      State.regs[ OP[1]       ] = quotient  = dividend / divisor;
-      State.regs[ OP[2] >> 11 ] = remainder = dividend % divisor;
+      divn (imm5, divide_by, divide_this, & quotient, & remainder, & overflow);
       
-      if ((divisor == 0)
-         || (quotient > (1 << imm5))
-         || (divisor == -1 && dividend == (1 << 31))
-         || (quotient < (((imm5 & 1) ? 1 : -1) << imm5)))
-       {
-         overflow = true;
-         quotient = dividend;
-       }
+      State.regs[ OP[1]       ] = quotient;
+      State.regs[ OP[2] >> 11 ] = remainder;
       
       /* Set condition codes.  */
       PSW &= ~(PSW_Z | PSW_S | PSW_OV);
@@ -2952,23 +3257,6 @@ OP_24207E0 (void)
   return 4;
 }
 
-/* end-sanitize-v850e */
-
-/* mulu reg1, reg2, reg3 */
-int
-OP_22207E0 (void)
-{
-  trace_input ("mulu", OP_REG_REG_REG, 0);
-
-  Multiply64 (false, State.regs[ OP[0] ]);
-
-  trace_output (OP_REG_REG_REG);
-
-  return 4;
-}
-
-/* start-sanitize-v850e */
-
 /* mul imm9, reg2, reg3 */
 int
 OP_24007E0 (void)
@@ -3083,7 +3371,7 @@ OP_34207E0 (void)
 
   if (value == 0) PSW |= PSW_Z;
   if (value & 0x80000000) PSW |= PSW_S;
-  if (((value & 0xffff) == 0) || (value & 0xffff0000) == 0) PSW |= PSW_CY;
+  if (((value & 0xff) == 0) || (value & 0x00ff) == 0) PSW |= PSW_CY;
 
   trace_output (OP_REG_REG3);
   
@@ -3101,6 +3389,21 @@ OP_107E0 (void)
 
       trace_input ("pushml", OP_PUSHPOP3, 0);
 
+      /* Store the registers with lower number registers being placed at higher addresses.  */
+      for (i = 0; i < 15; i++)
+       if ((OP[3] & (1 << type3_regs[ i ])))
+         {
+           SP -= 4;
+           store_mem (SP & ~ 3, 4, State.regs[ i + 1 ]);
+         }
+
+      if (OP[3] & (1 << 3))
+       {
+         SP -= 4;
+
+         store_mem (SP & ~ 3, 4, PSW);
+       }
+         
       if (OP[3] & (1 << 19))
        {
          SP -= 8;
@@ -3117,21 +3420,6 @@ OP_107E0 (void)
            }
        }
 
-      if (OP[3] & (1 << 3))
-       {
-         SP -= 4;
-
-         store_mem (SP & ~ 3, 4, PSW);
-       }
-         
-      /* Store the registers with lower number registers being placed at lower addresses.  */
-      for (i = 15; i--;)
-       if ((OP[3] & (1 << type3_regs[ i ])))
-         {
-           SP -= 4;
-           store_mem (SP & ~ 3, 4, State.regs[ i + 1 ]);
-         }
-
       trace_output (OP_PUSHPOP2);
     }
   else
@@ -3162,8 +3450,8 @@ OP_10780 (void)
       
       trace_input ("prepare", OP_PUSHPOP1, 0);
       
-      /* Store the registers with lower number registers being placed at lower addresses.  */
-      for (i = 12; i--;)
+      /* Store the registers with lower number registers being placed at higher addresses.  */
+      for (i = 0; i < 12; i++)
        if ((OP[3] & (1 << type1_regs[ i ])))
          {
            SP -= 4;
@@ -3180,7 +3468,8 @@ OP_10780 (void)
 
       trace_input ("ld.bu", OP_LOAD32, 1);
 
-      adr = State.regs[ OP[0] ] + SEXT16 (OP[2] & ~1) | ((OP[3] >> 5) & 1);
+      adr = (State.regs[ OP[0] ]
+            + (SEXT16 (OP[2] & ~1) | ((OP[3] >> 5) & 1)));
       
       State.regs[ OP[1] ] = load_mem (adr, 1);
   
@@ -3198,8 +3487,8 @@ OP_1B0780 (void)
   
   trace_input ("prepare", OP_PUSHPOP1, 0);
   
-  /* Store the registers with lower number registers being placed at lower addresses.  */
-  for (i = 12; i--;)
+  /* Store the registers with lower number registers being placed at higher addresses.  */
+  for (i = 0; i < 12; i++)
     if ((OP[3] & (1 << type1_regs[ i ])))
       {
        SP -= 4;
@@ -3223,8 +3512,8 @@ OP_130780 (void)
   
   trace_input ("prepare", OP_PUSHPOP1, 0);
   
-  /* Store the registers with lower number registers being placed at lower addresses.  */
-  for (i = 12; i--;)
+  /* Store the registers with lower number registers being placed at higher addresses.  */
+  for (i = 0; i < 12; i++)
     if ((OP[3] & (1 << type1_regs[ i ])))
       {
        SP -= 4;
@@ -3248,8 +3537,8 @@ OP_B0780 (void)
   
   trace_input ("prepare", OP_PUSHPOP1, 0);
   
-  /* Store the registers with lower number registers being placed at lower addresses.  */
-  for (i = 12; i--;)
+  /* Store the registers with lower number registers being placed at higher addresses.  */
+  for (i = 0; i < 12; i++)
     if ((OP[3] & (1 << type1_regs[ i ])))
       {
        SP -= 4;
@@ -3273,8 +3562,8 @@ OP_30780 (void)
   
   trace_input ("prepare", OP_PUSHPOP1, 0);
   
-  /* Store the registers with lower number registers being placed at lower addresses.  */
-  for (i = 12; i--;)
+  /* Store the registers with lower number registers being placed at higher addresses.  */
+  for (i = 0; i < 12; i++)
     if ((OP[3] & (1 << type1_regs[ i ])))
       {
        SP -= 4;
@@ -3290,6 +3579,59 @@ OP_30780 (void)
   return 4;
 }
 
+/* sld.hu */
+int
+OP_70 (void)
+{
+  unsigned long result;
+  
+  result  = load_mem (State.regs[30] + ((OP[3] & 0xf) << 1), 2);
+
+/* start-sanitize-v850eq */
+#ifdef ARCH_v850eq
+  trace_input ("sld.h", OP_LOAD16, 2);
+  
+  State.regs[ OP[1] ] = SEXT16 (result);
+#else
+/* end-sanitize-v850eq */
+  trace_input ("sld.hu", OP_LOAD16, 2);
+  
+  State.regs[ OP[1] ] = result;
+/* start-sanitize-v850eq */
+#endif
+/* end-sanitize-v850eq */
+  
+  trace_output (OP_LOAD16);
+  
+  return 2;
+}
+
+/* cmov reg1, reg2, reg3 */
+int
+OP_32007E0 (void)
+{
+  trace_input ("cmov", OP_REG_REG_REG, 0);
+
+  State.regs[ OP[2] >> 11 ] = condition_met (OP[0]) ? State.regs[ OP[0] ] : State.regs[ OP[1] ];
+  
+  trace_output (OP_REG_REG_REG);
+
+  return 4;
+}
+
+/* mul reg1, reg2, reg3 */
+int
+OP_22007E0 (void)
+{
+  trace_input ("mul", OP_REG_REG_REG, 0);
+
+  Multiply64 (true, State.regs[ OP[0] ]);
+
+  trace_output (OP_REG_REG_REG);
+
+  return 4;
+}
+
 /* end-sanitize-v850e */
 /* start-sanitize-v850eq */
 
@@ -3301,14 +3643,6 @@ OP_307F0 (void)
   
   trace_input ("popmh", OP_PUSHPOP2, 0);
   
-  /* Load the registers with lower number registers being retrieved from lower addresses.  */
-  for (i = 0; i++; i < 16)
-    if ((OP[3] & (1 << type2_regs[ i ])))
-      {
-       State.regs[ i + 16 ] = load_mem (SP & ~ 3, 4);
-       SP += 4;
-      }
-  
   if (OP[3] & (1 << 19))
     {
       if ((PSW & PSW_NP) && ((PSW & PSW_EP) == 0))
@@ -3325,6 +3659,14 @@ OP_307F0 (void)
       SP += 8;
     }
   
+  /* Load the registers with lower number registers being retrieved from higher addresses.  */
+  for (i = 16; i--;)
+    if ((OP[3] & (1 << type2_regs[ i ])))
+      {
+       State.regs[ i + 16 ] = load_mem (SP & ~ 3, 4);
+       SP += 4;
+      }
+  
   trace_output (OP_PUSHPOP2);
 
   return 4;
@@ -3338,20 +3680,6 @@ OP_107F0 (void)
 
   trace_input ("popml", OP_PUSHPOP3, 0);
 
-  /* Load the registers with lower number registers being retrieved from lower addresses.  */
-  for (i = 0; i++; i < 15)
-    if ((OP[3] & (1 << type3_regs[ i ])))
-      {
-       State.regs[ i + 1 ] = load_mem (SP & ~ 3, 4);
-       SP += 4;
-      }
-  
-  if (OP[3] & (1 << 3))
-    {
-      PSW = load_mem (SP & ~ 3, 4);
-      SP += 4;
-    }
-  
   if (OP[3] & (1 << 19))
     {
       if ((PSW & PSW_NP) && ((PSW & PSW_EP) == 0))
@@ -3368,7 +3696,23 @@ OP_107F0 (void)
       SP += 8;
     }
   
+  if (OP[3] & (1 << 3))
+    {
+      PSW = load_mem (SP & ~ 3, 4);
+      SP += 4;
+    }
+  
+  /* Load the registers with lower number registers being retrieved from higher addresses.  */
+  for (i = 15; i--;)
+    if ((OP[3] & (1 << type3_regs[ i ])))
+      {
+       State.regs[ i + 1 ] = load_mem (SP & ~ 3, 4);
+       SP += 4;
+      }
+  
   trace_output (OP_PUSHPOP2);
+
+  return 4;
 }
 
 /* pushmh list18 */
@@ -3379,6 +3723,14 @@ OP_307E0 (void)
 
   trace_input ("pushmh", OP_PUSHPOP2, 0);
   
+  /* Store the registers with lower number registers being placed at higher addresses.  */
+  for (i = 0; i < 16; i++)
+    if ((OP[3] & (1 << type2_regs[ i ])))
+      {
+       SP -= 4;
+       store_mem (SP & ~ 3, 4, State.regs[ i + 16 ]);
+      }
+  
   if (OP[3] & (1 << 19))
     {
       SP -= 8;
@@ -3395,73 +3747,9 @@ OP_307E0 (void)
        }
     }
   
-  /* Store the registers with lower number registers being placed at lower addresses.  */
-  for (i = 16; i--;)
-    if ((OP[3] & (1 << type2_regs[ i ])))
-      {
-       SP -= 4;
-       store_mem (SP & ~ 3, 4, State.regs[ i + 16 ]);
-      }
-  
   trace_output (OP_PUSHPOP2);
 
   return 4;
 }
 
 /* end-sanitize-v850eq */
-/* start-sanitize-v850e */
-
-/* sld.hu */
-int
-OP_70 (void)
-{
-  unsigned long result;
-  
-  result  = load_mem (State.regs[30] + ((OP[3] & 0xf) << 1), 2);
-
-/* start-sanitize-v850eq */
-#ifdef ARCH_v850eq
-  trace_input ("sld.h", OP_LOAD16, 2);
-  
-  State.regs[ OP[1] ] = SEXT16 (result);
-#else
-/* end-sanitize-v850eq */
-  trace_input ("sld.hu", OP_LOAD16, 2);
-  
-  State.regs[ OP[1] ] = result;
-/* start-sanitize-v850eq */
-#endif
-/* end-sanitize-v850eq */
-  
-  trace_output (OP_LOAD16);
-  
-  return 2;
-}
-
-/* cmov reg1, reg2, reg3 */
-int
-OP_32007E0 (void)
-{
-  trace_input ("cmov", OP_REG_REG_REG, 0);
-
-  State.regs[ OP[2] >> 11 ] = condition_met (OP[0]) ? State.regs[ OP[0] ] : State.regs[ OP[1] ];
-  
-  trace_output (OP_REG_REG_REG);
-
-  return 4;
-}
-
-/* mul reg1, reg2, reg3 */
-int
-OP_22007E0 (void)
-{
-  trace_input ("mul", OP_REG_REG_REG, 0);
-
-  Multiply64 (true, State.regs[ OP[0] ]);
-
-  trace_output (OP_REG_REG_REG);
-
-  return 4;
-}
-
-/* end-sanitize-v850e */