Add test cases for out-of-range argument handling for x87 instructions
FSIN, FCOS, FSINCOS and FPTAN.  Mozilla bug 995564.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13921 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/none/tests/amd64/Makefile.am b/none/tests/amd64/Makefile.am
index 99a8d33..d7ec56a 100644
--- a/none/tests/amd64/Makefile.am
+++ b/none/tests/amd64/Makefile.am
@@ -80,6 +80,7 @@
 	slahf-amd64.stderr.exp slahf-amd64.stdout.exp \
 	slahf-amd64.vgtest \
 	tm1.vgtest tm1.stderr.exp tm1.stdout.exp \
+	x87trigOOR.vgtest x87trigOOR.stderr.exp x87trigOOR.stdout.exp \
 	xacq_xrel.stderr.exp xacq_xrel.stdout.exp xacq_xrel.vgtest \
 	xadd.stderr.exp xadd.stdout.exp xadd.vgtest
 
@@ -96,6 +97,7 @@
 	smc1 \
 	sbbmisc \
 	nibz_bennee_mmap \
+	x87trigOOR \
 	xadd
 if BUILD_ADDR32_TESTS
  check_PROGRAMS += asorep
diff --git a/none/tests/amd64/x87trigOOR.c b/none/tests/amd64/x87trigOOR.c
new file mode 120000
index 0000000..64f32e6
--- /dev/null
+++ b/none/tests/amd64/x87trigOOR.c
@@ -0,0 +1 @@
+../x86/x87trigOOR.c
\ No newline at end of file
diff --git a/none/tests/amd64/x87trigOOR.stderr.exp b/none/tests/amd64/x87trigOOR.stderr.exp
new file mode 100644
index 0000000..139597f
--- /dev/null
+++ b/none/tests/amd64/x87trigOOR.stderr.exp
@@ -0,0 +1,2 @@
+
+
diff --git a/none/tests/amd64/x87trigOOR.stdout.exp b/none/tests/amd64/x87trigOOR.stdout.exp
new file mode 100644
index 0000000..46e889b
--- /dev/null
+++ b/none/tests/amd64/x87trigOOR.stdout.exp
@@ -0,0 +1,72 @@
+fsin         0.000000e+00 -->     0.000000e+00     3.141593e+00 0000
+fsin         1.230000e-01 -->     1.226901e-01     3.141593e+00 0000
+fsin        -4.560000e-01 -->    -4.403604e-01     3.141593e+00 0000
+fsin         3.700000e+01 -->    -6.435381e-01     3.141593e+00 0000
+fsin        -5.300000e+01 -->    -3.959252e-01     3.141593e+00 0000
+
+fsin         8.301035e+18 -->    -1.249775e-01     3.141593e+00 0000
+fsin         9.223363e+18 -->     2.344065e-01     3.141593e+00 0000
+fsin         9.223372e+18 -->     9.223372e+18     3.141593e+00 0400
+fsin         9.223381e+18 -->     9.223381e+18     3.141593e+00 0400
+fsin         1.014571e+19 -->     1.014571e+19     3.141593e+00 0400
+
+fsin        -8.301035e+18 -->     1.249775e-01     3.141593e+00 0000
+fsin        -9.223363e+18 -->    -2.344065e-01     3.141593e+00 0000
+fsin        -9.223372e+18 -->    -9.223372e+18     3.141593e+00 0400
+fsin        -9.223381e+18 -->    -9.223381e+18     3.141593e+00 0400
+fsin        -1.014571e+19 -->    -1.014571e+19     3.141593e+00 0400
+
+fcos         0.000000e+00 -->     1.000000e+00     3.141593e+00 0000
+fcos         1.230000e-01 -->     9.924450e-01     3.141593e+00 0000
+fcos        -4.560000e-01 -->     8.978211e-01     3.141593e+00 0000
+fcos         3.700000e+01 -->     7.654141e-01     3.141593e+00 0000
+fcos        -5.300000e+01 -->    -9.182828e-01     3.141593e+00 0000
+
+fcos         8.301035e+18 -->    -9.921596e-01     3.141593e+00 0000
+fcos         9.223363e+18 -->     9.721387e-01     3.141593e+00 0000
+fcos         9.223372e+18 -->     9.223372e+18     3.141593e+00 0400
+fcos         9.223381e+18 -->     9.223381e+18     3.141593e+00 0400
+fcos         1.014571e+19 -->     1.014571e+19     3.141593e+00 0400
+
+fcos        -8.301035e+18 -->    -9.921596e-01     3.141593e+00 0000
+fcos        -9.223363e+18 -->     9.721387e-01     3.141593e+00 0000
+fcos        -9.223372e+18 -->    -9.223372e+18     3.141593e+00 0400
+fcos        -9.223381e+18 -->    -9.223381e+18     3.141593e+00 0400
+fcos        -1.014571e+19 -->    -1.014571e+19     3.141593e+00 0400
+
+fsincos      0.000000e+00 -->     1.000000e+00     0.000000e+00 0000
+fsincos      1.230000e-01 -->     9.924450e-01     1.226901e-01 0000
+fsincos     -4.560000e-01 -->     8.978211e-01    -4.403604e-01 0000
+fsincos      3.700000e+01 -->     7.654141e-01    -6.435381e-01 0000
+fsincos     -5.300000e+01 -->    -9.182828e-01    -3.959252e-01 0000
+
+fsincos      8.301035e+18 -->    -9.921596e-01    -1.249775e-01 0000
+fsincos      9.223363e+18 -->     9.721387e-01     2.344065e-01 0000
+fsincos      9.223372e+18 -->     9.223372e+18     3.141593e+00 0400
+fsincos      9.223381e+18 -->     9.223381e+18     3.141593e+00 0400
+fsincos      1.014571e+19 -->     1.014571e+19     3.141593e+00 0400
+
+fsincos     -8.301035e+18 -->    -9.921596e-01     1.249775e-01 0000
+fsincos     -9.223363e+18 -->     9.721387e-01    -2.344065e-01 0000
+fsincos     -9.223372e+18 -->    -9.223372e+18     3.141593e+00 0400
+fsincos     -9.223381e+18 -->    -9.223381e+18     3.141593e+00 0400
+fsincos     -1.014571e+19 -->    -1.014571e+19     3.141593e+00 0400
+
+fptan        0.000000e+00 -->     1.000000e+00     0.000000e+00 0000
+fptan        1.230000e-01 -->     1.000000e+00     1.236241e-01 0000
+fptan       -4.560000e-01 -->     1.000000e+00    -4.904767e-01 0000
+fptan        3.700000e+01 -->     1.000000e+00    -8.407713e-01 0000
+fptan       -5.300000e+01 -->     1.000000e+00     4.311582e-01 0000
+
+fptan        8.301035e+18 -->     1.000000e+00     1.259651e-01 0000
+fptan        9.223363e+18 -->     1.000000e+00     2.411246e-01 0000
+fptan        9.223372e+18 -->     9.223372e+18     3.141593e+00 0400
+fptan        9.223381e+18 -->     9.223381e+18     3.141593e+00 0400
+fptan        1.014571e+19 -->     1.014571e+19     3.141593e+00 0400
+
+fptan       -8.301035e+18 -->     1.000000e+00    -1.259651e-01 0000
+fptan       -9.223363e+18 -->     1.000000e+00    -2.411246e-01 0000
+fptan       -9.223372e+18 -->    -9.223372e+18     3.141593e+00 0400
+fptan       -9.223381e+18 -->    -9.223381e+18     3.141593e+00 0400
+fptan       -1.014571e+19 -->    -1.014571e+19     3.141593e+00 0400
+
diff --git a/none/tests/amd64/x87trigOOR.vgtest b/none/tests/amd64/x87trigOOR.vgtest
new file mode 100644
index 0000000..1ff5fd7
--- /dev/null
+++ b/none/tests/amd64/x87trigOOR.vgtest
@@ -0,0 +1 @@
+prog: x87trigOOR
diff --git a/none/tests/x86/Makefile.am b/none/tests/x86/Makefile.am
index 0ed86e5..bab84b6 100644
--- a/none/tests/x86/Makefile.am
+++ b/none/tests/x86/Makefile.am
@@ -61,6 +61,7 @@
 	ssse3_misaligned.stderr.exp ssse3_misaligned.stdout.exp \
 	ssse3_misaligned.vgtest ssse3_misaligned.c \
 	x86locked.vgtest x86locked.stdout.exp x86locked.stderr.exp \
+	x87trigOOR.vgtest x87trigOOR.stdout.exp x87trigOOR.stderr.exp \
 	yield.stderr.exp yield.stdout.exp yield.disabled \
 	xadd.stdout.exp xadd.stderr.exp xadd.vgtest
 
@@ -94,6 +95,7 @@
 	shift_ndep \
 	smc1 \
 	x86locked \
+	x87trigOOR \
 	yield \
 	xadd
 if BUILD_SSSE3_TESTS
diff --git a/none/tests/x86/x87trigOOR.c b/none/tests/x86/x87trigOOR.c
new file mode 100644
index 0000000..0485559
--- /dev/null
+++ b/none/tests/x86/x87trigOOR.c
@@ -0,0 +1,159 @@
+
+/* Tests out of range handling for FSIN, FCOS, FSINCOS and FPTAN.  Be
+   careful with the inline assembly -- this program is compiled as
+   both a 32-bit and 64-bit test. */
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+typedef  unsigned short int      UShort;
+typedef  unsigned int            UInt;
+typedef  double                  Double;
+typedef  unsigned long long int  ULong;
+
+typedef  struct { Double arg; Double st0; Double st1; UShort fpusw; }  Res;
+
+#define SHIFT_C3   14
+#define SHIFT_C2   10
+#define SHIFT_C1   9
+#define SHIFT_C0   8
+
+
+#define my_offsetof(type,memb) ((int)(unsigned long int)&((type*)0)->memb)
+
+void do_fsin ( /*OUT*/Res* r, double d )
+{
+   assert(my_offsetof(Res,arg) == 0);
+   assert(my_offsetof(Res,st0) == 8);
+   assert(my_offsetof(Res,st1) == 16);
+   assert(my_offsetof(Res,fpusw) == 24);
+   memset(r, 0, sizeof(*r));
+   r->arg = d;
+   __asm__ __volatile__(
+     "finit"              "\n\t"
+     "fldpi"              "\n\t"
+     "fldl 0(%0)"         "\n\t" // .arg
+     "fsin"               "\n\t"
+     "fstsw %%ax"         "\n\t"
+     "fstpl 8(%0)"        "\n\t" // .st0
+     "fstpl 16(%0)"       "\n\t" // .st1
+     "movw %%ax, 24(%0)"  "\n\t" // .fpusw
+     "finit"              "\n"
+     : : "r"(r) : "eax","cc","memory"
+   );
+}
+
+void do_fcos ( /*OUT*/Res* r, double d )
+{
+   assert(my_offsetof(Res,arg) == 0);
+   assert(my_offsetof(Res,st0) == 8);
+   assert(my_offsetof(Res,st1) == 16);
+   assert(my_offsetof(Res,fpusw) == 24);
+   memset(r, 0, sizeof(*r));
+   r->arg = d;
+   __asm__ __volatile__(
+     "finit"              "\n\t"
+     "fldpi"              "\n\t"
+     "fldl 0(%0)"         "\n\t" // .arg
+     "fcos"               "\n\t"
+     "fstsw %%ax"         "\n\t"
+     "fstpl 8(%0)"        "\n\t" // .st0
+     "fstpl 16(%0)"       "\n\t" // .st1
+     "movw %%ax, 24(%0)"  "\n\t" // .fpusw
+     "finit"              "\n"
+     : : "r"(r) : "eax","cc","memory"
+   );
+}
+
+void do_fsincos ( /*OUT*/Res* r, double d )
+{
+   assert(my_offsetof(Res,arg) == 0);
+   assert(my_offsetof(Res,st0) == 8);
+   assert(my_offsetof(Res,st1) == 16);
+   assert(my_offsetof(Res,fpusw) == 24);
+   memset(r, 0, sizeof(*r));
+   r->arg = d;
+   __asm__ __volatile__(
+     "finit"              "\n\t"
+     "fldpi"              "\n\t"
+     "fldl 0(%0)"         "\n\t" // .arg
+     "fsincos"            "\n\t"
+     "fstsw %%ax"         "\n\t"
+     "fstpl 8(%0)"        "\n\t" // .st0
+     "fstpl 16(%0)"       "\n\t" // .st1
+     "movw %%ax, 24(%0)"  "\n\t" // .fpusw
+     "finit"              "\n"
+     : : "r"(r) : "eax","cc","memory"
+   );
+}
+
+void do_fptan ( /*OUT*/Res* r, double d )
+{
+   assert(my_offsetof(Res,arg) == 0);
+   assert(my_offsetof(Res,st0) == 8);
+   assert(my_offsetof(Res,st1) == 16);
+   assert(my_offsetof(Res,fpusw) == 24);
+   memset(r, 0, sizeof(*r));
+   r->arg = d;
+   __asm__ __volatile__(
+     "finit"              "\n\t"
+     "fldpi"              "\n\t"
+     "fldl 0(%0)"         "\n\t" // .arg
+     "fptan"              "\n\t"
+     "fstsw %%ax"         "\n\t"
+     "fstpl 8(%0)"        "\n\t" // .st0
+     "fstpl 16(%0)"       "\n\t" // .st1
+     "movw %%ax, 24(%0)"  "\n\t" // .fpusw
+     "finit"              "\n"
+     : : "r"(r) : "eax","cc","memory"
+   );
+}
+
+
+void try ( char* name, void(*fn)(Res*,double), double d )
+{
+   Res r;
+   fn(&r, d);
+   // Mask out all except C2 (range)
+   r.fpusw &= (1 << SHIFT_C2);
+   printf("%s  %16e --> %16e %16e %04x\n",
+          name, r.arg, r.st0, r.st1, (UInt)r.fpusw);
+}
+
+int main ( void )
+{
+   Double limit = 9223372036854775808.0; // 2^63
+
+   char* names[4] = { "fsin   ", "fcos   ", "fsincos", "fptan  " };
+   void(*fns[4])(Res*,double) = { do_fsin, do_fcos, do_fsincos, do_fptan };
+
+   int i;
+   for (i = 0; i < 4; i++) {
+      char* name = names[i];
+      void (*fn)(Res*,double) = fns[i];
+
+      try( name, fn,   0.0   );
+      try( name, fn,   0.123 );
+      try( name, fn,  -0.456 );
+      try( name, fn,  37.0   );
+      try( name, fn, -53.0   );
+      printf("\n");
+
+      try( name, fn, limit * 0.900000 );
+      try( name, fn, limit * 0.999999 );
+      try( name, fn, limit * 1.000000 );
+      try( name, fn, limit * 1.000001 );
+      try( name, fn, limit * 1.100000 );
+      printf("\n");
+
+      try( name, fn, -limit * 0.900000 );
+      try( name, fn, -limit * 0.999999 );
+      try( name, fn, -limit * 1.000000 );
+      try( name, fn, -limit * 1.000001 );
+      try( name, fn, -limit * 1.100000 );
+      printf("\n");
+   }
+
+   return 0;
+}
diff --git a/none/tests/x86/x87trigOOR.stderr.exp b/none/tests/x86/x87trigOOR.stderr.exp
new file mode 100644
index 0000000..139597f
--- /dev/null
+++ b/none/tests/x86/x87trigOOR.stderr.exp
@@ -0,0 +1,2 @@
+
+
diff --git a/none/tests/x86/x87trigOOR.stdout.exp b/none/tests/x86/x87trigOOR.stdout.exp
new file mode 100644
index 0000000..46e889b
--- /dev/null
+++ b/none/tests/x86/x87trigOOR.stdout.exp
@@ -0,0 +1,72 @@
+fsin         0.000000e+00 -->     0.000000e+00     3.141593e+00 0000
+fsin         1.230000e-01 -->     1.226901e-01     3.141593e+00 0000
+fsin        -4.560000e-01 -->    -4.403604e-01     3.141593e+00 0000
+fsin         3.700000e+01 -->    -6.435381e-01     3.141593e+00 0000
+fsin        -5.300000e+01 -->    -3.959252e-01     3.141593e+00 0000
+
+fsin         8.301035e+18 -->    -1.249775e-01     3.141593e+00 0000
+fsin         9.223363e+18 -->     2.344065e-01     3.141593e+00 0000
+fsin         9.223372e+18 -->     9.223372e+18     3.141593e+00 0400
+fsin         9.223381e+18 -->     9.223381e+18     3.141593e+00 0400
+fsin         1.014571e+19 -->     1.014571e+19     3.141593e+00 0400
+
+fsin        -8.301035e+18 -->     1.249775e-01     3.141593e+00 0000
+fsin        -9.223363e+18 -->    -2.344065e-01     3.141593e+00 0000
+fsin        -9.223372e+18 -->    -9.223372e+18     3.141593e+00 0400
+fsin        -9.223381e+18 -->    -9.223381e+18     3.141593e+00 0400
+fsin        -1.014571e+19 -->    -1.014571e+19     3.141593e+00 0400
+
+fcos         0.000000e+00 -->     1.000000e+00     3.141593e+00 0000
+fcos         1.230000e-01 -->     9.924450e-01     3.141593e+00 0000
+fcos        -4.560000e-01 -->     8.978211e-01     3.141593e+00 0000
+fcos         3.700000e+01 -->     7.654141e-01     3.141593e+00 0000
+fcos        -5.300000e+01 -->    -9.182828e-01     3.141593e+00 0000
+
+fcos         8.301035e+18 -->    -9.921596e-01     3.141593e+00 0000
+fcos         9.223363e+18 -->     9.721387e-01     3.141593e+00 0000
+fcos         9.223372e+18 -->     9.223372e+18     3.141593e+00 0400
+fcos         9.223381e+18 -->     9.223381e+18     3.141593e+00 0400
+fcos         1.014571e+19 -->     1.014571e+19     3.141593e+00 0400
+
+fcos        -8.301035e+18 -->    -9.921596e-01     3.141593e+00 0000
+fcos        -9.223363e+18 -->     9.721387e-01     3.141593e+00 0000
+fcos        -9.223372e+18 -->    -9.223372e+18     3.141593e+00 0400
+fcos        -9.223381e+18 -->    -9.223381e+18     3.141593e+00 0400
+fcos        -1.014571e+19 -->    -1.014571e+19     3.141593e+00 0400
+
+fsincos      0.000000e+00 -->     1.000000e+00     0.000000e+00 0000
+fsincos      1.230000e-01 -->     9.924450e-01     1.226901e-01 0000
+fsincos     -4.560000e-01 -->     8.978211e-01    -4.403604e-01 0000
+fsincos      3.700000e+01 -->     7.654141e-01    -6.435381e-01 0000
+fsincos     -5.300000e+01 -->    -9.182828e-01    -3.959252e-01 0000
+
+fsincos      8.301035e+18 -->    -9.921596e-01    -1.249775e-01 0000
+fsincos      9.223363e+18 -->     9.721387e-01     2.344065e-01 0000
+fsincos      9.223372e+18 -->     9.223372e+18     3.141593e+00 0400
+fsincos      9.223381e+18 -->     9.223381e+18     3.141593e+00 0400
+fsincos      1.014571e+19 -->     1.014571e+19     3.141593e+00 0400
+
+fsincos     -8.301035e+18 -->    -9.921596e-01     1.249775e-01 0000
+fsincos     -9.223363e+18 -->     9.721387e-01    -2.344065e-01 0000
+fsincos     -9.223372e+18 -->    -9.223372e+18     3.141593e+00 0400
+fsincos     -9.223381e+18 -->    -9.223381e+18     3.141593e+00 0400
+fsincos     -1.014571e+19 -->    -1.014571e+19     3.141593e+00 0400
+
+fptan        0.000000e+00 -->     1.000000e+00     0.000000e+00 0000
+fptan        1.230000e-01 -->     1.000000e+00     1.236241e-01 0000
+fptan       -4.560000e-01 -->     1.000000e+00    -4.904767e-01 0000
+fptan        3.700000e+01 -->     1.000000e+00    -8.407713e-01 0000
+fptan       -5.300000e+01 -->     1.000000e+00     4.311582e-01 0000
+
+fptan        8.301035e+18 -->     1.000000e+00     1.259651e-01 0000
+fptan        9.223363e+18 -->     1.000000e+00     2.411246e-01 0000
+fptan        9.223372e+18 -->     9.223372e+18     3.141593e+00 0400
+fptan        9.223381e+18 -->     9.223381e+18     3.141593e+00 0400
+fptan        1.014571e+19 -->     1.014571e+19     3.141593e+00 0400
+
+fptan       -8.301035e+18 -->     1.000000e+00    -1.259651e-01 0000
+fptan       -9.223363e+18 -->     1.000000e+00    -2.411246e-01 0000
+fptan       -9.223372e+18 -->    -9.223372e+18     3.141593e+00 0400
+fptan       -9.223381e+18 -->    -9.223381e+18     3.141593e+00 0400
+fptan       -1.014571e+19 -->    -1.014571e+19     3.141593e+00 0400
+
diff --git a/none/tests/x86/x87trigOOR.vgtest b/none/tests/x86/x87trigOOR.vgtest
new file mode 100644
index 0000000..1ff5fd7
--- /dev/null
+++ b/none/tests/x86/x87trigOOR.vgtest
@@ -0,0 +1 @@
+prog: x87trigOOR