Commit 7a0e1f41ceeb658791a1456ffc7f8f9edca7da19
1 parent
4ecc3190
soft float support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1336 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
9 changed files
with
139 additions
and
231 deletions
dyngen-exec.h
... | ... | @@ -62,17 +62,6 @@ extern int fprintf(FILE *, const char *, ...); |
62 | 62 | extern int printf(const char *, ...); |
63 | 63 | #undef NULL |
64 | 64 | #define NULL 0 |
65 | -#if defined(_BSD) && !defined(__APPLE__) | |
66 | -#include <ieeefp.h> | |
67 | - | |
68 | -#define FE_TONEAREST FP_RN | |
69 | -#define FE_DOWNWARD FP_RM | |
70 | -#define FE_UPWARD FP_RP | |
71 | -#define FE_TOWARDZERO FP_RZ | |
72 | -#define fesetround(x) fpsetround(x) | |
73 | -#else | |
74 | -#include <fenv.h> | |
75 | -#endif | |
76 | 65 | |
77 | 66 | #ifdef __i386__ |
78 | 67 | #define AREG0 "ebp" | ... | ... |
target-i386/cpu.h
... | ... | @@ -36,6 +36,8 @@ |
36 | 36 | |
37 | 37 | #include "cpu-defs.h" |
38 | 38 | |
39 | +#include "softfloat.h" | |
40 | + | |
39 | 41 | #if defined(__i386__) && !defined(CONFIG_SOFTMMU) |
40 | 42 | #define USE_CODE_COPY |
41 | 43 | #endif |
... | ... | @@ -332,14 +334,14 @@ enum { |
332 | 334 | CC_OP_NB, |
333 | 335 | }; |
334 | 336 | |
335 | -#if (defined(__i386__) || defined(__x86_64__)) && !defined(_BSD) | |
337 | +#ifdef FLOATX80 | |
336 | 338 | #define USE_X86LDOUBLE |
337 | 339 | #endif |
338 | 340 | |
339 | 341 | #ifdef USE_X86LDOUBLE |
340 | -typedef long double CPU86_LDouble; | |
342 | +typedef floatx80 CPU86_LDouble; | |
341 | 343 | #else |
342 | -typedef double CPU86_LDouble; | |
344 | +typedef float64 CPU86_LDouble; | |
343 | 345 | #endif |
344 | 346 | |
345 | 347 | typedef struct SegmentCache { |
... | ... | @@ -354,8 +356,8 @@ typedef union { |
354 | 356 | uint16_t _w[8]; |
355 | 357 | uint32_t _l[4]; |
356 | 358 | uint64_t _q[2]; |
357 | - float _s[4]; | |
358 | - double _d[2]; | |
359 | + float32 _s[4]; | |
360 | + float64 _d[2]; | |
359 | 361 | } XMMReg; |
360 | 362 | |
361 | 363 | typedef union { |
... | ... | @@ -441,6 +443,7 @@ typedef struct CPUX86State { |
441 | 443 | } fpregs[8]; |
442 | 444 | |
443 | 445 | /* emulator internal variables */ |
446 | + float_status fp_status; | |
444 | 447 | CPU86_LDouble ft0; |
445 | 448 | union { |
446 | 449 | float f; |
... | ... | @@ -449,6 +452,7 @@ typedef struct CPUX86State { |
449 | 452 | int64_t i64; |
450 | 453 | } fp_convert; |
451 | 454 | |
455 | + float_status sse_status; | |
452 | 456 | uint32_t mxcsr; |
453 | 457 | XMMReg xmm_regs[CPU_NB_REGS]; |
454 | 458 | XMMReg xmm_t0; | ... | ... |
target-i386/exec.h
... | ... | @@ -139,44 +139,6 @@ extern int loglevel; |
139 | 139 | #include "cpu.h" |
140 | 140 | #include "exec-all.h" |
141 | 141 | |
142 | -/* XXX: add a generic FPU library */ | |
143 | - | |
144 | -static inline double float32_to_float64(float a) | |
145 | -{ | |
146 | - return a; | |
147 | -} | |
148 | - | |
149 | -static inline float float64_to_float32(double a) | |
150 | -{ | |
151 | - return a; | |
152 | -} | |
153 | - | |
154 | -#if defined(__powerpc__) | |
155 | -/* better to call an helper on ppc */ | |
156 | -float int32_to_float32(int32_t a); | |
157 | -double int32_to_float64(int32_t a); | |
158 | -#else | |
159 | -static inline float int32_to_float32(int32_t a) | |
160 | -{ | |
161 | - return (float)a; | |
162 | -} | |
163 | - | |
164 | -static inline double int32_to_float64(int32_t a) | |
165 | -{ | |
166 | - return (double)a; | |
167 | -} | |
168 | -#endif | |
169 | - | |
170 | -static inline float int64_to_float32(int64_t a) | |
171 | -{ | |
172 | - return (float)a; | |
173 | -} | |
174 | - | |
175 | -static inline double int64_to_float64(int64_t a) | |
176 | -{ | |
177 | - return (double)a; | |
178 | -} | |
179 | - | |
180 | 142 | typedef struct CCTable { |
181 | 143 | int (*compute_all)(void); /* return all the flags */ |
182 | 144 | int (*compute_c)(void); /* return the C flag */ |
... | ... | @@ -358,9 +320,11 @@ static inline void stfl(target_ulong ptr, float v) |
358 | 320 | |
359 | 321 | #ifdef USE_X86LDOUBLE |
360 | 322 | /* use long double functions */ |
361 | -#define lrint lrintl | |
362 | -#define llrint llrintl | |
363 | -#define fabs fabsl | |
323 | +#define floatx_to_int32 floatx80_to_int32 | |
324 | +#define floatx_to_int64 floatx80_to_int64 | |
325 | +#define floatx_abs floatx80_abs | |
326 | +#define floatx_chs floatx80_chs | |
327 | +#define floatx_round_to_int floatx80_round_to_int | |
364 | 328 | #define sin sinl |
365 | 329 | #define cos cosl |
366 | 330 | #define sqrt sqrtl |
... | ... | @@ -370,17 +334,14 @@ static inline void stfl(target_ulong ptr, float v) |
370 | 334 | #define atan2 atan2l |
371 | 335 | #define floor floorl |
372 | 336 | #define ceil ceill |
373 | -#define rint rintl | |
374 | -#endif | |
375 | - | |
376 | -#if !defined(_BSD) | |
377 | -extern int lrint(CPU86_LDouble x); | |
378 | -extern int64_t llrint(CPU86_LDouble x); | |
379 | 337 | #else |
380 | -#define lrint(d) ((int)rint(d)) | |
381 | -#define llrint(d) ((int)rint(d)) | |
338 | +#define floatx_to_int32 float64_to_int32 | |
339 | +#define floatx_to_int64 float64_to_int64 | |
340 | +#define floatx_abs float64_abs | |
341 | +#define floatx_chs float64_chs | |
342 | +#define floatx_round_to_int float64_round_to_int | |
382 | 343 | #endif |
383 | -extern CPU86_LDouble fabs(CPU86_LDouble x); | |
344 | + | |
384 | 345 | extern CPU86_LDouble sin(CPU86_LDouble x); |
385 | 346 | extern CPU86_LDouble cos(CPU86_LDouble x); |
386 | 347 | extern CPU86_LDouble sqrt(CPU86_LDouble x); |
... | ... | @@ -390,7 +351,6 @@ extern CPU86_LDouble tan(CPU86_LDouble x); |
390 | 351 | extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble); |
391 | 352 | extern CPU86_LDouble floor(CPU86_LDouble x); |
392 | 353 | extern CPU86_LDouble ceil(CPU86_LDouble x); |
393 | -extern CPU86_LDouble rint(CPU86_LDouble x); | |
394 | 354 | |
395 | 355 | #define RC_MASK 0xc00 |
396 | 356 | #define RC_NEAR 0x000 |
... | ... | @@ -400,13 +360,6 @@ extern CPU86_LDouble rint(CPU86_LDouble x); |
400 | 360 | |
401 | 361 | #define MAXTAN 9223372036854775808.0 |
402 | 362 | |
403 | -#ifdef __arm__ | |
404 | -/* we have no way to do correct rounding - a FPU emulator is needed */ | |
405 | -#define FE_DOWNWARD FE_TONEAREST | |
406 | -#define FE_UPWARD FE_TONEAREST | |
407 | -#define FE_TOWARDZERO FE_TONEAREST | |
408 | -#endif | |
409 | - | |
410 | 363 | #ifdef USE_X86LDOUBLE |
411 | 364 | |
412 | 365 | /* only for x86 */ |
... | ... | @@ -596,6 +549,7 @@ float approx_rsqrt(float a); |
596 | 549 | float approx_rcp(float a); |
597 | 550 | double helper_sqrt(double a); |
598 | 551 | int fpu_isnan(double a); |
552 | +void update_fp_status(void); | |
599 | 553 | |
600 | 554 | extern const uint8_t parity_table[256]; |
601 | 555 | extern const uint8_t rclw_table[32]; | ... | ... |
target-i386/helper.c
... | ... | @@ -2541,13 +2541,11 @@ void helper_fbld_ST0_A0(void) |
2541 | 2541 | |
2542 | 2542 | void helper_fbst_ST0_A0(void) |
2543 | 2543 | { |
2544 | - CPU86_LDouble tmp; | |
2545 | 2544 | int v; |
2546 | 2545 | target_ulong mem_ref, mem_end; |
2547 | 2546 | int64_t val; |
2548 | 2547 | |
2549 | - tmp = rint(ST0); | |
2550 | - val = (int64_t)tmp; | |
2548 | + val = floatx_to_int64(ST0, &env->fp_status); | |
2551 | 2549 | mem_ref = A0; |
2552 | 2550 | mem_end = mem_ref + 9; |
2553 | 2551 | if (val < 0) { |
... | ... | @@ -2740,29 +2738,7 @@ void helper_fsincos(void) |
2740 | 2738 | |
2741 | 2739 | void helper_frndint(void) |
2742 | 2740 | { |
2743 | - CPU86_LDouble a; | |
2744 | - | |
2745 | - a = ST0; | |
2746 | -#ifdef __arm__ | |
2747 | - switch(env->fpuc & RC_MASK) { | |
2748 | - default: | |
2749 | - case RC_NEAR: | |
2750 | - asm("rndd %0, %1" : "=f" (a) : "f"(a)); | |
2751 | - break; | |
2752 | - case RC_DOWN: | |
2753 | - asm("rnddm %0, %1" : "=f" (a) : "f"(a)); | |
2754 | - break; | |
2755 | - case RC_UP: | |
2756 | - asm("rnddp %0, %1" : "=f" (a) : "f"(a)); | |
2757 | - break; | |
2758 | - case RC_CHOP: | |
2759 | - asm("rnddz %0, %1" : "=f" (a) : "f"(a)); | |
2760 | - break; | |
2761 | - } | |
2762 | -#else | |
2763 | - a = rint(a); | |
2764 | -#endif | |
2765 | - ST0 = a; | |
2741 | + ST0 = floatx_round_to_int(ST0, &env->fp_status); | |
2766 | 2742 | } |
2767 | 2743 | |
2768 | 2744 | void helper_fscale(void) |
... | ... | @@ -3263,25 +3239,43 @@ float approx_rcp(float a) |
3263 | 3239 | return 1.0 / a; |
3264 | 3240 | } |
3265 | 3241 | |
3266 | -/* XXX: find a better solution */ | |
3267 | -double helper_sqrt(double a) | |
3242 | +void update_fp_status(void) | |
3268 | 3243 | { |
3269 | - return sqrt(a); | |
3270 | -} | |
3244 | + int rnd_type; | |
3271 | 3245 | |
3272 | -/* XXX: move that to another file */ | |
3273 | -#if defined(__powerpc__) | |
3274 | -/* better to call an helper on ppc */ | |
3275 | -float int32_to_float32(int32_t a) | |
3276 | -{ | |
3277 | - return (float)a; | |
3278 | -} | |
3279 | - | |
3280 | -double int32_to_float64(int32_t a) | |
3281 | -{ | |
3282 | - return (double)a; | |
3283 | -} | |
3246 | + /* set rounding mode */ | |
3247 | + switch(env->fpuc & RC_MASK) { | |
3248 | + default: | |
3249 | + case RC_NEAR: | |
3250 | + rnd_type = float_round_nearest_even; | |
3251 | + break; | |
3252 | + case RC_DOWN: | |
3253 | + rnd_type = float_round_down; | |
3254 | + break; | |
3255 | + case RC_UP: | |
3256 | + rnd_type = float_round_up; | |
3257 | + break; | |
3258 | + case RC_CHOP: | |
3259 | + rnd_type = float_round_to_zero; | |
3260 | + break; | |
3261 | + } | |
3262 | + set_float_rounding_mode(rnd_type, &env->fp_status); | |
3263 | +#ifdef FLOATX80 | |
3264 | + switch((env->fpuc >> 8) & 3) { | |
3265 | + case 0: | |
3266 | + rnd_type = 32; | |
3267 | + break; | |
3268 | + case 2: | |
3269 | + rnd_type = 64; | |
3270 | + break; | |
3271 | + case 3: | |
3272 | + default: | |
3273 | + rnd_type = 80; | |
3274 | + break; | |
3275 | + } | |
3276 | + set_floatx80_rounding_precision(rnd_type, &env->fp_status); | |
3284 | 3277 | #endif |
3278 | +} | |
3285 | 3279 | |
3286 | 3280 | #if !defined(CONFIG_USER_ONLY) |
3287 | 3281 | ... | ... |
target-i386/op.c
... | ... | @@ -1598,26 +1598,6 @@ CCTable cc_table[CC_OP_NB] = { |
1598 | 1598 | functions comes from the LGPL'ed x86 emulator found in the Willows |
1599 | 1599 | TWIN windows emulator. */ |
1600 | 1600 | |
1601 | -#if defined(__powerpc__) | |
1602 | -extern CPU86_LDouble copysign(CPU86_LDouble, CPU86_LDouble); | |
1603 | - | |
1604 | -/* correct (but slow) PowerPC rint() (glibc version is incorrect) */ | |
1605 | -double qemu_rint(double x) | |
1606 | -{ | |
1607 | - double y = 4503599627370496.0; | |
1608 | - if (fabs(x) >= y) | |
1609 | - return x; | |
1610 | - if (x < 0) | |
1611 | - y = -y; | |
1612 | - y = (x + y) - y; | |
1613 | - if (y == 0.0) | |
1614 | - y = copysign(y, x); | |
1615 | - return y; | |
1616 | -} | |
1617 | - | |
1618 | -#define rint qemu_rint | |
1619 | -#endif | |
1620 | - | |
1621 | 1601 | /* fp load FT0 */ |
1622 | 1602 | |
1623 | 1603 | void OPPROTO op_flds_FT0_A0(void) |
... | ... | @@ -1866,7 +1846,7 @@ void OPPROTO op_fist_ST0_A0(void) |
1866 | 1846 | int val; |
1867 | 1847 | |
1868 | 1848 | d = ST0; |
1869 | - val = lrint(d); | |
1849 | + val = floatx_to_int32(d, &env->fp_status); | |
1870 | 1850 | if (val != (int16_t)val) |
1871 | 1851 | val = -32768; |
1872 | 1852 | stw(A0, val); |
... | ... | @@ -1883,7 +1863,7 @@ void OPPROTO op_fistl_ST0_A0(void) |
1883 | 1863 | int val; |
1884 | 1864 | |
1885 | 1865 | d = ST0; |
1886 | - val = lrint(d); | |
1866 | + val = floatx_to_int32(d, &env->fp_status); | |
1887 | 1867 | stl(A0, val); |
1888 | 1868 | FORCE_RET(); |
1889 | 1869 | } |
... | ... | @@ -1898,7 +1878,7 @@ void OPPROTO op_fistll_ST0_A0(void) |
1898 | 1878 | int64_t val; |
1899 | 1879 | |
1900 | 1880 | d = ST0; |
1901 | - val = llrint(d); | |
1881 | + val = floatx_to_int64(d, &env->fp_status); | |
1902 | 1882 | stq(A0, val); |
1903 | 1883 | FORCE_RET(); |
1904 | 1884 | } |
... | ... | @@ -2101,12 +2081,12 @@ void OPPROTO op_fdivr_STN_ST0(void) |
2101 | 2081 | /* misc FPU operations */ |
2102 | 2082 | void OPPROTO op_fchs_ST0(void) |
2103 | 2083 | { |
2104 | - ST0 = -ST0; | |
2084 | + ST0 = floatx_chs(ST0); | |
2105 | 2085 | } |
2106 | 2086 | |
2107 | 2087 | void OPPROTO op_fabs_ST0(void) |
2108 | 2088 | { |
2109 | - ST0 = fabs(ST0); | |
2089 | + ST0 = floatx_abs(ST0); | |
2110 | 2090 | } |
2111 | 2091 | |
2112 | 2092 | void OPPROTO op_fxam_ST0(void) |
... | ... | @@ -2251,25 +2231,8 @@ void OPPROTO op_fnstcw_A0(void) |
2251 | 2231 | |
2252 | 2232 | void OPPROTO op_fldcw_A0(void) |
2253 | 2233 | { |
2254 | - int rnd_type; | |
2255 | 2234 | env->fpuc = lduw(A0); |
2256 | - /* set rounding mode */ | |
2257 | - switch(env->fpuc & RC_MASK) { | |
2258 | - default: | |
2259 | - case RC_NEAR: | |
2260 | - rnd_type = FE_TONEAREST; | |
2261 | - break; | |
2262 | - case RC_DOWN: | |
2263 | - rnd_type = FE_DOWNWARD; | |
2264 | - break; | |
2265 | - case RC_UP: | |
2266 | - rnd_type = FE_UPWARD; | |
2267 | - break; | |
2268 | - case RC_CHOP: | |
2269 | - rnd_type = FE_TOWARDZERO; | |
2270 | - break; | |
2271 | - } | |
2272 | - fesetround(rnd_type); | |
2235 | + update_fp_status(); | |
2273 | 2236 | } |
2274 | 2237 | |
2275 | 2238 | void OPPROTO op_fclex(void) | ... | ... |
target-i386/ops_sse.h
... | ... | @@ -654,10 +654,10 @@ void OPPROTO op_ ## name ## ps (void)\ |
654 | 654 | Reg *d, *s;\ |
655 | 655 | d = (Reg *)((char *)env + PARAM1);\ |
656 | 656 | s = (Reg *)((char *)env + PARAM2);\ |
657 | - d->XMM_S(0) = F(d->XMM_S(0), s->XMM_S(0));\ | |
658 | - d->XMM_S(1) = F(d->XMM_S(1), s->XMM_S(1));\ | |
659 | - d->XMM_S(2) = F(d->XMM_S(2), s->XMM_S(2));\ | |
660 | - d->XMM_S(3) = F(d->XMM_S(3), s->XMM_S(3));\ | |
657 | + d->XMM_S(0) = F(32, d->XMM_S(0), s->XMM_S(0));\ | |
658 | + d->XMM_S(1) = F(32, d->XMM_S(1), s->XMM_S(1));\ | |
659 | + d->XMM_S(2) = F(32, d->XMM_S(2), s->XMM_S(2));\ | |
660 | + d->XMM_S(3) = F(32, d->XMM_S(3), s->XMM_S(3));\ | |
661 | 661 | }\ |
662 | 662 | \ |
663 | 663 | void OPPROTO op_ ## name ## ss (void)\ |
... | ... | @@ -665,15 +665,15 @@ void OPPROTO op_ ## name ## ss (void)\ |
665 | 665 | Reg *d, *s;\ |
666 | 666 | d = (Reg *)((char *)env + PARAM1);\ |
667 | 667 | s = (Reg *)((char *)env + PARAM2);\ |
668 | - d->XMM_S(0) = F(d->XMM_S(0), s->XMM_S(0));\ | |
668 | + d->XMM_S(0) = F(32, d->XMM_S(0), s->XMM_S(0));\ | |
669 | 669 | }\ |
670 | 670 | void OPPROTO op_ ## name ## pd (void)\ |
671 | 671 | {\ |
672 | 672 | Reg *d, *s;\ |
673 | 673 | d = (Reg *)((char *)env + PARAM1);\ |
674 | 674 | s = (Reg *)((char *)env + PARAM2);\ |
675 | - d->XMM_D(0) = F(d->XMM_D(0), s->XMM_D(0));\ | |
676 | - d->XMM_D(1) = F(d->XMM_D(1), s->XMM_D(1));\ | |
675 | + d->XMM_D(0) = F(64, d->XMM_D(0), s->XMM_D(0));\ | |
676 | + d->XMM_D(1) = F(64, d->XMM_D(1), s->XMM_D(1));\ | |
677 | 677 | }\ |
678 | 678 | \ |
679 | 679 | void OPPROTO op_ ## name ## sd (void)\ |
... | ... | @@ -681,16 +681,16 @@ void OPPROTO op_ ## name ## sd (void)\ |
681 | 681 | Reg *d, *s;\ |
682 | 682 | d = (Reg *)((char *)env + PARAM1);\ |
683 | 683 | s = (Reg *)((char *)env + PARAM2);\ |
684 | - d->XMM_D(0) = F(d->XMM_D(0), s->XMM_D(0));\ | |
684 | + d->XMM_D(0) = F(64, d->XMM_D(0), s->XMM_D(0));\ | |
685 | 685 | } |
686 | 686 | |
687 | -#define FPU_ADD(a, b) (a) + (b) | |
688 | -#define FPU_SUB(a, b) (a) - (b) | |
689 | -#define FPU_MUL(a, b) (a) * (b) | |
690 | -#define FPU_DIV(a, b) (a) / (b) | |
691 | -#define FPU_MIN(a, b) (a) < (b) ? (a) : (b) | |
692 | -#define FPU_MAX(a, b) (a) > (b) ? (a) : (b) | |
693 | -#define FPU_SQRT(a, b) helper_sqrt(b) | |
687 | +#define FPU_ADD(size, a, b) float ## size ## _add(a, b, &env->sse_status) | |
688 | +#define FPU_SUB(size, a, b) float ## size ## _sub(a, b, &env->sse_status) | |
689 | +#define FPU_MUL(size, a, b) float ## size ## _mul(a, b, &env->sse_status) | |
690 | +#define FPU_DIV(size, a, b) float ## size ## _div(a, b, &env->sse_status) | |
691 | +#define FPU_MIN(size, a, b) (a) < (b) ? (a) : (b) | |
692 | +#define FPU_MAX(size, a, b) (a) > (b) ? (a) : (b) | |
693 | +#define FPU_SQRT(size, a, b) float ## size ## _sqrt(b, &env->sse_status) | |
694 | 694 | |
695 | 695 | SSE_OP_S(add, FPU_ADD) |
696 | 696 | SSE_OP_S(sub, FPU_SUB) |
... | ... | @@ -710,8 +710,8 @@ void OPPROTO op_cvtps2pd(void) |
710 | 710 | s = (Reg *)((char *)env + PARAM2); |
711 | 711 | s0 = s->XMM_S(0); |
712 | 712 | s1 = s->XMM_S(1); |
713 | - d->XMM_D(0) = float32_to_float64(s0); | |
714 | - d->XMM_D(1) = float32_to_float64(s1); | |
713 | + d->XMM_D(0) = float32_to_float64(s0, &env->sse_status); | |
714 | + d->XMM_D(1) = float32_to_float64(s1, &env->sse_status); | |
715 | 715 | } |
716 | 716 | |
717 | 717 | void OPPROTO op_cvtpd2ps(void) |
... | ... | @@ -719,8 +719,8 @@ void OPPROTO op_cvtpd2ps(void) |
719 | 719 | Reg *d, *s; |
720 | 720 | d = (Reg *)((char *)env + PARAM1); |
721 | 721 | s = (Reg *)((char *)env + PARAM2); |
722 | - d->XMM_S(0) = float64_to_float32(s->XMM_D(0)); | |
723 | - d->XMM_S(1) = float64_to_float32(s->XMM_D(1)); | |
722 | + d->XMM_S(0) = float64_to_float32(s->XMM_D(0), &env->sse_status); | |
723 | + d->XMM_S(1) = float64_to_float32(s->XMM_D(1), &env->sse_status); | |
724 | 724 | d->Q(1) = 0; |
725 | 725 | } |
726 | 726 | |
... | ... | @@ -729,7 +729,7 @@ void OPPROTO op_cvtss2sd(void) |
729 | 729 | Reg *d, *s; |
730 | 730 | d = (Reg *)((char *)env + PARAM1); |
731 | 731 | s = (Reg *)((char *)env + PARAM2); |
732 | - d->XMM_D(0) = float32_to_float64(s->XMM_S(0)); | |
732 | + d->XMM_D(0) = float32_to_float64(s->XMM_S(0), &env->sse_status); | |
733 | 733 | } |
734 | 734 | |
735 | 735 | void OPPROTO op_cvtsd2ss(void) |
... | ... | @@ -737,7 +737,7 @@ void OPPROTO op_cvtsd2ss(void) |
737 | 737 | Reg *d, *s; |
738 | 738 | d = (Reg *)((char *)env + PARAM1); |
739 | 739 | s = (Reg *)((char *)env + PARAM2); |
740 | - d->XMM_S(0) = float64_to_float32(s->XMM_D(0)); | |
740 | + d->XMM_S(0) = float64_to_float32(s->XMM_D(0), &env->sse_status); | |
741 | 741 | } |
742 | 742 | |
743 | 743 | /* integer to float */ |
... | ... | @@ -745,10 +745,10 @@ void OPPROTO op_cvtdq2ps(void) |
745 | 745 | { |
746 | 746 | XMMReg *d = (XMMReg *)((char *)env + PARAM1); |
747 | 747 | XMMReg *s = (XMMReg *)((char *)env + PARAM2); |
748 | - d->XMM_S(0) = int32_to_float32(s->XMM_L(0)); | |
749 | - d->XMM_S(1) = int32_to_float32(s->XMM_L(1)); | |
750 | - d->XMM_S(2) = int32_to_float32(s->XMM_L(2)); | |
751 | - d->XMM_S(3) = int32_to_float32(s->XMM_L(3)); | |
748 | + d->XMM_S(0) = int32_to_float32(s->XMM_L(0), &env->sse_status); | |
749 | + d->XMM_S(1) = int32_to_float32(s->XMM_L(1), &env->sse_status); | |
750 | + d->XMM_S(2) = int32_to_float32(s->XMM_L(2), &env->sse_status); | |
751 | + d->XMM_S(3) = int32_to_float32(s->XMM_L(3), &env->sse_status); | |
752 | 752 | } |
753 | 753 | |
754 | 754 | void OPPROTO op_cvtdq2pd(void) |
... | ... | @@ -758,49 +758,49 @@ void OPPROTO op_cvtdq2pd(void) |
758 | 758 | int32_t l0, l1; |
759 | 759 | l0 = (int32_t)s->XMM_L(0); |
760 | 760 | l1 = (int32_t)s->XMM_L(1); |
761 | - d->XMM_D(0) = int32_to_float64(l0); | |
762 | - d->XMM_D(1) = int32_to_float64(l1); | |
761 | + d->XMM_D(0) = int32_to_float64(l0, &env->sse_status); | |
762 | + d->XMM_D(1) = int32_to_float64(l1, &env->sse_status); | |
763 | 763 | } |
764 | 764 | |
765 | 765 | void OPPROTO op_cvtpi2ps(void) |
766 | 766 | { |
767 | 767 | XMMReg *d = (Reg *)((char *)env + PARAM1); |
768 | 768 | MMXReg *s = (MMXReg *)((char *)env + PARAM2); |
769 | - d->XMM_S(0) = int32_to_float32(s->MMX_L(0)); | |
770 | - d->XMM_S(1) = int32_to_float32(s->MMX_L(1)); | |
769 | + d->XMM_S(0) = int32_to_float32(s->MMX_L(0), &env->sse_status); | |
770 | + d->XMM_S(1) = int32_to_float32(s->MMX_L(1), &env->sse_status); | |
771 | 771 | } |
772 | 772 | |
773 | 773 | void OPPROTO op_cvtpi2pd(void) |
774 | 774 | { |
775 | 775 | XMMReg *d = (Reg *)((char *)env + PARAM1); |
776 | 776 | MMXReg *s = (MMXReg *)((char *)env + PARAM2); |
777 | - d->XMM_D(0) = int32_to_float64(s->MMX_L(0)); | |
778 | - d->XMM_D(1) = int32_to_float64(s->MMX_L(1)); | |
777 | + d->XMM_D(0) = int32_to_float64(s->MMX_L(0), &env->sse_status); | |
778 | + d->XMM_D(1) = int32_to_float64(s->MMX_L(1), &env->sse_status); | |
779 | 779 | } |
780 | 780 | |
781 | 781 | void OPPROTO op_cvtsi2ss(void) |
782 | 782 | { |
783 | 783 | XMMReg *d = (Reg *)((char *)env + PARAM1); |
784 | - d->XMM_S(0) = int32_to_float32(T0); | |
784 | + d->XMM_S(0) = int32_to_float32(T0, &env->sse_status); | |
785 | 785 | } |
786 | 786 | |
787 | 787 | void OPPROTO op_cvtsi2sd(void) |
788 | 788 | { |
789 | 789 | XMMReg *d = (Reg *)((char *)env + PARAM1); |
790 | - d->XMM_D(0) = int32_to_float64(T0); | |
790 | + d->XMM_D(0) = int32_to_float64(T0, &env->sse_status); | |
791 | 791 | } |
792 | 792 | |
793 | 793 | #ifdef TARGET_X86_64 |
794 | 794 | void OPPROTO op_cvtsq2ss(void) |
795 | 795 | { |
796 | 796 | XMMReg *d = (Reg *)((char *)env + PARAM1); |
797 | - d->XMM_S(0) = int64_to_float32(T0); | |
797 | + d->XMM_S(0) = int64_to_float32(T0, &env->sse_status); | |
798 | 798 | } |
799 | 799 | |
800 | 800 | void OPPROTO op_cvtsq2sd(void) |
801 | 801 | { |
802 | 802 | XMMReg *d = (Reg *)((char *)env + PARAM1); |
803 | - d->XMM_D(0) = int64_to_float64(T0); | |
803 | + d->XMM_D(0) = int64_to_float64(T0, &env->sse_status); | |
804 | 804 | } |
805 | 805 | #endif |
806 | 806 | |
... | ... | @@ -809,18 +809,18 @@ void OPPROTO op_cvtps2dq(void) |
809 | 809 | { |
810 | 810 | XMMReg *d = (XMMReg *)((char *)env + PARAM1); |
811 | 811 | XMMReg *s = (XMMReg *)((char *)env + PARAM2); |
812 | - d->XMM_L(0) = lrint(s->XMM_S(0)); | |
813 | - d->XMM_L(1) = lrint(s->XMM_S(1)); | |
814 | - d->XMM_L(2) = lrint(s->XMM_S(2)); | |
815 | - d->XMM_L(3) = lrint(s->XMM_S(3)); | |
812 | + d->XMM_L(0) = float32_to_int32(s->XMM_S(0), &env->sse_status); | |
813 | + d->XMM_L(1) = float32_to_int32(s->XMM_S(1), &env->sse_status); | |
814 | + d->XMM_L(2) = float32_to_int32(s->XMM_S(2), &env->sse_status); | |
815 | + d->XMM_L(3) = float32_to_int32(s->XMM_S(3), &env->sse_status); | |
816 | 816 | } |
817 | 817 | |
818 | 818 | void OPPROTO op_cvtpd2dq(void) |
819 | 819 | { |
820 | 820 | XMMReg *d = (XMMReg *)((char *)env + PARAM1); |
821 | 821 | XMMReg *s = (XMMReg *)((char *)env + PARAM2); |
822 | - d->XMM_L(0) = lrint(s->XMM_D(0)); | |
823 | - d->XMM_L(1) = lrint(s->XMM_D(1)); | |
822 | + d->XMM_L(0) = float64_to_int32(s->XMM_D(0), &env->sse_status); | |
823 | + d->XMM_L(1) = float64_to_int32(s->XMM_D(1), &env->sse_status); | |
824 | 824 | d->XMM_Q(1) = 0; |
825 | 825 | } |
826 | 826 | |
... | ... | @@ -828,41 +828,41 @@ void OPPROTO op_cvtps2pi(void) |
828 | 828 | { |
829 | 829 | MMXReg *d = (MMXReg *)((char *)env + PARAM1); |
830 | 830 | XMMReg *s = (XMMReg *)((char *)env + PARAM2); |
831 | - d->MMX_L(0) = lrint(s->XMM_S(0)); | |
832 | - d->MMX_L(1) = lrint(s->XMM_S(1)); | |
831 | + d->MMX_L(0) = float32_to_int32(s->XMM_S(0), &env->sse_status); | |
832 | + d->MMX_L(1) = float32_to_int32(s->XMM_S(1), &env->sse_status); | |
833 | 833 | } |
834 | 834 | |
835 | 835 | void OPPROTO op_cvtpd2pi(void) |
836 | 836 | { |
837 | 837 | MMXReg *d = (MMXReg *)((char *)env + PARAM1); |
838 | 838 | XMMReg *s = (XMMReg *)((char *)env + PARAM2); |
839 | - d->MMX_L(0) = lrint(s->XMM_D(0)); | |
840 | - d->MMX_L(1) = lrint(s->XMM_D(1)); | |
839 | + d->MMX_L(0) = float64_to_int32(s->XMM_D(0), &env->sse_status); | |
840 | + d->MMX_L(1) = float64_to_int32(s->XMM_D(1), &env->sse_status); | |
841 | 841 | } |
842 | 842 | |
843 | 843 | void OPPROTO op_cvtss2si(void) |
844 | 844 | { |
845 | 845 | XMMReg *s = (XMMReg *)((char *)env + PARAM1); |
846 | - T0 = (int32_t)lrint(s->XMM_S(0)); | |
846 | + T0 = float32_to_int32(s->XMM_S(0), &env->sse_status); | |
847 | 847 | } |
848 | 848 | |
849 | 849 | void OPPROTO op_cvtsd2si(void) |
850 | 850 | { |
851 | 851 | XMMReg *s = (XMMReg *)((char *)env + PARAM1); |
852 | - T0 = (int32_t)lrint(s->XMM_D(0)); | |
852 | + T0 = float64_to_int32(s->XMM_D(0), &env->sse_status); | |
853 | 853 | } |
854 | 854 | |
855 | 855 | #ifdef TARGET_X86_64 |
856 | 856 | void OPPROTO op_cvtss2sq(void) |
857 | 857 | { |
858 | 858 | XMMReg *s = (XMMReg *)((char *)env + PARAM1); |
859 | - T0 = llrint(s->XMM_S(0)); | |
859 | + T0 = float32_to_int64(s->XMM_S(0), &env->sse_status); | |
860 | 860 | } |
861 | 861 | |
862 | 862 | void OPPROTO op_cvtsd2sq(void) |
863 | 863 | { |
864 | 864 | XMMReg *s = (XMMReg *)((char *)env + PARAM1); |
865 | - T0 = llrint(s->XMM_D(0)); | |
865 | + T0 = float64_to_int64(s->XMM_D(0), &env->sse_status); | |
866 | 866 | } |
867 | 867 | #endif |
868 | 868 | |
... | ... | @@ -871,18 +871,18 @@ void OPPROTO op_cvttps2dq(void) |
871 | 871 | { |
872 | 872 | XMMReg *d = (XMMReg *)((char *)env + PARAM1); |
873 | 873 | XMMReg *s = (XMMReg *)((char *)env + PARAM2); |
874 | - d->XMM_L(0) = (int32_t)s->XMM_S(0); | |
875 | - d->XMM_L(1) = (int32_t)s->XMM_S(1); | |
876 | - d->XMM_L(2) = (int32_t)s->XMM_S(2); | |
877 | - d->XMM_L(3) = (int32_t)s->XMM_S(3); | |
874 | + d->XMM_L(0) = float32_to_int32_round_to_zero(s->XMM_S(0), &env->sse_status); | |
875 | + d->XMM_L(1) = float32_to_int32_round_to_zero(s->XMM_S(1), &env->sse_status); | |
876 | + d->XMM_L(2) = float32_to_int32_round_to_zero(s->XMM_S(2), &env->sse_status); | |
877 | + d->XMM_L(3) = float32_to_int32_round_to_zero(s->XMM_S(3), &env->sse_status); | |
878 | 878 | } |
879 | 879 | |
880 | 880 | void OPPROTO op_cvttpd2dq(void) |
881 | 881 | { |
882 | 882 | XMMReg *d = (XMMReg *)((char *)env + PARAM1); |
883 | 883 | XMMReg *s = (XMMReg *)((char *)env + PARAM2); |
884 | - d->XMM_L(0) = (int32_t)s->XMM_D(0); | |
885 | - d->XMM_L(1) = (int32_t)s->XMM_D(1); | |
884 | + d->XMM_L(0) = float64_to_int32_round_to_zero(s->XMM_D(0), &env->sse_status); | |
885 | + d->XMM_L(1) = float64_to_int32_round_to_zero(s->XMM_D(1), &env->sse_status); | |
886 | 886 | d->XMM_Q(1) = 0; |
887 | 887 | } |
888 | 888 | |
... | ... | @@ -890,41 +890,41 @@ void OPPROTO op_cvttps2pi(void) |
890 | 890 | { |
891 | 891 | MMXReg *d = (MMXReg *)((char *)env + PARAM1); |
892 | 892 | XMMReg *s = (XMMReg *)((char *)env + PARAM2); |
893 | - d->MMX_L(0) = (int32_t)(s->XMM_S(0)); | |
894 | - d->MMX_L(1) = (int32_t)(s->XMM_S(1)); | |
893 | + d->MMX_L(0) = float32_to_int32_round_to_zero(s->XMM_S(0), &env->sse_status); | |
894 | + d->MMX_L(1) = float32_to_int32_round_to_zero(s->XMM_S(1), &env->sse_status); | |
895 | 895 | } |
896 | 896 | |
897 | 897 | void OPPROTO op_cvttpd2pi(void) |
898 | 898 | { |
899 | 899 | MMXReg *d = (MMXReg *)((char *)env + PARAM1); |
900 | 900 | XMMReg *s = (XMMReg *)((char *)env + PARAM2); |
901 | - d->MMX_L(0) = (int32_t)(s->XMM_D(0)); | |
902 | - d->MMX_L(1) = (int32_t)(s->XMM_D(1)); | |
901 | + d->MMX_L(0) = float64_to_int32_round_to_zero(s->XMM_D(0), &env->sse_status); | |
902 | + d->MMX_L(1) = float64_to_int32_round_to_zero(s->XMM_D(1), &env->sse_status); | |
903 | 903 | } |
904 | 904 | |
905 | 905 | void OPPROTO op_cvttss2si(void) |
906 | 906 | { |
907 | 907 | XMMReg *s = (XMMReg *)((char *)env + PARAM1); |
908 | - T0 = (int32_t)(s->XMM_S(0)); | |
908 | + T0 = float32_to_int32_round_to_zero(s->XMM_S(0), &env->sse_status); | |
909 | 909 | } |
910 | 910 | |
911 | 911 | void OPPROTO op_cvttsd2si(void) |
912 | 912 | { |
913 | 913 | XMMReg *s = (XMMReg *)((char *)env + PARAM1); |
914 | - T0 = (int32_t)(s->XMM_D(0)); | |
914 | + T0 = float64_to_int32_round_to_zero(s->XMM_D(0), &env->sse_status); | |
915 | 915 | } |
916 | 916 | |
917 | 917 | #ifdef TARGET_X86_64 |
918 | 918 | void OPPROTO op_cvttss2sq(void) |
919 | 919 | { |
920 | 920 | XMMReg *s = (XMMReg *)((char *)env + PARAM1); |
921 | - T0 = (int64_t)(s->XMM_S(0)); | |
921 | + T0 = float32_to_int64_round_to_zero(s->XMM_S(0), &env->sse_status); | |
922 | 922 | } |
923 | 923 | |
924 | 924 | void OPPROTO op_cvttsd2sq(void) |
925 | 925 | { |
926 | 926 | XMMReg *s = (XMMReg *)((char *)env + PARAM1); |
927 | - T0 = (int64_t)(s->XMM_D(0)); | |
927 | + T0 = float64_to_int64_round_to_zero(s->XMM_D(0), &env->sse_status); | |
928 | 928 | } |
929 | 929 | #endif |
930 | 930 | ... | ... |
target-sparc/cpu.h
... | ... | @@ -15,6 +15,8 @@ |
15 | 15 | |
16 | 16 | #include "cpu-defs.h" |
17 | 17 | |
18 | +#include "softfloat.h" | |
19 | + | |
18 | 20 | /*#define EXCP_INTERRUPT 0x100*/ |
19 | 21 | |
20 | 22 | /* trap definitions */ |
... | ... | @@ -150,6 +152,7 @@ typedef struct CPUSPARCState { |
150 | 152 | /* temporary float registers */ |
151 | 153 | float ft0, ft1, ft2; |
152 | 154 | double dt0, dt1, dt2; |
155 | + float_status fp_status; | |
153 | 156 | #if defined(TARGET_SPARC64) |
154 | 157 | target_ulong t0, t1, t2; |
155 | 158 | #endif | ... | ... |
target-sparc/op_helper.c
1 | -#include <math.h> | |
2 | -#include <fenv.h> | |
3 | 1 | #include "exec.h" |
4 | 2 | |
5 | 3 | //#define DEBUG_MMU |
... | ... | @@ -24,17 +22,17 @@ void do_fitod(void) |
24 | 22 | |
25 | 23 | void do_fabss(void) |
26 | 24 | { |
27 | - FT0 = fabsf(FT1); | |
25 | + FT0 = float32_abs(FT1); | |
28 | 26 | } |
29 | 27 | |
30 | 28 | void do_fsqrts(void) |
31 | 29 | { |
32 | - FT0 = sqrtf(FT1); | |
30 | + FT0 = float32_sqrt(FT1, &env->fp_status); | |
33 | 31 | } |
34 | 32 | |
35 | 33 | void do_fsqrtd(void) |
36 | 34 | { |
37 | - DT0 = sqrt(DT1); | |
35 | + DT0 = float64_sqrt(DT1, &env->fp_status); | |
38 | 36 | } |
39 | 37 | |
40 | 38 | void do_fcmps (void) |
... | ... | @@ -252,20 +250,22 @@ void helper_rett() |
252 | 250 | |
253 | 251 | void helper_ldfsr(void) |
254 | 252 | { |
253 | + int rnd_mode; | |
255 | 254 | switch (env->fsr & FSR_RD_MASK) { |
256 | 255 | case FSR_RD_NEAREST: |
257 | - fesetround(FE_TONEAREST); | |
256 | + rnd_mode = float_round_nearest_even; | |
258 | 257 | break; |
259 | 258 | case FSR_RD_ZERO: |
260 | - fesetround(FE_TOWARDZERO); | |
259 | + rnd_mode = float_round_to_zero; | |
261 | 260 | break; |
262 | 261 | case FSR_RD_POS: |
263 | - fesetround(FE_UPWARD); | |
262 | + rnd_mode = float_round_up; | |
264 | 263 | break; |
265 | 264 | case FSR_RD_NEG: |
266 | - fesetround(FE_DOWNWARD); | |
265 | + rnd_mode = float_round_down; | |
267 | 266 | break; |
268 | 267 | } |
268 | + set_float_rounding_mode(rnd_mode, &env->fp_status); | |
269 | 269 | } |
270 | 270 | |
271 | 271 | void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f) | ... | ... |
vl.c