mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-12-23 19:29:18 +00:00
Fix "ieee" FPU core on big endian and without long double > double support
- Handle conversions to/from host double for m68k long doubles formats - Make mathlib aware of sizeof(long double) == sizeof(double) arches - Attempt to fix FSCALE implementation
This commit is contained in:
parent
57e73de5f6
commit
e59e4904d3
@ -264,66 +264,61 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src)
|
||||
// to_exten
|
||||
PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
|
||||
{
|
||||
#if 1
|
||||
// FIXME: USE_QUAD_DOUBLE
|
||||
fpu_extended result;
|
||||
// is it zero?
|
||||
if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0)
|
||||
return 0.0;
|
||||
|
||||
fpu_register result;
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
uae_u32 sgn = (wrd1 >> 31) & 1;
|
||||
uae_u32 exp = (wrd1 >> 16) & 0x7fff;
|
||||
|
||||
// the explicit integer bit is not set, must normalize
|
||||
if ((wrd2 & 0x80000000) == 0) {
|
||||
fpu_debug(("make_extended denormalized mantissa (%X,%X,%X)\n",wrd1,wrd2,wrd3));
|
||||
if (wrd2 | wrd3) {
|
||||
// mantissa, not fraction.
|
||||
uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3;
|
||||
while (exp > 0 && (man & UVAL64(0x8000000000000000)) == 0) {
|
||||
man <<= 1;
|
||||
exp--;
|
||||
}
|
||||
wrd2 = (uae_u32)(man >> 32);
|
||||
wrd3 = (uae_u32)(man & 0xFFFFFFFF);
|
||||
}
|
||||
else if (exp != 0x7fff) // zero
|
||||
exp = FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS;
|
||||
}
|
||||
|
||||
if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS)
|
||||
exp = 0;
|
||||
else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS)
|
||||
exp = FP_DOUBLE_EXP_MAX;
|
||||
else
|
||||
exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS;
|
||||
|
||||
fp_declare_init_shape(srp, result, double);
|
||||
srp->ieee.negative = sgn;
|
||||
srp->ieee.exponent = exp;
|
||||
// drop the explicit integer bit
|
||||
srp->ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11;
|
||||
srp->ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11);
|
||||
#elif USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(srp, result, extended);
|
||||
srp->ieee.negative = (wrd1 >> 31) & 1;
|
||||
srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX;
|
||||
srp->ieee.mantissa0 = (wrd2 >> 16) & 0xffff;
|
||||
srp->ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff);
|
||||
srp->ieee.mantissa2 = (wrd3 & 0xffff) << 16;
|
||||
#else
|
||||
fp_declare_init_shape(srp, result, extended);
|
||||
srp->ieee.negative = (wrd1 >> 31) & 1;
|
||||
srp->ieee.exponent = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX;
|
||||
srp->ieee.mantissa0 = wrd2;
|
||||
srp->ieee.mantissa1 = wrd3;
|
||||
#endif
|
||||
fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result));
|
||||
return result;
|
||||
#elif 0 /* original code */
|
||||
if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0)
|
||||
return 0.0;
|
||||
|
||||
fpu_register result;
|
||||
uae_u32 *p = (uae_u32 *)&result;
|
||||
|
||||
uae_u32 sign = wrd1 & 0x80000000;
|
||||
uae_u32 exp = (wrd1 >> 16) & 0x7fff;
|
||||
|
||||
// The explicit integer bit is not set, must normalize.
|
||||
if((wrd2 & 0x80000000) == 0) {
|
||||
fpu_debug(("make_extended denormalized mantissa (%X,%X,%X)\n",wrd1,wrd2,wrd3));
|
||||
if( wrd2 | wrd3 ) {
|
||||
// mantissa, not fraction.
|
||||
uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3;
|
||||
while( exp > 0 && (man & UVAL64(0x8000000000000000)) == 0 ) {
|
||||
man <<= 1;
|
||||
exp--;
|
||||
}
|
||||
wrd2 = (uae_u32)( man >> 32 );
|
||||
wrd3 = (uae_u32)( man & 0xFFFFFFFF );
|
||||
} else {
|
||||
if(exp == 0x7FFF) {
|
||||
// Infinity.
|
||||
} else {
|
||||
// Zero
|
||||
exp = 16383 - 1023;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(exp < 16383 - 1023) {
|
||||
// should set underflow.
|
||||
exp = 0;
|
||||
} else if(exp > 16383 + 1023) {
|
||||
// should set overflow.
|
||||
exp = 2047;
|
||||
} else {
|
||||
exp = exp + 1023 - 16383;
|
||||
}
|
||||
|
||||
// drop the explicit integer bit.
|
||||
p[FLO] = (wrd2 << 21) | (wrd3 >> 11);
|
||||
p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
|
||||
|
||||
fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result));
|
||||
|
||||
return(result);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -335,48 +330,40 @@ PRIVATE inline void FFPU make_extended_no_normalize(
|
||||
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result
|
||||
)
|
||||
{
|
||||
#if 1
|
||||
// is it zero?
|
||||
if ((wrd1 && 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) {
|
||||
make_zero_positive(result);
|
||||
return;
|
||||
}
|
||||
// is it NaN?
|
||||
if ((wrd1 & 0x7fff0000) == 0x7fff0000 && wrd2 != 0 && wrd3 != 0) {
|
||||
make_nan(result);
|
||||
return;
|
||||
}
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
uae_u32 exp = (wrd1 >> 16) & 0x7fff;
|
||||
if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS)
|
||||
exp = 0;
|
||||
else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS)
|
||||
exp = FP_DOUBLE_EXP_MAX;
|
||||
else
|
||||
exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS;
|
||||
|
||||
fp_declare_init_shape(srp, result, double);
|
||||
srp->ieee.negative = (wrd1 >> 31) & 1;
|
||||
srp->ieee.exponent = exp;
|
||||
// drop the explicit integer bit
|
||||
srp->ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11;
|
||||
srp->ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11);
|
||||
#else
|
||||
// FIXME: USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(srp, result, extended);
|
||||
srp->ieee.negative = (wrd1 & 0x80000000) != 0;
|
||||
srp->ieee.exponent = (wrd1 >> 16) & 0x7fff;
|
||||
srp->ieee.mantissa0 = wrd2;
|
||||
srp->ieee.mantissa1 = wrd3;
|
||||
#elif 0 /* original code */
|
||||
// Is it zero?
|
||||
if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) {
|
||||
make_zero_positive(result);
|
||||
return;
|
||||
}
|
||||
|
||||
// Is it NaN?
|
||||
if( (wrd1 & 0x7FFF0000) == 0x7FFF0000 ) {
|
||||
if( (wrd1 & 0x0000FFFF) || wrd2 || wrd3 ) {
|
||||
make_nan(result);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uae_u32 sign = wrd1 & 0x80000000;
|
||||
uae_u32 exp = (wrd1 >> 16) & 0x7fff;
|
||||
|
||||
if(exp < 16383 - 1023) {
|
||||
// should set underflow.
|
||||
exp = 0;
|
||||
} else if(exp > 16383 + 1023) {
|
||||
// should set overflow.
|
||||
exp = 2047;
|
||||
} else {
|
||||
exp = exp + 1023 - 16383;
|
||||
}
|
||||
|
||||
// drop the explicit integer bit.
|
||||
uae_u32 *p = (uae_u32 *)&result;
|
||||
p[FLO] = (wrd2 << 21) | (wrd3 >> 11);
|
||||
p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
|
||||
|
||||
fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(float)(*(double *)p)));
|
||||
#endif
|
||||
fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result));
|
||||
}
|
||||
|
||||
// from_exten
|
||||
@ -384,40 +371,40 @@ PRIVATE inline void FFPU extract_extended(fpu_register const & src,
|
||||
uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
|
||||
)
|
||||
{
|
||||
#if 1
|
||||
// FIXME: USE_QUAD_DOUBLE and non little-endian specificities
|
||||
uae_u32 *p = (uae_u32 *)&src;
|
||||
*wrd3 = p[0];
|
||||
*wrd2 = p[1];
|
||||
*wrd1 = ( (uae_u32)*((uae_u16 *)&p[2]) ) << 16;
|
||||
fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3));
|
||||
#elif 0 /* original code */
|
||||
if (src == 0.0) {
|
||||
*wrd1 = *wrd2 = *wrd3 = 0;
|
||||
return;
|
||||
}
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(srp, src, double);
|
||||
fpu_debug(("extract_extended (%d,%d,%X,%X)\n",
|
||||
srp->ieee.negative , srp->ieee.exponent,
|
||||
srp->ieee.mantissa0, srp->ieee.mantissa1));
|
||||
|
||||
uae_u32 *p = (uae_u32 *)&src;
|
||||
uae_u32 exp = srp->ieee.exponent;
|
||||
|
||||
fpu_debug(("extract_extended (%X,%X)\n",p[FLO],p[FHI]));
|
||||
if (exp == FP_DOUBLE_EXP_MAX)
|
||||
exp = FP_EXTENDED_EXP_MAX;
|
||||
else
|
||||
exp += FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS;
|
||||
|
||||
uae_u32 sign = p[FHI] & 0x80000000;
|
||||
|
||||
uae_u32 exp = ((p[FHI] >> 20) & 0x7ff);
|
||||
// Check for maximum
|
||||
if(exp == 0x7FF) {
|
||||
exp = 0x7FFF;
|
||||
} else {
|
||||
exp += 16383 - 1023;
|
||||
}
|
||||
|
||||
*wrd1 = sign | (exp << 16);
|
||||
*wrd1 = (srp->ieee.negative << 31) | (exp << 16);
|
||||
// always set the explicit integer bit.
|
||||
*wrd2 = 0x80000000 | ((p[FHI] & 0x000FFFFF) << 11) | ((p[FLO] & 0xFFE00000) >> 21);
|
||||
*wrd3 = p[FLO] << 11;
|
||||
|
||||
fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3));
|
||||
*wrd2 = 0x80000000 | (srp->ieee.mantissa0 << 11) | ((srp->ieee.mantissa1 & 0xffe00000) >> 21);
|
||||
*wrd3 = srp->ieee.mantissa1 << 11;
|
||||
#else
|
||||
// FIXME: USE_QUAD_DOUBLE
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
*wrd1 = p[0];
|
||||
*wrd2 = p[1];
|
||||
*wrd3 = p[2];
|
||||
#else
|
||||
*wrd3 = p[0];
|
||||
*wrd2 = p[1];
|
||||
*wrd1 = ( (uae_u32)*((uae_u16 *)&p[2]) ) << 16;
|
||||
#endif
|
||||
#endif
|
||||
fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3));
|
||||
}
|
||||
|
||||
// to_double
|
||||
@ -425,7 +412,7 @@ PRIVATE inline fpu_register FFPU make_double(uae_u32 wrd1, uae_u32 wrd2)
|
||||
{
|
||||
union {
|
||||
fpu_double value;
|
||||
uae_u32 parts[2];
|
||||
uae_u32 parts[2];
|
||||
} dest;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
dest.parts[0] = wrd1;
|
||||
@ -445,7 +432,7 @@ PRIVATE inline void FFPU extract_double(fpu_register const & src,
|
||||
{
|
||||
union {
|
||||
fpu_double value;
|
||||
uae_u32 parts[2];
|
||||
uae_u32 parts[2];
|
||||
} dest;
|
||||
dest.value = (fpu_double)src;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
@ -1989,18 +1976,32 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
||||
|
||||
case 0x26: /* FSCALE */
|
||||
fpu_debug(("FSCALE %.04f\n",(double)src));
|
||||
|
||||
// TODO:
|
||||
// Overflow, underflow
|
||||
|
||||
if( isinf(FPU registers[reg]) ) {
|
||||
make_nan( FPU registers[reg] );
|
||||
}
|
||||
else {
|
||||
// TODO: overflow flags
|
||||
get_dest_flags(FPU registers[reg]);
|
||||
get_source_flags(src);
|
||||
if (fl_source.in_range && fl_dest.in_range) {
|
||||
// When the absolute value of the source operand is >= 2^14,
|
||||
// an overflow or underflow always results.
|
||||
// Here (int) cast is okay.
|
||||
fast_scale( FPU registers[reg], (int)fp_round_to_zero(src) );
|
||||
int scale_factor = (int)fp_round_to_zero(src);
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(sxp, FPU registers[reg], double);
|
||||
uae_u32 exp = sxp->ieee.exponent + scale_factor;
|
||||
if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS)
|
||||
exp = 0;
|
||||
else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS)
|
||||
exp = FP_DOUBLE_EXP_MAX;
|
||||
else
|
||||
exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS;
|
||||
sxp->ieee.exponent = exp;
|
||||
#else
|
||||
fp_declare_init_shape(sxp, FPU registers[reg], extended);
|
||||
sxp->ieee.exponent += scale_factor;
|
||||
#endif
|
||||
}
|
||||
else if (fl_source.infinity) {
|
||||
// Returns NaN for any Infinity source
|
||||
make_nan( FPU registers[reg] );
|
||||
}
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
|
@ -187,17 +187,20 @@ union fpu_double_shape {
|
||||
# endif
|
||||
#endif
|
||||
} ieee_nan;
|
||||
|
||||
/* This format is used to extract the sign_exponent and mantissa parts only */
|
||||
struct {
|
||||
#if UAE_FLOAT_WORD_ORDER == UAE_BIG_ENDIAN
|
||||
unsigned int msw:32;
|
||||
unsigned int lsw:32;
|
||||
#else
|
||||
unsigned int lsw:32;
|
||||
unsigned int msw:32;
|
||||
#endif
|
||||
} parts;
|
||||
};
|
||||
|
||||
#if SIZEOF_LONG_DOUBLE == 12
|
||||
# undef USE_QUAD_DOUBLE
|
||||
#elif SIZEOF_LONG_DOUBLE == 16
|
||||
# define USE_QUAD_DOUBLE
|
||||
#else
|
||||
# error "unsupported long double format"
|
||||
#endif
|
||||
|
||||
#ifndef USE_QUAD_DOUBLE
|
||||
#ifdef USE_LONG_DOUBLE
|
||||
// IEEE-854 long double format
|
||||
union fpu_extended_shape {
|
||||
fpu_extended value;
|
||||
@ -275,7 +278,9 @@ union fpu_extended_shape {
|
||||
#endif
|
||||
} parts;
|
||||
};
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef USE_QUAD_DOUBLE
|
||||
// IEEE-854 quad double format
|
||||
union fpu_extended_shape {
|
||||
fpu_extended value;
|
||||
@ -345,7 +350,7 @@ union fpu_extended_shape {
|
||||
} parts32;
|
||||
#endif
|
||||
};
|
||||
#endif // !USE_QUAD_DOUBLE
|
||||
#endif
|
||||
|
||||
// Declare and initialize a pointer to a shape of the requested FP type
|
||||
#define fp_declare_init_shape(psvar, rfvar, ftype) \
|
||||
@ -365,9 +370,17 @@ union fpu_extended_shape {
|
||||
|
||||
PRIVATE inline bool FFPU fp_do_isnan(fpu_register const & r)
|
||||
{
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
#ifdef BRANCHES_ARE_EXPENSIVE
|
||||
#ifdef USE_QUAD_DOUBLE
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
uae_s32 hx = sxp->parts.msw;
|
||||
uae_s32 lx = sxp->parts.lsw;
|
||||
hx &= 0x7fffffff;
|
||||
hx |= (uae_u32)(lx | (-lx)) >> 31;
|
||||
hx = 0x7ff00000 - hx;
|
||||
return (int)(((uae_u32)hx) >> 31);
|
||||
#elif USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
uae_s64 hx = sxp->parts64.msw;
|
||||
uae_s64 lx = sxp->parts64.lsw;
|
||||
hx &= 0x7fffffffffffffffLL;
|
||||
@ -375,6 +388,7 @@ PRIVATE inline bool FFPU fp_do_isnan(fpu_register const & r)
|
||||
hx = 0x7fff000000000000LL - hx;
|
||||
return (int)((uae_u64)hx >> 63);
|
||||
#else
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
uae_s32 se = sxp->parts.sign_exponent;
|
||||
uae_s32 hx = sxp->parts.msw;
|
||||
uae_s32 lx = sxp->parts.lsw;
|
||||
@ -386,7 +400,13 @@ PRIVATE inline bool FFPU fp_do_isnan(fpu_register const & r)
|
||||
return (int)(((uae_u32)(se)) >> 16);
|
||||
#endif
|
||||
#else
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
return (sxp->ieee_nan.exponent == FP_DOUBLE_EXP_MAX)
|
||||
#else
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
return (sxp->ieee_nan.exponent == FP_EXTENDED_EXP_MAX)
|
||||
#endif
|
||||
&& (sxp->ieee_nan.mantissa0 != 0)
|
||||
&& (sxp->ieee_nan.mantissa1 != 0)
|
||||
#ifdef USE_QUAD_DOUBLE
|
||||
@ -406,15 +426,23 @@ PRIVATE inline bool FFPU fp_do_isnan(fpu_register const & r)
|
||||
|
||||
PRIVATE inline bool FFPU fp_do_isinf(fpu_register const & r)
|
||||
{
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
#ifdef BRANCHES_ARE_EXPENSIVE
|
||||
#ifdef USE_QUAD_DOUBLE
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
uae_s32 hx = sxp->parts.msw;
|
||||
uae_s32 lx = sxp->parts.lsw;
|
||||
lx |= (hx & 0x7fffffff) ^ 0x7ff00000;
|
||||
lx |= -lx;
|
||||
return ~(lx >> 31) & (hx >> 30);
|
||||
#elif USE_QUAD_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
uae_s64 hx = sxp->parts64.msw;
|
||||
uae_s64 lx = sxp->parts64.lsw;
|
||||
lx |= (hx & 0x7fffffffffffffffLL) ^ 0x7fff000000000000LL;
|
||||
lx |= -lx;
|
||||
return ~(lx >> 63) & (hx >> 62);
|
||||
#else
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
uae_s32 se = sxp->parts.sign_exponent;
|
||||
uae_s32 hx = sxp->parts.msw;
|
||||
uae_s32 lx = sxp->parts.lsw;
|
||||
@ -431,7 +459,13 @@ PRIVATE inline bool FFPU fp_do_isinf(fpu_register const & r)
|
||||
return ~(lx >> 31) & (1 - (se >> 14));
|
||||
#endif
|
||||
#else
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
return (sxp->ieee_nan.exponent == FP_DOUBLE_EXP_MAX)
|
||||
#else
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
return (sxp->ieee_nan.exponent == FP_EXTENDED_EXP_MAX)
|
||||
#endif
|
||||
&& (sxp->ieee_nan.mantissa0 == 0)
|
||||
&& (sxp->ieee_nan.mantissa1 == 0)
|
||||
#ifdef USE_QUAD_DOUBLE
|
||||
@ -447,9 +481,12 @@ PRIVATE inline bool FFPU fp_do_isinf(fpu_register const & r)
|
||||
|
||||
PRIVATE inline bool FFPU fp_do_isneg(fpu_register const & r)
|
||||
{
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
#else
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
return (sxp->ieee.negative)
|
||||
;
|
||||
#endif
|
||||
return sxp->ieee.negative;
|
||||
}
|
||||
|
||||
#undef iszero
|
||||
@ -458,7 +495,11 @@ PRIVATE inline bool FFPU fp_do_isneg(fpu_register const & r)
|
||||
PRIVATE inline bool FFPU fp_do_iszero(fpu_register const & r)
|
||||
{
|
||||
// TODO: BRANCHES_ARE_EXPENSIVE
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
#else
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
#endif
|
||||
return (sxp->ieee.exponent == 0)
|
||||
&& (sxp->ieee.mantissa0 == 0)
|
||||
&& (sxp->ieee.mantissa1 == 0)
|
||||
@ -490,9 +531,15 @@ PRIVATE inline void FFPU get_source_flags(fpu_register const & r)
|
||||
PRIVATE inline void FFPU make_nan(fpu_register & r)
|
||||
{
|
||||
// FIXME: is that correct ?
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
sxp->ieee.exponent = FP_DOUBLE_EXP_MAX;
|
||||
sxp->ieee.mantissa0 = 0xfffff;
|
||||
#else
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
sxp->ieee.exponent = FP_EXTENDED_EXP_MAX;
|
||||
sxp->ieee.mantissa0 = 0xffffffff;
|
||||
#endif
|
||||
sxp->ieee.mantissa1 = 0xffffffff;
|
||||
#ifdef USE_QUAD_DOUBLE
|
||||
sxp->ieee.mantissa2 = 0xffffffff;
|
||||
@ -504,8 +551,12 @@ PRIVATE inline void FFPU make_zero_positive(fpu_register & r)
|
||||
{
|
||||
#if 1
|
||||
r = +0.0;
|
||||
#else
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
#else
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
#endif
|
||||
sxp->ieee.negative = 0;
|
||||
sxp->ieee.exponent = 0;
|
||||
sxp->ieee.mantissa0 = 0;
|
||||
@ -521,8 +572,12 @@ PRIVATE inline void FFPU make_zero_negative(fpu_register & r)
|
||||
{
|
||||
#if 1
|
||||
r = -0.0;
|
||||
#else
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
#else
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
#endif
|
||||
sxp->ieee.negative = 1;
|
||||
sxp->ieee.exponent = 0;
|
||||
sxp->ieee.mantissa0 = 0;
|
||||
@ -536,9 +591,14 @@ PRIVATE inline void FFPU make_zero_negative(fpu_register & r)
|
||||
|
||||
PRIVATE inline void FFPU make_inf_positive(fpu_register & r)
|
||||
{
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
sxp->ieee_nan.exponent = FP_DOUBLE_EXP_MAX;
|
||||
#else
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
sxp->ieee_nan.negative = 0;
|
||||
sxp->ieee_nan.exponent = FP_EXTENDED_EXP_MAX;
|
||||
#endif
|
||||
sxp->ieee_nan.negative = 0;
|
||||
sxp->ieee_nan.mantissa0 = 0;
|
||||
sxp->ieee_nan.mantissa1 = 0;
|
||||
#ifdef USE_QUAD_DOUBLE
|
||||
@ -549,9 +609,14 @@ PRIVATE inline void FFPU make_inf_positive(fpu_register & r)
|
||||
|
||||
PRIVATE inline void FFPU make_inf_negative(fpu_register & r)
|
||||
{
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
sxp->ieee_nan.exponent = FP_DOUBLE_EXP_MAX;
|
||||
#else
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
sxp->ieee_nan.negative = 1;
|
||||
sxp->ieee_nan.exponent = FP_EXTENDED_EXP_MAX;
|
||||
#endif
|
||||
sxp->ieee_nan.negative = 1;
|
||||
sxp->ieee_nan.mantissa0 = 0;
|
||||
sxp->ieee_nan.mantissa1 = 0;
|
||||
#ifdef USE_QUAD_DOUBLE
|
||||
@ -560,54 +625,48 @@ PRIVATE inline void FFPU make_inf_negative(fpu_register & r)
|
||||
#endif
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add)
|
||||
{
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
// TODO: overflow flags
|
||||
int exp = sxp->ieee.exponent + add;
|
||||
// FIXME: this test is not correct: see fpuop_fscale()
|
||||
if (exp > FP_EXTENDED_EXP_BIAS) {
|
||||
make_inf_positive(r);
|
||||
} else if (exp < 0) {
|
||||
// keep sign (+/- 0)
|
||||
if (isneg(r))
|
||||
make_inf_negative(r);
|
||||
else
|
||||
make_inf_positive(r);
|
||||
// p[FHI] &= 0x80000000;
|
||||
} else {
|
||||
sxp->ieee.exponent = exp;
|
||||
// p[FHI] = (p[FHI] & 0x800FFFFF) | ((uae_u32)exp << 20);
|
||||
}
|
||||
}
|
||||
|
||||
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r)
|
||||
{
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
return (sxp->ieee.exponent - FP_DOUBLE_EXP_BIAS);
|
||||
#else
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
return (sxp->ieee.exponent - FP_EXTENDED_EXP_BIAS);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Normalize to range 1..2
|
||||
PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r)
|
||||
{
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(sxp, r, double);
|
||||
sxp->ieee.exponent = FP_DOUBLE_EXP_BIAS;
|
||||
#else
|
||||
fp_declare_init_shape(sxp, r, extended);
|
||||
sxp->ieee.exponent = FP_EXTENDED_EXP_BIAS;
|
||||
#endif
|
||||
}
|
||||
|
||||
// The sign of the quotient is the exclusive-OR of the sign bits
|
||||
// of the source and destination operands.
|
||||
PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_register const & rb)
|
||||
{
|
||||
#ifndef USE_LONG_DOUBLE
|
||||
fp_declare_init_shape(sap, ra, double);
|
||||
fp_declare_init_shape(sbp, rb, double);
|
||||
#else
|
||||
fp_declare_init_shape(sap, ra, extended);
|
||||
fp_declare_init_shape(sbp, rb, extended);
|
||||
return (((sap->ieee.mantissa0 ^ sbp->ieee.mantissa0) & 0x80000000) ? 0x800000 : 0);
|
||||
#endif
|
||||
return ((sap->ieee.negative ^ sbp->ieee.negative) ? FPSR_QUOTIENT_SIGN : 0);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- Math functions --- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#if FPU_USE_ISO_C99
|
||||
#if FPU_USE_ISO_C99 && USE_LONG_DOUBLE
|
||||
# define fp_log logl
|
||||
# define fp_log10 log10l
|
||||
# define fp_exp expl
|
||||
|
@ -31,7 +31,8 @@
|
||||
#include "sysdeps.h"
|
||||
|
||||
/* Default behavior is *not* to use long doubles */
|
||||
#define USE_LONG_DOUBLE 0
|
||||
#undef USE_LONG_DOUBLE
|
||||
#undef USE_QUAD_DOUBLE
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* --- Original UAE fpu core --- */
|
||||
@ -127,21 +128,20 @@ typedef long double uae_f64;
|
||||
#if SIZEOF_LONG_DOUBLE == 12
|
||||
typedef long double uae_f96;
|
||||
typedef uae_f96 fpu_register;
|
||||
#define USE_LONG_DOUBLE 1
|
||||
#elif SIZEOF_LONG_DOUBLE == 16
|
||||
typedef long double uae_f128;
|
||||
typedef uae_f128 fpu_register;
|
||||
#define USE_LONG_DOUBLE 1
|
||||
#define USE_QUAD_DOUBLE 1
|
||||
#else
|
||||
#error "No float type bigger than 8 bytes, you lose."
|
||||
typedef uae_f64 fpu_register;
|
||||
#endif
|
||||
|
||||
/* We *do* use long doubles for the IEEE-based FPE */
|
||||
#undef USE_LONG_DOUBLE
|
||||
#define USE_LONG_DOUBLE 1
|
||||
|
||||
/* We need all those floating-point types */
|
||||
typedef fpu_register fpu_extended;
|
||||
typedef uae_f64 fpu_double;
|
||||
typedef uae_f32 fpu_single;
|
||||
typedef uae_f64 fpu_double;
|
||||
typedef uae_f32 fpu_single;
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user