From: Julian Seward Date: Sat, 4 Feb 2006 15:26:11 +0000 (+0000) Subject: Yet more x86 instruction tests, mostly aimed at wierd/transcendental X-Git-Tag: svn/VALGRIND_3_2_0~302 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b8904fc241a48b067ca2159e19330e610b059dee;p=thirdparty%2Fvalgrind.git Yet more x86 instruction tests, mostly aimed at wierd/transcendental x87 insns. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5609 --- diff --git a/memcheck/tests/x86/Makefile.am b/memcheck/tests/x86/Makefile.am index dbbce96dc1..9564b005c9 100644 --- a/memcheck/tests/x86/Makefile.am +++ b/memcheck/tests/x86/Makefile.am @@ -19,11 +19,14 @@ EXTRA_DIST = $(noinst_SCRIPTS) \ scalar_vfork.stderr.exp scalar_vfork.vgtest \ sse1_memory.stderr.exp sse1_memory.stdout.exp sse1_memory.vgtest \ sse2_memory.stderr.exp sse2_memory.stdout.exp sse2_memory.vgtest \ - tronical.stderr.exp tronical.vgtest + tronical.stderr.exp tronical.vgtest \ + more_x86_fp.stderr.exp more_x86_fp.stdout.exp more_x86_fp.vgtest \ + fprem.stderr.exp fprem.stdout.exp fprem.vgtest check_PROGRAMS = \ scalar_exit_group scalar_fork scalar_supp scalar_vfork \ - fpeflags pushfpopf scalar sse_memory tronical + fpeflags pushfpopf scalar sse_memory tronical \ + more_x86_fp fprem AM_CPPFLAGS = -I$(top_srcdir)/include AM_CFLAGS = $(WERROR) @FLAG_M32@ -Winline -Wall -Wshadow -g \ @@ -36,3 +39,4 @@ fpeflags_CFLAGS = $(AM_CFLAGS) -march=i686 pushfpopf_SOURCES = pushfpopf_c.c pushfpopf_s.s tronical_SOURCES = tronical.S +more_x86_fp_LDADD = -lm diff --git a/memcheck/tests/x86/fprem.c b/memcheck/tests/x86/fprem.c new file mode 100644 index 0000000000..d48b49ad9d --- /dev/null +++ b/memcheck/tests/x86/fprem.c @@ -0,0 +1,42 @@ + +/* Marginally test fprem/fprem1; these are hard to check otherwise */ + +#include + +double do_fprem ( void ) +{ + double res; + __asm__ __volatile__( + "ffree %%st(0)\n\t" + "ffree %%st(1)\n\t" + "fldpi\n\t" + "fldln2\n\t" + "fprem\n\t" + "fstpl 0(%0)" + : : "r"(&res) + ); + return res; +} + +double do_fprem1 ( void ) +{ + double res; + __asm__ __volatile__( + "ffree %%st(0)\n\t" + "ffree %%st(1)\n\t" + "fldpi\n\t" + "fldln2\n\t" + "fprem1\n\t" + "fstpl 0(%0)" + : : "r"(&res) + ); + return res; +} + +int main ( void ) +{ + __asm__ __volatile__("finit"); + printf("fprem %f\n", do_fprem()); + printf("fprem1 %f\n", do_fprem1()); + return 0; +} diff --git a/memcheck/tests/x86/fprem.stderr.exp b/memcheck/tests/x86/fprem.stderr.exp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/memcheck/tests/x86/fprem.stdout.exp b/memcheck/tests/x86/fprem.stdout.exp new file mode 100644 index 0000000000..5ba92bfdd8 --- /dev/null +++ b/memcheck/tests/x86/fprem.stdout.exp @@ -0,0 +1,2 @@ +fprem 0.693147 +fprem1 0.693147 diff --git a/memcheck/tests/x86/fprem.vgtest b/memcheck/tests/x86/fprem.vgtest new file mode 100644 index 0000000000..94a0a0d9d7 --- /dev/null +++ b/memcheck/tests/x86/fprem.vgtest @@ -0,0 +1,2 @@ +vgopts: -q +prog: fprem diff --git a/memcheck/tests/x86/more_x86_fp.c b/memcheck/tests/x86/more_x86_fp.c new file mode 100644 index 0000000000..fbbd957ad2 --- /dev/null +++ b/memcheck/tests/x86/more_x86_fp.c @@ -0,0 +1,263 @@ + +/* 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); + 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 int eflags; + /* test f(u)comi instruction */ + asm("fcomi %2, %1\n" + "pushf\n" + "pop %0\n" + : "=r" (eflags) + : "t" (a), "u" (b)); + printf("fcomi(%f %f)=%08x\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)%f = %f\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)); + 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 = %Ld\n", 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("push %3\n"\ + "popf\n"\ + "fcmov" CC " %2, %0\n"\ + : "=t" (res)\ + : "0" (a), "u" (b), "g" (eflags));\ + printf("fcmov%s eflags=0x%04x-> %f\n", \ + CC, eflags, res);\ +} + +void test_fcmov(void) +{ + double a, b; + 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/x86/more_x86_fp.stderr.exp b/memcheck/tests/x86/more_x86_fp.stderr.exp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/memcheck/tests/x86/more_x86_fp.stdout.exp b/memcheck/tests/x86/more_x86_fp.stdout.exp new file mode 100644 index 0000000000..4810929337 --- /dev/null +++ b/memcheck/tests/x86/more_x86_fp.stdout.exp @@ -0,0 +1,175 @@ +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 b=3.000000 fmod(a, b)=2.000000 +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 b=-5.000000 fmod(a, b)=1.400000 +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)0.500000 = 0.500000 +(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 = 1 +(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)-0.500000 = -0.500000 +(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 = -1 +(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)0.142857 = 0.142857 +(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 = 1 +(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)-0.111111 = -0.111111 +(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 = -1 +(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)32768.000000 = 32768.000000 +(long double)32768.000000 = 32768.000000 +a=40e0000000000000 +la=8000000000000000 400e +(short)a = -32768 +(int)a = 32768 +(int64_t)a = 32768 +rint(a) = 32768.000000 +(short)a = -32768 +(int)a = 32768 +(int64_t)a = 32768 +rint(a) = 32768.000000 +(short)a = -32768 +(int)a = 32768 +(int64_t)a = 32768 +rint(a) = 32768.000000 +(short)a = -32768 +(int)a = 32768 +(int64_t)a = 32768 +rint(a) = 32768.000000 +(float)-100000000000000000000.000000 = -100000002004087734272.000000 +(long double)-100000000000000000000.000000 = -100000000000000000000.000000 +a=c415af1d78b58c40 +la=ad78ebc5ac620000 c041 +(short)a = -32768 +(int)a = -2147483648 +(int64_t)a = -9223372036854775808 +rint(a) = -100000000000000000000.000000 +(short)a = -32768 +(int)a = -2147483648 +(int64_t)a = -9223372036854775808 +rint(a) = -100000000000000000000.000000 +(short)a = -32768 +(int)a = -2147483648 +(int64_t)a = -9223372036854775808 +rint(a) = -100000000000000000000.000000 +(short)a = -32768 +(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/x86/more_x86_fp.vgtest b/memcheck/tests/x86/more_x86_fp.vgtest new file mode 100644 index 0000000000..9cf90f3614 --- /dev/null +++ b/memcheck/tests/x86/more_x86_fp.vgtest @@ -0,0 +1,2 @@ +vgopts: -q +prog: more_x86_fp