float128_t f16_to_f128( float16_t a ) { union ui16_f16 uA; uint_fast16_t uiA; bool sign; int_fast8_t exp; uint_fast16_t frac; struct commonNaN commonNaN; struct uint128 uiZ; struct exp8_sig16 normExpSig; union ui128_f128 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA = uA.ui; sign = signF16UI( uiA ); exp = expF16UI( uiA ); frac = fracF16UI( uiA ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp == 0x1F ) { if ( frac ) { softfloat_f16UIToCommonNaN( uiA, &commonNaN ); uiZ = softfloat_commonNaNToF128UI( &commonNaN ); } else { uiZ.v64 = packToF128UI64( sign, 0x7FFF, 0 ); uiZ.v0 = 0; } goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! exp ) { if ( ! frac ) { uiZ.v64 = packToF128UI64( sign, 0, 0 ); uiZ.v0 = 0; goto uiZ; } normExpSig = softfloat_normSubnormalF16Sig( frac ); exp = normExpSig.exp - 1; frac = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiZ.v64 = packToF128UI64( sign, exp + 0x3FF0, (uint_fast64_t) frac<<38 ); uiZ.v0 = 0; uiZ: uZ.ui = uiZ; return uZ.f; }
float128_t f128_scaledResult(int_fast16_t scale) { int_fast32_t exp; union ui128_f128 uZ; struct exp32_sig128 z; struct uint128 uA; exp = softfloat_raw.Exp + 16382 + scale; /* Note that the high-order bit of the saved significand is the units position. This is effectively */ /* added to the exponent in packToF128UI64 so that the units position disappears and the exponent is */ /* incremented. So going in, the exponent limit must be one less than the float128 maximum of 0x7FFE. */ /* Note also that, unlike the C << operator, the function softfloat_shortShiftLeft128 behaves very */ /* badly when passed a shift count of zero. When passed zero, softfloat_shortShiftLeft128 or's the */ /* the second half of the 128-bit significand into the first. Not a bug, really, because this */ /* function is not a part of the Softfloat 3a API, but troubling nontheless. Softfloat 3b did not */ /* change this behavior. */ if (exp < 0 || exp > 0x7FFD) { uZ.ui.v64 = (defaultNaNF128UI64 & ~UINT64_C(0x0000800000000000)) | UINT64_C(0x00000DEAD0000000); uZ.ui.v0 = defaultNaNF128UI0; } else { uA = softfloat_shortShiftRight128(softfloat_raw.Sig64, softfloat_raw.Sig0, 14); if (softfloat_raw.Tiny && (uA.v64 < 0x0001000000000000ULL)) /* result an unnormallized subnormal? */ { z = softfloat_normSubnormalF128Sig(uA.v64, uA.v0); exp += (z.exp - 1); uZ.ui.v64 = packToF128UI64(softfloat_raw.Sign, exp, z.sig.v64); /* should not be needed */ uZ.ui.v0 = z.sig.v0; } else { uZ.ui.v64 = packToF128UI64(softfloat_raw.Sign, exp, uA.v64); uZ.ui.v0 = uA.v0; } } softfloat_exceptionFlags &= ~(softfloat_flag_inexact | softfloat_flag_incremented | softfloat_flag_tiny); softfloat_exceptionFlags |= (softfloat_raw.Inexact ? softfloat_flag_inexact : 0) | (softfloat_raw.Incre ? softfloat_flag_incremented : 0); return uZ.f; }
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; struct commonNaN commonNaN; struct uint128 uiZ; bool sign; struct uint128 frac128; union ui128_f128 uZ; uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; exp = expExtF80UI64( uiA64 ); frac = uiA0 & UINT64_C( 0x7FFFFFFFFFFFFFFF ); if ( (exp == 0x7FFF) && frac ) { softfloat_extF80UIToCommonNaN( uiA64, uiA0, &commonNaN ); uiZ = softfloat_commonNaNToF128UI( &commonNaN ); } else { sign = signExtF80UI64( uiA64 ); frac128 = softfloat_shortShiftLeft128( 0, frac, 49 ); uiZ.v64 = packToF128UI64( sign, exp, frac128.v64 ); uiZ.v0 = frac128.v0; } uZ.ui = uiZ; return uZ.f; }
float128_t ui64_to_f128( uint64_t a ) { uint_fast64_t uiZ64, uiZ0; int_fast8_t shiftCount; struct uint128 zSig; union ui128_f128 uZ; if ( ! a ) { uiZ64 = 0; uiZ0 = 0; } else { shiftCount = softfloat_countLeadingZeros64( a ) + 49; if ( 64 <= shiftCount ) { zSig.v64 = a<<(shiftCount - 64); zSig.v0 = 0; } else { zSig = softfloat_shortShiftLeft128( 0, a, shiftCount ); } uiZ64 = packToF128UI64( 0, 0x406E - shiftCount, zSig.v64 ); uiZ0 = zSig.v0; } uZ.ui.v64 = uiZ64; uZ.ui.v0 = uiZ0; return uZ.f; }
float128_t i64_to_f128( int64_t a ) { uint_fast64_t uiZ64, uiZ0; bool sign; uint_fast64_t absA; int_fast8_t shiftCount; struct uint128 zSig; union ui128_f128 uZ; if ( ! a ) { uiZ64 = 0; uiZ0 = 0; } else { sign = (a < 0); absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a; shiftCount = softfloat_countLeadingZeros64( absA ) + 49; if ( 64 <= shiftCount ) { zSig.v64 = absA<<(shiftCount - 64); zSig.v0 = 0; } else { zSig = softfloat_shortShiftLeft128( 0, absA, shiftCount ); } uiZ64 = packToF128UI64( sign, 0x406E - shiftCount, zSig.v64 ); uiZ0 = zSig.v0; } uZ.ui.v64 = uiZ64; uZ.ui.v0 = uiZ0; return uZ.f; }
float128_t f64_to_f128( float64_t a ) { union ui64_f64 uA; uint_fast64_t uiA; bool sign; int_fast16_t exp; uint_fast64_t sig; struct commonNaN commonNaN; struct uint128 uiZ; struct exp16_sig64 normExpSig; struct uint128 sig128; union ui128_f128 uZ; uA.f = a; uiA = uA.ui; sign = signF64UI( uiA ); exp = expF64UI( uiA ); sig = fracF64UI( uiA ); if ( exp == 0x7FF ) { if ( sig ) { softfloat_f64UIToCommonNaN( uiA, &commonNaN ); uiZ = softfloat_commonNaNToF128UI( &commonNaN ); } else { uiZ.v64 = packToF128UI64( sign, 0x7FFF, 0 ); uiZ.v0 = 0; } goto uiZ; } if ( ! exp ) { if ( ! sig ) { uiZ.v64 = packToF128UI64( sign, 0, 0 ); uiZ.v0 = 0; goto uiZ; } normExpSig = softfloat_normSubnormalF64Sig( sig ); exp = normExpSig.exp - 1; sig = normExpSig.sig; } sig128 = softfloat_shortShiftLeft128( 0, sig, 60 ); uiZ.v64 = packToF128UI64( sign, exp + 0x3C00, sig128.v64 ); uiZ.v0 = sig128.v0; uiZ: uZ.ui = uiZ; return uZ.f; }
float128_t f32_to_f128( float32_t a ) { union ui32_f32 uA; uint_fast32_t uiA; bool sign; int_fast16_t exp; uint_fast32_t sig; struct commonNaN commonNaN; struct uint128 uiZ; struct exp16_sig32 normExpSig; union ui128_f128 uZ; uA.f = a; uiA = uA.ui; sign = signF32UI( uiA ); exp = expF32UI( uiA ); sig = fracF32UI( uiA ); if ( exp == 0xFF ) { if ( sig ) { softfloat_f32UIToCommonNaN( uiA, &commonNaN ); uiZ = softfloat_commonNaNToF128UI( &commonNaN ); } else { uiZ.v64 = packToF128UI64( sign, 0x7FFF, 0 ); uiZ.v0 = 0; } goto uiZ; } if ( ! exp ) { if ( ! sig ) { uiZ.v64 = packToF128UI64( sign, 0, 0 ); uiZ.v0 = 0; goto uiZ; } normExpSig = softfloat_normSubnormalF32Sig( sig ); exp = normExpSig.exp - 1; sig = normExpSig.sig; } uiZ.v64 = packToF128UI64( sign, exp + 0x3F80, (uint_fast64_t) sig<<25 ); uiZ.v0 = 0; uiZ: uZ.ui = uiZ; return uZ.f; }
float128_t ui32_to_f128( uint32_t a ) { uint_fast64_t uiZ64; int_fast8_t shiftCount; union ui128_f128 uZ; uiZ64 = 0; if ( a ) { shiftCount = softfloat_countLeadingZeros32( a ) + 17; uiZ64 = packToF128UI64( 0, 0x402E - shiftCount, (uint_fast64_t) a<<shiftCount ); } uZ.ui.v64 = uiZ64; uZ.ui.v0 = 0; return uZ.f; }
float128_t softfloat_normRoundPackToF128( bool sign, int_fast32_t exp, uint_fast64_t sig64, uint_fast64_t sig0 ) { int_fast8_t shiftDist; struct uint128 sig128; union ui128_f128 uZ; uint_fast64_t sigExtra; struct uint128_extra sig128Extra; if ( ! sig64 ) { exp -= 64; sig64 = sig0; sig0 = 0; } shiftDist = softfloat_countLeadingZeros64( sig64 ) - 15; exp -= shiftDist; if ( 0 <= shiftDist ) { if ( shiftDist ) { sig128 = softfloat_shortShiftLeft128( sig64, sig0, shiftDist ); sig64 = sig128.v64; sig0 = sig128.v0; } if ( (uint32_t) exp < 0x7FFD ) { uZ.ui.v64 = packToF128UI64( sign, sig64 | sig0 ? exp : 0, sig64 ); uZ.ui.v0 = sig0; return uZ.f; } sigExtra = 0; } else { sig128Extra = softfloat_shortShiftRightJam128Extra( sig64, sig0, 0, -shiftDist ); sig64 = sig128Extra.v.v64; sig0 = sig128Extra.v.v0; sigExtra = sig128Extra.extra; } return softfloat_roundPackToF128( sign, exp, sig64, sig0, sigExtra ); }
float128_t i32_to_f128( int32_t a ) { uint_fast64_t uiZ64; bool sign; uint_fast32_t absA; int_fast8_t shiftDist; union ui128_f128 uZ; uiZ64 = 0; if ( a ) { sign = (a < 0); absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a; shiftDist = softfloat_countLeadingZeros32( absA ) + 17; uiZ64 = packToF128UI64( sign, 0x402E - shiftDist, (uint_fast64_t) absA<<shiftDist ); } uZ.ui.v64 = uiZ64; uZ.ui.v0 = 0; return uZ.f; }
float128_t softfloat_roundPackToF128( bool sign, int_fast32_t exp, uint_fast64_t sig64, uint_fast64_t sig0, uint_fast64_t sigExtra ) { uint_fast8_t roundingMode; bool roundNearEven, doIncrement, isTiny; struct uint128_extra sig128Extra; uint_fast64_t uiZ64, uiZ0; struct uint128 sig128; union ui128_f128 uZ; roundingMode = softfloat_roundingMode; roundNearEven = (roundingMode == softfloat_round_near_even); doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra); if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { doIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; } if ( 0x7FFD <= (uint32_t) exp ) { if ( exp < 0 ) { isTiny = (softfloat_detectTininess == softfloat_tininess_beforeRounding) || (exp < -1) || ! doIncrement || softfloat_lt128( sig64, sig0, UINT64_C( 0x0001FFFFFFFFFFFF ), UINT64_C( 0xFFFFFFFFFFFFFFFF ) ); sig128Extra = softfloat_shiftRightJam128Extra( sig64, sig0, sigExtra, -exp ); sig64 = sig128Extra.v.v64; sig0 = sig128Extra.v.v0; sigExtra = sig128Extra.extra; exp = 0; if ( isTiny && sigExtra ) { softfloat_raiseFlags( softfloat_flag_underflow ); } doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra); if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { doIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; } } else if ( (0x7FFD < exp) || ((exp == 0x7FFD) && softfloat_eq128( sig64, sig0, UINT64_C( 0x0001FFFFFFFFFFFF ), UINT64_C( 0xFFFFFFFFFFFFFFFF ) ) && doIncrement) ) { softfloat_raiseFlags( softfloat_flag_overflow | softfloat_flag_inexact ); if ( roundNearEven || (roundingMode == softfloat_round_near_maxMag) || (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ) { uiZ64 = packToF128UI64( sign, 0x7FFF, 0 ); uiZ0 = 0; } else { uiZ64 = packToF128UI64( sign, 0x7FFE, UINT64_C( 0x0000FFFFFFFFFFFF ) ); uiZ0 = UINT64_C( 0xFFFFFFFFFFFFFFFF ); } goto uiZ; } } if ( sigExtra ) softfloat_exceptionFlags |= softfloat_flag_inexact; if ( doIncrement ) { sig128 = softfloat_add128( sig64, sig0, 0, 1 ); sig64 = sig128.v64; sig0 = sig128.v0 & ~(uint64_t) (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF )) & roundNearEven); } else { if ( ! (sig64 | sig0) ) exp = 0; } uiZ64 = packToF128UI64( sign, exp, sig64 ); uiZ0 = sig0; uiZ: uZ.ui.v64 = uiZ64; uZ.ui.v0 = uiZ0; return uZ.f; }
float128_t f128_mul( float128_t a, float128_t b ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; bool signA; int_fast32_t expA; struct uint128 sigA; union ui128_f128 uB; uint_fast64_t uiB64, uiB0; bool signB; int_fast32_t expB; struct uint128 sigB; bool signZ; uint_fast64_t magBits; struct exp32_sig128 normExpSig; int_fast32_t expZ; uint64_t sig256Z[4]; uint_fast64_t sigZExtra; struct uint128 sigZ; struct uint128_extra sig128Extra; struct uint128 uiZ; union ui128_f128 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; signA = signF128UI64( uiA64 ); expA = expF128UI64( uiA64 ); sigA.v64 = fracF128UI64( uiA64 ); sigA.v0 = uiA0; uB.f = b; uiB64 = uB.ui.v64; uiB0 = uB.ui.v0; signB = signF128UI64( uiB64 ); expB = expF128UI64( uiB64 ); sigB.v64 = fracF128UI64( uiB64 ); sigB.v0 = uiB0; signZ = signA ^ signB; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FFF ) { if ( (sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0)) ) { goto propagateNaN; } magBits = expB | sigB.v64 | sigB.v0; goto infArg; } if ( expB == 0x7FFF ) { if ( sigB.v64 | sigB.v0 ) goto propagateNaN; magBits = expA | sigA.v64 | sigA.v0; goto infArg; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) { if ( ! (sigA.v64 | sigA.v0) ) goto zero; normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 ); expA = normExpSig.exp; sigA = normExpSig.sig; } if ( ! expB ) { if ( ! (sigB.v64 | sigB.v0) ) goto zero; normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 ); expB = normExpSig.exp; sigB = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA + expB - 0x4000; sigA.v64 |= UINT64_C( 0x0001000000000000 ); sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 16 ); softfloat_mul128To256M( sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z ); sigZExtra = sig256Z[indexWord( 4, 1 )] | (sig256Z[indexWord( 4, 0 )] != 0); sigZ = softfloat_add128( sig256Z[indexWord( 4, 3 )], sig256Z[indexWord( 4, 2 )], sigA.v64, sigA.v0 ); if ( UINT64_C( 0x0002000000000000 ) <= sigZ.v64 ) { ++expZ; sig128Extra = softfloat_shortShiftRightJam128Extra( sigZ.v64, sigZ.v0, sigZExtra, 1 ); sigZ = sig128Extra.v; sigZExtra = sig128Extra.extra; } return softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 ); goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ infArg: if ( ! magBits ) { softfloat_raiseFlags( softfloat_flag_invalid ); uiZ.v64 = defaultNaNF128UI64; uiZ.v0 = defaultNaNF128UI0; goto uiZ; } uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 ); goto uiZ0; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zero: uiZ.v64 = packToF128UI64( signZ, 0, 0 ); uiZ0: uiZ.v0 = 0; uiZ: uZ.ui = uiZ; return uZ.f; }
float128_t softfloat_addMagsF128( uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0, bool signZ ) { int_fast32_t expA; struct uint128 sigA; int_fast32_t expB; struct uint128 sigB; int_fast32_t expDiff; struct uint128 uiZ, sigZ; int_fast32_t expZ; uint_fast64_t sigZExtra; struct uint128_extra sig128Extra; union ui128_f128 uZ; expA = expF128UI64( uiA64 ); sigA.v64 = fracF128UI64( uiA64 ); sigA.v0 = uiA0; expB = expF128UI64( uiB64 ); sigB.v64 = fracF128UI64( uiB64 ); sigB.v0 = uiB0; expDiff = expA - expB; if ( ! expDiff ) { if ( expA == 0x7FFF ) { if ( sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0 ) goto propagateNaN; uiZ.v64 = uiA64; uiZ.v0 = uiA0; goto uiZ; } sigZ = softfloat_add128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 ); if ( ! expA ) { uiZ.v64 = packToF128UI64( signZ, 0, sigZ.v64 ); uiZ.v0 = sigZ.v0; goto uiZ; } expZ = expA; sigZ.v64 |= UINT64_C( 0x0002000000000000 ); sigZExtra = 0; goto shiftRight1; } if ( expDiff < 0 ) { if ( expB == 0x7FFF ) { if ( sigB.v64 | sigB.v0 ) goto propagateNaN; uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 ); uiZ.v0 = 0; goto uiZ; } expZ = expB; if ( expA ) { sigA.v64 |= UINT64_C( 0x0001000000000000 ); } else { ++expDiff; sigZExtra = 0; if ( ! expDiff ) goto newlyAligned; } sig128Extra = softfloat_shiftRightJam128Extra( sigA.v64, sigA.v0, 0, -expDiff ); sigA = sig128Extra.v; sigZExtra = sig128Extra.extra; } else { if ( expA == 0x7FFF ) { if ( sigA.v64 | sigA.v0 ) goto propagateNaN; uiZ.v64 = uiA64; uiZ.v0 = uiA0; goto uiZ; } expZ = expA; if ( expB ) { sigB.v64 |= UINT64_C( 0x0001000000000000 ); } else { --expDiff; sigZExtra = 0; if ( ! expDiff ) goto newlyAligned; } sig128Extra = softfloat_shiftRightJam128Extra( sigB.v64, sigB.v0, 0, expDiff ); sigB = sig128Extra.v; sigZExtra = sig128Extra.extra; } newlyAligned: sigZ = softfloat_add128( sigA.v64 | UINT64_C( 0x0001000000000000 ), sigA.v0, sigB.v64, sigB.v0 ); --expZ; if ( sigZ.v64 < UINT64_C( 0x0002000000000000 ) ) goto roundAndPack; ++expZ; shiftRight1: sig128Extra = softfloat_shortShiftRightJam128Extra( sigZ.v64, sigZ.v0, sigZExtra, 1 ); sigZ = sig128Extra.v; sigZExtra = sig128Extra.extra; roundAndPack: return softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra ); propagateNaN: uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 ); uiZ: uZ.ui = uiZ; return uZ.f; }
float128_t softfloat_subMagsF128( uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0, bool signZ ) { int_fast32_t expA; struct uint128 sigA; int_fast32_t expB; struct uint128 sigB, sigZ; int_fast32_t expDiff, expZ; struct uint128 uiZ; union ui128_f128 uZ; expA = expF128UI64( uiA64 ); sigA.v64 = fracF128UI64( uiA64 ); sigA.v0 = uiA0; expB = expF128UI64( uiB64 ); sigB.v64 = fracF128UI64( uiB64 ); sigB.v0 = uiB0; sigA = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 4 ); sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 4 ); expDiff = expA - expB; if ( 0 < expDiff ) goto expABigger; if ( expDiff < 0 ) goto expBBigger; if ( expA == 0x7FFF ) { if ( sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0 ) goto propagateNaN; softfloat_raiseFlags( softfloat_flag_invalid ); uiZ.v64 = defaultNaNF128UI64; uiZ.v0 = defaultNaNF128UI0; goto uiZ; } expZ = expA; if ( ! expZ ) expZ = 1; if ( sigB.v64 < sigA.v64 ) goto aBigger; if ( sigA.v64 < sigB.v64 ) goto bBigger; if ( sigB.v0 < sigA.v0 ) goto aBigger; if ( sigA.v0 < sigB.v0 ) goto bBigger; uiZ.v64 = packToF128UI64( (softfloat_roundingMode == softfloat_round_min), 0, 0 ); uiZ.v0 = 0; goto uiZ; expBBigger: if ( expB == 0x7FFF ) { if ( sigB.v64 | sigB.v0 ) goto propagateNaN; uiZ.v64 = packToF128UI64( signZ ^ 1, 0x7FFF, 0 ); uiZ.v0 = 0; goto uiZ; } if ( expA ) { sigA.v64 |= UINT64_C( 0x0010000000000000 ); } else { ++expDiff; if ( ! expDiff ) goto newlyAlignedBBigger; } sigA = softfloat_shiftRightJam128( sigA.v64, sigA.v0, -expDiff ); newlyAlignedBBigger: expZ = expB; sigB.v64 |= UINT64_C( 0x0010000000000000 ); bBigger: signZ = ! signZ; sigZ = softfloat_sub128( sigB.v64, sigB.v0, sigA.v64, sigA.v0 ); goto normRoundPack; expABigger: if ( expA == 0x7FFF ) { if ( sigA.v64 | sigA.v0 ) goto propagateNaN; uiZ.v64 = uiA64; uiZ.v0 = uiA0; goto uiZ; } if ( expB ) { sigB.v64 |= UINT64_C( 0x0010000000000000 ); } else { --expDiff; if ( ! expDiff ) goto newlyAlignedABigger; } sigB = softfloat_shiftRightJam128( sigB.v64, sigB.v0, expDiff ); newlyAlignedABigger: expZ = expA; sigA.v64 |= UINT64_C( 0x0010000000000000 ); aBigger: sigZ = softfloat_sub128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 ); normRoundPack: return softfloat_normRoundPackToF128( signZ, expZ - 5, sigZ.v64, sigZ.v0 ); propagateNaN: uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 ); uiZ: uZ.ui = uiZ; return uZ.f; }