Revision 7a0e1f41
b/dyngen-exec.h | ||
---|---|---|
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" |
b/target-i386/cpu.h | ||
---|---|---|
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 | 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 | 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 | 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 | 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; |
b/target-i386/exec.h | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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]; |
b/target-i386/helper.c | ||
---|---|---|
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 | 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 | 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 |
|
b/target-i386/op.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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) |
b/target-i386/ops_sse.h | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 |
|
b/target-sparc/cpu.h | ||
---|---|---|
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 | 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 |
b/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 | 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 | 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) |
b/vl.c | ||
---|---|---|
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; |
Also available in: Unified diff