From 4fc858a562bcc7ffa7239f5e8fa6849d6c9cb9b3 Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Mon, 6 Feb 2006 04:49:58 +0000 Subject: [PATCH] Test program aimed at exercising x87 insns a bit on amd64. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5613 --- memcheck/tests/amd64/Makefile.am | 7 +- memcheck/tests/amd64/more_x87_fp.c | 273 ++++++++++++++++++++ memcheck/tests/amd64/more_x87_fp.stderr.exp | 0 memcheck/tests/amd64/more_x87_fp.stdout.exp | 173 +++++++++++++ memcheck/tests/amd64/more_x87_fp.vgtest | 2 + 5 files changed, 454 insertions(+), 1 deletion(-) create mode 100644 memcheck/tests/amd64/more_x87_fp.c create mode 100644 memcheck/tests/amd64/more_x87_fp.stderr.exp create mode 100644 memcheck/tests/amd64/more_x87_fp.stdout.exp create mode 100644 memcheck/tests/amd64/more_x87_fp.vgtest diff --git a/memcheck/tests/amd64/Makefile.am b/memcheck/tests/amd64/Makefile.am index 76300461c5..a62b428ab8 100644 --- a/memcheck/tests/amd64/Makefile.am +++ b/memcheck/tests/amd64/Makefile.am @@ -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 index 0000000000..1633b5480f --- /dev/null +++ b/memcheck/tests/amd64/more_x87_fp.c @@ -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 +#include +#include +#include +#include + +/**********************************************/ + +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 index 0000000000..e69de29bb2 diff --git a/memcheck/tests/amd64/more_x87_fp.stdout.exp b/memcheck/tests/amd64/more_x87_fp.stdout.exp new file mode 100644 index 0000000000..ad2c6244a0 --- /dev/null +++ b/memcheck/tests/amd64/more_x87_fp.stdout.exp @@ -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 index 0000000000..5e34ef8628 --- /dev/null +++ b/memcheck/tests/amd64/more_x87_fp.vgtest @@ -0,0 +1,2 @@ +prog: more_x87_fp +vgopts: -q -- 2.47.3