From: Toni Wilen Date: Tue, 31 Jan 2017 19:46:39 +0000 (+0200) Subject: FPU update. X-Git-Tag: 3500~109 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=bd8bf3695c4297da5568db2571ef708a7298da14;p=francis%2Fwinuae.git FPU update. --- diff --git a/fpp.cpp b/fpp.cpp index e7bd149e..af152c1e 100644 --- a/fpp.cpp +++ b/fpp.cpp @@ -105,6 +105,7 @@ FPP_AB fpp_scale; FPP_AB fpp_sub; FPP_AB fpp_sgldiv; FPP_AB fpp_sglmul; +FPP_AB fpp_cmp; #define DEBUG_FPP 0 #define EXCEPTION_FPP 1 @@ -308,15 +309,6 @@ static void from_exten(fpdata *fpd, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wr #define FPSR_QUOT_SIGN 0x00800000 #define FPSR_QUOT_LSB 0x007F0000 -#define FPSR_BSUN 0x00008000 -#define FPSR_SNAN 0x00004000 -#define FPSR_OPERR 0x00002000 -#define FPSR_OVFL 0x00001000 -#define FPSR_UNFL 0x00000800 -#define FPSR_DZ 0x00000400 -#define FPSR_INEX2 0x00000200 -#define FPSR_INEX1 0x00000100 - #define FPSR_AE_IOP 0x00000080 #define FPSR_AE_OVFL 0x00000040 #define FPSR_AE_UNFL 0x00000020 @@ -324,7 +316,7 @@ static void from_exten(fpdata *fpd, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wr #define FPSR_AE_INEX 0x00000008 -static void fpsr_set_exception(uae_u32 exception) +void fpsr_set_exception(uae_u32 exception) { regs.fpsr |= exception; } @@ -347,26 +339,28 @@ static void fpsr_check_exception(void) write_log (_T("FPU exception: FPSR: %08x, FPCR: %04x (vector: %d)!\n"), regs.fpsr, regs.fpcr, vector); } } + + static void fpsr_set_result(fpdata *result) { - regs.fp_result = *result; - - // condition code byte +#ifdef JIT + regs.fp_result = *result; +#endif + // condition code byte regs.fpsr &= 0x00fffff8; // clear cc - if (fpp_is_nan (®s.fp_result)) { + if (fpp_is_nan (result)) { regs.fpsr |= FPSR_CC_NAN; + // check if result is signaling nan + if (fpp_is_snan(result)) + regs.fpsr |= FPSR_SNAN; } else { - if (fpp_is_zero(®s.fp_result)) + if (fpp_is_zero(result)) regs.fpsr |= FPSR_CC_Z; - if (fpp_is_infinity (®s.fp_result)) + if (fpp_is_infinity (result)) regs.fpsr |= FPSR_CC_I; } - if (fpp_is_neg(®s.fp_result)) + if (fpp_is_neg(result)) regs.fpsr |= FPSR_CC_N; - - // check if result is signaling nan - if (fpp_is_snan(®s.fp_result)) - regs.fpsr |= FPSR_SNAN; } static void fpsr_clear_status(void) { @@ -929,8 +923,6 @@ static void fpu_null (void) regs.fpcr = 0; regs.fpsr = 0; regs.fpiar = 0; - fpset(®s.fp_result, 1); - fpclear (®s.fp_result); for (int i = 0; i < 8; i++) fpnan (®s.fp[i]); } @@ -1607,11 +1599,9 @@ STATIC_INLINE int get_fp_ad (uae_u32 opcode, uae_u32 * ad) int fpp_cond (int condition) { - int NotANumber, Z, N; - - NotANumber = fpp_is_nan(®s.fp_result); - N = fpp_is_neg(®s.fp_result); - Z = fpp_is_zero(®s.fp_result); + int NotANumber = (regs.fpsr & FPSR_CC_NAN) != 0; + int N = (regs.fpsr & FPSR_CC_N) != 0; + int Z = (regs.fpsr & FPSR_CC_Z) != 0; if ((condition & 0x10) && NotANumber) { if (fpsr_set_bsun()) @@ -2419,12 +2409,9 @@ static bool arithmetic(fpdata *src, int reg, int extra) break; case 0x38: /* FCMP */ { - fpdata t = *dst; - uae_u32 status = regs.fpsr; - fpp_sub(&t, src); - fpsr_clear_status(); - fpp_set_fpsr(status); - fpsr_set_result(&t); + fpdata v = *dst; + fpp_cmp(&v, src); + fpsr_set_result(&v); return true; } case 0x3a: /* FTST */ @@ -2754,7 +2741,6 @@ void fpu_reset (void) regs.fpcr = regs.fpsr = regs.fpiar = 0; regs.fpu_exp_state = 0; - fpset (®s.fp_result, 1); fpsr_make_status(); fpux_restore (NULL); } diff --git a/fpp_native.cpp b/fpp_native.cpp index 3611969e..87455467 100644 --- a/fpp_native.cpp +++ b/fpp_native.cpp @@ -121,6 +121,8 @@ static const double twoto32 = 4294967296.0; #define FPCR_PRECISION_DOUBLE 0x00000080 #define FPCR_PRECISION_EXTENDED 0x00000000 +static struct float_status fs; + #if defined(CPU_i386) || defined(CPU_x86_64) /* The main motivation for dynamically creating an x86(-64) function in @@ -244,15 +246,15 @@ static void fp_get_status(uae_u32 *status) int exp_flags = fetestexcept(FE_ALL_EXCEPT); if (exp_flags) { if (exp_flags & FE_INEXACT) - *status |= 0x0200; + *status |= FPSR_INEX2; if (exp_flags & FE_DIVBYZERO) - *status |= 0x0400; + *status |= FPSR_DZ; if (exp_flags & FE_UNDERFLOW) - *status |= 0x0800; + *status |= FPSR_UNFL; if (exp_flags & FE_OVERFLOW) - *status |= 0x1000; + *status |= FPSR_OVFL; if (exp_flags & FE_INVALID) - *status |= 0x2000; + *status |= FPSR_OPERR; } } @@ -300,11 +302,13 @@ static bool fp_is_neg(fpdata *fpd) } static bool fp_is_denormal(fpdata *fpd) { - return (isnormal(fpd->fp) == 0); /* FIXME: how to differ denormal/unnormal? */ + return false; + //return (isnormal(fpd->fp) == 0); /* FIXME: how to differ denormal/unnormal? */ } static bool fp_is_unnormal(fpdata *fpd) { - return (isnormal(fpd->fp) == 0); /* FIXME: how to differ denormal/unnormal? */ + return false; + //return (isnormal(fpd->fp) == 0); /* FIXME: how to differ denormal/unnormal? */ } /* Functions for converting between float formats */ @@ -438,6 +442,13 @@ static void fp_from_exten_x(fpdata *fpd, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 * #else // if !USE_LONG_DOUBLE static void fp_to_exten_x(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) { +#if 1 + floatx80 fx80; + fx80.high = wrd1 >> 16; + fx80.low = (((uae_u64)wrd2) << 32) | wrd3; + float64 f = floatx80_to_float64(fx80, &fs); + fp_to_double_x(fpd, f >> 32, (uae_u32)f); +#else double frac; if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { fpd->fp = (wrd1 & 0x80000000) ? -0.0 : +0.0; @@ -447,9 +458,18 @@ static void fp_to_exten_x(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) if (wrd1 & 0x80000000) frac = -frac; fpd->fp = ldexp (frac, ((wrd1 >> 16) & 0x7fff) - 16383); +#endif } static void fp_from_exten_x(fpdata *fpd, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3) { +#if 1 + uae_u32 w1, w2; + fp_from_double_x(fpd, &w1, &w2); + floatx80 f = float64_to_floatx80(((uae_u64)w1 << 32) | w2, &fs); + *wrd1 = f.high << 16; + *wrd2 = f.low >> 32; + *wrd3 = (uae_u32)f.low; +#else int expon; double frac; fptype v; @@ -476,6 +496,7 @@ static void fp_from_exten_x(fpdata *fpd, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 * *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16); *wrd2 = (uae_u32) (frac * twoto32); *wrd3 = (uae_u32) ((frac * twoto32 - *wrd2) * twoto32); +#endif } #endif // !USE_LONG_DOUBLE @@ -489,10 +510,34 @@ static uae_s64 fp_to_int(fpdata *src, int size) }; fptype fp = src->fp; - if (fp < fxsizes[size * 2 + 0]) + if (fp_is_nan(src)) { + uae_u32 w1, w2, w3; + fp_from_exten_x(src, &w1, &w2, &w3); + uae_s64 v = 0; + fpsr_set_exception(FPSR_OPERR); + // return mantissa + switch (size) + { + case 0: + v = w2 >> 24; + break; + case 1: + v = w2 >> 16; + break; + case 2: + v = w2 >> 0; + break; + } + return v; + } + if (fp < fxsizes[size * 2 + 0]) { fp = fxsizes[size * 2 + 0]; - if (fp > fxsizes[size * 2 + 1]) + fpsr_set_exception(FPSR_OPERR); + } + if (fp > fxsizes[size * 2 + 1]) { fp = fxsizes[size * 2 + 1]; + fpsr_set_exception(FPSR_OPERR); + } #ifdef USE_HOST_ROUNDING #ifdef USE_LONG_DOUBLE return lrintl(fp); @@ -830,8 +875,60 @@ static void fp_normalize(fpdata *a) { } +static void fp_cmp(fpdata *a, fpdata *b) +{ + bool a_neg = fpp_is_neg(a); + bool b_neg = fpp_is_neg(b); + bool a_inf = fpp_is_infinity(a); + bool b_inf = fpp_is_infinity(b); + bool a_zero = fpp_is_zero(a); + bool b_zero = fpp_is_zero(b); + bool a_nan = fpp_is_nan(a); + bool b_nan = fpp_is_nan(b); + fptype v = 1.0; + + if (a_nan || b_nan) { + // FCMP never returns N + NaN + v = *fp_nan; + } else if (a_zero && b_zero) { + if ((a_neg && b_neg) || (a_neg && !b_neg)) + v = -0.0; + else + v = 0.0; + } else if (a_zero && b_inf) { + if (!b_neg) + v = -1.0; + else + v = 1.0; + } else if (a_inf && b_zero) { + if (!a_neg) + v = -1.0; + else + v = 1.0; + } else if (a_inf && b_inf) { + if (a_neg == b_neg) + v = 0.0; + if ((a_neg && b_neg) || (a_neg && !b_neg)) + v = -v; + } else if (a_inf) { + if (a_neg) + v = -1.0; + } else if (b_inf) { + if (!b_neg) + v = -1.0; + } else { + fpp_sub(a, b); + v = a->fp; + fp_clear_status(); + } + a->fp = v; +} + void fp_init_native(void) { + set_floatx80_rounding_precision(80, &fs); + set_float_rounding_mode(float_round_to_zero, &fs); + fpp_print = fp_print; fpp_is_snan = fp_is_snan; fpp_unset_snan = fp_unset_snan; @@ -904,4 +1001,5 @@ void fp_init_native(void) fpp_sub = fp_sub; fpp_sgldiv = fp_sgldiv; fpp_sglmul = fp_sglmul; + fpp_cmp = fp_cmp; } diff --git a/fpp_softfloat.cpp b/fpp_softfloat.cpp index 83aa2d43..00d11fd0 100644 --- a/fpp_softfloat.cpp +++ b/fpp_softfloat.cpp @@ -39,8 +39,6 @@ #define FPCR_PRECISION_DOUBLE 0x00000080 #define FPCR_PRECISION_EXTENDED 0x00000000 -static floatx80 fxsizes[6]; -static floatx80 fxzero; static struct float_status fs; /* Functions for setting host/library modes and getting status */ @@ -172,6 +170,15 @@ static bool fp_is_unnormal(fpdata *fpd) return floatx80_is_unnormal(fpd->fpx) != 0; } +static inline int32_t extractFloatx80Exp( floatx80 a ) +{ + return a.high & 0x7FFF; +} +static inline uint64_t extractFloatx80Frac( floatx80 a ) +{ + return a.low; +} + /* Functions for converting between float formats */ static const fptype twoto32 = 4294967296.0; @@ -214,6 +221,18 @@ static void to_native(fptype *fp, fpdata *fpd) #endif } +static bool to_native_checked(fptype *fp, fpdata *fpd, fpdata *dst) +{ + uint64_t aSig = extractFloatx80Frac(fpd->fpx); + int32_t aExp = extractFloatx80Exp(fpd->fpx); + if (aExp == 0x7FFF && (uint64_t)(aSig << 1)) { + dst->fpx = propagateFloatx80NaN(fpd->fpx, fpd->fpx, &fs); + return true; + } + to_native(fp, fpd); + return false; +} + static void from_native(fptype fp, fpdata *fpd) { int expon; @@ -313,13 +332,12 @@ static void from_exten_x(fpdata *fpd, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd static uae_s64 to_int(fpdata *src, int size) { - if (floatx80_lt(src->fpx, fxsizes[size * 2 + 0], &fs)) { - return floatx80_to_int32(fxsizes[size * 2 + 0], &fs); - } - if (floatx80_le(fxsizes[size * 2 + 1], src->fpx, &fs)) { - return floatx80_to_int32(fxsizes[size * 2 + 1], &fs); - } - return floatx80_to_int32(src->fpx, &fs); + switch (size) { + case 0: return floatx80_to_int8(src->fpx, &fs); + case 1: return floatx80_to_int16(src->fpx, &fs); + case 2: return floatx80_to_int32(src->fpx, &fs); + default: return 0; + } } static void from_int(fpdata *fpd, uae_s32 src) { @@ -327,16 +345,6 @@ static void from_int(fpdata *fpd, uae_s32 src) } -static inline int32_t extractFloatx80Exp( floatx80 a ) -{ - return a.high & 0x7FFF; -} -static inline uint64_t extractFloatx80Frac( floatx80 a ) -{ - return a.low; -} - - /* Functions for rounding */ static floatx80 fp_to_sgl(floatx80 a) @@ -391,14 +399,16 @@ static void fp_sqrt(fpdata *a, fpdata *dst) static void fp_lognp1(fpdata *a, fpdata *dst) { fptype fpa; - to_native(&fpa, a); + if (to_native_checked(&fpa, a, dst)) + return; fpa = log(a->fp + 1.0); from_native(fpa, dst); } static void fp_sin(fpdata *a, fpdata *dst) { fptype fpa; - to_native(&fpa, a); + if (to_native_checked(&fpa, a, dst)) + return; fpa = sin(fpa); from_native(fpa, dst); } @@ -502,7 +512,10 @@ static void fp_sub(fpdata *a, fpdata *b) { a->fpx = floatx80_sub(a->fpx, b->fpx, &fs); } - +static void fp_cmp(fpdata *a, fpdata *b) +{ + a->fpx = floatx80_cmp(a->fpx, b->fpx, &fs); +} /* FIXME: create softfloat functions for following arithmetics */ @@ -594,12 +607,6 @@ void fp_init_softfloat(void) float_status fsx = { 0 }; set_floatx80_rounding_precision(80, &fsx); set_float_rounding_mode(float_round_to_zero, &fsx); - fxsizes[0] = int32_to_floatx80(-128, &fsx); - fxsizes[1] = int32_to_floatx80(127, &fsx); - fxsizes[2] = int32_to_floatx80(-32768, &fsx); - fxsizes[3] = int32_to_floatx80(32767, &fsx); - fxsizes[4] = int32_to_floatx80(-2147483648, &fsx); - fxsizes[5] = int32_to_floatx80(2147483647, &fsx); fpp_print = fp_print; fpp_is_snan = fp_is_snan; @@ -673,5 +680,6 @@ void fp_init_softfloat(void) fpp_sub = fp_sub; fpp_sgldiv = fp_sgldiv; fpp_sglmul = fp_sglmul; + fpp_cmp = fp_cmp; } diff --git a/include/fpp.h b/include/fpp.h index 0eed12d6..434059ef 100644 --- a/include/fpp.h +++ b/include/fpp.h @@ -1,6 +1,16 @@ extern void fp_init_native(void); extern void fp_init_softfloat(void); +extern void fpsr_set_exception(uae_u32 exception); + +#define FPSR_BSUN 0x00008000 +#define FPSR_SNAN 0x00004000 +#define FPSR_OPERR 0x00002000 +#define FPSR_OVFL 0x00001000 +#define FPSR_UNFL 0x00000800 +#define FPSR_DZ 0x00000400 +#define FPSR_INEX2 0x00000200 +#define FPSR_INEX1 0x00000100 #if defined(CPU_i386) || defined(CPU_x86_64) extern void init_fpucw_x87(void); @@ -109,3 +119,4 @@ extern FPP_AB fpp_scale; extern FPP_AB fpp_sub; extern FPP_AB fpp_sgldiv; extern FPP_AB fpp_sglmul; +extern FPP_AB fpp_cmp; diff --git a/include/newcpu.h b/include/newcpu.h index 28985839..5d6020fd 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -180,7 +180,9 @@ struct regstruct #ifdef FPUEMU fpdata fp[8]; +#ifdef JIT fpdata fp_result; +#endif uae_u32 fp_result_status; uae_u32 fpcr, fpsr, fpiar; uae_u32 fpu_state; diff --git a/softfloat/softfloat.cpp b/softfloat/softfloat.cpp index 83af324e..a24dc90f 100644 --- a/softfloat/softfloat.cpp +++ b/softfloat/softfloat.cpp @@ -186,6 +186,87 @@ static int32_t roundAndPackInt32(flag zSign, uint64_t absZ, float_status *status } + +#ifdef SOFTFLOAT_68K // 30-01-2017: Added for Previous +static int16_t roundAndPackInt16( flag zSign, uint64_t absZ, float_status *status ) +{ + int8_t roundingMode; + flag roundNearestEven; + int8_t roundIncrement, roundBits; + int16_t z; + + roundingMode = status->float_rounding_mode; + roundNearestEven = ( roundingMode == float_round_nearest_even ); + roundIncrement = 0x40; + if ( ! roundNearestEven ) { + if ( roundingMode == float_round_to_zero ) { + roundIncrement = 0; + } + else { + roundIncrement = 0x7F; + if ( zSign ) { + if ( roundingMode == float_round_up ) roundIncrement = 0; + } + else { + if ( roundingMode == float_round_down ) roundIncrement = 0; + } + } + } + roundBits = absZ & 0x7F; + absZ = ( absZ + roundIncrement )>>7; + absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); + z = absZ; + if ( zSign ) z = - z; + z = (int16_t) z; + if ( ( absZ>>16 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { + float_raise( float_flag_invalid, status ); + return zSign ? (int16_t) 0x8000 : 0x7FFF; + } + if ( roundBits ) status->float_exception_flags |= float_flag_inexact; + return z; + +} + +static int8_t roundAndPackInt8( flag zSign, uint64_t absZ, float_status *status ) +{ + int8_t roundingMode; + flag roundNearestEven; + int8_t roundIncrement, roundBits; + int8_t z; + + roundingMode = status->float_rounding_mode; + roundNearestEven = ( roundingMode == float_round_nearest_even ); + roundIncrement = 0x40; + if ( ! roundNearestEven ) { + if ( roundingMode == float_round_to_zero ) { + roundIncrement = 0; + } + else { + roundIncrement = 0x7F; + if ( zSign ) { + if ( roundingMode == float_round_up ) roundIncrement = 0; + } + else { + if ( roundingMode == float_round_down ) roundIncrement = 0; + } + } + } + roundBits = absZ & 0x7F; + absZ = ( absZ + roundIncrement )>>7; + absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); + z = absZ; + if ( zSign ) z = - z; + z = (int8_t) z; + if ( ( absZ>>8 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { + float_raise( float_flag_invalid, status ); + return zSign ? (int8_t) 0x80 : 0x7F; + } + if ( roundBits ) status->float_exception_flags |= float_flag_inexact; + return z; + +} +#endif // End of addition for Previous + /*---------------------------------------------------------------------------- | Takes the 128-bit fixed-point value formed by concatenating `absZ0' and | `absZ1', with binary point between bits 63 and 64 (between the input words), @@ -4995,7 +5076,15 @@ int32_t floatx80_to_int32(floatx80 a, float_status *status) aSig = extractFloatx80Frac( a ); aExp = extractFloatx80Exp( a ); aSign = extractFloatx80Sign( a ); - if ( ( aExp == 0x7FFF ) && (uint64_t) ( aSig<<1 ) ) aSign = 0; +#ifdef SOFTFLOAT_68K + if ( aExp == 0x7FFF ) { + float_raise( float_flag_invalid, status ); + if ( (uint64_t) ( aSig<<1 ) ) return (int32_t)(aSig>>32); + return aSign ? (int32_t) 0x80000000 : 0x7FFFFFFF; + } +#else + if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; +#endif shiftCount = 0x4037 - aExp; if ( shiftCount <= 0 ) shiftCount = 1; shift64RightJamming( aSig, shiftCount, &aSig ); @@ -5003,6 +5092,50 @@ int32_t floatx80_to_int32(floatx80 a, float_status *status) } +#ifdef SOFTFLOAT_68K // 30-01-2017: Addition for Previous +int16_t floatx80_to_int16( floatx80 a, float_status *status) +{ + flag aSign; + int32_t aExp, shiftCount; + uint64_t aSig; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( aExp == 0x7FFF ) { + float_raise( float_flag_invalid, status ); + if ( (uint64_t) ( aSig<<1 ) ) return (int16_t)(aSig>>48); + return aSign ? (int16_t) 0x8000 : 0x7FFF; + } + shiftCount = 0x4037 - aExp; + if ( shiftCount <= 0 ) shiftCount = 1; + shift64RightJamming( aSig, shiftCount, &aSig ); + return roundAndPackInt16( aSign, aSig, status ); + +} +int8_t floatx80_to_int8( floatx80 a, float_status *status) +{ + flag aSign; + int32_t aExp, shiftCount; + uint64_t aSig; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( aExp == 0x7FFF ) { + float_raise( float_flag_invalid, status ); + if ( (uint64_t) ( aSig<<1 ) ) return (int8_t)(aSig>>56); + return aSign ? (int8_t) 0x80 : 0x7F; + } + shiftCount = 0x4037 - aExp; + if ( shiftCount <= 0 ) shiftCount = 1; + shift64RightJamming( aSig, shiftCount, &aSig ); + return roundAndPackInt8( aSign, aSig, status ); + +} +#endif // End of addition for Previous + + /*---------------------------------------------------------------------------- | Returns the result of converting the extended double-precision floating- | point value `a' to the 32-bit two's complement integer format. The @@ -6100,8 +6233,7 @@ floatx80 floatx80_rem( floatx80 a, floatx80 b, uint64_t *q, flag *s, float_statu mul64To128( bSig, qTemp, &term0, &term1 ); sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 ); - *q += qTemp; - *q <<= 62; + *q = ( expDiff > 63 ) ? 0 : ( qTemp< 63 ) ? 0 : ( qTemp<floatx80_rounding_precision, aSign, aExp, aSig, 0, status); } -#endif // End of addition for Previous +/*---------------------------------------------------------------------------- + | Returns the result of comparing the extended double-precision floating- + | point values `a' and `b'. The result is abstracted for matching the + | corresponding condition codes. + *----------------------------------------------------------------------------*/ + +floatx80 floatx80_cmp( floatx80 a, floatx80 b, float_status *status ) +{ + flag aSign, bSign; + int32_t aExp, bExp; + uint64_t aSig, bSig; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + bSig = extractFloatx80Frac( b ); + bExp = extractFloatx80Exp( b ); + bSign = extractFloatx80Sign( b ); + + if ( ( aExp == 0x7FFF && (uint64_t) ( aSig<<1 ) ) || + ( bExp == 0x7FFF && (uint64_t) ( bSig<<1 ) ) ) { + return packFloatx80(0, 0x7FFF, floatx80_default_nan_low); } + + if ( bExp < aExp ) return packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); + if ( aExp < bExp ) return packFloatx80( bSign ^ 1, 0x3FFF, LIT64( 0x8000000000000000 ) ); + + if ( aExp == 0x7FFF ) { + if ( aSign == bSign ) return packFloatx80( aSign, 0, 0 ); + return packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); + } + + if ( bSig < aSig ) return packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); + if ( aSig < bSig ) return packFloatx80( bSign ^ 1, 0x3FFF, LIT64( 0x8000000000000000 ) ); + + if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); + + if ( aSign == bSign ) return packFloatx80( 0, 0, 0 ); + + return packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); + +} + +#endif // End of addition for Previous /*---------------------------------------------------------------------------- | Returns 1 if the extended double-precision floating-point value `a' is equal diff --git a/softfloat/softfloat.h b/softfloat/softfloat.h index e9eeeaac..f5f1c470 100644 --- a/softfloat/softfloat.h +++ b/softfloat/softfloat.h @@ -596,6 +596,10 @@ float64 float64_default_nan(float_status *status); | Software IEC/IEEE extended double-precision conversion routines. *----------------------------------------------------------------------------*/ int32_t floatx80_to_int32(floatx80, float_status *status); +#ifdef SOFTFLOAT_68K +int16_t floatx80_to_int16(floatx80, float_status *status); +int8_t floatx80_to_int8(floatx80, float_status *status); +#endif int32_t floatx80_to_int32_round_to_zero(floatx80, float_status *status); int64_t floatx80_to_int64(floatx80, float_status *status); int64_t floatx80_to_int64_round_to_zero(floatx80, float_status *status); @@ -624,6 +628,7 @@ floatx80 floatx80_mod( floatx80 a, floatx80 b, uint64_t *q, flag *s, float_statu floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status); floatx80 floatx80_sglmul( floatx80 a, floatx80 b, float_status *status); floatx80 floatx80_sgldiv( floatx80 a, floatx80 b, float_status *status); +floatx80 floatx80_cmp( floatx80 a, floatx80 b, float_status *status); /*---------------------------------------------------------------------------- | Software IEC/IEEE extended double-precision operations.