VirtualBox

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

Last change on this file since 76553 was 76553, checked in by vboxsync, 5 years ago

scm --update-copyright-year

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

© 2023 Oracle
ContactPrivacy policyTerms of Use