--- /dev/null
+
+/* 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;
+}
--- /dev/null
+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