VirtualBox

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

Last change on this file since 55786 was 42474, checked in by vboxsync, 12 years ago

recompiler/Sun/testmath.c: be a bit more generous with the rounding. Necessary on a VIA system with gcc 4.6.3

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