uint_fast64_t f128M_to_ui64( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) { const uint32_t *aWPtr; uint32_t uiA96; bool sign; int32_t exp; uint32_t sig96; int32_t shiftDist; uint32_t sig[4]; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; sign = signF128UI96( uiA96 ); exp = expF128UI96( uiA96 ); sig96 = fracF128UI96( uiA96 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftDist = 0x404F - exp; if ( shiftDist < 17 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return (exp == 0x7FFF) && (sig96 || (aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )])) ? ui64_fromNaN : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp ) sig96 |= 0x00010000; sig[indexWord( 4, 3 )] = sig96; sig[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; sig[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; sig[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; softfloat_shiftRightJam128M( sig, shiftDist, sig ); return softfloat_roundMToUI64( sign, sig + indexMultiwordLo( 4, 3 ), roundingMode, exact ); }
int_fast64_t f128M_to_i64( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) { const uint32_t *aWPtr; uint32_t uiA96; int32_t exp; bool sign; uint32_t sig96; int32_t shiftCount; uint32_t sig[4]; aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; exp = expF128UI96( uiA96 ); sign = signF128UI96( uiA96 ); sig96 = fracF128UI96( uiA96 ); shiftCount = 0x404F - exp; if ( shiftCount < 17 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return ! sign || ((exp == 0x7FFF) && (sig96 || ( aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ))) ? INT64_C( 0x7FFFFFFFFFFFFFFF ) : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; } if ( exp ) sig96 |= 0x00010000; sig[indexWord( 4, 3 )] = sig96; sig[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; sig[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; sig[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; softfloat_shiftRightJam128M( sig, shiftCount, sig ); return softfloat_roundPackMToI64( sign, sig + indexMultiwordLo( 4, 3 ), roundingMode, exact ); }
float64_t softfloat_mulAddF64( uint_fast64_t uiA, uint_fast64_t uiB, uint_fast64_t uiC, uint_fast8_t op ) { bool signA; int_fast16_t expA; uint64_t sigA; bool signB; int_fast16_t expB; uint64_t sigB; bool signC; int_fast16_t expC; uint64_t sigC; bool signZ; uint64_t magBits, uiZ; struct exp16_sig64 normExpSig; int_fast16_t expZ; uint32_t sig128Z[4]; uint64_t sigZ; int_fast16_t shiftCount, expDiff; uint32_t sig128C[4]; union ui64_f64 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ signA = signF64UI( uiA ); expA = expF64UI( uiA ); sigA = fracF64UI( uiA ); signB = signF64UI( uiB ); expB = expF64UI( uiB ); sigB = fracF64UI( uiB ); signC = signF64UI( uiC ) ^ (op == softfloat_mulAdd_subC); expC = expF64UI( uiC ); sigC = fracF64UI( uiC ); signZ = signA ^ signB ^ (op == softfloat_mulAdd_subProd); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FF ) { if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN_ABC; magBits = expB | sigB; goto infProdArg; } if ( expB == 0x7FF ) { if ( sigB ) goto propagateNaN_ABC; magBits = expA | sigA; goto infProdArg; } if ( expC == 0x7FF ) { if ( sigC ) { uiZ = 0; goto propagateNaN_ZC; } uiZ = uiC; goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) { if ( ! sigA ) goto zeroProd; normExpSig = softfloat_normSubnormalF64Sig( sigA ); expA = normExpSig.exp; sigA = normExpSig.sig; } if ( ! expB ) { if ( ! sigB ) goto zeroProd; normExpSig = softfloat_normSubnormalF64Sig( sigB ); expB = normExpSig.exp; sigB = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA + expB - 0x3FE; sigA = (sigA | UINT64_C( 0x0010000000000000 ))<<10; sigB = (sigB | UINT64_C( 0x0010000000000000 ))<<11; softfloat_mul64To128M( sigA, sigB, sig128Z ); sigZ = (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )]; shiftCount = 0; if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) { --expZ; shiftCount = -1; } if ( ! expC ) { if ( ! sigC ) { if ( shiftCount ) sigZ <<= 1; goto sigZ; } normExpSig = softfloat_normSubnormalF64Sig( sigC ); expC = normExpSig.exp; sigC = normExpSig.sig; } sigC = (sigC | UINT64_C( 0x0010000000000000 ))<<10; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expDiff = expZ - expC; if ( expDiff < 0 ) { expZ = expC; if ( (signZ == signC) || (expDiff < -1) ) { shiftCount -= expDiff; if ( shiftCount) { sigZ = softfloat_shiftRightJam64( sigZ, shiftCount ); } } else { if ( ! shiftCount ) { softfloat_shortShiftRight128M( sig128Z, 1, sig128Z ); } } } else { if ( shiftCount ) softfloat_add128M( sig128Z, sig128Z, sig128Z ); if ( ! expDiff ) { sigZ = (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )]; } else { sig128C[indexWord( 4, 3 )] = sigC>>32; sig128C[indexWord( 4, 2 )] = sigC; sig128C[indexWord( 4, 1 )] = 0; sig128C[indexWord( 4, 0 )] = 0; softfloat_shiftRightJam128M( sig128C, expDiff, sig128C ); } } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( signZ == signC ) { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ if ( expDiff <= 0 ) { sigZ += sigC; } else { softfloat_add128M( sig128Z, sig128C, sig128Z ); sigZ = (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )]; } if ( sigZ & UINT64_C( 0x8000000000000000 ) ) { ++expZ; sigZ = softfloat_shortShiftRightJam64( sigZ, 1 ); } } else { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ if ( expDiff < 0 ) { signZ = signC; if ( expDiff < -1 ) { sigZ = sigC - sigZ; if ( sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )] ) { sigZ = (sigZ - 1) | 1; } if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) { --expZ; sigZ <<= 1; } goto roundPack; } else { sig128C[indexWord( 4, 3 )] = sigC>>32; sig128C[indexWord( 4, 2 )] = sigC; sig128C[indexWord( 4, 1 )] = 0; sig128C[indexWord( 4, 0 )] = 0; softfloat_sub128M( sig128C, sig128Z, sig128Z ); } } else if ( ! expDiff ) {