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