• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* On amd64, to exercise x87, compile with
3     gcc4 -ffast-math -mfpmath=387 -mfancy-math-387
4 
5   gcc4 really does generate all the sin cos tan stuff as
6   x87 insns inline.  gcc 3.3 doesn't, which makes the test
7   pretty useless, but it should still pass.  To be on the safe
8   side we need to link with -lm to handle the gcc 3.3 behaviour.
9 */
10 
11 /* Derived from: */
12 
13 /*
14  *  x86 CPU test
15  *
16  *  Copyright (c) 2003 Fabrice Bellard
17  *
18  *  This program is free software; you can redistribute it and/or modify
19  *  it under the terms of the GNU General Public License as published by
20  *  the Free Software Foundation; either version 2 of the License, or
21  *  (at your option) any later version.
22  *
23  *  This program is distributed in the hope that it will be useful,
24  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
25  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  *  GNU General Public License for more details.
27  *
28  *  You should have received a copy of the GNU General Public License
29  *  along with this program; if not, write to the Free Software
30  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31  */
32 
33 
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <inttypes.h>
38 #include <math.h>
39 
40 /**********************************************/
41 
test_fops(double a,double b)42 void test_fops(double a, double b)
43 {
44     printf("a=%f b=%f a+b=%f\n", a, b, a + b);
45     printf("a=%f b=%f a-b=%f\n", a, b, a - b);
46     printf("a=%f b=%f a*b=%f\n", a, b, a * b);
47     printf("a=%f b=%f a/b=%f\n", a, b, a / b);
48     // requires fprem/fprem1 -- not done
49     //printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b));
50     printf("a=%f sqrt(a)=%f\n", a, sqrt(a));
51     printf("a=%f sin(a)=%f\n", a, sin(a));
52     printf("a=%f cos(a)=%f\n", a, cos(a));
53     printf("a=%f tan(a)=%f\n", a, tan(a));
54     printf("a=%f log(a)=%f\n", a, log(a));
55     printf("a=%f exp(a)=%f\n", a, exp(a));
56     printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
57     /* just to test some op combining */
58     printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a)));
59     printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a)));
60     printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));
61 }
62 #define CC_C    0x0001
63 #define CC_P    0x0004
64 #define CC_A    0x0010
65 #define CC_Z    0x0040
66 #define CC_S    0x0080
67 #define CC_O    0x0800
68 
69 
test_fcmp(double a,double b)70 void test_fcmp(double a, double b)
71 {
72     printf("(%f<%f)=%d\n",
73            a, b, a < b);
74     printf("(%f<=%f)=%d\n",
75            a, b, a <= b);
76     printf("(%f==%f)=%d\n",
77            a, b, a == b);
78     printf("(%f>%f)=%d\n",
79            a, b, a > b);
80     printf("(%f<=%f)=%d\n",
81            a, b, a >= b);
82     {
83         unsigned long long int eflags;
84         /* test f(u)comi instruction */
85         asm("fcomi %2, %1\n"
86             "pushfq\n"
87             "popq %0\n"
88             : "=r" (eflags)
89             : "t" (a), "u" (b));
90         printf("fcomi(%f %f)=%08llx\n", a, b, eflags & (CC_Z | CC_P | CC_C));
91     }
92 }
93 
test_fcvt(double a)94 void test_fcvt(double a)
95 {
96     float fa;
97     long double la;
98     int16_t fpuc;
99     int i;
100     int64_t lla;
101     int ia;
102     int16_t wa;
103     double ra;
104 
105     fa = a;
106     la = a;
107     printf("(float)%e = %e\n", a, fa);
108     printf("(long double)%f = %Lf\n", a, la);
109     printf("a=%016Lx\n", *(long long *)&a);
110     printf("la=%016Lx %04x\n", *(long long *)&la,
111            *(unsigned short *)((char *)(&la) + 8));
112 
113     /* test all roundings */
114     asm volatile ("fstcw %0" : "=m" (fpuc));
115     for(i=0;i<4;i++) {
116       int16_t tmp = (fpuc & ~0x0c00) | (i << 10);
117         asm volatile ("fldcw %0" : : "m" (tmp));
118         wa=0;//asm volatile ("fist %0" : "=m" (wa) : "t" (a));
119 	asm volatile ("fistl %0" : "=m" (ia) : "t" (a));
120         asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st");
121         asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a));
122         asm volatile ("fldcw %0" : : "m" (fpuc));
123         printf("(short)a = %d\n", wa);
124         printf("(int)a = %d\n", ia);
125         printf("(int64_t)a = %lld\n", (long long int)lla);
126         printf("rint(a) = %f\n", ra);
127     }
128 }
129 
130 #define TEST(N) \
131     asm("fld" #N : "=t" (a)); \
132     printf("fld" #N "= %f\n", a);
133 
test_fconst(void)134 void test_fconst(void)
135 {
136     double a;
137     TEST(1);
138     TEST(l2t);
139     TEST(l2e);
140     TEST(pi);
141     TEST(lg2);
142     TEST(ln2);
143     TEST(z);
144 }
145 
test_fbcd(double a)146 void test_fbcd(double a)
147 {
148     unsigned short bcd[5];
149     double b;
150 
151     asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st");
152     asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
153     printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n",
154            a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);
155 }
156 
157 #define TEST_ENV(env, save, restore)\
158 {\
159     memset((env), 0xaa, sizeof(*(env)));\
160     for(i=0;i<5;i++)\
161         asm volatile ("fldl %0" : : "m" (dtab[i]));\
162     asm(save " %0\n" : : "m" (*(env)));\
163     asm(restore " %0\n": : "m" (*(env)));\
164     for(i=0;i<5;i++)\
165         asm volatile ("fstpl %0" : "=m" (rtab[i]));\
166     for(i=0;i<5;i++)\
167         printf("res[%d]=%f\n", i, rtab[i]);\
168     printf("fpuc=%04x fpus=%04x fptag=%04x\n",\
169            (env)->fpuc,\
170            (env)->fpus & 0xff00,\
171            (env)->fptag);\
172 }
173 
test_fenv(void)174 void test_fenv(void)
175 {
176     struct __attribute__((packed)) {
177         uint16_t fpuc;
178         uint16_t dummy1;
179         uint16_t fpus;
180         uint16_t dummy2;
181         uint16_t fptag;
182         uint16_t dummy3;
183         uint32_t ignored[4];
184         long double fpregs[8];
185     } float_env32;
186     struct __attribute__((packed)) {
187         uint16_t fpuc;
188         uint16_t fpus;
189         uint16_t fptag;
190         uint16_t ignored[4];
191         long double fpregs[8];
192     } float_env16;
193     double dtab[8];
194     double rtab[8];
195     int i;
196 
197     for(i=0;i<8;i++)
198         dtab[i] = i + 1;
199 
200     TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv");
201     TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor");
202     TEST_ENV(&float_env32, "fnstenv", "fldenv");
203     TEST_ENV(&float_env32, "fnsave", "frstor");
204 
205     /* test for ffree */
206     for(i=0;i<5;i++)
207         asm volatile ("fldl %0" : : "m" (dtab[i]));
208     asm volatile("ffree %st(2)");
209     asm volatile ("fnstenv %0\n" : : "m" (float_env32));
210     asm volatile ("fninit");
211     printf("fptag=%04x\n", float_env32.fptag);
212 }
213 
214 
215 #define TEST_FCMOV(a, b, eflags, CC)\
216 {\
217     double res;\
218     asm("pushq %3\n"\
219         "popfq\n"\
220         "fcmov" CC " %2, %0\n"\
221         : "=t" (res)\
222         : "0" (a), "u" (b), "g" ((long long int)eflags));\
223     printf("fcmov%s eflags=0x%04llx-> %f\n", \
224            CC, (long long int)eflags, res);\
225 }
226 
test_fcmov(void)227 void test_fcmov(void)
228 {
229     double a, b;
230     long long int eflags, i;
231 
232     a = 1.0;
233     b = 2.0;
234     for(i = 0; i < 4; i++) {
235         eflags = 0;
236         if (i & 1)
237             eflags |= CC_C;
238         if (i & 2)
239             eflags |= CC_Z;
240         TEST_FCMOV(a, b, eflags, "b");
241         TEST_FCMOV(a, b, eflags, "e");
242         TEST_FCMOV(a, b, eflags, "be");
243         TEST_FCMOV(a, b, eflags, "nb");
244         TEST_FCMOV(a, b, eflags, "ne");
245         TEST_FCMOV(a, b, eflags, "nbe");
246     }
247     TEST_FCMOV(a, b, 0, "u");
248     TEST_FCMOV(a, b, CC_P, "u");
249     TEST_FCMOV(a, b, 0, "nu");
250     TEST_FCMOV(a, b, CC_P, "nu");
251 }
252 
test_floats(void)253 void test_floats(void)
254 {
255     test_fops(2, 3);
256     test_fops(1.4, -5);
257     test_fcmp(2, -1);
258     test_fcmp(2, 2);
259     test_fcmp(2, 3);
260     test_fcvt(0.5);
261     test_fcvt(-0.5);
262     test_fcvt(1.0/7.0);
263     test_fcvt(-1.0/9.0);
264     test_fcvt(32768);
265     test_fcvt(-1e20);
266     test_fconst();
267 }
268 
main(void)269 int main ( void )
270 {
271   test_floats();
272   return 0;
273 }
274