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,17 +62,6 @@ extern int fprintf(FILE *, const char *, ...);
62 extern int printf(const char *, ...); 62 extern int printf(const char *, ...);
63 #undef NULL 63 #undef NULL
64 #define NULL 0 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 #ifdef __i386__ 66 #ifdef __i386__
78 #define AREG0 "ebp" 67 #define AREG0 "ebp"
target-i386/cpu.h
@@ -36,6 +36,8 @@ @@ -36,6 +36,8 @@
36 36
37 #include "cpu-defs.h" 37 #include "cpu-defs.h"
38 38
  39 +#include "softfloat.h"
  40 +
39 #if defined(__i386__) && !defined(CONFIG_SOFTMMU) 41 #if defined(__i386__) && !defined(CONFIG_SOFTMMU)
40 #define USE_CODE_COPY 42 #define USE_CODE_COPY
41 #endif 43 #endif
@@ -332,14 +334,14 @@ enum { @@ -332,14 +334,14 @@ enum {
332 CC_OP_NB, 334 CC_OP_NB,
333 }; 335 };
334 336
335 -#if (defined(__i386__) || defined(__x86_64__)) && !defined(_BSD) 337 +#ifdef FLOATX80
336 #define USE_X86LDOUBLE 338 #define USE_X86LDOUBLE
337 #endif 339 #endif
338 340
339 #ifdef USE_X86LDOUBLE 341 #ifdef USE_X86LDOUBLE
340 -typedef long double CPU86_LDouble; 342 +typedef floatx80 CPU86_LDouble;
341 #else 343 #else
342 -typedef double CPU86_LDouble; 344 +typedef float64 CPU86_LDouble;
343 #endif 345 #endif
344 346
345 typedef struct SegmentCache { 347 typedef struct SegmentCache {
@@ -354,8 +356,8 @@ typedef union { @@ -354,8 +356,8 @@ typedef union {
354 uint16_t _w[8]; 356 uint16_t _w[8];
355 uint32_t _l[4]; 357 uint32_t _l[4];
356 uint64_t _q[2]; 358 uint64_t _q[2];
357 - float _s[4];  
358 - double _d[2]; 359 + float32 _s[4];
  360 + float64 _d[2];
359 } XMMReg; 361 } XMMReg;
360 362
361 typedef union { 363 typedef union {
@@ -441,6 +443,7 @@ typedef struct CPUX86State { @@ -441,6 +443,7 @@ typedef struct CPUX86State {
441 } fpregs[8]; 443 } fpregs[8];
442 444
443 /* emulator internal variables */ 445 /* emulator internal variables */
  446 + float_status fp_status;
444 CPU86_LDouble ft0; 447 CPU86_LDouble ft0;
445 union { 448 union {
446 float f; 449 float f;
@@ -449,6 +452,7 @@ typedef struct CPUX86State { @@ -449,6 +452,7 @@ typedef struct CPUX86State {
449 int64_t i64; 452 int64_t i64;
450 } fp_convert; 453 } fp_convert;
451 454
  455 + float_status sse_status;
452 uint32_t mxcsr; 456 uint32_t mxcsr;
453 XMMReg xmm_regs[CPU_NB_REGS]; 457 XMMReg xmm_regs[CPU_NB_REGS];
454 XMMReg xmm_t0; 458 XMMReg xmm_t0;
target-i386/exec.h
@@ -139,44 +139,6 @@ extern int loglevel; @@ -139,44 +139,6 @@ extern int loglevel;
139 #include "cpu.h" 139 #include "cpu.h"
140 #include "exec-all.h" 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 typedef struct CCTable { 142 typedef struct CCTable {
181 int (*compute_all)(void); /* return all the flags */ 143 int (*compute_all)(void); /* return all the flags */
182 int (*compute_c)(void); /* return the C flag */ 144 int (*compute_c)(void); /* return the C flag */
@@ -358,9 +320,11 @@ static inline void stfl(target_ulong ptr, float v) @@ -358,9 +320,11 @@ static inline void stfl(target_ulong ptr, float v)
358 320
359 #ifdef USE_X86LDOUBLE 321 #ifdef USE_X86LDOUBLE
360 /* use long double functions */ 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 #define sin sinl 328 #define sin sinl
365 #define cos cosl 329 #define cos cosl
366 #define sqrt sqrtl 330 #define sqrt sqrtl
@@ -370,17 +334,14 @@ static inline void stfl(target_ulong ptr, float v) @@ -370,17 +334,14 @@ static inline void stfl(target_ulong ptr, float v)
370 #define atan2 atan2l 334 #define atan2 atan2l
371 #define floor floorl 335 #define floor floorl
372 #define ceil ceill 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 #else 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 #endif 343 #endif
383 -extern CPU86_LDouble fabs(CPU86_LDouble x); 344 +
384 extern CPU86_LDouble sin(CPU86_LDouble x); 345 extern CPU86_LDouble sin(CPU86_LDouble x);
385 extern CPU86_LDouble cos(CPU86_LDouble x); 346 extern CPU86_LDouble cos(CPU86_LDouble x);
386 extern CPU86_LDouble sqrt(CPU86_LDouble x); 347 extern CPU86_LDouble sqrt(CPU86_LDouble x);
@@ -390,7 +351,6 @@ extern CPU86_LDouble tan(CPU86_LDouble x); @@ -390,7 +351,6 @@ extern CPU86_LDouble tan(CPU86_LDouble x);
390 extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble); 351 extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble);
391 extern CPU86_LDouble floor(CPU86_LDouble x); 352 extern CPU86_LDouble floor(CPU86_LDouble x);
392 extern CPU86_LDouble ceil(CPU86_LDouble x); 353 extern CPU86_LDouble ceil(CPU86_LDouble x);
393 -extern CPU86_LDouble rint(CPU86_LDouble x);  
394 354
395 #define RC_MASK 0xc00 355 #define RC_MASK 0xc00
396 #define RC_NEAR 0x000 356 #define RC_NEAR 0x000
@@ -400,13 +360,6 @@ extern CPU86_LDouble rint(CPU86_LDouble x); @@ -400,13 +360,6 @@ extern CPU86_LDouble rint(CPU86_LDouble x);
400 360
401 #define MAXTAN 9223372036854775808.0 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 #ifdef USE_X86LDOUBLE 363 #ifdef USE_X86LDOUBLE
411 364
412 /* only for x86 */ 365 /* only for x86 */
@@ -596,6 +549,7 @@ float approx_rsqrt(float a); @@ -596,6 +549,7 @@ float approx_rsqrt(float a);
596 float approx_rcp(float a); 549 float approx_rcp(float a);
597 double helper_sqrt(double a); 550 double helper_sqrt(double a);
598 int fpu_isnan(double a); 551 int fpu_isnan(double a);
  552 +void update_fp_status(void);
599 553
600 extern const uint8_t parity_table[256]; 554 extern const uint8_t parity_table[256];
601 extern const uint8_t rclw_table[32]; 555 extern const uint8_t rclw_table[32];
target-i386/helper.c
@@ -2541,13 +2541,11 @@ void helper_fbld_ST0_A0(void) @@ -2541,13 +2541,11 @@ void helper_fbld_ST0_A0(void)
2541 2541
2542 void helper_fbst_ST0_A0(void) 2542 void helper_fbst_ST0_A0(void)
2543 { 2543 {
2544 - CPU86_LDouble tmp;  
2545 int v; 2544 int v;
2546 target_ulong mem_ref, mem_end; 2545 target_ulong mem_ref, mem_end;
2547 int64_t val; 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 mem_ref = A0; 2549 mem_ref = A0;
2552 mem_end = mem_ref + 9; 2550 mem_end = mem_ref + 9;
2553 if (val < 0) { 2551 if (val < 0) {
@@ -2740,29 +2738,7 @@ void helper_fsincos(void) @@ -2740,29 +2738,7 @@ void helper_fsincos(void)
2740 2738
2741 void helper_frndint(void) 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 void helper_fscale(void) 2744 void helper_fscale(void)
@@ -3263,25 +3239,43 @@ float approx_rcp(float a) @@ -3263,25 +3239,43 @@ float approx_rcp(float a)
3263 return 1.0 / a; 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 #endif 3277 #endif
  3278 +}
3285 3279
3286 #if !defined(CONFIG_USER_ONLY) 3280 #if !defined(CONFIG_USER_ONLY)
3287 3281
target-i386/op.c
@@ -1598,26 +1598,6 @@ CCTable cc_table[CC_OP_NB] = { @@ -1598,26 +1598,6 @@ CCTable cc_table[CC_OP_NB] = {
1598 functions comes from the LGPL'ed x86 emulator found in the Willows 1598 functions comes from the LGPL'ed x86 emulator found in the Willows
1599 TWIN windows emulator. */ 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 /* fp load FT0 */ 1601 /* fp load FT0 */
1622 1602
1623 void OPPROTO op_flds_FT0_A0(void) 1603 void OPPROTO op_flds_FT0_A0(void)
@@ -1866,7 +1846,7 @@ void OPPROTO op_fist_ST0_A0(void) @@ -1866,7 +1846,7 @@ void OPPROTO op_fist_ST0_A0(void)
1866 int val; 1846 int val;
1867 1847
1868 d = ST0; 1848 d = ST0;
1869 - val = lrint(d); 1849 + val = floatx_to_int32(d, &env->fp_status);
1870 if (val != (int16_t)val) 1850 if (val != (int16_t)val)
1871 val = -32768; 1851 val = -32768;
1872 stw(A0, val); 1852 stw(A0, val);
@@ -1883,7 +1863,7 @@ void OPPROTO op_fistl_ST0_A0(void) @@ -1883,7 +1863,7 @@ void OPPROTO op_fistl_ST0_A0(void)
1883 int val; 1863 int val;
1884 1864
1885 d = ST0; 1865 d = ST0;
1886 - val = lrint(d); 1866 + val = floatx_to_int32(d, &env->fp_status);
1887 stl(A0, val); 1867 stl(A0, val);
1888 FORCE_RET(); 1868 FORCE_RET();
1889 } 1869 }
@@ -1898,7 +1878,7 @@ void OPPROTO op_fistll_ST0_A0(void) @@ -1898,7 +1878,7 @@ void OPPROTO op_fistll_ST0_A0(void)
1898 int64_t val; 1878 int64_t val;
1899 1879
1900 d = ST0; 1880 d = ST0;
1901 - val = llrint(d); 1881 + val = floatx_to_int64(d, &env->fp_status);
1902 stq(A0, val); 1882 stq(A0, val);
1903 FORCE_RET(); 1883 FORCE_RET();
1904 } 1884 }
@@ -2101,12 +2081,12 @@ void OPPROTO op_fdivr_STN_ST0(void) @@ -2101,12 +2081,12 @@ void OPPROTO op_fdivr_STN_ST0(void)
2101 /* misc FPU operations */ 2081 /* misc FPU operations */
2102 void OPPROTO op_fchs_ST0(void) 2082 void OPPROTO op_fchs_ST0(void)
2103 { 2083 {
2104 - ST0 = -ST0; 2084 + ST0 = floatx_chs(ST0);
2105 } 2085 }
2106 2086
2107 void OPPROTO op_fabs_ST0(void) 2087 void OPPROTO op_fabs_ST0(void)
2108 { 2088 {
2109 - ST0 = fabs(ST0); 2089 + ST0 = floatx_abs(ST0);
2110 } 2090 }
2111 2091
2112 void OPPROTO op_fxam_ST0(void) 2092 void OPPROTO op_fxam_ST0(void)
@@ -2251,25 +2231,8 @@ void OPPROTO op_fnstcw_A0(void) @@ -2251,25 +2231,8 @@ void OPPROTO op_fnstcw_A0(void)
2251 2231
2252 void OPPROTO op_fldcw_A0(void) 2232 void OPPROTO op_fldcw_A0(void)
2253 { 2233 {
2254 - int rnd_type;  
2255 env->fpuc = lduw(A0); 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 void OPPROTO op_fclex(void) 2238 void OPPROTO op_fclex(void)
target-i386/ops_sse.h
@@ -654,10 +654,10 @@ void OPPROTO op_ ## name ## ps (void)\ @@ -654,10 +654,10 @@ void OPPROTO op_ ## name ## ps (void)\
654 Reg *d, *s;\ 654 Reg *d, *s;\
655 d = (Reg *)((char *)env + PARAM1);\ 655 d = (Reg *)((char *)env + PARAM1);\
656 s = (Reg *)((char *)env + PARAM2);\ 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 void OPPROTO op_ ## name ## ss (void)\ 663 void OPPROTO op_ ## name ## ss (void)\
@@ -665,15 +665,15 @@ void OPPROTO op_ ## name ## ss (void)\ @@ -665,15 +665,15 @@ void OPPROTO op_ ## name ## ss (void)\
665 Reg *d, *s;\ 665 Reg *d, *s;\
666 d = (Reg *)((char *)env + PARAM1);\ 666 d = (Reg *)((char *)env + PARAM1);\
667 s = (Reg *)((char *)env + PARAM2);\ 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 void OPPROTO op_ ## name ## pd (void)\ 670 void OPPROTO op_ ## name ## pd (void)\
671 {\ 671 {\
672 Reg *d, *s;\ 672 Reg *d, *s;\
673 d = (Reg *)((char *)env + PARAM1);\ 673 d = (Reg *)((char *)env + PARAM1);\
674 s = (Reg *)((char *)env + PARAM2);\ 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 void OPPROTO op_ ## name ## sd (void)\ 679 void OPPROTO op_ ## name ## sd (void)\
@@ -681,16 +681,16 @@ void OPPROTO op_ ## name ## sd (void)\ @@ -681,16 +681,16 @@ void OPPROTO op_ ## name ## sd (void)\
681 Reg *d, *s;\ 681 Reg *d, *s;\
682 d = (Reg *)((char *)env + PARAM1);\ 682 d = (Reg *)((char *)env + PARAM1);\
683 s = (Reg *)((char *)env + PARAM2);\ 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 SSE_OP_S(add, FPU_ADD) 695 SSE_OP_S(add, FPU_ADD)
696 SSE_OP_S(sub, FPU_SUB) 696 SSE_OP_S(sub, FPU_SUB)
@@ -710,8 +710,8 @@ void OPPROTO op_cvtps2pd(void) @@ -710,8 +710,8 @@ void OPPROTO op_cvtps2pd(void)
710 s = (Reg *)((char *)env + PARAM2); 710 s = (Reg *)((char *)env + PARAM2);
711 s0 = s->XMM_S(0); 711 s0 = s->XMM_S(0);
712 s1 = s->XMM_S(1); 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 void OPPROTO op_cvtpd2ps(void) 717 void OPPROTO op_cvtpd2ps(void)
@@ -719,8 +719,8 @@ void OPPROTO op_cvtpd2ps(void) @@ -719,8 +719,8 @@ void OPPROTO op_cvtpd2ps(void)
719 Reg *d, *s; 719 Reg *d, *s;
720 d = (Reg *)((char *)env + PARAM1); 720 d = (Reg *)((char *)env + PARAM1);
721 s = (Reg *)((char *)env + PARAM2); 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 d->Q(1) = 0; 724 d->Q(1) = 0;
725 } 725 }
726 726
@@ -729,7 +729,7 @@ void OPPROTO op_cvtss2sd(void) @@ -729,7 +729,7 @@ void OPPROTO op_cvtss2sd(void)
729 Reg *d, *s; 729 Reg *d, *s;
730 d = (Reg *)((char *)env + PARAM1); 730 d = (Reg *)((char *)env + PARAM1);
731 s = (Reg *)((char *)env + PARAM2); 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 void OPPROTO op_cvtsd2ss(void) 735 void OPPROTO op_cvtsd2ss(void)
@@ -737,7 +737,7 @@ void OPPROTO op_cvtsd2ss(void) @@ -737,7 +737,7 @@ void OPPROTO op_cvtsd2ss(void)
737 Reg *d, *s; 737 Reg *d, *s;
738 d = (Reg *)((char *)env + PARAM1); 738 d = (Reg *)((char *)env + PARAM1);
739 s = (Reg *)((char *)env + PARAM2); 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 /* integer to float */ 743 /* integer to float */
@@ -745,10 +745,10 @@ void OPPROTO op_cvtdq2ps(void) @@ -745,10 +745,10 @@ void OPPROTO op_cvtdq2ps(void)
745 { 745 {
746 XMMReg *d = (XMMReg *)((char *)env + PARAM1); 746 XMMReg *d = (XMMReg *)((char *)env + PARAM1);
747 XMMReg *s = (XMMReg *)((char *)env + PARAM2); 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 void OPPROTO op_cvtdq2pd(void) 754 void OPPROTO op_cvtdq2pd(void)
@@ -758,49 +758,49 @@ void OPPROTO op_cvtdq2pd(void) @@ -758,49 +758,49 @@ void OPPROTO op_cvtdq2pd(void)
758 int32_t l0, l1; 758 int32_t l0, l1;
759 l0 = (int32_t)s->XMM_L(0); 759 l0 = (int32_t)s->XMM_L(0);
760 l1 = (int32_t)s->XMM_L(1); 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 void OPPROTO op_cvtpi2ps(void) 765 void OPPROTO op_cvtpi2ps(void)
766 { 766 {
767 XMMReg *d = (Reg *)((char *)env + PARAM1); 767 XMMReg *d = (Reg *)((char *)env + PARAM1);
768 MMXReg *s = (MMXReg *)((char *)env + PARAM2); 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 void OPPROTO op_cvtpi2pd(void) 773 void OPPROTO op_cvtpi2pd(void)
774 { 774 {
775 XMMReg *d = (Reg *)((char *)env + PARAM1); 775 XMMReg *d = (Reg *)((char *)env + PARAM1);
776 MMXReg *s = (MMXReg *)((char *)env + PARAM2); 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 void OPPROTO op_cvtsi2ss(void) 781 void OPPROTO op_cvtsi2ss(void)
782 { 782 {
783 XMMReg *d = (Reg *)((char *)env + PARAM1); 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 void OPPROTO op_cvtsi2sd(void) 787 void OPPROTO op_cvtsi2sd(void)
788 { 788 {
789 XMMReg *d = (Reg *)((char *)env + PARAM1); 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 #ifdef TARGET_X86_64 793 #ifdef TARGET_X86_64
794 void OPPROTO op_cvtsq2ss(void) 794 void OPPROTO op_cvtsq2ss(void)
795 { 795 {
796 XMMReg *d = (Reg *)((char *)env + PARAM1); 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 void OPPROTO op_cvtsq2sd(void) 800 void OPPROTO op_cvtsq2sd(void)
801 { 801 {
802 XMMReg *d = (Reg *)((char *)env + PARAM1); 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 #endif 805 #endif
806 806
@@ -809,18 +809,18 @@ void OPPROTO op_cvtps2dq(void) @@ -809,18 +809,18 @@ void OPPROTO op_cvtps2dq(void)
809 { 809 {
810 XMMReg *d = (XMMReg *)((char *)env + PARAM1); 810 XMMReg *d = (XMMReg *)((char *)env + PARAM1);
811 XMMReg *s = (XMMReg *)((char *)env + PARAM2); 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 void OPPROTO op_cvtpd2dq(void) 818 void OPPROTO op_cvtpd2dq(void)
819 { 819 {
820 XMMReg *d = (XMMReg *)((char *)env + PARAM1); 820 XMMReg *d = (XMMReg *)((char *)env + PARAM1);
821 XMMReg *s = (XMMReg *)((char *)env + PARAM2); 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 d->XMM_Q(1) = 0; 824 d->XMM_Q(1) = 0;
825 } 825 }
826 826
@@ -828,41 +828,41 @@ void OPPROTO op_cvtps2pi(void) @@ -828,41 +828,41 @@ void OPPROTO op_cvtps2pi(void)
828 { 828 {
829 MMXReg *d = (MMXReg *)((char *)env + PARAM1); 829 MMXReg *d = (MMXReg *)((char *)env + PARAM1);
830 XMMReg *s = (XMMReg *)((char *)env + PARAM2); 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 void OPPROTO op_cvtpd2pi(void) 835 void OPPROTO op_cvtpd2pi(void)
836 { 836 {
837 MMXReg *d = (MMXReg *)((char *)env + PARAM1); 837 MMXReg *d = (MMXReg *)((char *)env + PARAM1);
838 XMMReg *s = (XMMReg *)((char *)env + PARAM2); 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 void OPPROTO op_cvtss2si(void) 843 void OPPROTO op_cvtss2si(void)
844 { 844 {
845 XMMReg *s = (XMMReg *)((char *)env + PARAM1); 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 void OPPROTO op_cvtsd2si(void) 849 void OPPROTO op_cvtsd2si(void)
850 { 850 {
851 XMMReg *s = (XMMReg *)((char *)env + PARAM1); 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 #ifdef TARGET_X86_64 855 #ifdef TARGET_X86_64
856 void OPPROTO op_cvtss2sq(void) 856 void OPPROTO op_cvtss2sq(void)
857 { 857 {
858 XMMReg *s = (XMMReg *)((char *)env + PARAM1); 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 void OPPROTO op_cvtsd2sq(void) 862 void OPPROTO op_cvtsd2sq(void)
863 { 863 {
864 XMMReg *s = (XMMReg *)((char *)env + PARAM1); 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 #endif 867 #endif
868 868
@@ -871,18 +871,18 @@ void OPPROTO op_cvttps2dq(void) @@ -871,18 +871,18 @@ void OPPROTO op_cvttps2dq(void)
871 { 871 {
872 XMMReg *d = (XMMReg *)((char *)env + PARAM1); 872 XMMReg *d = (XMMReg *)((char *)env + PARAM1);
873 XMMReg *s = (XMMReg *)((char *)env + PARAM2); 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 void OPPROTO op_cvttpd2dq(void) 880 void OPPROTO op_cvttpd2dq(void)
881 { 881 {
882 XMMReg *d = (XMMReg *)((char *)env + PARAM1); 882 XMMReg *d = (XMMReg *)((char *)env + PARAM1);
883 XMMReg *s = (XMMReg *)((char *)env + PARAM2); 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 d->XMM_Q(1) = 0; 886 d->XMM_Q(1) = 0;
887 } 887 }
888 888
@@ -890,41 +890,41 @@ void OPPROTO op_cvttps2pi(void) @@ -890,41 +890,41 @@ void OPPROTO op_cvttps2pi(void)
890 { 890 {
891 MMXReg *d = (MMXReg *)((char *)env + PARAM1); 891 MMXReg *d = (MMXReg *)((char *)env + PARAM1);
892 XMMReg *s = (XMMReg *)((char *)env + PARAM2); 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 void OPPROTO op_cvttpd2pi(void) 897 void OPPROTO op_cvttpd2pi(void)
898 { 898 {
899 MMXReg *d = (MMXReg *)((char *)env + PARAM1); 899 MMXReg *d = (MMXReg *)((char *)env + PARAM1);
900 XMMReg *s = (XMMReg *)((char *)env + PARAM2); 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 void OPPROTO op_cvttss2si(void) 905 void OPPROTO op_cvttss2si(void)
906 { 906 {
907 XMMReg *s = (XMMReg *)((char *)env + PARAM1); 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 void OPPROTO op_cvttsd2si(void) 911 void OPPROTO op_cvttsd2si(void)
912 { 912 {
913 XMMReg *s = (XMMReg *)((char *)env + PARAM1); 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 #ifdef TARGET_X86_64 917 #ifdef TARGET_X86_64
918 void OPPROTO op_cvttss2sq(void) 918 void OPPROTO op_cvttss2sq(void)
919 { 919 {
920 XMMReg *s = (XMMReg *)((char *)env + PARAM1); 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 void OPPROTO op_cvttsd2sq(void) 924 void OPPROTO op_cvttsd2sq(void)
925 { 925 {
926 XMMReg *s = (XMMReg *)((char *)env + PARAM1); 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 #endif 929 #endif
930 930
target-sparc/cpu.h
@@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
15 15
16 #include "cpu-defs.h" 16 #include "cpu-defs.h"
17 17
  18 +#include "softfloat.h"
  19 +
18 /*#define EXCP_INTERRUPT 0x100*/ 20 /*#define EXCP_INTERRUPT 0x100*/
19 21
20 /* trap definitions */ 22 /* trap definitions */
@@ -150,6 +152,7 @@ typedef struct CPUSPARCState { @@ -150,6 +152,7 @@ typedef struct CPUSPARCState {
150 /* temporary float registers */ 152 /* temporary float registers */
151 float ft0, ft1, ft2; 153 float ft0, ft1, ft2;
152 double dt0, dt1, dt2; 154 double dt0, dt1, dt2;
  155 + float_status fp_status;
153 #if defined(TARGET_SPARC64) 156 #if defined(TARGET_SPARC64)
154 target_ulong t0, t1, t2; 157 target_ulong t0, t1, t2;
155 #endif 158 #endif
target-sparc/op_helper.c
1 -#include <math.h>  
2 -#include <fenv.h>  
3 #include "exec.h" 1 #include "exec.h"
4 2
5 //#define DEBUG_MMU 3 //#define DEBUG_MMU
@@ -24,17 +22,17 @@ void do_fitod(void) @@ -24,17 +22,17 @@ void do_fitod(void)
24 22
25 void do_fabss(void) 23 void do_fabss(void)
26 { 24 {
27 - FT0 = fabsf(FT1); 25 + FT0 = float32_abs(FT1);
28 } 26 }
29 27
30 void do_fsqrts(void) 28 void do_fsqrts(void)
31 { 29 {
32 - FT0 = sqrtf(FT1); 30 + FT0 = float32_sqrt(FT1, &env->fp_status);
33 } 31 }
34 32
35 void do_fsqrtd(void) 33 void do_fsqrtd(void)
36 { 34 {
37 - DT0 = sqrt(DT1); 35 + DT0 = float64_sqrt(DT1, &env->fp_status);
38 } 36 }
39 37
40 void do_fcmps (void) 38 void do_fcmps (void)
@@ -252,20 +250,22 @@ void helper_rett() @@ -252,20 +250,22 @@ void helper_rett()
252 250
253 void helper_ldfsr(void) 251 void helper_ldfsr(void)
254 { 252 {
  253 + int rnd_mode;
255 switch (env->fsr & FSR_RD_MASK) { 254 switch (env->fsr & FSR_RD_MASK) {
256 case FSR_RD_NEAREST: 255 case FSR_RD_NEAREST:
257 - fesetround(FE_TONEAREST); 256 + rnd_mode = float_round_nearest_even;
258 break; 257 break;
259 case FSR_RD_ZERO: 258 case FSR_RD_ZERO:
260 - fesetround(FE_TOWARDZERO); 259 + rnd_mode = float_round_to_zero;
261 break; 260 break;
262 case FSR_RD_POS: 261 case FSR_RD_POS:
263 - fesetround(FE_UPWARD); 262 + rnd_mode = float_round_up;
264 break; 263 break;
265 case FSR_RD_NEG: 264 case FSR_RD_NEG:
266 - fesetround(FE_DOWNWARD); 265 + rnd_mode = float_round_down;
267 break; 266 break;
268 } 267 }
  268 + set_float_rounding_mode(rnd_mode, &env->fp_status);
269 } 269 }
270 270
271 void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f) 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,6 +2271,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
2271 } 2271 }
2272 2272
2273 env->fpuc = fpuc; 2273 env->fpuc = fpuc;
  2274 + /* XXX: restore FPU round state */
2274 env->fpstt = (fpus >> 11) & 7; 2275 env->fpstt = (fpus >> 11) & 7;
2275 env->fpus = fpus & ~0x3800; 2276 env->fpus = fpus & ~0x3800;
2276 fptag ^= 0xff; 2277 fptag ^= 0xff;