]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Test program aimed at exercising x87 insns a bit on amd64.
authorJulian Seward <jseward@acm.org>
Mon, 6 Feb 2006 04:49:58 +0000 (04:49 +0000)
committerJulian Seward <jseward@acm.org>
Mon, 6 Feb 2006 04:49:58 +0000 (04:49 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5613

memcheck/tests/amd64/Makefile.am
memcheck/tests/amd64/more_x87_fp.c [new file with mode: 0644]
memcheck/tests/amd64/more_x87_fp.stderr.exp [new file with mode: 0644]
memcheck/tests/amd64/more_x87_fp.stdout.exp [new file with mode: 0644]
memcheck/tests/amd64/more_x87_fp.vgtest [new file with mode: 0644]

index 76300461c50a1b41c7f5bfe328934199c9e88740..a62b428ab86a4a07fdc7e8ba0c2861474cd2b3c3 100644 (file)
@@ -8,11 +8,16 @@ EXTRA_DIST = $(noinst_SCRIPTS) \
        $(addsuffix .stderr.exp,$(INSN_TESTS)) \
        $(addsuffix .stdout.exp,$(INSN_TESTS)) \
        $(addsuffix .vgtest,$(INSN_TESTS)) \
+       more_x87_fp.stderr.exp more_x87_fp.stdout.exp more_x87_fp.vgtest \
        sse_memory.stderr.exp sse_memory.stdout.exp sse_memory.vgtest
 
-check_PROGRAMS = sse_memory
+check_PROGRAMS = more_x87_fp sse_memory
 
 AM_CPPFLAGS = -I$(top_srcdir)/include
 AM_CFLAGS   = $(WERROR) -Winline -Wall -Wshadow -g -I$(top_srcdir)/include
                @FLAG_M64@
 AM_CXXFLAGS = $(AM_CFLAGS)
+
+more_x87_fp_CFLAGS     = $(AM_CFLAGS) -O -ffast-math -mfpmath=387 \
+                               -mfancy-math-387
+more_x87_fp_LDADD      = -lm
diff --git a/memcheck/tests/amd64/more_x87_fp.c b/memcheck/tests/amd64/more_x87_fp.c
new file mode 100644 (file)
index 0000000..1633b54
--- /dev/null
@@ -0,0 +1,273 @@
+
+/* On amd64, to exercise x87, compile with 
+    gcc4 -ffast-math -mfpmath=387 -mfancy-math-387
+
+  gcc4 really does generate all the sin cos tan stuff as 
+  x87 insns inline.  gcc 3.3 doesn't, which makes the test
+  pretty useless, but it should still pass.  To be on the safe
+  side we need to link with -lm to handle the gcc 3.3 behaviour.
+*/
+
+/* Derived from: */
+
+/*
+ *  x86 CPU test
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+
+/**********************************************/
+
+void test_fops(double a, double b)
+{
+    printf("a=%f b=%f a+b=%f\n", a, b, a + b);
+    printf("a=%f b=%f a-b=%f\n", a, b, a - b);
+    printf("a=%f b=%f a*b=%f\n", a, b, a * b);
+    printf("a=%f b=%f a/b=%f\n", a, b, a / b);
+    // requires fprem/fprem1 -- not done
+    //printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b));
+    printf("a=%f sqrt(a)=%f\n", a, sqrt(a));
+    printf("a=%f sin(a)=%f\n", a, sin(a));
+    printf("a=%f cos(a)=%f\n", a, cos(a));
+    printf("a=%f tan(a)=%f\n", a, tan(a));
+    printf("a=%f log(a)=%f\n", a, log(a));
+    printf("a=%f exp(a)=%f\n", a, exp(a));
+    printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
+    /* just to test some op combining */
+    printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a)));
+    printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a)));
+    printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));
+}
+#define CC_C    0x0001
+#define CC_P    0x0004
+#define CC_A    0x0010
+#define CC_Z    0x0040
+#define CC_S    0x0080
+#define CC_O    0x0800
+
+
+void test_fcmp(double a, double b)
+{
+    printf("(%f<%f)=%d\n",
+           a, b, a < b);
+    printf("(%f<=%f)=%d\n",
+           a, b, a <= b);
+    printf("(%f==%f)=%d\n",
+           a, b, a == b);
+    printf("(%f>%f)=%d\n",
+           a, b, a > b);
+    printf("(%f<=%f)=%d\n",
+           a, b, a >= b);
+    {
+        unsigned long long int eflags;
+        /* test f(u)comi instruction */
+        asm("fcomi %2, %1\n"
+            "pushfq\n"
+            "popq %0\n"
+            : "=r" (eflags)
+            : "t" (a), "u" (b));
+        printf("fcomi(%f %f)=%08llx\n", a, b, eflags & (CC_Z | CC_P | CC_C));
+    }
+}
+
+void test_fcvt(double a)
+{
+    float fa;
+    long double la;
+    int16_t fpuc;
+    int i;
+    int64_t lla;
+    int ia;
+    int16_t wa;
+    double ra;
+
+    fa = a;
+    la = a;
+    printf("(float)%e = %e\n", a, fa);
+    printf("(long double)%f = %Lf\n", a, la);
+    printf("a=%016Lx\n", *(long long *)&a);
+    printf("la=%016Lx %04x\n", *(long long *)&la, 
+           *(unsigned short *)((char *)(&la) + 8));
+
+    /* test all roundings */
+    asm volatile ("fstcw %0" : "=m" (fpuc));
+    for(i=0;i<4;i++) {
+      int16_t tmp = (fpuc & ~0x0c00) | (i << 10);
+        asm volatile ("fldcw %0" : : "m" (tmp));
+        wa=0;//asm volatile ("fist %0" : "=m" (wa) : "t" (a));
+       asm volatile ("fistl %0" : "=m" (ia) : "t" (a));
+        asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st");
+        asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a));
+        asm volatile ("fldcw %0" : : "m" (fpuc));
+        printf("(short)a = %d\n", wa);
+        printf("(int)a = %d\n", ia);
+        printf("(int64_t)a = %lld\n", (long long int)lla);
+        printf("rint(a) = %f\n", ra);
+    }
+}
+
+#define TEST(N) \
+    asm("fld" #N : "=t" (a)); \
+    printf("fld" #N "= %f\n", a);
+
+void test_fconst(void)
+{
+    double a;
+    TEST(1);
+    TEST(l2t);
+    TEST(l2e);
+    TEST(pi);
+    TEST(lg2);
+    TEST(ln2);
+    TEST(z);
+}
+
+void test_fbcd(double a)
+{
+    unsigned short bcd[5];
+    double b;
+
+    asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st");
+    asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
+    printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n", 
+           a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);
+}
+
+#define TEST_ENV(env, save, restore)\
+{\
+    memset((env), 0xaa, sizeof(*(env)));\
+    for(i=0;i<5;i++)\
+        asm volatile ("fldl %0" : : "m" (dtab[i]));\
+    asm(save " %0\n" : : "m" (*(env)));\
+    asm(restore " %0\n": : "m" (*(env)));\
+    for(i=0;i<5;i++)\
+        asm volatile ("fstpl %0" : "=m" (rtab[i]));\
+    for(i=0;i<5;i++)\
+        printf("res[%d]=%f\n", i, rtab[i]);\
+    printf("fpuc=%04x fpus=%04x fptag=%04x\n",\
+           (env)->fpuc,\
+           (env)->fpus & 0xff00,\
+           (env)->fptag);\
+}
+
+void test_fenv(void)
+{
+    struct __attribute__((packed)) {
+        uint16_t fpuc;
+        uint16_t dummy1;
+        uint16_t fpus;
+        uint16_t dummy2;
+        uint16_t fptag;
+        uint16_t dummy3;
+        uint32_t ignored[4];
+        long double fpregs[8];
+    } float_env32;
+    struct __attribute__((packed)) {
+        uint16_t fpuc;
+        uint16_t fpus;
+        uint16_t fptag;
+        uint16_t ignored[4];
+        long double fpregs[8];
+    } float_env16;
+    double dtab[8];
+    double rtab[8];
+    int i;
+
+    for(i=0;i<8;i++)
+        dtab[i] = i + 1;
+
+    TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv");
+    TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor");
+    TEST_ENV(&float_env32, "fnstenv", "fldenv");
+    TEST_ENV(&float_env32, "fnsave", "frstor");
+
+    /* test for ffree */
+    for(i=0;i<5;i++)
+        asm volatile ("fldl %0" : : "m" (dtab[i]));
+    asm volatile("ffree %st(2)");
+    asm volatile ("fnstenv %0\n" : : "m" (float_env32));
+    asm volatile ("fninit");
+    printf("fptag=%04x\n", float_env32.fptag);
+}
+
+
+#define TEST_FCMOV(a, b, eflags, CC)\
+{\
+    double res;\
+    asm("pushq %3\n"\
+        "popfq\n"\
+        "fcmov" CC " %2, %0\n"\
+        : "=t" (res)\
+        : "0" (a), "u" (b), "g" ((long long int)eflags));\
+    printf("fcmov%s eflags=0x%04llx-> %f\n", \
+           CC, (long long int)eflags, res);\
+}
+
+void test_fcmov(void)
+{
+    double a, b;
+    long long int eflags, i;
+
+    a = 1.0;
+    b = 2.0;
+    for(i = 0; i < 4; i++) {
+        eflags = 0;
+        if (i & 1)
+            eflags |= CC_C;
+        if (i & 2)
+            eflags |= CC_Z;
+        TEST_FCMOV(a, b, eflags, "b");
+        TEST_FCMOV(a, b, eflags, "e");
+        TEST_FCMOV(a, b, eflags, "be");
+        TEST_FCMOV(a, b, eflags, "nb");
+        TEST_FCMOV(a, b, eflags, "ne");
+        TEST_FCMOV(a, b, eflags, "nbe");
+    }
+    TEST_FCMOV(a, b, 0, "u");
+    TEST_FCMOV(a, b, CC_P, "u");
+    TEST_FCMOV(a, b, 0, "nu");
+    TEST_FCMOV(a, b, CC_P, "nu");
+}
+
+void test_floats(void)
+{
+    test_fops(2, 3);
+    test_fops(1.4, -5);
+    test_fcmp(2, -1);
+    test_fcmp(2, 2);
+    test_fcmp(2, 3);
+    test_fcvt(0.5);
+    test_fcvt(-0.5);
+    test_fcvt(1.0/7.0);
+    test_fcvt(-1.0/9.0);
+    test_fcvt(32768);
+    test_fcvt(-1e20);
+    test_fconst();
+}
+
+int main ( void )
+{
+  test_floats();
+  return 0;
+}
diff --git a/memcheck/tests/amd64/more_x87_fp.stderr.exp b/memcheck/tests/amd64/more_x87_fp.stderr.exp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/memcheck/tests/amd64/more_x87_fp.stdout.exp b/memcheck/tests/amd64/more_x87_fp.stdout.exp
new file mode 100644 (file)
index 0000000..ad2c624
--- /dev/null
@@ -0,0 +1,173 @@
+a=2.000000 b=3.000000 a+b=5.000000
+a=2.000000 b=3.000000 a-b=-1.000000
+a=2.000000 b=3.000000 a*b=6.000000
+a=2.000000 b=3.000000 a/b=0.666667
+a=2.000000 sqrt(a)=1.414214
+a=2.000000 sin(a)=0.909297
+a=2.000000 cos(a)=-0.416147
+a=2.000000 tan(a)=-2.185040
+a=2.000000 log(a)=0.693147
+a=2.000000 exp(a)=7.389056
+a=2.000000 b=3.000000 atan2(a, b)=0.588003
+a=2.000000 asin(sin(a))=1.141593
+a=2.000000 acos(cos(a))=2.000000
+a=2.000000 atan(tan(a))=-1.141593
+a=1.400000 b=-5.000000 a+b=-3.600000
+a=1.400000 b=-5.000000 a-b=6.400000
+a=1.400000 b=-5.000000 a*b=-7.000000
+a=1.400000 b=-5.000000 a/b=-0.280000
+a=1.400000 sqrt(a)=1.183216
+a=1.400000 sin(a)=0.985450
+a=1.400000 cos(a)=0.169967
+a=1.400000 tan(a)=5.797884
+a=1.400000 log(a)=0.336472
+a=1.400000 exp(a)=4.055200
+a=1.400000 b=-5.000000 atan2(a, b)=2.868584
+a=1.400000 asin(sin(a))=1.400000
+a=1.400000 acos(cos(a))=1.400000
+a=1.400000 atan(tan(a))=1.400000
+(2.000000<-1.000000)=0
+(2.000000<=-1.000000)=0
+(2.000000==-1.000000)=0
+(2.000000>-1.000000)=1
+(2.000000<=-1.000000)=1
+fcomi(2.000000 -1.000000)=00000000
+(2.000000<2.000000)=0
+(2.000000<=2.000000)=1
+(2.000000==2.000000)=1
+(2.000000>2.000000)=0
+(2.000000<=2.000000)=1
+fcomi(2.000000 2.000000)=00000040
+(2.000000<3.000000)=1
+(2.000000<=3.000000)=1
+(2.000000==3.000000)=0
+(2.000000>3.000000)=0
+(2.000000<=3.000000)=0
+fcomi(2.000000 3.000000)=00000001
+(float)5.000000e-01 = 5.000000e-01
+(long double)0.500000 = 0.500000
+a=3fe0000000000000
+la=8000000000000000 3ffe
+(short)a = 0
+(int)a = 0
+(int64_t)a = 0
+rint(a) = 0.000000
+(short)a = 0
+(int)a = 0
+(int64_t)a = 0
+rint(a) = 0.000000
+(short)a = 0
+(int)a = 1
+(int64_t)a = 1
+rint(a) = 1.000000
+(short)a = 0
+(int)a = 0
+(int64_t)a = 0
+rint(a) = 0.000000
+(float)-5.000000e-01 = -5.000000e-01
+(long double)-0.500000 = -0.500000
+a=bfe0000000000000
+la=8000000000000000 bffe
+(short)a = 0
+(int)a = 0
+(int64_t)a = 0
+rint(a) = -0.000000
+(short)a = 0
+(int)a = -1
+(int64_t)a = -1
+rint(a) = -1.000000
+(short)a = 0
+(int)a = 0
+(int64_t)a = 0
+rint(a) = -0.000000
+(short)a = 0
+(int)a = 0
+(int64_t)a = 0
+rint(a) = -0.000000
+(float)1.428571e-01 = 1.428571e-01
+(long double)0.142857 = 0.142857
+a=3fc2492492492492
+la=9249249249249000 3ffc
+(short)a = 0
+(int)a = 0
+(int64_t)a = 0
+rint(a) = 0.000000
+(short)a = 0
+(int)a = 0
+(int64_t)a = 0
+rint(a) = 0.000000
+(short)a = 0
+(int)a = 1
+(int64_t)a = 1
+rint(a) = 1.000000
+(short)a = 0
+(int)a = 0
+(int64_t)a = 0
+rint(a) = 0.000000
+(float)-1.111111e-01 = -1.111111e-01
+(long double)-0.111111 = -0.111111
+a=bfbc71c71c71c71c
+la=e38e38e38e38e000 bffb
+(short)a = 0
+(int)a = 0
+(int64_t)a = 0
+rint(a) = -0.000000
+(short)a = 0
+(int)a = -1
+(int64_t)a = -1
+rint(a) = -1.000000
+(short)a = 0
+(int)a = 0
+(int64_t)a = 0
+rint(a) = -0.000000
+(short)a = 0
+(int)a = 0
+(int64_t)a = 0
+rint(a) = -0.000000
+(float)3.276800e+04 = 3.276800e+04
+(long double)32768.000000 = 32768.000000
+a=40e0000000000000
+la=8000000000000000 400e
+(short)a = 0
+(int)a = 32768
+(int64_t)a = 32768
+rint(a) = 32768.000000
+(short)a = 0
+(int)a = 32768
+(int64_t)a = 32768
+rint(a) = 32768.000000
+(short)a = 0
+(int)a = 32768
+(int64_t)a = 32768
+rint(a) = 32768.000000
+(short)a = 0
+(int)a = 32768
+(int64_t)a = 32768
+rint(a) = 32768.000000
+(float)-1.000000e+20 = -1.000000e+20
+(long double)-100000000000000000000.000000 = -100000000000000000000.000000
+a=c415af1d78b58c40
+la=ad78ebc5ac620000 c041
+(short)a = 0
+(int)a = -2147483648
+(int64_t)a = -9223372036854775808
+rint(a) = -100000000000000000000.000000
+(short)a = 0
+(int)a = -2147483648
+(int64_t)a = -9223372036854775808
+rint(a) = -100000000000000000000.000000
+(short)a = 0
+(int)a = -2147483648
+(int64_t)a = -9223372036854775808
+rint(a) = -100000000000000000000.000000
+(short)a = 0
+(int)a = -2147483648
+(int64_t)a = -9223372036854775808
+rint(a) = -100000000000000000000.000000
+fld1= 1.000000
+fldl2t= 3.321928
+fldl2e= 1.442695
+fldpi= 3.141593
+fldlg2= 0.301030
+fldln2= 0.693147
+fldz= 0.000000
diff --git a/memcheck/tests/amd64/more_x87_fp.vgtest b/memcheck/tests/amd64/more_x87_fp.vgtest
new file mode 100644 (file)
index 0000000..5e34ef8
--- /dev/null
@@ -0,0 +1,2 @@
+prog: more_x87_fp
+vgopts: -q