Commit 7a0e1f41ceeb658791a1456ffc7f8f9edca7da19

Authored by bellard
1 parent 4ecc3190

soft float support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1336 c046a42c-6fe2-441c-8c8c-71466251a162
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)
... ...
... ... @@ -2271,6 +2271,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
2271 2271 }
2272 2272  
2273 2273 env->fpuc = fpuc;
  2274 + /* XXX: restore FPU round state */
2274 2275 env->fpstt = (fpus >> 11) & 7;
2275 2276 env->fpus = fpus & ~0x3800;
2276 2277 fptag ^= 0xff;
... ...