aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sim/ChangeLog5
-rwxr-xr-xsim/configure1
-rw-r--r--sim/configure.ac1
-rw-r--r--sim/testsuite/ChangeLog20
-rw-r--r--sim/testsuite/sim/v850/allinsns.exp39
-rw-r--r--sim/testsuite/sim/v850/bsh.cgs55
-rw-r--r--sim/testsuite/sim/v850/div.cgs118
-rw-r--r--sim/testsuite/sim/v850/divh.cgs96
-rw-r--r--sim/testsuite/sim/v850/divh_3.cgs130
-rw-r--r--sim/testsuite/sim/v850/divhu.cgs94
-rw-r--r--sim/testsuite/sim/v850/divu.cgs83
-rw-r--r--sim/testsuite/sim/v850/sar.cgs91
-rw-r--r--sim/testsuite/sim/v850/satadd.cgs79
-rw-r--r--sim/testsuite/sim/v850/satsub.cgs65
-rw-r--r--sim/testsuite/sim/v850/satsubi.cgs59
-rw-r--r--sim/testsuite/sim/v850/satsubr.cgs65
-rw-r--r--sim/testsuite/sim/v850/shl.cgs75
-rw-r--r--sim/testsuite/sim/v850/shr.cgs91
-rw-r--r--sim/testsuite/sim/v850/testutils.cgs12
-rw-r--r--sim/testsuite/sim/v850/testutils.inc205
-rw-r--r--sim/v850/ChangeLog26
-rw-r--r--sim/v850/simops.c233
-rw-r--r--sim/v850/v850.igen36
23 files changed, 1579 insertions, 100 deletions
diff --git a/sim/ChangeLog b/sim/ChangeLog
index 4317f7e..0a3741a 100644
--- a/sim/ChangeLog
+++ b/sim/ChangeLog
@@ -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.
diff --git a/sim/configure b/sim/configure
index c4cd59c..ac45dab 100755
--- a/sim/configure
+++ b/sim/configure
@@ -3532,6 +3532,7 @@ subdirs="$subdirs ppc"
subdirs="$subdirs v850"
igen=yes
+ testsuite=yes
;;
*)
# No simulator subdir, so the subdir "common" isn't needed.
diff --git a/sim/configure.ac b/sim/configure.ac
index d7e822c1..48f590f 100644
--- a/sim/configure.ac
+++ b/sim/configure.ac
@@ -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.
diff --git a/sim/testsuite/ChangeLog b/sim/testsuite/ChangeLog
index 91c5484..337aeeb 100644
--- a/sim/testsuite/ChangeLog
+++ b/sim/testsuite/ChangeLog
@@ -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
index 0000000..f60c3d6
--- /dev/null
+++ b/sim/testsuite/sim/v850/allinsns.exp
@@ -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
index 0000000..e9d216e
--- /dev/null
+++ b/sim/testsuite/sim/v850/bsh.cgs
@@ -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
index 0000000..16683f1
--- /dev/null
+++ b/sim/testsuite/sim/v850/div.cgs
@@ -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
index 0000000..1cef7f9
--- /dev/null
+++ b/sim/testsuite/sim/v850/divh.cgs
@@ -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
index 0000000..77d14af
--- /dev/null
+++ b/sim/testsuite/sim/v850/divh_3.cgs
@@ -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
index 0000000..911e96e
--- /dev/null
+++ b/sim/testsuite/sim/v850/divhu.cgs
@@ -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
index 0000000..fb44185
--- /dev/null
+++ b/sim/testsuite/sim/v850/divu.cgs
@@ -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
index 0000000..4372e6c
--- /dev/null
+++ b/sim/testsuite/sim/v850/sar.cgs
@@ -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
index 0000000..60ac654
--- /dev/null
+++ b/sim/testsuite/sim/v850/satadd.cgs
@@ -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
index 0000000..b7085e7
--- /dev/null
+++ b/sim/testsuite/sim/v850/satsub.cgs
@@ -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
index 0000000..b86b26d
--- /dev/null
+++ b/sim/testsuite/sim/v850/satsubi.cgs
@@ -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
index 0000000..7e91e0c
--- /dev/null
+++ b/sim/testsuite/sim/v850/satsubr.cgs
@@ -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
index 0000000..6ad8213
--- /dev/null
+++ b/sim/testsuite/sim/v850/shl.cgs
@@ -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
index 0000000..e4fdc38
--- /dev/null
+++ b/sim/testsuite/sim/v850/shr.cgs
@@ -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
index 0000000..12b5611
--- /dev/null
+++ b/sim/testsuite/sim/v850/testutils.cgs
@@ -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
index 0000000..e496698
--- /dev/null
+++ b/sim/testsuite/sim/v850/testutils.inc
@@ -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:
diff --git a/sim/v850/ChangeLog b/sim/v850/ChangeLog
index 4214046..536d979 100644
--- a/sim/v850/ChangeLog
+++ b/sim/v850/ChangeLog
@@ -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.
diff --git a/sim/v850/simops.c b/sim/v850/simops.c
index 38ec0a6..5513341 100644
--- a/sim/v850/simops.c
+++ b/sim/v850/simops.c
@@ -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);
diff --git a/sim/v850/v850.igen b/sim/v850/v850.igen
index 4796ea5..6617bd8 100644
--- a/sim/v850/v850.igen
+++ b/sim/v850/v850.igen
@@ -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);