diff --git a/sim/ChangeLog b/sim/ChangeLog index 4317f7e2e8e..0a3741ab141 100644 --- a/sim/ChangeLog +++ b/sim/ChangeLog @@ -1,3 +1,8 @@ +2008-02-05 DJ Delorie + + * configure.ac (v850): V850 now has a testsuite. + * configure (v850): Likewise. + 2008-01-01 Daniel Jacobowitz Updated copyright notices for most files. diff --git a/sim/configure b/sim/configure index c4cd59cf577..ac45dab2796 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 d7e822c1205..48f590fc1e0 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 91c54842834..337aeeb3ff5 100644 --- a/sim/testsuite/ChangeLog +++ b/sim/testsuite/ChangeLog @@ -1,3 +1,23 @@ +2008-02-05 DJ Delorie + + * 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 * 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 00000000000..f60c3d66aa4 --- /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 00000000000..e9d216e149d --- /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 00000000000..16683f19d31 --- /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 00000000000..1cef7f9a1f5 --- /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 00000000000..77d14af0f91 --- /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 00000000000..911e96ec3cd --- /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 00000000000..fb441858d2b --- /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 00000000000..4372e6c1adb --- /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 00000000000..60ac654cf23 --- /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 00000000000..b7085e72c3a --- /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 00000000000..b86b26d23cd --- /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 00000000000..7e91e0c8e33 --- /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 00000000000..6ad82138c1d --- /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 00000000000..e4fdc38bdae --- /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 00000000000..12b5611d89a --- /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 00000000000..e4966984aa5 --- /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 4214046f917..536d97929cb 100644 --- a/sim/v850/ChangeLog +++ b/sim/v850/ChangeLog @@ -1,3 +1,29 @@ +2008-02-05 DJ Delorie + + * 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 * Makefile.in (interp.o): Uncomment and update. diff --git a/sim/v850/simops.c b/sim/v850/simops.c index 38ec0a6af03..551334175c7 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) { - 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); diff --git a/sim/v850/v850.igen b/sim/v850/v850.igen index 4796ea5e4e3..6617bd85659 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; + 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)); } - - /* 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)); trace_output (OP_REG_REG);