VirtualBox

source: vbox/trunk/src/recompiler/Sun/testmath.c@ 8189

Last change on this file since 8189 was 8189, checked in by vboxsync, 16 years ago

gcc warning

  • Property svn:keywords set to Id
File size: 24.3 KB
Line 
1/* $Id: testmath.c 8189 2008-04-19 20:30:49Z vboxsync $ */
2/** @file
3 * Testcase for the no-crt math stuff.
4 */
5
6
7/*******************************************************************************
8* Header Files *
9*******************************************************************************/
10#ifndef MATHTEST_STANDALONE
11# include <iprt/assert.h>
12# include <math.h>
13# undef printf
14# define printf AssertMsg2
15#else
16# include <stdio.h>
17# include <math.h>
18#endif
19
20#if defined(__GNUC__) && ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3) || (__GNUC__ > 4))
21 /* gcc starting with version 4.3 uses the MPFR library which results in more accurate results */
22# define SIN180 -0.8011526357338304777463731115L
23#else
24# define SIN180 -0.801152635733830477871L
25#endif
26
27static void bitch(const char *pszWhat, const long double *plrdResult, const long double *plrdExpected)
28{
29 const unsigned char *pach1 = (const unsigned char *)plrdResult;
30 const unsigned char *pach2 = (const unsigned char *)plrdExpected;
31#ifndef MATHTEST_STANDALONE
32 printf("error: %s - %d instead of %d\n", pszWhat, (int)(*plrdResult * 100000), (int)(*plrdExpected * 100000));
33#else
34 printf("error: %s - %.25f instead of %.25f\n", pszWhat, (double)*plrdResult, (double)*plrdExpected);
35#endif
36 printf(" %02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x\n", pach1[0], pach1[1], pach1[2], pach1[3], pach1[4], pach1[5], pach1[6], pach1[7], pach1[8], pach1[9]);
37 printf(" %02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x\n", pach2[0], pach2[1], pach2[2], pach2[3], pach2[4], pach2[5], pach2[6], pach2[7], pach2[8], pach2[9]);
38}
39
40static void bitchll(const char *pszWhat, long long llResult, long long llExpected)
41{
42#if defined(__MINGW32__) && !defined(Assert)
43 printf("error: %s - %I64d instead of %I64d\n", pszWhat, llResult, llExpected);
44#else
45 printf("error: %s - %lld instead of %lld\n", pszWhat, llResult, llExpected);
46#endif
47}
48
49static void bitchl(const char *pszWhat, long lResult, long lExpected)
50{
51 printf("error: %s - %ld instead of %ld\n", pszWhat, lResult, lExpected);
52}
53
54extern int testsin(void)
55{
56 return sinl(180.0L) == SIN180;
57}
58
59extern int testremainder(void)
60{
61 static double s_rd1 = 2.5;
62 static double s_rd2 = 2.0;
63 static double s_rd3 = 0.5;
64 return remainder(s_rd1, s_rd2) == s_rd3;
65}
66
67static __inline__ void set_cw(unsigned cw)
68{
69 __asm __volatile("fldcw %0" : : "m" (cw));
70}
71
72static __inline__ unsigned get_cw(void)
73{
74 unsigned cw;
75 __asm __volatile("fstcw %0" : : "m" (cw));
76 return cw & 0xffff;
77}
78
79static long double check_lrd(const long double lrd, const unsigned long long ull, const unsigned short us)
80{
81 static volatile long double lrd2;
82 lrd2 = lrd;
83 if ( *(unsigned long long *)&lrd2 != ull
84 || ((unsigned short *)&lrd2)[4] != us)
85 {
86#if defined(__MINGW32__) && !defined(Assert)
87 printf("%I64x:%04x instead of %I64x:%04x\n", *(unsigned long long *)&lrd2, ((unsigned short *)&lrd2)[4], ull, us);
88#else
89 printf("%llx:%04x instead of %llx:%04x\n", *(unsigned long long *)&lrd2, ((unsigned short *)&lrd2)[4], ull, us);
90#endif
91 __asm__("int3\n");
92 }
93 return lrd;
94}
95
96
97static long double make_lrd(const unsigned long long ull, const unsigned short us)
98{
99 union
100 {
101 long double lrd;
102 struct
103 {
104 unsigned long long ull;
105 unsigned short us;
106 } i;
107 } u;
108
109 u.i.ull = ull;
110 u.i.us = us;
111 return u.lrd;
112}
113
114static long double check_lrd_cw(const long double lrd, const unsigned long long ull, const unsigned short us, const unsigned cw)
115{
116 set_cw(cw);
117 if (cw != get_cw())
118 {
119 printf("get_cw() -> %#x expected %#x\n", get_cw(), cw);
120 __asm__("int3\n");
121 }
122 return check_lrd(lrd, ull, us);
123}
124
125static long double make_lrd_cw(unsigned long long ull, unsigned short us, unsigned cw)
126{
127 set_cw(cw);
128 return check_lrd_cw(make_lrd(ull, us), ull, us, cw);
129}
130
131extern int testmath(void)
132{
133 unsigned cErrors = 0;
134 long double lrdResult;
135 long double lrdExpect;
136 long double lrd;
137#define CHECK(operation, expect) \
138 do { \
139 lrdExpect = expect; \
140 lrdResult = operation; \
141 if (lrdResult != lrdExpect) \
142 { \
143 bitch(#operation, &lrdResult, &lrdExpect); \
144 cErrors++; \
145 } \
146 } while (0)
147
148 long long llResult;
149 long long llExpect;
150#define CHECKLL(operation, expect) \
151 do { \
152 llExpect = expect; \
153 llResult = operation; \
154 if (llResult != llExpect) \
155 { \
156 bitchll(#operation, llResult, llExpect); \
157 cErrors++; \
158 } \
159 } while (0)
160
161 long lResult;
162 long lExpect;
163#define CHECKL(operation, expect) \
164 do { \
165 lExpect = expect; \
166 lResult = operation; \
167 if (lResult != lExpect) \
168 { \
169 bitchl(#operation, lResult, lExpect); \
170 cErrors++; \
171 } \
172 } while (0)
173
174 CHECK(atan2l(1.0L, 1.0L), 0.785398163397448309603L);
175 CHECK(atan2l(2.3L, 3.3L), 0.608689307327411694890L);
176
177 CHECK(ceill(1.9L), 2.0L);
178 CHECK(ceill(4.5L), 5.0L);
179 CHECK(ceill(3.3L), 4.0L);
180 CHECK(ceill(6.1L), 7.0L);
181
182 CHECK(floorl(1.9L), 1.0L);
183 CHECK(floorl(4.5L), 4.0L);
184 CHECK(floorl(7.3L), 7.0L);
185 CHECK(floorl(1234.1L), 1234.0L);
186 CHECK(floor(1233.1), 1233.0);
187 CHECK(floor(1239.98989898), 1239.0);
188 CHECK(floorf(9999.999), 9999.0);
189
190 CHECK(ldexpl(1.0L, 1), 2.0L);
191 CHECK(ldexpl(1.0L, 10), 1024.0L);
192 CHECK(ldexpl(2.25L, 10), 2304.0L);
193
194 CHECKLL(llrintl(1.0L), 1);
195 CHECKLL(llrintl(1.3L), 1);
196 CHECKLL(llrintl(1.5L), 2);
197 CHECKLL(llrintl(1.9L), 2);
198 CHECKLL(llrintf(123.34), 123);
199 CHECKLL(llrintf(-123.50), -124);
200 CHECKLL(llrint(42.42), 42);
201 CHECKLL(llrint(-2147483648.12343), -2147483648LL);
202#if !defined(RT_ARCH_AMD64)
203 CHECKLL(lrint(-21474836499.12343), -2147483648LL);
204 CHECKLL(lrint(-2147483649932412.12343), -2147483648LL);
205#else
206 CHECKLL(lrint(-21474836499.12343), -21474836499L);
207 CHECKLL(lrint(-2147483649932412.12343), -2147483649932412L);
208#endif
209
210// __asm__("int3");
211 CHECKL(lrintl(make_lrd_cw(000000000000000000ULL,000000,0x027f)), 0L);
212 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x3ffe,0x027f)), 0L);
213 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x3ffe,0x027f)), 0L);
214 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x3ffe,0x067f)), 0L);
215 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x3ffe,0x067f)), 0L);
216 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x3ffe,0x0a7f)), 1L);
217 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x3ffe,0x0a7f)), 1L);
218 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x3ffe,0x0e7f)), 0L);
219 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x3ffe,0x0e7f)), 0L);
220 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0xbffe,0x027f)), 0L);
221 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0xbffe,0x027f)), 0L);
222 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0xbffe,0x067f)), -1L);
223 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0xbffe,0x067f)), -1L);
224 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0xbffe,0x0a7f)), 0L);
225 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0xbffe,0x0a7f)), 0L);
226 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0xbffe,0x0e7f)), 0L);
227 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0xbffe,0x0e7f)), 0L);
228 CHECKL(lrintl(make_lrd_cw(0x9249249249249000ULL,0x3ffc,0x027f)), 0L);
229 CHECKL(lrintl(make_lrd_cw(0x9249249249249000ULL,0x3ffc,0x027f)), 0L);
230 CHECKL(lrintl(make_lrd_cw(0x9249249249249000ULL,0x3ffc,0x067f)), 0L);
231 CHECKL(lrintl(make_lrd_cw(0x9249249249249000ULL,0x3ffc,0x067f)), 0L);
232 CHECKL(lrintl(make_lrd_cw(0x9249249249249000ULL,0x3ffc,0x0a7f)), 1L);
233 CHECKL(lrintl(make_lrd_cw(0x9249249249249000ULL,0x3ffc,0x0a7f)), 1L);
234 CHECKL(lrintl(make_lrd_cw(0x9249249249249000ULL,0x3ffc,0x0e7f)), 0L);
235 CHECKL(lrintl(make_lrd_cw(0x9249249249249000ULL,0x3ffc,0x0e7f)), 0L);
236 CHECKL(lrintl(make_lrd_cw(0xe38e38e38e38e000ULL,0xbffb,0x027f)), 0L);
237 CHECKL(lrintl(make_lrd_cw(0xe38e38e38e38e000ULL,0xbffb,0x027f)), 0L);
238 CHECKL(lrintl(make_lrd_cw(0xe38e38e38e38e000ULL,0xbffb,0x067f)), -1L);
239 CHECKL(lrintl(make_lrd_cw(0xe38e38e38e38e000ULL,0xbffb,0x067f)), -1L);
240 CHECKL(lrintl(make_lrd_cw(0xe38e38e38e38e000ULL,0xbffb,0x0a7f)), 0L);
241 CHECKL(lrintl(make_lrd_cw(0xe38e38e38e38e000ULL,0xbffb,0x0a7f)), 0L);
242 CHECKL(lrintl(make_lrd_cw(0xe38e38e38e38e000ULL,0xbffb,0x0e7f)), 0L);
243 CHECKL(lrintl(make_lrd_cw(0xe38e38e38e38e000ULL,0xbffb,0x0e7f)), 0L);
244 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x400e,0x027f)), 32768L);
245 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x400e,0x027f)), 32768L);
246 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x400e,0x067f)), 32768L);
247 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x400e,0x067f)), 32768L);
248 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x400e,0x0a7f)), 32768L);
249 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x400e,0x0a7f)), 32768L);
250 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x400e,0x0e7f)), 32768L);
251 CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x400e,0x0e7f)), 32768L);
252#if !defined(RT_ARCH_AMD64)
253 /* c90 says that the constant is 2147483648 (which is not representable as a signed 32-bit
254 * value). To that constant you've then applied the negation operation. c90 doesn't have
255 * negative constants, only positive ones that have been negated. */
256 CHECKL(lrintl(make_lrd_cw(0xad78ebc5ac620000ULL,0xc041,0x027f)), (long)(-2147483647L - 1));
257 CHECKL(lrintl(make_lrd_cw(0xad78ebc5ac620000ULL,0xc041,0x027f)), (long)(-2147483647L - 1));
258 CHECKL(lrintl(make_lrd_cw(0xad78ebc5ac620000ULL,0xc041,0x067f)), (long)(-2147483647L - 1));
259 CHECKL(lrintl(make_lrd_cw(0xad78ebc5ac620000ULL,0xc041,0x067f)), (long)(-2147483647L - 1));
260 CHECKL(lrintl(make_lrd_cw(0xad78ebc5ac620000ULL,0xc041,0x0a7f)), (long)(-2147483647L - 1));
261 CHECKL(lrintl(make_lrd_cw(0xad78ebc5ac620000ULL,0xc041,0x0a7f)), (long)(-2147483647L - 1));
262 CHECKL(lrintl(make_lrd_cw(0xad78ebc5ac620000ULL,0xc041,0x0e7f)), (long)(-2147483647L - 1));
263 CHECKL(lrintl(make_lrd_cw(0xad78ebc5ac620000ULL,0xc041,0x0e7f)), (long)(-2147483647L - 1));
264#endif
265 set_cw(0x27f);
266
267 CHECK(logl(2.7182818284590452353602874713526625L), 1.0);
268
269 CHECK(remainderl(1.0L, 1.0L), 0.0);
270 CHECK(remainderl(1.0L, 1.5L), -0.5);
271 CHECK(remainderl(42.0L, 34.25L), 7.75);
272 CHECK(remainderf(43.0, 34.25), 8.75);
273 CHECK(remainder(44.25, 34.25), 10.00);
274 double rd1 = 44.25;
275 double rd2 = 34.25;
276 CHECK(remainder(rd1, rd2), 10.00);
277 CHECK(remainder(2.5, 2.0), 0.5);
278 CHECK(remainder(2.5, 2.0), 0.5);
279 CHECK(remainder(2.5, 2.0), 0.5);
280 CHECKLL(testremainder(), 1);
281
282
283 CHECK(rintl(1.0L), 1.0);
284 CHECK(rintl(1.4L), 1.0);
285 CHECK(rintl(1.3L), 1.0);
286 CHECK(rintl(0.9L), 1.0);
287 CHECK(rintl(3123.1232L), 3123.0);
288 CHECK(rint(3985.13454), 3985.0);
289 CHECK(rintf(9999.999), 10000.0);
290
291 CHECK(sinl(1.0L), 0.84147098480789650664L);
292 lrd = 180.0L;
293 CHECK(sinl(lrd), -0.801152635733830477871L);
294 CHECK(sinl(180.0L), SIN180);
295 CHECKLL(testsin(), 1);
296
297 CHECK(sqrtl(1.0L), 1.0);
298 CHECK(sqrtl(4.0L), 2.0);
299 CHECK(sqrtl(1525225.0L), 1235.0);
300
301 CHECK(tanl(0.0L), 0.0);
302 CHECK(tanl(0.7853981633974483096156608458198757L), 1.0);
303
304 CHECK(powl(0.0, 0.0), 1.0);
305 CHECK(powl(2.0, 2.0), 4.0);
306 CHECK(powl(3.0, 3.0), 27.0);
307
308 return cErrors;
309}
310
311
312/////////////////////////////////////////////////////////////////////////////////////////
313/////////////////////////////////////////////////////////////////////////////////////////
314/////////////////////////////////////////////////////////////////////////////////////////
315#if 0
316
317#define floatx_to_int32 floatx80_to_int32
318#define floatx_to_int64 floatx80_to_int64
319#define floatx_to_int32_round_to_zero floatx80_to_int32_round_to_zero
320#define floatx_to_int64_round_to_zero floatx80_to_int64_round_to_zero
321#define floatx_abs floatx80_abs
322#define floatx_chs floatx80_chs
323#define floatx_round_to_int(foo, bar) floatx80_round_to_int(foo, NULL)
324#define floatx_compare floatx80_compare
325#define floatx_compare_quiet floatx80_compare_quiet
326#undef sin
327#undef cos
328#undef sqrt
329#undef pow
330#undef log
331#undef tan
332#undef atan2
333#undef floor
334#undef ceil
335#undef ldexp
336#define sin sinl
337#define cos cosl
338#define sqrt sqrtl
339#define pow powl
340#define log logl
341#define tan tanl
342#define atan2 atan2l
343#define floor floorl
344#define ceil ceill
345#define ldexp ldexpl
346
347
348typedef long double CPU86_LDouble;
349
350typedef union {
351 long double d;
352 struct {
353 unsigned long long lower;
354 unsigned short upper;
355 } l;
356} CPU86_LDoubleU;
357
358/* the following deal with x86 long double-precision numbers */
359#define MAXEXPD 0x7fff
360#define EXPBIAS 16383
361#define EXPD(fp) (fp.l.upper & 0x7fff)
362#define SIGND(fp) ((fp.l.upper) & 0x8000)
363#define MANTD(fp) (fp.l.lower)
364#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
365
366typedef long double floatx80;
367#define STATUS_PARAM , void *pv
368
369static floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM)
370{
371 return rintl(a);
372}
373
374
375
376struct myenv
377{
378 unsigned int fpstt; /* top of stack index */
379 unsigned int fpus;
380 unsigned int fpuc;
381 unsigned char fptags[8]; /* 0 = valid, 1 = empty */
382 union {
383#ifdef USE_X86LDOUBLE
384 CPU86_LDouble d __attribute__((aligned(16)));
385#else
386 CPU86_LDouble d;
387#endif
388 } fpregs[8];
389
390} my_env, env_org, env_res, *env = &my_env;
391
392
393#define ST0 (env->fpregs[env->fpstt].d)
394#define ST(n) (env->fpregs[(env->fpstt + (n)) & 7].d)
395#define ST1 ST(1)
396#define MAXTAN 9223372036854775808.0
397
398
399static inline void fpush(void)
400{
401 env->fpstt = (env->fpstt - 1) & 7;
402 env->fptags[env->fpstt] = 0; /* validate stack entry */
403}
404
405static inline void fpop(void)
406{
407 env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
408 env->fpstt = (env->fpstt + 1) & 7;
409}
410
411static void helper_f2xm1(void)
412{
413 ST0 = pow(2.0,ST0) - 1.0;
414}
415
416static void helper_fyl2x(void)
417{
418 CPU86_LDouble fptemp;
419
420 fptemp = ST0;
421 if (fptemp>0.0){
422 fptemp = log(fptemp)/log(2.0); /* log2(ST) */
423 ST1 *= fptemp;
424 fpop();
425 } else {
426 env->fpus &= (~0x4700);
427 env->fpus |= 0x400;
428 }
429}
430
431static void helper_fptan(void)
432{
433 CPU86_LDouble fptemp;
434
435 fptemp = ST0;
436 if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
437 env->fpus |= 0x400;
438 } else {
439 ST0 = tan(fptemp);
440 fpush();
441 ST0 = 1.0;
442 env->fpus &= (~0x400); /* C2 <-- 0 */
443 /* the above code is for |arg| < 2**52 only */
444 }
445}
446
447static void helper_fpatan(void)
448{
449 CPU86_LDouble fptemp, fpsrcop;
450
451 fpsrcop = ST1;
452 fptemp = ST0;
453 ST1 = atan2(fpsrcop,fptemp);
454 fpop();
455}
456
457static void helper_fxtract(void)
458{
459 CPU86_LDoubleU temp;
460 unsigned int expdif;
461
462 temp.d = ST0;
463 expdif = EXPD(temp) - EXPBIAS;
464 /*DP exponent bias*/
465 ST0 = expdif;
466 fpush();
467 BIASEXPONENT(temp);
468 ST0 = temp.d;
469}
470
471static void helper_fprem1(void)
472{
473 CPU86_LDouble dblq, fpsrcop, fptemp;
474 CPU86_LDoubleU fpsrcop1, fptemp1;
475 int expdif;
476 int q;
477
478 fpsrcop = ST0;
479 fptemp = ST1;
480 fpsrcop1.d = fpsrcop;
481 fptemp1.d = fptemp;
482 expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
483 if (expdif < 53) {
484 dblq = fpsrcop / fptemp;
485 dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
486 ST0 = fpsrcop - fptemp*dblq;
487 q = (int)dblq; /* cutting off top bits is assumed here */
488 env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
489 /* (C0,C1,C3) <-- (q2,q1,q0) */
490 env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
491 env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
492 env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
493 } else {
494 env->fpus |= 0x400; /* C2 <-- 1 */
495 fptemp = pow(2.0, expdif-50);
496 fpsrcop = (ST0 / ST1) / fptemp;
497 /* fpsrcop = integer obtained by rounding to the nearest */
498 fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
499 floor(fpsrcop): ceil(fpsrcop);
500 ST0 -= (ST1 * fpsrcop * fptemp);
501 }
502}
503
504static void helper_fprem(void)
505{
506#if 0
507LogFlow(("helper_fprem: ST0=%.*Vhxs ST1=%.*Vhxs fpus=%#x\n", sizeof(ST0), &ST0, sizeof(ST1), &ST1, env->fpus));
508
509 __asm__ __volatile__("fldt (%2)\n"
510 "fldt (%1)\n"
511 "fprem \n"
512 "fnstsw (%0)\n"
513 "fstpt (%1)\n"
514 "fstpt (%2)\n"
515 : : "r" (&env->fpus), "r" (&ST0), "r" (&ST1) : "memory");
516
517LogFlow(("helper_fprem: -> ST0=%.*Vhxs fpus=%#x c\n", sizeof(ST0), &ST0, env->fpus));
518#else
519 CPU86_LDouble dblq, fpsrcop, fptemp;
520 CPU86_LDoubleU fpsrcop1, fptemp1;
521 int expdif;
522 int q;
523
524 fpsrcop = ST0;
525 fptemp = ST1;
526 fpsrcop1.d = fpsrcop;
527 fptemp1.d = fptemp;
528
529 expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
530 if ( expdif < 53 ) {
531 dblq = fpsrcop / fptemp;
532 dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
533 ST0 = fpsrcop - fptemp*dblq;
534 q = (int)dblq; /* cutting off top bits is assumed here */
535 env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
536 /* (C0,C1,C3) <-- (q2,q1,q0) */
537 env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
538 env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
539 env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
540 } else {
541 env->fpus |= 0x400; /* C2 <-- 1 */
542 fptemp = pow(2.0, expdif-50);
543 fpsrcop = (ST0 / ST1) / fptemp;
544 /* fpsrcop = integer obtained by chopping */
545 fpsrcop = (fpsrcop < 0.0)?
546 -(floor(fabs(fpsrcop))): floor(fpsrcop);
547 ST0 -= (ST1 * fpsrcop * fptemp);
548 }
549#endif
550}
551
552static void helper_fyl2xp1(void)
553{
554 CPU86_LDouble fptemp;
555
556 fptemp = ST0;
557 if ((fptemp+1.0)>0.0) {
558 fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
559 ST1 *= fptemp;
560 fpop();
561 } else {
562 env->fpus &= (~0x4700);
563 env->fpus |= 0x400;
564 }
565}
566
567static void helper_fsqrt(void)
568{
569 CPU86_LDouble fptemp;
570
571 fptemp = ST0;
572 if (fptemp<0.0) {
573 env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
574 env->fpus |= 0x400;
575 }
576 ST0 = sqrt(fptemp);
577}
578
579static void helper_fsincos(void)
580{
581 CPU86_LDouble fptemp;
582
583 fptemp = ST0;
584 if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
585 env->fpus |= 0x400;
586 } else {
587 ST0 = sin(fptemp);
588 fpush();
589 ST0 = cos(fptemp);
590 env->fpus &= (~0x400); /* C2 <-- 0 */
591 /* the above code is for |arg| < 2**63 only */
592 }
593}
594
595static void helper_frndint(void)
596{
597 ST0 = floatx_round_to_int(ST0, &env->fp_status);
598}
599
600static void helper_fscale(void)
601{
602 ST0 = ldexp (ST0, (int)(ST1));
603}
604
605static void helper_fsin(void)
606{
607 CPU86_LDouble fptemp;
608
609 fptemp = ST0;
610 if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
611 env->fpus |= 0x400;
612 } else {
613 ST0 = sin(fptemp);
614 env->fpus &= (~0x400); /* C2 <-- 0 */
615 /* the above code is for |arg| < 2**53 only */
616 }
617}
618
619static void helper_fcos(void)
620{
621 CPU86_LDouble fptemp;
622
623 fptemp = ST0;
624 if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
625 env->fpus |= 0x400;
626 } else {
627 ST0 = cos(fptemp);
628 env->fpus &= (~0x400); /* C2 <-- 0 */
629 /* the above code is for |arg5 < 2**63 only */
630 }
631}
632
633static void helper_fxam_ST0(void)
634{
635 CPU86_LDoubleU temp;
636 int expdif;
637
638 temp.d = ST0;
639
640 env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
641 if (SIGND(temp))
642 env->fpus |= 0x200; /* C1 <-- 1 */
643
644 /* XXX: test fptags too */
645 expdif = EXPD(temp);
646 if (expdif == MAXEXPD) {
647#ifdef USE_X86LDOUBLE
648 if (MANTD(temp) == 0x8000000000000000ULL)
649#else
650 if (MANTD(temp) == 0)
651#endif
652 env->fpus |= 0x500 /*Infinity*/;
653 else
654 env->fpus |= 0x100 /*NaN*/;
655 } else if (expdif == 0) {
656 if (MANTD(temp) == 0)
657 env->fpus |= 0x4000 /*Zero*/;
658 else
659 env->fpus |= 0x4400 /*Denormal*/;
660 } else {
661 env->fpus |= 0x400;
662 }
663}
664
665
666void check_env(void)
667{
668 int i;
669 for (i = 0; i < 8; i++)
670 {
671 CPU86_LDoubleU my, res;
672 my.d = env->fpregs[i].d;
673 res.d = env_res.fpregs[i].d;
674
675 if ( my.l.lower != res.l.lower
676 || my.l.upper != res.l.upper)
677 printf("register %i: %#018llx:%#06x\n"
678 " expected %#018llx:%#06x\n",
679 i,
680 my.l.lower, my.l.upper,
681 res.l.lower, res.l.upper);
682 }
683 for (i = 0; i < 8; i++)
684 if (env->fptags[i] != env_res.fptags[i])
685 printf("tag %i: %d != %d\n", i, env->fptags[i], env_res.fptags[i]);
686 if (env->fpstt != env_res.fpstt)
687 printf("fpstt: %#06x != %#06x\n", env->fpstt, env_res.fpstt);
688 if (env->fpuc != env_res.fpuc)
689 printf("fpuc: %#06x != %#06x\n", env->fpuc, env_res.fpuc);
690 if (env->fpus != env_res.fpus)
691 printf("fpus: %#06x != %#06x\n", env->fpus, env_res.fpus);
692}
693#endif /* not used. */
694
695#if 0 /* insert this into helper.c */
696/* FPU helpers */
697CPU86_LDoubleU my_st[8];
698unsigned int my_fpstt;
699unsigned int my_fpus;
700unsigned int my_fpuc;
701unsigned char my_fptags[8];
702
703void hlp_fpu_enter(void)
704{
705 int i;
706 for (i = 0; i < 8; i++)
707 my_st[i].d = env->fpregs[i].d;
708 my_fpstt = env->fpstt;
709 my_fpus = env->fpus;
710 my_fpuc = env->fpuc;
711 memcpy(&my_fptags, &env->fptags, sizeof(my_fptags));
712}
713
714void hlp_fpu_leave(const char *psz)
715{
716 int i;
717 Log(("/*code*/ \n"));
718 for (i = 0; i < 8; i++)
719 Log(("/*code*/ *(unsigned long long *)&env_org.fpregs[%d] = %#018llxULL; ((unsigned short *)&env_org.fpregs[%d])[4] = %#06x; env_org.fptags[%d]=%d;\n",
720 i, my_st[i].l.lower, i, my_st[i].l.upper, i, my_fptags[i]));
721 Log(("/*code*/ env_org.fpstt=%#x;\n", my_fpstt));
722 Log(("/*code*/ env_org.fpus=%#x;\n", my_fpus));
723 Log(("/*code*/ env_org.fpuc=%#x;\n", my_fpuc));
724 for (i = 0; i < 8; i++)
725 {
726 CPU86_LDoubleU u;
727 u.d = env->fpregs[i].d;
728 Log(("/*code*/ *(unsigned long long *)&env_res.fpregs[%d] = %#018llxULL; ((unsigned short *)&env_res.fpregs[%d])[4] = %#06x; env_res.fptags[%d]=%d;\n",
729 i, u.l.lower, i, u.l.upper, i, env->fptags[i]));
730 }
731 Log(("/*code*/ env_res.fpstt=%#x;\n", env->fpstt));
732 Log(("/*code*/ env_res.fpus=%#x;\n", env->fpus));
733 Log(("/*code*/ env_res.fpuc=%#x;\n", env->fpuc));
734
735 Log(("/*code*/ my_env = env_org;\n"));
736 Log(("/*code*/ %s();\n", psz));
737 Log(("/*code*/ check_env();\n"));
738}
739#endif /* helper.c */
740
741extern void testmath2(void )
742{
743#if 0
744#include "/tmp/code.h"
745#endif
746}
747
748
749/////////////////////////////////////////////////////////////////////////////////////////
750/////////////////////////////////////////////////////////////////////////////////////////
751/////////////////////////////////////////////////////////////////////////////////////////
752
753#ifdef MATHTEST_STANDALONE
754
755void test_fops(double a, double b)
756{
757 printf("a=%f b=%f a+b=%f\n", a, b, a + b);
758 printf("a=%f b=%f a-b=%f\n", a, b, a - b);
759 printf("a=%f b=%f a*b=%f\n", a, b, a * b);
760 printf("a=%f b=%f a/b=%f\n", a, b, a / b);
761 printf("a=%f b=%f fmod(a, b)=%f\n", a, b, (double)fmod(a, b));
762 printf("a=%f sqrt(a)=%f\n", a, (double)sqrtl(a));
763 printf("a=%f sin(a)=%f\n", a, (double)sinl(a));
764 printf("a=%f cos(a)=%f\n", a, (double)cos(a));
765 printf("a=%f tan(a)=%f\n", a, (double)tanl(a));
766 printf("a=%f log(a)=%f\n", a, (double)log(a));
767 printf("a=%f exp(a)=%f\n", a, (double)exp(a));
768 printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
769 /* just to test some op combining */
770 printf("a=%f asin(sinl(a))=%f\n", a, (double)asin(sinl(a)));
771 printf("a=%f acos(cos(a))=%f\n", a, (double)acos(cos(a)));
772 printf("a=%f atan(tanl(a))=%f\n", a, (double)atan(tanl(a)));
773}
774
775int main()
776{
777 unsigned cErrors = testmath();
778
779 testmath2();
780 test_fops(2, 3);
781 test_fops(1.4, -5);
782
783 printf("cErrors=%d\n", cErrors);
784 return cErrors;
785}
786#endif
787
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette