Index: ChangeLog
authorDJ Delorie <dj@redhat.com>
Wed, 6 Feb 2008 00:40:05 +0000 (00:40 +0000)
committerDJ Delorie <dj@redhat.com>
Wed, 6 Feb 2008 00:40:05 +0000 (00:40 +0000)
* configure.ac (v850): V850 now has a testsuite.
* configure (v850): Likewise.

Index: testsuite/ChangeLog

* sim/v850/: New directory.
* sim/v850/allinsns.exp: New.
* sim/v850/bsh.cgs: New.
* sim/v850/div.cgs: New.
* sim/v850/divh.cgs: New.
* sim/v850/divh_3.cgs: New.
* sim/v850/divhu.cgs: New.
* sim/v850/divu.cgs: New.
* sim/v850/sar.cgs: New.
* sim/v850/satadd.cgs: New.
* sim/v850/satsub.cgs: New.
* sim/v850/satsubi.cgs: New.
* sim/v850/satsubr.cgs: New.
* sim/v850/shl.cgs: New.
* sim/v850/shr.cgs: New.
* sim/v850/testutils.cgs: New.
* sim/v850/testutils.inc: New.

Index: v850/ChangeLog

* simops.c (OP_C0): Correct saturation logic.
(OP_220): Likewise.
(OP_A0): Likewise.
(OP_660): Likewise.
(OP_80): Likewise.

* simops.c (OP_2A0): If the shift count is zero, clear the
carry.
(OP_A007E0): Likewise.
(OP_2C0): Likewise.
(OP_C007E0): Likewise.
(OP_280): Likewise.
(OP_8007E0): Likewise.

* simops.c (OP_2C207E0): Correct PSW flags for special divu
conditions.
(OP_2C007E0): Likewise, for div.
(OP_28207E0): Likewise, for divhu.
(OP_28007E0): Likewise, for divh.  Also, sign-extend the correct
operand.
* v850.igen (divh): Likewise, for 2-op divh.

* v850.igen (bsh): Fix carry logic.

23 files changed:
sim/ChangeLog
sim/configure
sim/configure.ac
sim/testsuite/ChangeLog
sim/testsuite/sim/v850/allinsns.exp [new file with mode: 0644]
sim/testsuite/sim/v850/bsh.cgs [new file with mode: 0644]
sim/testsuite/sim/v850/div.cgs [new file with mode: 0644]
sim/testsuite/sim/v850/divh.cgs [new file with mode: 0644]
sim/testsuite/sim/v850/divh_3.cgs [new file with mode: 0644]
sim/testsuite/sim/v850/divhu.cgs [new file with mode: 0644]
sim/testsuite/sim/v850/divu.cgs [new file with mode: 0644]
sim/testsuite/sim/v850/sar.cgs [new file with mode: 0644]
sim/testsuite/sim/v850/satadd.cgs [new file with mode: 0644]
sim/testsuite/sim/v850/satsub.cgs [new file with mode: 0644]
sim/testsuite/sim/v850/satsubi.cgs [new file with mode: 0644]
sim/testsuite/sim/v850/satsubr.cgs [new file with mode: 0644]
sim/testsuite/sim/v850/shl.cgs [new file with mode: 0644]
sim/testsuite/sim/v850/shr.cgs [new file with mode: 0644]
sim/testsuite/sim/v850/testutils.cgs [new file with mode: 0644]
sim/testsuite/sim/v850/testutils.inc [new file with mode: 0644]
sim/v850/ChangeLog
sim/v850/simops.c
sim/v850/v850.igen

index 4317f7e..0a3741a 100644 (file)
@@ -1,3 +1,8 @@
+2008-02-05  DJ Delorie  <dj@redhat.com>
+
+       * configure.ac (v850): V850 now has a testsuite.
+       * configure (v850): Likewise.
+
 2008-01-01  Daniel Jacobowitz  <dan@codesourcery.com>
 
        Updated copyright notices for most files.
index c4cd59c..ac45dab 100755 (executable)
@@ -3532,6 +3532,7 @@ subdirs="$subdirs ppc"
 subdirs="$subdirs v850"
 
           igen=yes
+          testsuite=yes
           ;;
        *)
           # No simulator subdir, so the subdir "common" isn't needed.
index d7e822c..48f590f 100644 (file)
@@ -112,6 +112,7 @@ if test "${enable_sim}" != no; then
        v850*-*-* )
            AC_CONFIG_SUBDIRS(v850)
           igen=yes
+          testsuite=yes
           ;;
        *)
           # No simulator subdir, so the subdir "common" isn't needed.
index 91c5484..337aeeb 100644 (file)
@@ -1,3 +1,23 @@
+2008-02-05  DJ Delorie  <dj@redhat.com>
+
+       * sim/v850/: New directory.
+       * sim/v850/allinsns.exp: New.
+       * sim/v850/bsh.cgs: New.
+       * sim/v850/div.cgs: New.
+       * sim/v850/divh.cgs: New.
+       * sim/v850/divh_3.cgs: New.
+       * sim/v850/divhu.cgs: New.
+       * sim/v850/divu.cgs: New.
+       * sim/v850/sar.cgs: New.
+       * sim/v850/satadd.cgs: New.
+       * sim/v850/satsub.cgs: New.
+       * sim/v850/satsubi.cgs: New.
+       * sim/v850/satsubr.cgs: New.
+       * sim/v850/shl.cgs: New.
+       * sim/v850/shr.cgs: New.
+       * sim/v850/testutils.cgs: New.
+       * sim/v850/testutils.inc: New.
+
 2007-11-08  Hans-Peter Nilsson  <hp@axis.com>
 
        * sim/cris/asm/x0-v10.ms, sim/cris/asm/x0-v32.ms: Tweak
diff --git a/sim/testsuite/sim/v850/allinsns.exp b/sim/testsuite/sim/v850/allinsns.exp
new file mode 100644 (file)
index 0000000..f60c3d6
--- /dev/null
@@ -0,0 +1,39 @@
+# v850 simulator testsuite.
+
+if [istarget v850*-*] {
+    global opt
+
+    # load support procs (none yet)
+    # load_lib cgen.exp
+    # all machines
+
+    switch -regexp -- $opt {
+       .*v850e.* {
+           set all_machs "v850e"
+       }
+       default {
+           set all_machs "v850"
+       }
+    }
+    # gas doesn't support any '=' option for v850.
+    #set cpu_option -m
+
+    # The .cgs suffix is for "cgen .s".
+    foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.cgs]] {
+       # If we're only testing specific files and this isn't one of them,
+       # skip it.
+       if ![runtest_file_p $runtests $src] {
+           continue
+       }
+       run_sim_test $src $all_machs
+    }
+}
+
+#foreach var [lsort [info globals]] {
+#    if [array exists ::$var] {
+#      puts [format "%-27s %s" $var Array:]
+#      continue
+#    }
+#    puts [format "%-30s %s" $var "[set ::$var]"]
+#}
+       
\ No newline at end of file
diff --git a/sim/testsuite/sim/v850/bsh.cgs b/sim/testsuite/sim/v850/bsh.cgs
new file mode 100644 (file)
index 0000000..e9d216e
--- /dev/null
@@ -0,0 +1,55 @@
+# v850 bsh
+# mach: v850e
+# as(v850e): -mv850e
+
+       .include "testutils.inc"
+
+       seti    0x12345678, r1
+       bsh     r1, r2
+
+       flags   0
+       reg     r2, 0x34127856
+
+# CY is 1 if one or more bytes in the result half-word is zero, else 0
+
+       seti    0x12345600, r1
+       bsh     r1, r2
+       flags   c
+       reg     r2, 0x34120056
+
+       seti    0x12340078, r1
+       bsh     r1, r2
+       flags   c
+       reg     r2, 0x34127800
+
+       seti    0x12005678, r1
+       bsh     r1, r2
+       flags   0
+       reg     r2, 0x00127856
+
+       seti    0x00345678, r1
+       bsh     r1, r2
+       flags   0
+       reg     r2, 0x34007856
+
+# S is set if the result is negative
+
+       seti    0x00800000, r1
+       bsh     r1, r2
+       flags   s + c + z
+       reg     r2, 0x80000000
+
+# Z is set if the result is zero
+# According to NEC, the Z flag depends on only the lower half-word
+
+       seti    0x00000000, r1
+       bsh     r1, r2
+       flags   c + z
+       reg     r2, 0x00000000
+
+       seti    0xffff0000, r1
+       bsh     r1, r2
+       flags   c + s + z
+       reg     r2, 0xffff0000
+
+       pass
diff --git a/sim/testsuite/sim/v850/div.cgs b/sim/testsuite/sim/v850/div.cgs
new file mode 100644 (file)
index 0000000..16683f1
--- /dev/null
@@ -0,0 +1,118 @@
+# v850 div
+# mach: v850e
+# as(v850e): -mv850e
+
+       .include "testutils.inc"
+
+# Regular division - check signs
+# The S flag is based on the quotient, not the remainder
+
+       seti    6, r1
+       seti    45, r2
+       div     r1, r2, r3
+
+       flags   0
+       reg     r1, 6
+       reg     r2, 7
+       reg     r3, 3
+
+       seti    -6, r1
+       seti    45, r2
+       div     r1, r2, r3
+
+       flags   s
+       reg     r1, -6
+       reg     r2, -7
+       reg     r3, 3
+
+       seti    6, r1
+       seti    -45, r2
+       div     r1, r2, r3
+
+       flags   s
+       reg     r1, 6
+       reg     r2, -7
+       reg     r3, -3
+
+       seti    -6, r1
+       seti    -45, r2
+       div     r1, r2, r3
+
+       flags   0
+       reg     r1, -6
+       reg     r2, 7
+       reg     r3, -3
+
+# If the data is divided by zero, OV=1 and the quotient is undefined.
+# According to NEC, the S and Z flags, and the output registers, are
+# unchanged.
+
+       noflags
+       seti    0, r1
+       seti    45, r2
+       seti    67, r3
+       div     r1, r2, r3
+
+       flags   v
+       reg     r2, 45
+       reg     r3, 67
+
+       allflags
+       seti    0, r1
+       seti    45, r2
+       seti    67, r3
+       div     r1, r2, r3
+
+       flags   sat + c + v + s + z
+       reg     r2, 45
+       reg     r3, 67
+
+# Zero / (N!=0) => normal
+
+       noflags
+       seti    45, r1
+       seti    0, r2
+       seti    67, r3
+       div     r1, r2, r3
+
+       flags   z
+       reg     r1, 45
+       reg     r2, 0
+       reg     r3, 0
+
+# Test for regular overflow
+
+       noflags
+       seti    -1, r1
+       seti    0x80000000, r2
+       seti    67, r3
+       div     r1, r2, r3
+
+       flags   v + s
+       reg     r1, -1
+       reg     r2, 0x80000000
+       reg     r3, 0
+
+# The Z flag is based on the quotient, not the remainder
+
+       noflags
+       seti    45, r1
+       seti    16, r2
+       div     r1, r2, r3
+
+       flags   z
+       reg     r2, 0
+       reg     r3, 16
+
+# If the quot and rem registers are the same, the remainder is stored.
+
+       seti    6, r1
+       seti    45, r2
+       div     r1, r2, r2
+
+       flags   0
+       reg     r1, 6
+       reg     r2, 3
+
+
+       pass
diff --git a/sim/testsuite/sim/v850/divh.cgs b/sim/testsuite/sim/v850/divh.cgs
new file mode 100644 (file)
index 0000000..1cef7f9
--- /dev/null
@@ -0,0 +1,96 @@
+# v850 divh
+# mach: all
+
+       .include "testutils.inc"
+
+# Regular division - check signs
+
+       seti    6, r1
+       seti    45, r2
+       divh    r1, r2
+
+       flags   0
+       reg     r1, 6
+       reg     r2, 7
+
+       seti    -6, r1
+       seti    45, r2
+       divh    r1, r2
+
+       flags   s
+       reg     r1, -6
+       reg     r2, -7
+
+       seti    6, r1
+       seti    -45, r2
+       divh    r1, r2
+
+       flags   s
+       reg     r1, 6
+       reg     r2, -7
+
+       seti    -6, r1
+       seti    -45, r2
+       divh    r1, r2
+
+       flags   0
+       reg     r1, -6
+       reg     r2, 7
+
+# Only the lower half of the dividend is used
+
+       seti    0x0000fffa, r1
+       seti    -45, r2
+       divh    r1, r2
+
+       flags   0
+       reg     r1, 0x0000fffa
+       reg     r2, 7
+
+# If the data is divhided by zero, OV=1 and the quotient is undefined.
+# According to NEC, the S and Z flags, and the output registers, are
+# unchanged.
+
+       noflags
+       seti    0, r1
+       seti    45, r2
+       seti    67, r3
+       divh    r1, r2
+
+       flags   v
+       reg     r2, 45
+
+       allflags
+       seti    0, r1
+       seti    45, r2
+       seti    67, r3
+       divh    r1, r2
+
+       flags   sat + c + v + s + z
+       reg     r2, 45
+
+# Zero / (N!=0) => normal
+
+       noflags
+       seti    45, r1
+       seti    0, r2
+       seti    67, r3
+       divh    r1, r2
+
+       flags   z
+       reg     r1, 45
+       reg     r2, 0
+
+# Test for regular overflow
+
+       noflags
+       seti    -1, r1
+       seti    0x80000000, r2
+       divh    r1, r2
+
+       flags   v + s
+       reg     r1, -1
+       reg     r2, 0x80000000
+
+
+       pass
diff --git a/sim/testsuite/sim/v850/divh_3.cgs b/sim/testsuite/sim/v850/divh_3.cgs
new file mode 100644 (file)
index 0000000..77d14af
--- /dev/null
@@ -0,0 +1,130 @@
+# v850 divh_3
+# mach: v850e
+# as(v850e): -mv850e
+
+       .include "testutils.inc"
+
+# Regular divhision - check signs
+# The S flag is based on the quotient, not the remainder
+
+       seti    6, r1
+       seti    45, r2
+       divh    r1, r2, r3
+
+       flags   0
+       reg     r1, 6
+       reg     r2, 7
+       reg     r3, 3
+
+       seti    -6, r1
+       seti    45, r2
+       divh    r1, r2, r3
+
+       flags   s
+       reg     r1, -6
+       reg     r2, -7
+       reg     r3, 3
+
+       seti    6, r1
+       seti    -45, r2
+       divh    r1, r2, r3
+
+       flags   s
+       reg     r1, 6
+       reg     r2, -7
+       reg     r3, -3
+
+       seti    -6, r1
+       seti    -45, r2
+       divh    r1, r2, r3
+
+       flags   0
+       reg     r1, -6
+       reg     r2, 7
+       reg     r3, -3
+
+# Only the lower half of the dividend is used
+
+       seti    0x0000fffa, r1
+       seti    -45, r2
+       divh    r1, r2, r3
+
+       flags   0
+       reg     r1, 0x0000fffa
+       reg     r2, 7
+       reg     r3, -3
+
+
+# If the data is divhided by zero, OV=1 and the quotient is undefined.
+# According to NEC, the S and Z flags, and the output registers, are
+# unchanged.
+
+       noflags
+       seti    0, r1
+       seti    45, r2
+       seti    67, r3
+       divh    r1, r2, r3
+
+       flags   v
+       reg     r2, 45
+       reg     r3, 67
+
+       allflags
+       seti    0, r1
+       seti    45, r2
+       seti    67, r3
+       divh    r1, r2, r3
+
+       flags   sat + c + v + s + z
+       reg     r2, 45
+       reg     r3, 67
+
+# Zero / (N!=0) => normal
+
+       noflags
+       seti    45, r1
+       seti    0, r2
+       seti    67, r3
+       divh    r1, r2, r3
+
+       flags   z
+       reg     r1, 45
+       reg     r2, 0
+       reg     r3, 0
+
+# Test for regular overflow
+
+       noflags
+       seti    -1, r1
+       seti    0x80000000, r2
+       seti    67, r3
+       divh    r1, r2, r3
+
+       flags   v + s
+       reg     r1, -1
+       reg     r2, 0x80000000
+       reg     r3, 0
+
+# The Z flag is based on the quotient, not the remainder
+
+       noflags
+       seti    45, r1
+       seti    16, r2
+       divh    r1, r2, r3
+
+       flags   z
+       reg     r2, 0
+       reg     r3, 16
+
+# If the quot and rem registers are the same, the remainder is stored.
+
+       seti    6, r1
+       seti    45, r2
+       divh    r1, r2, r2
+
+       flags   0
+       reg     r1, 6
+       reg     r2, 3
+
+
+       pass
diff --git a/sim/testsuite/sim/v850/divhu.cgs b/sim/testsuite/sim/v850/divhu.cgs
new file mode 100644 (file)
index 0000000..911e96e
--- /dev/null
@@ -0,0 +1,94 @@
+# v850 divu
+# mach: v850e
+# as(v850e): -mv850e
+
+       .include "testutils.inc"
+
+       seti    6, r1
+       seti    45, r2
+       divu    r1, r2, r3
+
+       flags   0
+       reg     r1, 6
+       reg     r2, 7
+       reg     r3, 3
+
+       seti    4, r1
+       seti    0x40000000, r2
+       divu    r1, r2, r3
+
+       flags   0
+       reg     r1, 4
+       reg     r2, 0x10000000
+       reg     r3, 0
+
+# Only the lower half of the dividend is used
+
+       seti    0x00010006, r1
+       seti    45, r2
+       divhu   r1, r2, r3
+
+       flags   0
+       reg     r1, 0x00010006
+       reg     r2, 7
+       reg     r3, 3
+
+# If the data is divided by zero, OV=1 and the quotient is undefined.
+# According to NEC, the S and Z flags, and the output registers, are
+# unchanged.
+
+       noflags
+       seti    0, r1
+       seti    45, r2
+       seti    67, r3
+       divu    r1, r2, r3
+
+       flags   v
+       reg     r2, 45
+       reg     r3, 67
+
+       allflags
+       seti    0, r1
+       seti    45, r2
+       seti    67, r3
+       divu    r1, r2, r3
+
+       flags   sat + c + v + s + z
+       reg     r2, 45
+       reg     r3, 67
+
+# Zero / (N!=0) => normal
+
+       noflags
+       seti    45, r1
+       seti    0, r2
+       seti    67, r3
+       divu    r1, r2, r3
+
+       flags   z
+       reg     r1, 45
+       reg     r2, 0
+       reg     r3, 0
+
+# The Z flag is based on the quotient, not the remainder
+
+       noflags
+       seti    45, r1
+       seti    16, r2
+       divu    r1, r2, r3
+
+       flags   z
+       reg     r2, 0
+       reg     r3, 16
+
+# If the quot and rem registers are the same, the remainder is stored.
+
+       seti    6, r1
+       seti    45, r2
+       divu    r1, r2, r2
+
+       flags   0
+       reg     r1, 6
+       reg     r2, 3
+
+       pass
diff --git a/sim/testsuite/sim/v850/divu.cgs b/sim/testsuite/sim/v850/divu.cgs
new file mode 100644 (file)
index 0000000..fb44185
--- /dev/null
@@ -0,0 +1,83 @@
+# v850 divu
+# mach: v850e
+# as(v850e): -mv850e
+
+       .include "testutils.inc"
+
+       seti    6, r1
+       seti    45, r2
+       divu    r1, r2, r3
+
+       flags   0
+       reg     r1, 6
+       reg     r2, 7
+       reg     r3, 3
+
+       seti    4, r1
+       seti    0x40000000, r2
+       divu    r1, r2, r3
+
+       flags   0
+       reg     r1, 4
+       reg     r2, 0x10000000
+       reg     r3, 0
+
+# If the data is divided by zero, OV=1 and the quotient is undefined.
+# According to NEC, the S and Z flags, and the output registers, are
+# unchanged.
+
+       noflags
+       seti    0, r1
+       seti    45, r2
+       seti    67, r3
+       divu    r1, r2, r3
+
+       flags   v
+       reg     r2, 45
+       reg     r3, 67
+
+       allflags
+       seti    0, r1
+       seti    45, r2
+       seti    67, r3
+       divu    r1, r2, r3
+
+       flags   sat + c + v + s + z
+       reg     r2, 45
+       reg     r3, 67
+
+# Zero / (N!=0) => normal
+
+       noflags
+       seti    45, r1
+       seti    0, r2
+       seti    67, r3
+       divu    r1, r2, r3
+
+       flags   z
+       reg     r1, 45
+       reg     r2, 0
+       reg     r3, 0
+
+# The Z flag is based on the quotient, not the remainder
+
+       noflags
+       seti    45, r1
+       seti    16, r2
+       divu    r1, r2, r3
+
+       flags   z
+       reg     r2, 0
+       reg     r3, 16
+
+# If the quot and rem registers are the same, the remainder is stored.
+
+       seti    6, r1
+       seti    45, r2
+       divu    r1, r2, r2
+
+       flags   0
+       reg     r1, 6
+       reg     r2, 3
+
+       pass
diff --git a/sim/testsuite/sim/v850/sar.cgs b/sim/testsuite/sim/v850/sar.cgs
new file mode 100644 (file)
index 0000000..4372e6c
--- /dev/null
@@ -0,0 +1,91 @@
+# v850 sar
+# mach: all
+
+       .include "testutils.inc"
+
+# CY is set to 1 if the bit shifted out last is 1, else 0
+# OV is set to zero.
+# Z is set if the result is 0, else 0
+
+       noflags
+       seti    4, r1
+       seti    0x00000000, r2
+       sar     r1, r2
+
+       flags   z
+       reg     r2, 0
+
+       noflags
+       seti    4, r1
+       seti    0x00000001, r2
+       sar     r1, r2
+
+       flags   z
+       reg     r2, 0
+
+       noflags
+       seti    4, r1
+       seti    0x00000008, r2
+       sar     r1, r2
+
+       flags   c + z
+       reg     r2, 0
+
+       noflags
+       seti    0x00000000, r2
+       sar     4, r2
+
+       flags   z
+       reg     r2, 0
+
+       noflags
+       seti    0x00000001, r2
+       sar     4, r2
+
+       flags   z
+       reg     r2, 0
+
+       noflags
+       seti    0x00000008, r2
+       sar     4, r2
+
+       flags   c + z
+       reg     r2, 0
+
+# However, if the number of shifts is 0, CY is 0.
+
+       noflags
+       seti    0, r1
+       seti    0xffffffff, r2
+       sar     r1, r2
+
+       flags   s
+       reg     r2, 0xffffffff
+
+       noflags
+       seti    0xffffffff, r2
+       sar     0, r2
+
+       flags   s
+       reg     r2, 0xffffffff
+
+# Old MSB is copied as new MSB after shift
+# S is 1 if the result is negative, else 0
+
+       noflags
+       seti    1, r1
+       seti    0x80000000, r2
+       sar     r1, r2
+
+       flags   s
+       reg     r2, 0xc0000000
+
+       noflags
+       seti    1, r1
+       seti    0x40000000, r2
+       sar     r1, r2
+
+       flags   0
+       reg     r2, 0x20000000
+
+       pass
diff --git a/sim/testsuite/sim/v850/satadd.cgs b/sim/testsuite/sim/v850/satadd.cgs
new file mode 100644 (file)
index 0000000..60ac654
--- /dev/null
@@ -0,0 +1,79 @@
+# v850 satadd
+# mach: all
+
+       .include "testutils.inc"
+
+# If the result of the add is "negative", that means we went too
+# positive.  The result should be the most positive number.
+
+       noflags
+       seti    0x70000000, r1
+       seti    0x70000000, r2
+       satadd  r1, r2
+
+       flags   sat + nc + v + ns + nz
+       reg     r2, 0x7fffffff
+
+       noflags
+       seti    0x7ffffffe, r1
+       satadd  10, r1
+
+       flags   sat + nc + v + ns + nz
+       reg     r1, 0x7fffffff
+
+# Similarly, if the result of the add is "positive", that means we
+# went too negative.  The result should be the most negative number.
+
+       noflags
+       seti    0x90000000, r1
+       seti    0x90000000, r2
+       satadd  r1, r2
+
+       flags   sat + c + v + s + nz
+       reg     r2, 0x80000000
+
+       noflags
+       seti    0x80000001, r1
+       satadd  -10, r1
+
+       flags   sat + c + v + s + nz
+       reg     r1, 0x80000000
+
+# Check that the SAT flag remains set until reset
+
+       seti    1, r1
+       seti    2, r2
+       satadd  r1,r2
+
+       flags   sat + nc + nv + ns + nz
+       reg     r2, 3
+
+       noflags
+       seti    1, r1
+       seti    2, r2
+       satadd  r1,r2
+
+       flags   nsat + nc + nv + ns + nz
+       reg     r2, 3
+
+# Check that results exactly equal to min/max don't saturate
+
+       noflags
+       seti    0x70000000, r1
+       seti    0x0fffffff, r2
+       satadd  r1,r2
+
+       flags   nsat + nc + nv + ns + nz
+       reg     r2, 0x7fffffff
+
+
+       noflags
+       seti    0x90000000, r1
+       seti    0xf0000000, r2
+       satadd  r1,r2
+
+       flags   nsat + c + nv + s + nz
+       reg     r2, 0x80000000
+
+
+       pass
diff --git a/sim/testsuite/sim/v850/satsub.cgs b/sim/testsuite/sim/v850/satsub.cgs
new file mode 100644 (file)
index 0000000..b7085e7
--- /dev/null
@@ -0,0 +1,65 @@
+# v850 satsub
+# mach: all
+
+       .include "testutils.inc"
+
+# If the result of the add is "negative", that means we went too
+# positive.  The result should be the most positive number.
+
+       noflags
+       seti    0x90000000, r1
+       seti    0x70000000, r2
+       satsub  r1, r2
+
+       flags   sat + c + v + ns + nz
+       reg     r2, 0x7fffffff
+
+# Similarly, if the result of the add is "positive", that means we
+# went too negative.  The result should be the most negative number.
+
+       noflags
+       seti    0x70000000, r1
+       seti    0x90000000, r2
+       satsub  r1, r2
+
+       flags   sat + nc + v + s + nz
+       reg     r2, 0x80000000
+
+# Check that the SAT flag remains set until reset
+
+       seti    1, r1
+       seti    2, r2
+       satsub  r1,r2
+
+       flags   sat + nc + nv + ns + nz
+       reg     r2, 1
+
+       noflags
+       seti    1, r1
+       seti    2, r2
+       satsub  r1,r2
+
+       flags   nsat + nc + nv + ns + nz
+       reg     r2, 1
+
+# Check that results exactly equal to min/max don't saturate
+
+       noflags
+       seti    0x90000000, r1
+       seti    0x0fffffff, r2
+       satsub  r1,r2
+
+       flags   nsat + c + nv + ns + nz
+       reg     r2, 0x7fffffff
+
+
+       noflags
+       seti    0x70000000, r1
+       seti    0xf0000000, r2
+       satsub  r1,r2
+
+       flags   nsat + nc + nv + s + nz
+       reg     r2, 0x80000000
+
+
+       pass
diff --git a/sim/testsuite/sim/v850/satsubi.cgs b/sim/testsuite/sim/v850/satsubi.cgs
new file mode 100644 (file)
index 0000000..b86b26d
--- /dev/null
@@ -0,0 +1,59 @@
+# v850 satsubi
+# mach: all
+
+       .include "testutils.inc"
+
+# If the result of the add is "negative", that means we went too
+# positive.  The result should be the most positive number.
+
+       noflags
+       seti    0x7ffffffe, r1
+       satsubi -10, r1, r2
+
+       flags   sat + c + v + ns + nz
+       reg     r2, 0x7fffffff
+
+# Similarly, if the result of the add is "positive", that means we
+# went too negative.  The result should be the most negative number.
+
+       noflags
+       seti    0x80000001, r1
+       satsubi 10, r1, r2
+
+       flags   sat + nc + v + s + nz
+       reg     r2, 0x80000000
+
+# Check that the SAT flag remains set until reset
+
+       seti    2, r1
+       satsubi 1, r1, r2
+
+       flags   sat + nc + nv + ns + nz
+       reg     r2, 1
+
+       noflags
+       seti    2, r1
+       satsubi 1, r1, r2
+
+       flags   nsat + nc + nv + ns + nz
+       reg     r2, 1
+
+# Check that results exactly equal to min/max don't saturate
+
+       noflags
+       seti    0x7ffffffe, r1
+       satsubi -1, r1, r2
+
+       flags   nsat + c + nv + ns + nz
+       reg     r2, 0x7fffffff
+
+
+       noflags
+       seti    0x80000001, r1
+       satsubi 1, r1, r2
+
+       flags   nsat + nc + nv + s + nz
+       reg     r2, 0x80000000
+
+
+       pass
diff --git a/sim/testsuite/sim/v850/satsubr.cgs b/sim/testsuite/sim/v850/satsubr.cgs
new file mode 100644 (file)
index 0000000..7e91e0c
--- /dev/null
@@ -0,0 +1,65 @@
+# v850 satsub
+# mach: all
+
+       .include "testutils.inc"
+
+# If the result of the add is "negative", that means we went too
+# positive.  The result should be the most positive number.
+
+       noflags
+       seti    0x90000000, r1
+       seti    0x70000000, r2
+       satsubr r2, r1
+
+       flags   sat + c + v + ns + nz
+       reg     r1, 0x7fffffff
+
+# Similarly, if the result of the add is "positive", that means we
+# went too negative.  The result should be the most negative number.
+
+       noflags
+       seti    0x70000000, r1
+       seti    0x90000000, r2
+       satsubr r2, r1
+
+       flags   sat + nc + v + s + nz
+       reg     r1, 0x80000000
+
+# Check that the SAT flag remains set until reset
+
+       seti    1, r1
+       seti    2, r2
+       satsubr r2, r1
+
+       flags   sat + nc + nv + ns + nz
+       reg     r1, 1
+
+       noflags
+       seti    1, r1
+       seti    2, r2
+       satsubr r2, r1
+
+       flags   nsat + nc + nv + ns + nz
+       reg     r1, 1
+
+# Check that results exactly equal to min/max don't saturate
+
+       noflags
+       seti    0x90000000, r1
+       seti    0x0fffffff, r2
+       satsubr r2, r1
+
+       flags   nsat + c + nv + ns + nz
+       reg     r1, 0x7fffffff
+
+
+       noflags
+       seti    0x70000000, r1
+       seti    0xf0000000, r2
+       satsubr r2, r1
+
+       flags   nsat + nc + nv + s + nz
+       reg     r1, 0x80000000
+
+
+       pass
diff --git a/sim/testsuite/sim/v850/shl.cgs b/sim/testsuite/sim/v850/shl.cgs
new file mode 100644 (file)
index 0000000..6ad8213
--- /dev/null
@@ -0,0 +1,75 @@
+# v850 shl
+# mach: all
+
+       .include "testutils.inc"
+
+# CY is set to 1 if the bit shifted out last is 1, else 0
+# OV is set to zero.
+# Z is set if the result is 0, else 0
+
+       noflags
+       seti    1, r1
+       seti    0x00000000, r2
+       shl     r1, r2
+
+       flags   z
+       reg     r2, 0
+
+       noflags
+       seti    1, r1
+       seti    0x80000000, r2
+       shl     r1, r2
+
+       flags   c + z
+       reg     r2, 0
+
+       noflags
+       seti    0x00000000, r2
+       shl     1, r2
+
+       flags   z
+       reg     r2, 0
+
+       noflags
+       seti    0x80000000, r2
+       shl     1, r2
+
+       flags   c + z
+       reg     r2, 0
+
+# However, if the number of shifts is 0, CY is 0.
+
+       noflags
+       seti    0, r1
+       seti    0xffffffff, r2
+       shl     r1, r2
+
+       flags   s
+       reg     r2, 0xffffffff
+
+       noflags
+       seti    0xffffffff, r2
+       shl     0, r2
+
+       flags   s
+       reg     r2, 0xffffffff
+
+# Zero is shifted into the LSB
+# S is 1 if the result is negative, else 0
+
+       noflags
+       seti    1, r1
+       seti    0x4000000f, r2
+       shl     r1, r2
+
+       flags   s
+       reg     r2, 0x8000001e
+
+       noflags
+       seti    0x4000000f, r2
+       shl     1, r2
+
+       flags   s
+       reg     r2, 0x8000001e
+
+       pass
diff --git a/sim/testsuite/sim/v850/shr.cgs b/sim/testsuite/sim/v850/shr.cgs
new file mode 100644 (file)
index 0000000..e4fdc38
--- /dev/null
@@ -0,0 +1,91 @@
+# v850 shr
+# mach: all
+
+       .include "testutils.inc"
+
+# CY is set to 1 if the bit shifted out last is 1, else 0
+# OV is set to zero.
+# Z is set if the result is 0, else 0
+
+       noflags
+       seti    4, r1
+       seti    0x00000000, r2
+       shr     r1, r2
+
+       flags   z
+       reg     r2, 0
+
+       noflags
+       seti    4, r1
+       seti    0x00000001, r2
+       shr     r1, r2
+
+       flags   z
+       reg     r2, 0
+
+       noflags
+       seti    4, r1
+       seti    0x00000008, r2
+       shr     r1, r2
+
+       flags   c + z
+       reg     r2, 0
+
+       noflags
+       seti    0x00000000, r2
+       shr     4, r2
+
+       flags   z
+       reg     r2, 0
+
+       noflags
+       seti    0x00000001, r2
+       shr     4, r2
+
+       flags   z
+       reg     r2, 0
+
+       noflags
+       seti    0x00000008, r2
+       shr     4, r2
+
+       flags   c + z
+       reg     r2, 0
+
+# However, if the number of shifts is 0, CY is 0.
+
+       noflags
+       seti    0, r1
+       seti    0xffffffff, r2
+       shr     r1, r2
+
+       flags   s
+       reg     r2, 0xffffffff
+
+       noflags
+       seti    0xffffffff, r2
+       shr     0, r2
+
+       flags   s
+       reg     r2, 0xffffffff
+
+# Zere is shifted into the MSB
+# S is 1 if the result is negative, else 0
+
+       noflags
+       seti    1, r1
+       seti    0x80000000, r2
+       shr     r1, r2
+
+       flags   0
+       reg     r2, 0x40000000
+
+       noflags
+       seti    1, r1
+       seti    0x40000000, r2
+       shr     r1, r2
+
+       flags   0
+       reg     r2, 0x20000000
+
+       pass
diff --git a/sim/testsuite/sim/v850/testutils.cgs b/sim/testsuite/sim/v850/testutils.cgs
new file mode 100644 (file)
index 0000000..12b5611
--- /dev/null
@@ -0,0 +1,12 @@
+# v850 test framework
+# mach: all
+
+       .include "testutils.inc"
+
+# This just makes sure that a passing test will pass.
+
+       seti    0x12345678, r1
+
+       reg     r1, 0x12345678
+
+       pass
diff --git a/sim/testsuite/sim/v850/testutils.inc b/sim/testsuite/sim/v850/testutils.inc
new file mode 100644 (file)
index 0000000..e496698
--- /dev/null
@@ -0,0 +1,205 @@
+SYS_exit = 1
+SYS_write = 4
+
+       .bss
+       .space 64
+_stack:
+
+       .data
+pass_text:
+       .string "pass\n"
+fail_text:
+       .string "fail\n"
+
+       .text
+       .global _start
+_start:
+       movhi   hi(_stack),     r0,     sp
+       movea   lo(_stack),     sp,     sp
+       jr      start_test
+
+       .macro  seti    val reg
+       movhi   hi(\val),r0,\reg
+       movea   lo(\val),\reg,\reg
+       .endm
+
+_pass_1:
+       mov     SYS_write,r6
+       mov     1,r7
+       seti    pass_text,r8
+       mov     5,r9
+       trap    31
+
+       mov     0, r7
+       jr      _exit
+
+_fail_1:
+       mov     SYS_write,r6
+       mov     1,r7
+       seti    fail_text,r8
+       mov     5,r9
+       trap    31
+
+       mov     1, r7
+       jr      _exit
+
+_exit:
+       mov     SYS_exit, r6
+       mov     0, r8
+       mov     0, r9
+       trap    31
+
+_pass:
+       jr      _pass_1
+
+_fail:
+       jr      _fail_1
+
+       .macro  pass
+       jr      _pass
+       .endm
+       .macro  fail
+       jr      _fail
+       .endm
+
+       # These pass or fail if the given flag is set or not set
+       # Currently, it assumed that the code of any test is going to
+       # be less than 256 bytes.  Else, we'll have to use a
+       # branch-around-jump design instead.
+
+       .macro  pass_c
+       bc      _pass
+       .endm
+       .macro  fail_c
+       bc      _fail
+       .endm
+       .macro  pass_nc
+       bnc     _pass
+       .endm
+       .macro  fail_nc
+       bnc     _fail
+       .endm
+
+       .macro  pass_z
+       bz      _pass
+       .endm
+       .macro  fail_z
+       bz      _fail
+       .endm
+       .macro  pass_nz
+       bnz     _pass
+       .endm
+       .macro  fail_nz
+       bnz     _fail
+       .endm
+
+       .macro  pass_v
+       bv      _pass
+       .endm
+       .macro  fail_v
+       bv      _fail
+       .endm
+       .macro  pass_nv
+       bnv     _pass
+       .endm
+       .macro  fail_nv
+       bnv     _fail
+       .endm
+
+       .macro  pass_s
+       bn      _pass
+       .endm
+       .macro  fail_s
+       bn      _fail
+       .endm
+       .macro  pass_ns
+       bp      _pass
+       .endm
+       .macro  fail_ns
+       bp      _fail
+       .endm
+
+       .macro  pass_sat
+       bsa     _pass
+       .endm
+       .macro  fail_sat
+       bsa     _fail
+       .endm
+       .macro  pass_nsat
+       bsa     1f
+       br      _pass
+1:
+       .endm
+       .macro  fail_nsat
+       bsa     1f
+       br      _fail
+1:
+       .endm
+
+       # These pass/fail if the given register has/hasn't the specified value in it.
+
+       .macro  pass_req        reg val
+       seti    \val,r10
+       cmp     r10,\reg
+       be      _pass
+       .endm
+
+       .macro  pass_rne        reg val
+       seti    \val,r10
+       cmp     r10,\reg
+       bne     _pass
+       .endm
+
+       .macro  fail_req        reg val
+       seti    \val,r10
+       cmp     r10,\reg
+       be      _fail
+       .endm
+
+       .macro  fail_rne        reg val
+       seti    \val,r10
+       cmp     r10,\reg
+       bne     _fail
+       .endm
+
+# convenience version
+       .macro  reg     reg val
+       seti    \val,r10
+       cmp     r10,\reg
+       bne     _fail
+       .endm
+
+z    = 1
+nz   = 0
+s    = 2
+ns   = 0
+v    = 4
+nv   = 0
+c    = 8
+nc   = 0
+sat  = 16
+nsat = 0
+
+# sat c v s z
+
+       .macro  flags   fval
+       stsr    psw, r10
+       movea   +(\fval), r0, r9
+       andi    31, r10, r10
+       cmp     r9, r10
+       bne     _fail
+       .endm
+
+       .macro  noflags
+       stsr    psw, r10
+       andi    ~0x1f, r10, r10
+       ldsr    r10, psw
+       .endm
+
+       .macro  allflags
+       stsr    psw, r10
+       ori     0x1f, r10, r10
+       ldsr    r10, psw
+       .endm
+
+start_test:
index 4214046..536d979 100644 (file)
@@ -1,3 +1,29 @@
+2008-02-05  DJ Delorie  <dj@redhat.com>
+
+       * simops.c (OP_C0): Correct saturation logic.
+       (OP_220): Likewise.
+       (OP_A0): Likewise.
+       (OP_660): Likewise.
+       (OP_80): Likewise.
+
+       * simops.c (OP_2A0): If the shift count is zero, clear the
+       carry.
+       (OP_A007E0): Likewise.
+       (OP_2C0): Likewise.
+       (OP_C007E0): Likewise.
+       (OP_280): Likewise.
+       (OP_8007E0): Likewise.
+
+       * simops.c (OP_2C207E0): Correct PSW flags for special divu
+       conditions.
+       (OP_2C007E0): Likewise, for div.
+       (OP_28207E0): Likewise, for divhu.
+       (OP_28007E0): Likewise, for divh.  Also, sign-extend the correct
+       operand.
+       * v850.igen (divh): Likewise, for 2-op divh.
+       
+       * v850.igen (bsh): Fix carry logic.
+
 2007-02-20  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * Makefile.in (interp.o): Uncomment and update.
index 38ec0a6..5513341 100644 (file)
@@ -864,18 +864,29 @@ OP_C0 ()
        && (op0 & 0x80000000) != (result & 0x80000000));
   sat = ov;
   
+  /* Handle saturated results.  */
+  if (sat && s)
+    {
+      /* An overflow that results in a negative result implies that we
+        became too positive.  */
+      result = 0x7fffffff;
+      s = 0;
+    }
+  else if (sat)
+    {
+      /* Any other overflow must have thus been too negative.  */
+      result = 0x80000000;
+      s = 1;
+      z = 0;
+    }
+
   /* Store the result and condition codes.  */
   State.regs[OP[1]] = result;
   PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
   PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
          | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)
          | (sat ? PSW_SAT : 0));
-  
-  /* Handle saturated results.  */
-  if (sat && s)
-    State.regs[OP[1]] = 0x80000000;
-  else if (sat)
-    State.regs[OP[1]] = 0x7fffffff;
+
   trace_output (OP_REG_REG);
 
   return 2;
@@ -905,18 +916,28 @@ OP_220 ()
        && (op0 & 0x80000000) != (result & 0x80000000));
   sat = ov;
 
+  /* Handle saturated results.  */
+  if (sat && s)
+    {
+      /* An overflow that results in a negative result implies that we
+        became too positive.  */
+      result = 0x7fffffff;
+      s = 0;
+    }
+  else if (sat)
+    {
+      /* Any other overflow must have thus been too negative.  */
+      result = 0x80000000;
+      s = 1;
+      z = 0;
+    }
+
   /* Store the result and condition codes.  */
   State.regs[OP[1]] = result;
   PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
   PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
                | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)
                | (sat ? PSW_SAT : 0));
-
-  /* Handle saturated results.  */
-  if (sat && s)
-    State.regs[OP[1]] = 0x80000000;
-  else if (sat)
-    State.regs[OP[1]] = 0x7fffffff;
   trace_output (OP_IMM_REG);
 
   return 2;
@@ -942,7 +963,23 @@ OP_A0 ()
   ov = ((op1 & 0x80000000) != (op0 & 0x80000000)
        && (op1 & 0x80000000) != (result & 0x80000000));
   sat = ov;
-  
+
+  /* Handle saturated results.  */
+  if (sat && s)
+    {
+      /* An overflow that results in a negative result implies that we
+        became too positive.  */
+      result = 0x7fffffff;
+      s = 0;
+    }
+  else if (sat)
+    {
+      /* Any other overflow must have thus been too negative.  */
+      result = 0x80000000;
+      s = 1;
+      z = 0;
+    }
+
   /* Store the result and condition codes.  */
   State.regs[OP[1]] = result;
   PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
@@ -950,11 +987,6 @@ OP_A0 ()
          | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)
          | (sat ? PSW_SAT : 0));
   
-  /* Handle saturated results.  */
-  if (sat && s)
-    State.regs[OP[1]] = 0x80000000;
-  else if (sat)
-    State.regs[OP[1]] = 0x7fffffff;
   trace_output (OP_REG_REG);
   return 2;
 }
@@ -982,6 +1014,22 @@ OP_660 ()
        && (op1 & 0x80000000) != (result & 0x80000000));
   sat = ov;
 
+  /* Handle saturated results.  */
+  if (sat && s)
+    {
+      /* An overflow that results in a negative result implies that we
+        became too positive.  */
+      result = 0x7fffffff;
+      s = 0;
+    }
+  else if (sat)
+    {
+      /* Any other overflow must have thus been too negative.  */
+      result = 0x80000000;
+      s = 1;
+      z = 0;
+    }
+
   /* Store the result and condition codes.  */
   State.regs[OP[1]] = result;
   PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
@@ -989,11 +1037,6 @@ OP_660 ()
                | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)
                | (sat ? PSW_SAT : 0));
 
-  /* Handle saturated results.  */
-  if (sat && s)
-    State.regs[OP[1]] = 0x80000000;
-  else if (sat)
-    State.regs[OP[1]] = 0x7fffffff;
   trace_output (OP_IMM_REG);
 
   return 4;
@@ -1015,10 +1058,26 @@ OP_80 ()
   /* Compute the condition codes.  */
   z = (result == 0);
   s = (result & 0x80000000);
-  cy = (result < op0);
-  ov = ((op1 & 0x80000000) != (op0 & 0x80000000)
-       && (op1 & 0x80000000) != (result & 0x80000000));
+  cy = (op0 < op1);
+  ov = ((op0 & 0x80000000) != (op1 & 0x80000000)
+       && (op0 & 0x80000000) != (result & 0x80000000));
   sat = ov;
+
+  /* Handle saturated results.  */
+  if (sat && s)
+    {
+      /* An overflow that results in a negative result implies that we
+        became too positive.  */
+      result = 0x7fffffff;
+      s = 0;
+    }
+  else if (sat)
+    {
+      /* Any other overflow must have thus been too negative.  */
+      result = 0x80000000;
+      s = 1;
+      z = 0;
+    }
   
   /* Store the result and condition codes.  */
   State.regs[OP[1]] = result;
@@ -1027,11 +1086,6 @@ OP_80 ()
          | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)
          | (sat ? PSW_SAT : 0));
   
-  /* Handle saturated results.  */
-  if (sat && s)
-    State.regs[OP[1]] = 0x80000000;
-  else if (sat)
-    State.regs[OP[1]] = 0x7fffffff;
   trace_output (OP_REG_REG);
 
   return 2;
@@ -1104,7 +1158,7 @@ OP_2A0 ()
   /* Compute the condition codes.  */
   z = (result == 0);
   s = (result & 0x80000000);
-  cy = (op1 & (1 << (op0 - 1)));
+  cy = op0 ? (op1 & (1 << (op0 - 1))) : 0;
 
   /* Store the result and condition codes.  */
   State.regs[ OP[1] ] = result;
@@ -1131,7 +1185,7 @@ OP_A007E0 ()
   /* Compute the condition codes.  */
   z = (result == 0);
   s = (result & 0x80000000);
-  cy = (op1 & (1 << (op0 - 1)));
+  cy = op0 ? (op1 & (1 << (op0 - 1))) : 0;
 
   /* Store the result and condition codes.  */
   State.regs[OP[1]] = result;
@@ -1157,7 +1211,7 @@ OP_2C0 ()
   /* Compute the condition codes.  */
   z = (result == 0);
   s = (result & 0x80000000);
-  cy = (op1 & (1 << (32 - op0)));
+  cy = op0 ? (op1 & (1 << (32 - op0))) : 0;
 
   /* Store the result and condition codes.  */
   State.regs[OP[1]] = result;
@@ -1183,7 +1237,7 @@ OP_C007E0 ()
   /* Compute the condition codes.  */
   z = (result == 0);
   s = (result & 0x80000000);
-  cy = (op1 & (1 << (32 - op0)));
+  cy = op0 ? (op1 & (1 << (32 - op0))) : 0;
 
   /* Store the result and condition codes.  */
   State.regs[OP[1]] = result;
@@ -1209,7 +1263,7 @@ OP_280 ()
   /* Compute the condition codes.  */
   z = (result == 0);
   s = (result & 0x80000000);
-  cy = (op1 & (1 << (op0 - 1)));
+  cy = op0 ? (op1 & (1 << (op0 - 1))) : 0;
 
   /* Store the result and condition codes.  */
   State.regs[OP[1]] = result;
@@ -1235,7 +1289,7 @@ OP_8007E0 ()
   /* Compute the condition codes.  */
   z = (result == 0);
   s = (result & 0x80000000);
-  cy = (op1 & (1 << (op0 - 1)));
+  cy = op0 ? (op1 & (1 << (op0 - 1))) : 0;
 
   /* Store the result and condition codes.  */
   State.regs[OP[1]] = result;
@@ -2264,19 +2318,20 @@ OP_2C207E0 (void)
   
   if (divide_by == 0)
     {
-      overflow = 1;
-      divide_by  = 1;
+      PSW |= PSW_OV;
     }
+  else
+    {
+      State.regs[ OP[1]       ] = quotient  = divide_this / divide_by;
+      State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
   
-  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);
   
-  /* 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;
+      if (overflow)      PSW |= PSW_OV;
+      if (quotient == 0) PSW |= PSW_Z;
+      if (quotient & 0x80000000) PSW |= PSW_S;
+    }
   
   trace_output (OP_REG_REG_REG);
 
@@ -2291,7 +2346,6 @@ OP_2C007E0 (void)
   signed long int remainder;
   signed long int divide_by;
   signed long int divide_this;
-  int         overflow = 0;
   
   trace_input ("div", OP_REG_REG_REG, 0);
   
@@ -2300,21 +2354,28 @@ OP_2C007E0 (void)
   divide_by   = State.regs[ OP[0] ];
   divide_this = State.regs[ OP[1] ];
   
-  if (divide_by == 0 || (divide_by == -1 && divide_this == (1 << 31)))
+  if (divide_by == 0)
     {
-      overflow  = 1;
-      divide_by = 1;
+      PSW |= PSW_OV;
     }
+  else if (divide_by == -1 && divide_this == (1 << 31))
+    {
+      PSW &= ~PSW_Z;
+      PSW |= PSW_OV | PSW_S;
+      State.regs[ OP[1] ] = (1 << 31);
+      State.regs[ OP[2] >> 11 ] = 0;
+    }
+  else
+    {
+      State.regs[ OP[1]       ] = quotient  = divide_this / divide_by;
+      State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
   
-  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);
+      /* Set condition codes.  */
+      PSW &= ~(PSW_Z | PSW_S | PSW_OV);
   
-  if (overflow)      PSW |= PSW_OV;
-  if (quotient == 0) PSW |= PSW_Z;
-  if (quotient <  0) PSW |= PSW_S;
+      if (quotient == 0) PSW |= PSW_Z;
+      if (quotient <  0) PSW |= PSW_S;
+    }
   
   trace_output (OP_REG_REG_REG);
 
@@ -2340,19 +2401,20 @@ OP_28207E0 (void)
   
   if (divide_by == 0)
     {
-      overflow = 1;
-      divide_by  = 1;
+      PSW |= PSW_OV;
     }
+  else
+    {
+      State.regs[ OP[1]       ] = quotient  = divide_this / divide_by;
+      State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
   
-  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);
+      /* 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;
+      if (overflow)      PSW |= PSW_OV;
+      if (quotient == 0) PSW |= PSW_Z;
+      if (quotient & 0x80000000) PSW |= PSW_S;
+    }
   
   trace_output (OP_REG_REG_REG);
 
@@ -2373,24 +2435,31 @@ OP_28007E0 (void)
   
   /* Compute the result.  */
   
-  divide_by  = State.regs[ OP[0] ];
-  divide_this = EXTEND16 (State.regs[ OP[1] ]);
+  divide_by  = EXTEND16 (State.regs[ OP[0] ]);
+  divide_this = State.regs[ OP[1] ];
   
-  if (divide_by == 0 || (divide_by == -1 && divide_this == (1 << 31)))
+  if (divide_by == 0)
+    {
+      PSW |= PSW_OV;
+    }
+  else if (divide_by == -1 && divide_this == (1 << 31))
     {
-      overflow = 1;
-      divide_by  = 1;
+      PSW &= ~PSW_Z;
+      PSW |= PSW_OV | PSW_S;
+      State.regs[ OP[1] ] = (1 << 31);
+      State.regs[ OP[2] >> 11 ] = 0;
     }
+  else
+    {
+      State.regs[ OP[1]       ] = quotient  = divide_this / divide_by;
+      State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
   
-  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);
   
-  /* Set condition codes.  */
-  PSW &= ~(PSW_Z | PSW_S | PSW_OV);
-  
-  if (overflow)      PSW |= PSW_OV;
-  if (quotient == 0) PSW |= PSW_Z;
-  if (quotient <  0) PSW |= PSW_S;
+      if (quotient == 0) PSW |= PSW_Z;
+      if (quotient <  0) PSW |= PSW_S;
+    }
   
   trace_output (OP_REG_REG_REG);
 
index 4796ea5..6617bd8 100644 (file)
@@ -171,9 +171,9 @@ rrrrr,11111100000 + wwwww,01101000010:XII:::bsh
 
   GR[reg3] = value;
   PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
-  if (value == 0) PSW |= PSW_Z;
+  if ((value & 0xffff) == 0) PSW |= PSW_Z;
   if (value & 0x80000000) PSW |= PSW_S;
-  if (((value & 0xff) == 0) || (value & 0x00ff) == 0) PSW |= PSW_CY;
+  if (((value & 0xff) == 0) || ((value & 0xff00) == 0)) PSW |= PSW_CY;
 
   TRACE_ALU_RESULT (GR[reg3]);
 }
@@ -358,28 +358,28 @@ rrrrr!0,000010,RRRRR!0:I:::divh
   
   if (op0 == 0xffffffff && op1 == 0x80000000)
     {
-      result = 0x80000000;
-      ov = 1;
+      PSW &= ~PSW_Z;
+      PSW |= PSW_OV | PSW_S;
+      State.regs[OP[1]] = 0x80000000;
     }
-  else if (op0 != 0)
+  else if (op0 == 0)
     {
-      result = op1 / op0;
-      ov = 0;
+      PSW |= PSW_OV;
     }
   else
     {
-      result = 0x0;
-      ov = 1;
-    }
-  
-  /* Compute the condition codes.  */
-  z = (result == 0);
-  s = (result & 0x80000000);
+      result = op1 / op0;
+      ov = 0;
+
+      /* Compute the condition codes.  */
+      z = (result == 0);
+      s = (result & 0x80000000);
   
-  /* Store the result and condition codes.  */
-  State.regs[OP[1]] = result;
-  PSW &= ~(PSW_Z | PSW_S | PSW_OV);
-  PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (ov ? PSW_OV : 0));
+      /* Store the result and condition codes.  */
+      State.regs[OP[1]] = result;
+      PSW &= ~(PSW_Z | PSW_S | PSW_OV);
+      PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) | (ov ? PSW_OV : 0));
+    }
 
   trace_output (OP_REG_REG);