diff --git a/build/Linux-386-GCC/Makefile b/build/Linux-386-GCC/Makefile index faeb3972..24d9b735 100644 --- a/build/Linux-386-GCC/Makefile +++ b/build/Linux-386-GCC/Makefile @@ -133,6 +133,9 @@ OBJS_OTHERS = \ s_tryPropagateNaNExtF80M$(OBJ) \ s_invalidExtF80M$(OBJ) \ s_normExtF80SigM$(OBJ) \ + s_normSubnormalExtF80Sig$(OBJ) \ + s_canonicalizeExtF80M$(OBJ) \ + s_canonicalizeExtF80MUI$(OBJ) \ s_roundPackMToExtF80M$(OBJ) \ s_normRoundPackMToExtF80M$(OBJ) \ s_addExtF80M$(OBJ) \ diff --git a/build/Linux-386-SSE2-GCC/Makefile b/build/Linux-386-SSE2-GCC/Makefile index ced977b6..b041561d 100644 --- a/build/Linux-386-SSE2-GCC/Makefile +++ b/build/Linux-386-SSE2-GCC/Makefile @@ -133,6 +133,9 @@ OBJS_OTHERS = \ s_tryPropagateNaNExtF80M$(OBJ) \ s_invalidExtF80M$(OBJ) \ s_normExtF80SigM$(OBJ) \ + s_normSubnormalExtF80Sig$(OBJ) \ + s_canonicalizeExtF80M$(OBJ) \ + s_canonicalizeExtF80MUI$(OBJ) \ s_roundPackMToExtF80M$(OBJ) \ s_normRoundPackMToExtF80M$(OBJ) \ s_addExtF80M$(OBJ) \ diff --git a/build/Linux-ARM-VFPv2-GCC/Makefile b/build/Linux-ARM-VFPv2-GCC/Makefile index a1e7c830..23252179 100644 --- a/build/Linux-ARM-VFPv2-GCC/Makefile +++ b/build/Linux-ARM-VFPv2-GCC/Makefile @@ -131,6 +131,9 @@ OBJS_OTHERS = \ s_tryPropagateNaNExtF80M$(OBJ) \ s_invalidExtF80M$(OBJ) \ s_normExtF80SigM$(OBJ) \ + s_normSubnormalExtF80Sig$(OBJ) \ + s_canonicalizeExtF80M$(OBJ) \ + s_canonicalizeExtF80MUI$(OBJ) \ s_roundPackMToExtF80M$(OBJ) \ s_normRoundPackMToExtF80M$(OBJ) \ s_addExtF80M$(OBJ) \ diff --git a/build/Linux-RISCV64-GCC/Makefile b/build/Linux-RISCV64-GCC/Makefile index 72e1f632..fa34548e 100644 --- a/build/Linux-RISCV64-GCC/Makefile +++ b/build/Linux-RISCV64-GCC/Makefile @@ -140,6 +140,8 @@ OBJS_OTHERS = \ s_subMagsF64$(OBJ) \ s_mulAddF64$(OBJ) \ s_normSubnormalExtF80Sig$(OBJ) \ + s_canonicalizeExtF80$(OBJ) \ + s_canonicalizeExtF80UI$(OBJ) \ s_roundPackToExtF80$(OBJ) \ s_normRoundPackToExtF80$(OBJ) \ s_addMagsExtF80$(OBJ) \ diff --git a/build/Linux-x86_64-GCC/Makefile b/build/Linux-x86_64-GCC/Makefile index 72f251a5..b7744aef 100644 --- a/build/Linux-x86_64-GCC/Makefile +++ b/build/Linux-x86_64-GCC/Makefile @@ -137,6 +137,8 @@ OBJS_OTHERS = \ s_subMagsF64$(OBJ) \ s_mulAddF64$(OBJ) \ s_normSubnormalExtF80Sig$(OBJ) \ + s_canonicalizeExtF80$(OBJ) \ + s_canonicalizeExtF80UI$(OBJ) \ s_roundPackToExtF80$(OBJ) \ s_normRoundPackToExtF80$(OBJ) \ s_addMagsExtF80$(OBJ) \ diff --git a/build/Win32-MinGW/Makefile b/build/Win32-MinGW/Makefile index faeb3972..24d9b735 100644 --- a/build/Win32-MinGW/Makefile +++ b/build/Win32-MinGW/Makefile @@ -133,6 +133,9 @@ OBJS_OTHERS = \ s_tryPropagateNaNExtF80M$(OBJ) \ s_invalidExtF80M$(OBJ) \ s_normExtF80SigM$(OBJ) \ + s_normSubnormalExtF80Sig$(OBJ) \ + s_canonicalizeExtF80M$(OBJ) \ + s_canonicalizeExtF80MUI$(OBJ) \ s_roundPackMToExtF80M$(OBJ) \ s_normRoundPackMToExtF80M$(OBJ) \ s_addExtF80M$(OBJ) \ diff --git a/build/Win32-SSE2-MinGW/Makefile b/build/Win32-SSE2-MinGW/Makefile index ced977b6..b041561d 100644 --- a/build/Win32-SSE2-MinGW/Makefile +++ b/build/Win32-SSE2-MinGW/Makefile @@ -133,6 +133,9 @@ OBJS_OTHERS = \ s_tryPropagateNaNExtF80M$(OBJ) \ s_invalidExtF80M$(OBJ) \ s_normExtF80SigM$(OBJ) \ + s_normSubnormalExtF80Sig$(OBJ) \ + s_canonicalizeExtF80M$(OBJ) \ + s_canonicalizeExtF80MUI$(OBJ) \ s_roundPackMToExtF80M$(OBJ) \ s_normRoundPackMToExtF80M$(OBJ) \ s_addExtF80M$(OBJ) \ diff --git a/build/Win64-MinGW-w64/Makefile b/build/Win64-MinGW-w64/Makefile index cc5bc0c5..d3686ccb 100644 --- a/build/Win64-MinGW-w64/Makefile +++ b/build/Win64-MinGW-w64/Makefile @@ -133,6 +133,8 @@ OBJS_OTHERS = \ s_subMagsF64$(OBJ) \ s_mulAddF64$(OBJ) \ s_normSubnormalExtF80Sig$(OBJ) \ + s_canonicalizeExtF80$(OBJ) \ + s_canonicalizeExtF80UI$(OBJ) \ s_roundPackToExtF80$(OBJ) \ s_normRoundPackToExtF80$(OBJ) \ s_addMagsExtF80$(OBJ) \ diff --git a/build/template-FAST_INT64/Makefile b/build/template-FAST_INT64/Makefile index e04c2160..867674a0 100644 --- a/build/template-FAST_INT64/Makefile +++ b/build/template-FAST_INT64/Makefile @@ -136,6 +136,8 @@ OBJS_OTHERS = \ s_subMagsF64$(OBJ) \ s_mulAddF64$(OBJ) \ s_normSubnormalExtF80Sig$(OBJ) \ + s_canonicalizeExtF80$(OBJ) \ + s_canonicalizeExtF80UI$(OBJ) \ s_roundPackToExtF80$(OBJ) \ s_normRoundPackToExtF80$(OBJ) \ s_addMagsExtF80$(OBJ) \ diff --git a/build/template-not-FAST_INT64/Makefile b/build/template-not-FAST_INT64/Makefile index 48b2cd6b..33d79759 100644 --- a/build/template-not-FAST_INT64/Makefile +++ b/build/template-not-FAST_INT64/Makefile @@ -133,6 +133,9 @@ OBJS_OTHERS = \ s_tryPropagateNaNExtF80M$(OBJ) \ s_invalidExtF80M$(OBJ) \ s_normExtF80SigM$(OBJ) \ + s_normSubnormalExtF80Sig$(OBJ) \ + s_canonicalizeExtF80M$(OBJ) \ + s_canonicalizeExtF80MUI$(OBJ) \ s_roundPackMToExtF80M$(OBJ) \ s_normRoundPackMToExtF80M$(OBJ) \ s_addExtF80M$(OBJ) \ diff --git a/source/extF80M_eq.c b/source/extF80M_eq.c index 24800371..533c28eb 100644 --- a/source/extF80M_eq.c +++ b/source/extF80M_eq.c @@ -70,6 +70,8 @@ bool extF80M_eq( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) uiA0 = aSPtr->signif; uiB64 = bSPtr->signExp; uiB0 = bSPtr->signif; + softfloat_canonicalizeExtF80MUI( &uiA64, &uiA0 ); + softfloat_canonicalizeExtF80MUI( &uiB64, &uiB0 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { diff --git a/source/extF80M_eq_signaling.c b/source/extF80M_eq_signaling.c index 785eba1e..81b31ab9 100644 --- a/source/extF80M_eq_signaling.c +++ b/source/extF80M_eq_signaling.c @@ -69,6 +69,8 @@ bool extF80M_eq_signaling( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) uiA0 = aSPtr->signif; uiB64 = bSPtr->signExp; uiB0 = bSPtr->signif; + softfloat_canonicalizeExtF80MUI( &uiA64, &uiA0 ); + softfloat_canonicalizeExtF80MUI( &uiB64, &uiB0 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { diff --git a/source/extF80M_le.c b/source/extF80M_le.c index 24edae87..a164f97b 100644 --- a/source/extF80M_le.c +++ b/source/extF80M_le.c @@ -70,6 +70,8 @@ bool extF80M_le( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) uiA0 = aSPtr->signif; uiB64 = bSPtr->signExp; uiB0 = bSPtr->signif; + softfloat_canonicalizeExtF80MUI( &uiA64, &uiA0 ); + softfloat_canonicalizeExtF80MUI( &uiB64, &uiB0 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { diff --git a/source/extF80M_le_quiet.c b/source/extF80M_le_quiet.c index 3880e36d..16e4ee4c 100644 --- a/source/extF80M_le_quiet.c +++ b/source/extF80M_le_quiet.c @@ -71,6 +71,8 @@ bool extF80M_le_quiet( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) uiA0 = aSPtr->signif; uiB64 = bSPtr->signExp; uiB0 = bSPtr->signif; + softfloat_canonicalizeExtF80MUI( &uiA64, &uiA0 ); + softfloat_canonicalizeExtF80MUI( &uiB64, &uiB0 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { diff --git a/source/extF80M_lt.c b/source/extF80M_lt.c index 70fa8f05..ec9a33a6 100644 --- a/source/extF80M_lt.c +++ b/source/extF80M_lt.c @@ -70,6 +70,8 @@ bool extF80M_lt( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) uiA0 = aSPtr->signif; uiB64 = bSPtr->signExp; uiB0 = bSPtr->signif; + softfloat_canonicalizeExtF80MUI( &uiA64, &uiA0 ); + softfloat_canonicalizeExtF80MUI( &uiB64, &uiB0 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { diff --git a/source/extF80M_lt_quiet.c b/source/extF80M_lt_quiet.c index b119af30..385e358c 100644 --- a/source/extF80M_lt_quiet.c +++ b/source/extF80M_lt_quiet.c @@ -71,6 +71,8 @@ bool extF80M_lt_quiet( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) uiA0 = aSPtr->signif; uiB64 = bSPtr->signExp; uiB0 = bSPtr->signif; + softfloat_canonicalizeExtF80MUI( &uiA64, &uiA0 ); + softfloat_canonicalizeExtF80MUI( &uiB64, &uiB0 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { diff --git a/source/extF80M_rem.c b/source/extF80M_rem.c index 065e271a..18355e93 100644 --- a/source/extF80M_rem.c +++ b/source/extF80M_rem.c @@ -79,6 +79,10 @@ void uiA64 = aSPtr->signExp; expA = expExtF80UI64( uiA64 ); expB = expExtF80UI64( bSPtr->signExp ); + sigA = aSPtr->signif; + x64 = bSPtr->signif; + softfloat_canonicalizeExtF80M( &expA, &sigA ); + softfloat_canonicalizeExtF80M( &expB, &x64 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { @@ -95,14 +99,12 @@ void /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expB ) expB = 1; - x64 = bSPtr->signif; if ( ! (x64 & UINT64_C( 0x8000000000000000 )) ) { if ( ! x64 ) goto invalid; expB += softfloat_normExtF80SigM( &x64 ); } signRem = signExtF80UI64( uiA64 ); if ( ! expA ) expA = 1; - sigA = aSPtr->signif; if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { if ( ! sigA ) { expA = 0; diff --git a/source/extF80M_to_i32.c b/source/extF80M_to_i32.c index c0464b13..e8b7046d 100644 --- a/source/extF80M_to_i32.c +++ b/source/extF80M_to_i32.c @@ -72,6 +72,7 @@ int_fast32_t sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; + softfloat_canonicalizeExtF80M( &exp, &sig ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x4032 - exp; diff --git a/source/extF80M_to_i64.c b/source/extF80M_to_i64.c index 2e07207a..892dba80 100644 --- a/source/extF80M_to_i64.c +++ b/source/extF80M_to_i64.c @@ -73,6 +73,7 @@ int_fast64_t sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; + softfloat_canonicalizeExtF80M( &exp, &sig ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x403E - exp; diff --git a/source/extF80M_to_ui32.c b/source/extF80M_to_ui32.c index 72579e41..9a9a01d7 100644 --- a/source/extF80M_to_ui32.c +++ b/source/extF80M_to_ui32.c @@ -72,6 +72,7 @@ uint_fast32_t sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; + softfloat_canonicalizeExtF80M( &exp, &sig ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x4032 - exp; diff --git a/source/extF80M_to_ui64.c b/source/extF80M_to_ui64.c index a7ee39fb..53bbdfb3 100644 --- a/source/extF80M_to_ui64.c +++ b/source/extF80M_to_ui64.c @@ -73,6 +73,7 @@ uint_fast64_t sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; + softfloat_canonicalizeExtF80M( &exp, &sig ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x403E - exp; diff --git a/source/extF80_eq.c b/source/extF80_eq.c index 60f29daf..e2034921 100644 --- a/source/extF80_eq.c +++ b/source/extF80_eq.c @@ -65,6 +65,8 @@ bool extF80_eq( extFloat80_t a, extFloat80_t b ) } return false; } + softfloat_canonicalizeExtF80UI( &uiA64, &uiA0 ); + softfloat_canonicalizeExtF80UI( &uiB64, &uiB0 ); return (uiA0 == uiB0) && ((uiA64 == uiB64) || (! uiA0 && ! ((uiA64 | uiB64) & 0x7FFF))); diff --git a/source/extF80_eq_signaling.c b/source/extF80_eq_signaling.c index 5a0dfe4a..45d8b862 100644 --- a/source/extF80_eq_signaling.c +++ b/source/extF80_eq_signaling.c @@ -59,6 +59,8 @@ bool extF80_eq_signaling( extFloat80_t a, extFloat80_t b ) softfloat_raiseFlags( softfloat_flag_invalid ); return false; } + softfloat_canonicalizeExtF80UI( &uiA64, &uiA0 ); + softfloat_canonicalizeExtF80UI( &uiB64, &uiB0 ); return (uiA0 == uiB0) && ((uiA64 == uiB64) || (! uiA0 && ! ((uiA64 | uiB64) & 0x7FFF))); diff --git a/source/extF80_le.c b/source/extF80_le.c index 2a1ee60f..dd352954 100644 --- a/source/extF80_le.c +++ b/source/extF80_le.c @@ -61,6 +61,8 @@ bool extF80_le( extFloat80_t a, extFloat80_t b ) softfloat_raiseFlags( softfloat_flag_invalid ); return false; } + softfloat_canonicalizeExtF80UI( &uiA64, &uiA0 ); + softfloat_canonicalizeExtF80UI( &uiB64, &uiB0 ); signA = signExtF80UI64( uiA64 ); signB = signExtF80UI64( uiB64 ); return diff --git a/source/extF80_le_quiet.c b/source/extF80_le_quiet.c index 5d0c3ae7..62309bad 100644 --- a/source/extF80_le_quiet.c +++ b/source/extF80_le_quiet.c @@ -66,6 +66,8 @@ bool extF80_le_quiet( extFloat80_t a, extFloat80_t b ) } return false; } + softfloat_canonicalizeExtF80UI( &uiA64, &uiA0 ); + softfloat_canonicalizeExtF80UI( &uiB64, &uiB0 ); signA = signExtF80UI64( uiA64 ); signB = signExtF80UI64( uiB64 ); return diff --git a/source/extF80_lt.c b/source/extF80_lt.c index 9560d8ec..400ce084 100644 --- a/source/extF80_lt.c +++ b/source/extF80_lt.c @@ -61,6 +61,8 @@ bool extF80_lt( extFloat80_t a, extFloat80_t b ) softfloat_raiseFlags( softfloat_flag_invalid ); return false; } + softfloat_canonicalizeExtF80UI( &uiA64, &uiA0 ); + softfloat_canonicalizeExtF80UI( &uiB64, &uiB0 ); signA = signExtF80UI64( uiA64 ); signB = signExtF80UI64( uiB64 ); return diff --git a/source/extF80_lt_quiet.c b/source/extF80_lt_quiet.c index 711652c7..d37c6a73 100644 --- a/source/extF80_lt_quiet.c +++ b/source/extF80_lt_quiet.c @@ -66,6 +66,8 @@ bool extF80_lt_quiet( extFloat80_t a, extFloat80_t b ) } return false; } + softfloat_canonicalizeExtF80UI( &uiA64, &uiA0 ); + softfloat_canonicalizeExtF80UI( &uiB64, &uiB0 ); signA = signExtF80UI64( uiA64 ); signB = signExtF80UI64( uiB64 ); return diff --git a/source/extF80_mul.c b/source/extF80_mul.c index c0c50a6c..06b48c77 100644 --- a/source/extF80_mul.c +++ b/source/extF80_mul.c @@ -56,7 +56,6 @@ extFloat80_t extF80_mul( extFloat80_t a, extFloat80_t b ) int_fast32_t expB; uint_fast64_t sigB; bool signZ; - uint_fast64_t magBits; struct exp32_sig64 normExpSig; int_fast32_t expZ; struct uint128 sig128Z, uiZ; @@ -88,13 +87,13 @@ extFloat80_t extF80_mul( extFloat80_t a, extFloat80_t b ) ) { goto propagateNaN; } - magBits = expB | sigB; - goto infArg; + if ( (expB != 0x7FFF) && ! sigB ) goto invalid; + goto infinity; } if ( expB == 0x7FFF ) { if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; - magBits = expA | sigA; - goto infArg; + if ( ! sigA ) goto invalid; + goto infinity; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ @@ -134,15 +133,16 @@ extFloat80_t extF80_mul( extFloat80_t a, extFloat80_t b ) goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ - infArg: - if ( ! magBits ) { - softfloat_raiseFlags( softfloat_flag_invalid ); - uiZ64 = defaultNaNExtF80UI64; - uiZ0 = defaultNaNExtF80UI0; - } else { - uiZ64 = packToExtF80UI64( signZ, 0x7FFF ); - uiZ0 = UINT64_C( 0x8000000000000000 ); - } + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ64 = defaultNaNExtF80UI64; + uiZ0 = defaultNaNExtF80UI0; + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infinity: + uiZ64 = packToExtF80UI64( signZ, 0x7FFF ); + uiZ0 = UINT64_C( 0x8000000000000000 ); goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ diff --git a/source/extF80_rem.c b/source/extF80_rem.c index a2ebaad8..85f2310c 100644 --- a/source/extF80_rem.c +++ b/source/extF80_rem.c @@ -97,6 +97,7 @@ extFloat80_t extF80_rem( extFloat80_t a, extFloat80_t b ) | that `expDiff' later is less than -1, which will result in returning | a canonicalized version of argument a. *--------------------------------------------------------------------*/ + sigB = UINT64_C( 0x8000000000000000 ); expB += expB; } /*------------------------------------------------------------------------ diff --git a/source/extF80_sqrt.c b/source/extF80_sqrt.c index 5d328a0e..0b7964ba 100644 --- a/source/extF80_sqrt.c +++ b/source/extF80_sqrt.c @@ -78,7 +78,11 @@ extFloat80_t extF80_sqrt( extFloat80_t a ) uiZ0 = uiZ.v0; goto uiZ; } - if ( ! signA ) return a; + if ( ! signA ) { + uiZ64 = packToExtF80UI64( 0, 0x7FFF ); + uiZ0 = UINT64_C( 0x8000000000000000 ); + goto uiZ; + } goto invalid; } /*------------------------------------------------------------------------ diff --git a/source/extF80_to_f128.c b/source/extF80_to_f128.c index 7fbc9cb6..a190ac9a 100644 --- a/source/extF80_to_f128.c +++ b/source/extF80_to_f128.c @@ -46,8 +46,8 @@ float128_t extF80_to_f128( extFloat80_t a ) union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; - uint_fast16_t exp; - uint_fast64_t frac; + int_fast32_t exp; + uint_fast64_t sig, frac; struct commonNaN commonNaN; struct uint128 uiZ; bool sign; @@ -58,7 +58,9 @@ float128_t extF80_to_f128( extFloat80_t a ) uiA64 = uA.s.signExp; uiA0 = uA.s.signif; exp = expExtF80UI64( uiA64 ); - frac = uiA0 & UINT64_C( 0x7FFFFFFFFFFFFFFF ); + sig = uiA0; + softfloat_canonicalizeExtF80( &exp, &sig ); + frac = sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ); if ( (exp == 0x7FFF) && frac ) { softfloat_extF80UIToCommonNaN( uiA64, uiA0, &commonNaN ); uiZ = softfloat_commonNaNToF128UI( &commonNaN ); diff --git a/source/extF80_to_f16.c b/source/extF80_to_f16.c index ca5050f4..8e410663 100644 --- a/source/extF80_to_f16.c +++ b/source/extF80_to_f16.c @@ -61,6 +61,7 @@ float16_t extF80_to_f16( extFloat80_t a ) sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = uiA0; + softfloat_canonicalizeExtF80( &exp, &sig ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp == 0x7FFF ) { diff --git a/source/extF80_to_f32.c b/source/extF80_to_f32.c index 357f56e9..78739441 100644 --- a/source/extF80_to_f32.c +++ b/source/extF80_to_f32.c @@ -61,6 +61,7 @@ float32_t extF80_to_f32( extFloat80_t a ) sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = uiA0; + softfloat_canonicalizeExtF80( &exp, &sig ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp == 0x7FFF ) { diff --git a/source/extF80_to_f64.c b/source/extF80_to_f64.c index c3873992..0716fdb5 100644 --- a/source/extF80_to_f64.c +++ b/source/extF80_to_f64.c @@ -61,6 +61,7 @@ float64_t extF80_to_f64( extFloat80_t a ) sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = uiA0; + softfloat_canonicalizeExtF80( &exp, &sig ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! (exp | sig) ) { diff --git a/source/extF80_to_i32.c b/source/extF80_to_i32.c index 549ca765..78ecf6ea 100644 --- a/source/extF80_to_i32.c +++ b/source/extF80_to_i32.c @@ -58,6 +58,7 @@ int_fast32_t sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; + softfloat_canonicalizeExtF80( &exp, &sig ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ #if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow) diff --git a/source/extF80_to_i32_r_minMag.c b/source/extF80_to_i32_r_minMag.c index 2b7b9e2b..13d3ce04 100644 --- a/source/extF80_to_i32_r_minMag.c +++ b/source/extF80_to_i32_r_minMag.c @@ -57,6 +57,7 @@ int_fast32_t extF80_to_i32_r_minMag( extFloat80_t a, bool exact ) uiA64 = uA.s.signExp; exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; + softfloat_canonicalizeExtF80( &exp, &sig ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x403E - exp; diff --git a/source/extF80_to_i64.c b/source/extF80_to_i64.c index 35f55de8..9b194c36 100644 --- a/source/extF80_to_i64.c +++ b/source/extF80_to_i64.c @@ -60,6 +60,7 @@ int_fast64_t sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; + softfloat_canonicalizeExtF80( &exp, &sig ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x403E - exp; diff --git a/source/extF80_to_i64_r_minMag.c b/source/extF80_to_i64_r_minMag.c index 215876da..a12c2546 100644 --- a/source/extF80_to_i64_r_minMag.c +++ b/source/extF80_to_i64_r_minMag.c @@ -57,6 +57,7 @@ int_fast64_t extF80_to_i64_r_minMag( extFloat80_t a, bool exact ) uiA64 = uA.s.signExp; exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; + softfloat_canonicalizeExtF80( &exp, &sig ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x403E - exp; diff --git a/source/extF80_to_ui32.c b/source/extF80_to_ui32.c index d121c480..d193e6f0 100644 --- a/source/extF80_to_ui32.c +++ b/source/extF80_to_ui32.c @@ -58,6 +58,7 @@ uint_fast32_t sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; + softfloat_canonicalizeExtF80( &exp, &sig ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ #if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow) diff --git a/source/extF80_to_ui32_r_minMag.c b/source/extF80_to_ui32_r_minMag.c index ad304834..fb5b1465 100644 --- a/source/extF80_to_ui32_r_minMag.c +++ b/source/extF80_to_ui32_r_minMag.c @@ -57,6 +57,7 @@ uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t a, bool exact ) uiA64 = uA.s.signExp; exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; + softfloat_canonicalizeExtF80( &exp, &sig ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x403E - exp; diff --git a/source/extF80_to_ui64.c b/source/extF80_to_ui64.c index a81bbd1b..191f5cde 100644 --- a/source/extF80_to_ui64.c +++ b/source/extF80_to_ui64.c @@ -60,6 +60,7 @@ uint_fast64_t sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; + softfloat_canonicalizeExtF80( &exp, &sig ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x403E - exp; diff --git a/source/extF80_to_ui64_r_minMag.c b/source/extF80_to_ui64_r_minMag.c index 65adfe7e..7f658790 100644 --- a/source/extF80_to_ui64_r_minMag.c +++ b/source/extF80_to_ui64_r_minMag.c @@ -57,6 +57,7 @@ uint_fast64_t extF80_to_ui64_r_minMag( extFloat80_t a, bool exact ) uiA64 = uA.s.signExp; exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; + softfloat_canonicalizeExtF80( &exp, &sig ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x403E - exp; diff --git a/source/include/internals.h b/source/include/internals.h index 5e6d4bd3..3bfa52ac 100644 --- a/source/include/internals.h +++ b/source/include/internals.h @@ -162,14 +162,23 @@ float64_t #define isNaNExtF80UI( a64, a0 ) ((((a64) & 0x7FFF) == 0x7FFF) && ((a0) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) +struct exp32_sig64 { int_fast32_t exp; uint64_t sig; }; +struct exp32_sig64 softfloat_normSubnormalExtF80Sig( uint_fast64_t ); + +void + softfloat_canonicalizeExtF80( int_fast32_t *, uint_fast64_t * ); +void + softfloat_canonicalizeExtF80UI( uint_fast16_t *, uint_fast64_t * ); +void + softfloat_canonicalizeExtF80M( int32_t *, uint64_t * ); +void + softfloat_canonicalizeExtF80MUI( uint_fast16_t *, uint64_t * ); + #ifdef SOFTFLOAT_FAST_INT64 /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ -struct exp32_sig64 { int_fast32_t exp; uint64_t sig; }; -struct exp32_sig64 softfloat_normSubnormalExtF80Sig( uint_fast64_t ); - extFloat80_t softfloat_roundPackToExtF80( bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); diff --git a/source/s_addExtF80M.c b/source/s_addExtF80M.c index f0142905..343676a8 100644 --- a/source/s_addExtF80M.c +++ b/source/s_addExtF80M.c @@ -53,10 +53,11 @@ void int32_t expA; uint32_t uiB64; int32_t expB; + uint64_t sigA, sigB; uint32_t uiZ64; bool signZ, signB; const struct extFloat80M *tempSPtr; - uint64_t sigZ, sigB; + uint64_t sigZ; void (*roundPackRoutinePtr)( bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * ); @@ -69,6 +70,12 @@ void expA = expExtF80UI64( uiA64 ); uiB64 = bSPtr->signExp; expB = expExtF80UI64( uiB64 ); + sigA = aSPtr->signif; + sigB = bSPtr->signif; + softfloat_canonicalizeExtF80M( &expA, &sigA ); + softfloat_canonicalizeExtF80M( &expB, &sigB ); + uiA64 = packToExtF80UI64( signExtF80UI64( uiA64 ), expA ); + uiB64 = packToExtF80UI64( signExtF80UI64( uiB64 ), expB ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { @@ -91,19 +98,21 @@ void signB = signExtF80UI64( uiB64 ) ^ negateB; negateB = (signZ != signB); if ( expA < expB ) { + int32_t tmpExp; + uint64_t tmpSig; signZ = signB; + tmpExp = expA; expA = expB; - expB = expExtF80UI64( uiA64 ); - tempSPtr = aSPtr; - aSPtr = bSPtr; - bSPtr = tempSPtr; + expB = tmpExp; + tmpSig = sigA; + sigA = sigB; + sigB = tmpSig; } if ( ! expB ) { expB = 1; if ( ! expA ) expA = 1; } - sigZ = aSPtr->signif; - sigB = bSPtr->signif; + sigZ = sigA; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ roundPackRoutinePtr = softfloat_roundPackMToExtF80M; diff --git a/source/s_addMagsExtF80.c b/source/s_addMagsExtF80.c index 6e7d1a6f..b4869296 100644 --- a/source/s_addMagsExtF80.c +++ b/source/s_addMagsExtF80.c @@ -69,6 +69,8 @@ extFloat80_t sigA = uiA0; expB = expExtF80UI64( uiB64 ); sigB = uiB0; + softfloat_canonicalizeExtF80( &expA, &sigA ); + softfloat_canonicalizeExtF80( &expB, &sigB ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expDiff = expA - expB; @@ -78,12 +80,21 @@ extFloat80_t goto propagateNaN; } uiZ64 = uiA64; - uiZ0 = uiA0; + uiZ0 = UINT64_C( 0x8000000000000000 ); goto uiZ; } sigZ = sigA + sigB; sigZExtra = 0; if ( ! expA ) { + if ( sigZ < sigA ) { + /*------------------------------------------------------------ + | Significand addition carried (e.g., two pseudo-denormals + | with J=1). Treat as effective exp=1 and fall through to + | `shiftRight1', which captures the carry. + *------------------------------------------------------------*/ + expZ = 1; + goto shiftRight1; + } normExpSig = softfloat_normSubnormalExtF80Sig( sigZ ); expZ = normExpSig.exp + 1; sigZ = normExpSig.sig; @@ -98,7 +109,7 @@ extFloat80_t if ( expB == 0x7FFF ) { if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; uiZ64 = packToExtF80UI64( signZ, 0x7FFF ); - uiZ0 = uiB0; + uiZ0 = UINT64_C( 0x8000000000000000 ); goto uiZ; } expZ = expB; @@ -114,7 +125,7 @@ extFloat80_t if ( expA == 0x7FFF ) { if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; uiZ64 = uiA64; - uiZ0 = uiA0; + uiZ0 = UINT64_C( 0x8000000000000000 ); goto uiZ; } expZ = expA; @@ -129,6 +140,7 @@ extFloat80_t } newlyAligned: sigZ = sigA + sigB; + if ( sigZ < sigA ) goto shiftRight1; if ( sigZ & UINT64_C( 0x8000000000000000 ) ) goto roundAndPack; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ diff --git a/source/s_canonicalizeExtF80.c b/source/s_canonicalizeExtF80.c new file mode 100644 index 00000000..c4ab5481 --- /dev/null +++ b/source/s_canonicalizeExtF80.c @@ -0,0 +1,122 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +/* This particular file was written by John Byrd. */ + +#include +#include "platform.h" +#include "internals.h" + +/*---------------------------------------------------------------------------- +| The 80-bit extended double format (extFloat80) is unique among IEEE 754 +| types in that it stores the integer bit of the significand explicitly as +| bit 63 of the 64-bit significand field, commonly called the 'J' bit. In +| all other IEEE 754 binary formats, the integer bit is implicit and +| determined solely by the exponent. Because the J bit is stored +| independently from the exponent in extFloat80, it is possible to construct +| encodings where the two are inconsistent. These inconsistent encodings +| are called "non-canonical" or, on the 8087 through 80287, "unnormal". +| Intel no longer generates non-canonical encodings, but the 80-bit format +| is still defined to accept them. +| This function rewrites the exponent '*expPtr' and significand '*sigPtr' +| of an extFloat80 value in place so that the encoding is canonical, i.e., +| the J bit is consistent with the exponent. The mathematical value +| represented by the encoding is preserved. If the encoding is already +| canonical, the values are unchanged. +| There are four classes of non-canonical encoding, each resolved as +| follows: +| +| 1. Unnormals (0 < exp < 0x7FFF, J = 0). The significand is nonzero +| but lacks its integer bit. If the significand can be left-shifted +| to set bit 63 without driving the biased exponent below 1, the value +| is renormalized. If the shift would require a biased exponent less +| than 1, the value is flushed to a denormal (exp = 0) with whatever +| significand bits survive the limited shift. If the significand is +| entirely zero, the exponent is set to 0 (encoding positive or +| negative zero, depending on the sign bit, which is not touched here). +| +| 2. Pseudo-denormals (exp = 0, J = 1). These represent the same value +| as a biased exponent of 1, so the exponent is set to 1 and the +| significand is left unchanged. +| +| 3. Pseudo-infinities (exp = 0x7FFF, J = 0, significand = 0). The +| J bit is forced to 1, producing the canonical infinity encoding. +| +| 4. Pseudo-NaNs (exp = 0x7FFF, J = 0, significand != 0). The J bit +| is forced to 1. The remaining significand bits (the NaN payload) +| are preserved, so quiet vs. signaling status is maintained. +| +| Cases 3 and 4 are handled together: when the biased exponent is +| 0x7FFF, the J bit is unconditionally set. +| +| This function does not modify the sign bit, which is not part of the +| exponent or significand fields passed here. It also does not raise any +| floating-point exception flags; canonicalization is a silent rewrite of +| the encoding only. +*----------------------------------------------------------------------------*/ +void + softfloat_canonicalizeExtF80( + int_fast32_t *expPtr, uint_fast64_t *sigPtr ) +{ + int_fast32_t exp; + uint_fast64_t sig; + struct exp32_sig64 normExpSig; + + exp = *expPtr; + sig = *sigPtr; + if ( exp == 0x7FFF ) { + *sigPtr = sig | UINT64_C( 0x8000000000000000 ); + } else if ( exp ) { + if ( ! (sig & UINT64_C( 0x8000000000000000 )) ) { + if ( ! sig ) { + *expPtr = 0; + } else { + normExpSig = softfloat_normSubnormalExtF80Sig( sig ); + if ( exp + normExpSig.exp >= 1 ) { + *expPtr = exp + normExpSig.exp; + *sigPtr = normExpSig.sig; + } else { + if ( exp > 1 ) *sigPtr = sig << (exp - 1); + *expPtr = 0; + } + } + } + } else { + if ( sig & UINT64_C( 0x8000000000000000 ) ) + *expPtr = 1; + } + +} diff --git a/source/s_canonicalizeExtF80M.c b/source/s_canonicalizeExtF80M.c new file mode 100644 index 00000000..ab10f0d2 --- /dev/null +++ b/source/s_canonicalizeExtF80M.c @@ -0,0 +1,81 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +/* This particular file was written by John Byrd. */ + +#include +#include "platform.h" +#include "internals.h" + +/*---------------------------------------------------------------------------- +| Equivalent to 'softfloat_canonicalizeExtF80' (see s_canonicalizeExtF80.c +| for the full description of extFloat80 non-canonical encodings and the +| canonicalization rules), but using 'int32_t' and 'uint64_t' parameter +| types to match the non-FAST_INT64 code paths. The algorithm and behavior +| are identical. +*----------------------------------------------------------------------------*/ +void + softfloat_canonicalizeExtF80M( int32_t *expPtr, uint64_t *sigPtr ) +{ + int32_t exp; + uint64_t sig; + struct exp32_sig64 normExpSig; + + exp = *expPtr; + sig = *sigPtr; + if ( exp == 0x7FFF ) { + *sigPtr = sig | UINT64_C( 0x8000000000000000 ); + } else if ( exp ) { + if ( ! (sig & UINT64_C( 0x8000000000000000 )) ) { + if ( ! sig ) { + *expPtr = 0; + } else { + normExpSig = softfloat_normSubnormalExtF80Sig( sig ); + if ( exp + normExpSig.exp >= 1 ) { + *expPtr = exp + normExpSig.exp; + *sigPtr = normExpSig.sig; + } else { + if ( exp > 1 ) *sigPtr = sig << (exp - 1); + *expPtr = 0; + } + } + } + } else { + if ( sig & UINT64_C( 0x8000000000000000 ) ) + *expPtr = 1; + } + +} diff --git a/source/s_canonicalizeExtF80MUI.c b/source/s_canonicalizeExtF80MUI.c new file mode 100644 index 00000000..0de3b7fc --- /dev/null +++ b/source/s_canonicalizeExtF80MUI.c @@ -0,0 +1,62 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +/* This particular file was written by John Byrd. */ + +#include +#include "platform.h" +#include "internals.h" + +/*---------------------------------------------------------------------------- +| Canonicalizes an extFloat80 value whose exponent and sign are stored in the +| packed 'signExp' layout used by the non-FAST_INT64 comparison functions. +| The packed 16-bit field '*signExpPtr' holds the sign in bit 15 and the +| 15-bit biased exponent in bits 14:0. This function extracts the exponent, +| passes it along with '*sigPtr' to 'softfloat_canonicalizeExtF80M' (see +| s_canonicalizeExtF80.c for the full canonicalization rules), and repacks +| the possibly-modified exponent back into '*signExpPtr' with the original +| sign bit preserved. +*----------------------------------------------------------------------------*/ +void + softfloat_canonicalizeExtF80MUI( + uint_fast16_t *signExpPtr, uint64_t *sigPtr ) +{ + int32_t exp = expExtF80UI64( *signExpPtr ); + + softfloat_canonicalizeExtF80M( &exp, sigPtr ); + *signExpPtr = packToExtF80UI64( signExtF80UI64( *signExpPtr ), exp ); + +} diff --git a/source/s_canonicalizeExtF80UI.c b/source/s_canonicalizeExtF80UI.c new file mode 100644 index 00000000..dbc1ea34 --- /dev/null +++ b/source/s_canonicalizeExtF80UI.c @@ -0,0 +1,62 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +/* This particular file was written by John Byrd. */ + +#include +#include "platform.h" +#include "internals.h" + +/*---------------------------------------------------------------------------- +| Canonicalizes an extFloat80 value whose exponent and sign are stored in the +| packed 'signExp' layout used by the FAST_INT64 comparison functions. The +| packed 16-bit field '*signExpPtr' holds the sign in bit 15 and the 15-bit +| biased exponent in bits 14:0. This function extracts the exponent, passes +| it along with '*sigPtr' to 'softfloat_canonicalizeExtF80' (see +| s_canonicalizeExtF80.c for the full canonicalization rules), and repacks +| the possibly-modified exponent back into '*signExpPtr' with the original +| sign bit preserved. +*----------------------------------------------------------------------------*/ +void + softfloat_canonicalizeExtF80UI( + uint_fast16_t *signExpPtr, uint_fast64_t *sigPtr ) +{ + int_fast32_t exp = *signExpPtr & 0x7FFF; + + softfloat_canonicalizeExtF80( &exp, sigPtr ); + *signExpPtr = (*signExpPtr & 0x8000) | exp; + +} diff --git a/source/s_compareNonnormExtF80M.c b/source/s_compareNonnormExtF80M.c index 6712e576..4d6b9833 100644 --- a/source/s_compareNonnormExtF80M.c +++ b/source/s_compareNonnormExtF80M.c @@ -56,16 +56,16 @@ int sigA = aSPtr->signif; signB = signExtF80UI64( uiB64 ); sigB = bSPtr->signif; + expA = expExtF80UI64( uiA64 ); + expB = expExtF80UI64( uiB64 ); + softfloat_canonicalizeExtF80M( &expA, &sigA ); + softfloat_canonicalizeExtF80M( &expB, &sigB ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (uiA64 ^ uiB64) & 0x8000 ) { if ( ! (sigA | sigB) ) return 0; goto resultFromSignB; } - /*------------------------------------------------------------------------ - *------------------------------------------------------------------------*/ - expA = expExtF80UI64( uiA64 ); - expB = expExtF80UI64( uiB64 ); if ( expA == 0x7FFF ) { if (expB == 0x7FFF) return 0; signB = ! signB; diff --git a/source/s_subMagsExtF80.c b/source/s_subMagsExtF80.c index 86ffd9b8..1a2ec530 100644 --- a/source/s_subMagsExtF80.c +++ b/source/s_subMagsExtF80.c @@ -68,6 +68,8 @@ extFloat80_t sigA = uiA0; expB = expExtF80UI64( uiB64 ); sigB = uiB0; + softfloat_canonicalizeExtF80( &expA, &sigA ); + softfloat_canonicalizeExtF80( &expB, &sigB ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expDiff = expA - expB; @@ -112,6 +114,12 @@ extFloat80_t sigExtra = sig128.v0; newlyAlignedBBigger: expZ = expB; + if ( sigA < sigB ) goto bBigger; + if ( sigB < sigA ) goto aBigger; + uiZ64 = + packToExtF80UI64( (softfloat_roundingMode == softfloat_round_min), 0 ); + uiZ0 = 0; + goto uiZ; bBigger: signZ = ! signZ; sig128 = softfloat_sub128( sigB, 0, sigA, sigExtra ); @@ -122,7 +130,7 @@ extFloat80_t if ( expA == 0x7FFF ) { if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; uiZ64 = uiA64; - uiZ0 = uiA0; + uiZ0 = UINT64_C( 0x8000000000000000 ); goto uiZ; } if ( ! expB ) { @@ -135,6 +143,12 @@ extFloat80_t sigExtra = sig128.v0; newlyAlignedABigger: expZ = expA; + if ( sigB < sigA ) goto aBigger; + if ( sigA < sigB ) goto bBigger; + uiZ64 = + packToExtF80UI64( (softfloat_roundingMode == softfloat_round_min), 0 ); + uiZ0 = 0; + goto uiZ; aBigger: sig128 = softfloat_sub128( sigA, 0, sigB, sigExtra ); /*------------------------------------------------------------------------