~ubuntu-branches/ubuntu/gutsy/virtualbox-ose/gutsy

« back to all changes in this revision

Viewing changes to src/recompiler/InnoTek/testmath.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2007-09-08 16:44:58 UTC
  • Revision ID: james.westby@ubuntu.com-20070908164458-wao29470vqtr8ksy
Tags: upstream-1.5.0-dfsg2
ImportĀ upstreamĀ versionĀ 1.5.0-dfsg2

Show diffs side-by-side

added added

removed removed

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