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