From 602c329c3ce88afcb4b269b39ed51a24669d9e09 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Tue, 7 Feb 2017 17:05:41 +0200 Subject: [PATCH] FPU update 20b merge + nan/invalid fix. --- fpp_softfloat.cpp | 1 + softfloat/softfloat-specialize.h | 12 +++------- softfloat/softfloat.cpp | 40 ++++++++++++++++++++++++++++---- softfloat/softfloat.h | 2 +- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/fpp_softfloat.cpp b/fpp_softfloat.cpp index 7043ebab..b30f2620 100644 --- a/fpp_softfloat.cpp +++ b/fpp_softfloat.cpp @@ -44,6 +44,7 @@ static struct float_status fs; static void fp_set_mode(uae_u32 mode_control) { set_floatx80_rounding_precision(80, &fs); + set_float_detect_tininess(float_tininess_before_rounding, &fs); switch(mode_control & FPCR_ROUNDING_MODE) { case FPCR_ROUND_NEAR: // to neareset set_float_rounding_mode(float_round_nearest_even, &fs); diff --git a/softfloat/softfloat-specialize.h b/softfloat/softfloat-specialize.h index 1586f3f7..315debbb 100644 --- a/softfloat/softfloat-specialize.h +++ b/softfloat/softfloat-specialize.h @@ -97,15 +97,9 @@ static inline flag floatx80_is_nan( floatx80 a ) static floatx80 floatx80_default_nan(float_status *status) { floatx80 r; - - if (status->snan_bit_is_one) { - r.low = LIT64(0xBFFFFFFFFFFFFFFF); - r.high = 0x7FFF; - } else { - r.low = LIT64(0xC000000000000000); - r.high = 0xFFFF; - } - return r; + r.high = 0x7FFF; + r.low = LIT64( 0xFFFFFFFFFFFFFFFF ); + return r; } /*---------------------------------------------------------------------------- diff --git a/softfloat/softfloat.cpp b/softfloat/softfloat.cpp index d61934f9..781178c2 100644 --- a/softfloat/softfloat.cpp +++ b/softfloat/softfloat.cpp @@ -425,7 +425,12 @@ static float32 roundAndPackFloat32(flag zSign, int zExp, uint32_t zSig, || ( ( zExp == 0xFD ) && ( (int32_t) ( zSig + roundIncrement ) < 0 ) ) ) { +#ifdef SOFTFLOAT_68K + float_raise( float_flag_overflow, status ); + if ( roundBits ) float_raise( float_flag_inexact, status ); +#else float_raise(float_flag_overflow | float_flag_inexact, status); +#endif return packFloat32( zSign, 0xFF, - ( roundIncrement == 0 )); } if ( zExp < 0 ) { @@ -441,9 +446,13 @@ static float32 roundAndPackFloat32(flag zSign, int zExp, uint32_t zSig, shift32RightJamming( zSig, - zExp, &zSig ); zExp = 0; roundBits = zSig & 0x7F; +#ifdef SOFTFLOAT_68K + if ( isTiny ) float_raise( float_flag_underflow, status ); +#else if (isTiny && roundBits) { float_raise(float_flag_underflow, status); } +#endif } } if (roundBits) { @@ -617,7 +626,12 @@ static float64 roundAndPackFloat64(flag zSign, int zExp, uint64_t zSig, || ( ( zExp == 0x7FD ) && ( (int64_t) ( zSig + roundIncrement ) < 0 ) ) ) { +#ifdef SOFTFLOAT_68K + float_raise( float_flag_overflow, status ); + if ( roundBits ) float_raise( float_flag_inexact, status ); +#else float_raise(float_flag_overflow | float_flag_inexact, status); +#endif return packFloat64( zSign, 0x7FF, - ( roundIncrement == 0 )); } if ( zExp < 0 ) { @@ -633,9 +647,13 @@ static float64 roundAndPackFloat64(flag zSign, int zExp, uint64_t zSig, shift64RightJamming( zSig, - zExp, &zSig ); zExp = 0; roundBits = zSig & 0x3FF; +#ifdef SOFTFLOAT_68K + if ( isTiny ) float_raise( float_flag_underflow, status ); +#else if (isTiny && roundBits) { float_raise(float_flag_underflow, status); } +#endif } } if (roundBits) { @@ -839,10 +857,14 @@ floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign, #endif zExp = 0; roundBits = zSig0 & roundMask; +#ifdef SOFTFLOAT_68K + if ( isTiny ) float_raise( float_flag_underflow, status ); +#else if (isTiny && roundBits) { float_raise(float_flag_underflow, status); } - if (roundBits) { +#endif +if (roundBits) { status->float_exception_flags |= float_flag_inexact; } zSig0 += roundIncrement; @@ -903,8 +925,13 @@ floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign, ) { roundMask = 0; overflow: +#ifndef SOFTFLOAT_68K float_raise(float_flag_overflow | float_flag_inexact, status); - if ( ( roundingMode == float_round_to_zero ) +#else + float_raise( float_flag_overflow, status ); + if ( ( zSig0 & roundMask ) || zSig1 ) float_raise( float_flag_inexact, status ); +#endif + if ( ( roundingMode == float_round_to_zero ) || ( zSign && ( roundingMode == float_round_up ) ) || ( ! zSign && ( roundingMode == float_round_down ) ) ) { @@ -933,9 +960,13 @@ floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign, shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 ); #endif zExp = 0; +#ifdef SOFTFLOAT_68K + if ( isTiny ) float_raise( float_flag_underflow, status ); +#else if (isTiny && zSig1) { float_raise(float_flag_underflow, status); } +#endif if (zSig1) { status->float_exception_flags |= float_flag_inexact; } @@ -1019,7 +1050,8 @@ floatx80 roundAndPackFloatx80Sgl( flag zSign, int32_t zExp, uint64_t zSig0, uint if ( ( 0x7FFE < zExp ) || ( ( zExp == 0x7FFE ) && ( zSig0 + roundIncrement < zSig0 ) ) ) { - float_raise( float_flag_overflow | float_flag_inexact, status ); + float_raise( float_flag_overflow, status ); + if ( zSig0 & roundMask ) float_raise( float_flag_inexact, status ); if ( ( roundingMode == float_round_to_zero ) || ( zSign && ( roundingMode == float_round_up ) ) || ( ! zSign && ( roundingMode == float_round_down ) ) @@ -1037,7 +1069,7 @@ floatx80 roundAndPackFloatx80Sgl( flag zSign, int32_t zExp, uint64_t zSig0, uint shift64RightJamming( zSig0, -zExp, &zSig0 ); zExp = 0; roundBits = zSig0 & roundMask; - if ( isTiny && roundBits ) float_raise( float_flag_underflow, status ); + if ( isTiny ) float_raise( float_flag_underflow, status ); if ( roundBits ) status->float_exception_flags |= float_flag_inexact; if ( ( zSig0 & ~roundMask ) == 0 ) { zSig0 = ( roundIncrement != roundMask ); diff --git a/softfloat/softfloat.h b/softfloat/softfloat.h index 3ec8ebc7..9d59a6e5 100644 --- a/softfloat/softfloat.h +++ b/softfloat/softfloat.h @@ -456,7 +456,7 @@ static inline int floatx80_is_any_nan(floatx80 a) *----------------------------------------------------------------------------*/ static inline bool floatx80_invalid_encoding(floatx80 a) { - return (a.low & (1ULL << 63)) == 0 && (a.high & 0x7FFF) != 0; + return (a.low & (1ULL << 63)) == 0 && (a.high & 0x7FFF) != 0 && (a.high & 0x7FFF) != 0x7FFF; } #define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL) -- 2.47.3