aboutsummaryrefslogtreecommitdiff
path: root/source/slowfloat.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/slowfloat.c')
-rw-r--r--source/slowfloat.c3098
1 files changed, 3098 insertions, 0 deletions
diff --git a/source/slowfloat.c b/source/slowfloat.c
new file mode 100644
index 0000000..ac54bb5
--- /dev/null
+++ b/source/slowfloat.c
@@ -0,0 +1,3098 @@
+
+/*============================================================================
+
+This C source file is part of TestFloat, Release 3, a package of programs for
+testing the correctness of floating-point arithmetic complying with the IEEE
+Standard for Floating-Point, by John R. Hauser.
+
+Copyright 2011, 2012, 2013, 2014 The Regents of the University of California
+(Regents). All Rights Reserved. Redistribution and use in source and binary
+forms, with or without modification, are permitted provided that the following
+conditions are met:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions, and the following two paragraphs of disclaimer.
+Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions, and the following two paragraphs of disclaimer in the
+documentation and/or other materials provided with the distribution. Neither
+the name of the Regents nor the names of its contributors may be used to
+endorse or promote products derived from this software without specific prior
+written permission.
+
+IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
+OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
+BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
+HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
+MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+=============================================================================*/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "platform.h"
+#include "uint128.h"
+#include "softfloat.h"
+#include "slowfloat.h"
+
+uint_fast8_t slowfloat_roundingMode;
+uint_fast8_t slowfloat_detectTininess;
+uint_fast8_t slowfloat_exceptionFlags;
+#ifdef EXTFLOAT80
+uint_fast8_t slow_extF80_roundingPrecision;
+#endif
+
+union ui32_f32 { uint32_t ui; float32_t f; };
+union ui64_f64 { uint64_t ui; float64_t f; };
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+
+struct floatX {
+ bool isNaN;
+ bool isInf;
+ bool isZero;
+ bool sign;
+ int_fast32_t exp;
+ struct uint128 sig;
+};
+
+static const struct floatX floatXNaN =
+ { true, false, false, false, 0, { 0, 0 } };
+static const struct floatX floatXPositiveZero =
+ { false, false, true, false, 0, { 0, 0 } };
+static const struct floatX floatXNegativeZero =
+ { false, false, true, true, 0, { 0, 0 } };
+
+static
+ void
+ roundFloatXTo24(
+ bool isTiny, struct floatX *xPtr, uint_fast8_t roundingMode, bool exact )
+{
+ uint_fast64_t sigX64;
+ uint_fast32_t roundBits;
+
+ sigX64 = xPtr->sig.v64 | (xPtr->sig.v0 != 0);
+ roundBits = (uint32_t) sigX64;
+ sigX64 -= roundBits;
+ if ( roundBits ) {
+ if ( exact ) slowfloat_exceptionFlags |= softfloat_flag_inexact;
+ if ( isTiny ) slowfloat_exceptionFlags |= softfloat_flag_underflow;
+ switch ( roundingMode ) {
+ case softfloat_round_near_even:
+ if ( roundBits < 0x80000000 ) goto noIncrement;
+ if (
+ (roundBits == 0x80000000)
+ && ! (sigX64 & UINT64_C( 0x100000000 ))
+ ) {
+ goto noIncrement;
+ }
+ break;
+ case softfloat_round_minMag:
+ goto noIncrement;
+ case softfloat_round_min:
+ if ( ! xPtr->sign ) goto noIncrement;
+ break;
+ case softfloat_round_max:
+ if ( xPtr->sign ) goto noIncrement;
+ break;
+ case softfloat_round_near_maxMag:
+ if ( roundBits < 0x80000000 ) goto noIncrement;
+ break;
+ }
+ sigX64 += UINT64_C( 0x100000000 );
+ if ( sigX64 == UINT64_C( 0x0100000000000000 ) ) {
+ ++xPtr->exp;
+ sigX64 = UINT64_C( 0x0080000000000000 );
+ }
+ }
+ noIncrement:
+ xPtr->sig.v64 = sigX64;
+ xPtr->sig.v0 = 0;
+
+}
+
+static
+ void
+ roundFloatXTo53(
+ bool isTiny, struct floatX *xPtr, uint_fast8_t roundingMode, bool exact )
+{
+ uint_fast64_t sigX64;
+ uint_fast8_t roundBits;
+
+ sigX64 = xPtr->sig.v64 | (xPtr->sig.v0 != 0);
+ roundBits = sigX64 & 7;
+ sigX64 -= roundBits;
+ if ( roundBits ) {
+ if ( exact ) slowfloat_exceptionFlags |= softfloat_flag_inexact;
+ if ( isTiny ) slowfloat_exceptionFlags |= softfloat_flag_underflow;
+ switch ( roundingMode ) {
+ case softfloat_round_near_even:
+ if ( roundBits < 4 ) goto noIncrement;
+ if ( (roundBits == 4) && ! (sigX64 & 8) ) goto noIncrement;
+ break;
+ case softfloat_round_minMag:
+ goto noIncrement;
+ case softfloat_round_min:
+ if ( ! xPtr->sign ) goto noIncrement;
+ break;
+ case softfloat_round_max:
+ if ( xPtr->sign ) goto noIncrement;
+ break;
+ case softfloat_round_near_maxMag:
+ if ( roundBits < 4 ) goto noIncrement;
+ break;
+ }
+ sigX64 += 8;
+ if ( sigX64 == UINT64_C( 0x0100000000000000 ) ) {
+ ++xPtr->exp;
+ sigX64 = UINT64_C( 0x0080000000000000 );
+ }
+ }
+ noIncrement:
+ xPtr->sig.v64 = sigX64;
+ xPtr->sig.v0 = 0;
+
+}
+
+static
+ void
+ roundFloatXTo64(
+ bool isTiny, struct floatX *xPtr, uint_fast8_t roundingMode, bool exact )
+{
+ uint_fast64_t sigX0;
+ int_fast64_t roundBits;
+ uint_fast64_t sigX64;
+
+ sigX0 = xPtr->sig.v0;
+ roundBits = sigX0 & UINT64_C( 0x00FFFFFFFFFFFFFF );
+ sigX0 -= roundBits;
+ if ( roundBits ) {
+ if ( exact ) slowfloat_exceptionFlags |= softfloat_flag_inexact;
+ if ( isTiny ) slowfloat_exceptionFlags |= softfloat_flag_underflow;
+ switch ( roundingMode ) {
+ case softfloat_round_near_even:
+ if ( roundBits < UINT64_C( 0x0080000000000000 ) ) goto noIncrement;
+ if (
+ (roundBits == UINT64_C( 0x0080000000000000 ))
+ && ! (sigX0 & UINT64_C( 0x0100000000000000 ))
+ ) {
+ goto noIncrement;
+ }
+ break;
+ case softfloat_round_minMag:
+ goto noIncrement;
+ case softfloat_round_min:
+ if ( ! xPtr->sign ) goto noIncrement;
+ break;
+ case softfloat_round_max:
+ if ( xPtr->sign ) goto noIncrement;
+ break;
+ case softfloat_round_near_maxMag:
+ if ( roundBits < UINT64_C( 0x0080000000000000 ) ) goto noIncrement;
+ break;
+ }
+ sigX0 += UINT64_C( 0x0100000000000000 );
+ sigX64 = xPtr->sig.v64 + ! sigX0;
+ if ( sigX64 == UINT64_C( 0x0100000000000000 ) ) {
+ ++xPtr->exp;
+ sigX64 = UINT64_C( 0x0080000000000000 );
+ }
+ xPtr->sig.v64 = sigX64;
+ }
+ noIncrement:
+ xPtr->sig.v0 = sigX0;
+
+}
+
+static
+ void
+ roundFloatXTo113(
+ bool isTiny, struct floatX *xPtr, uint_fast8_t roundingMode, bool exact )
+{
+ uint_fast64_t sigX0;
+ int_fast64_t roundBits;
+ uint_fast64_t sigX64;
+
+ sigX0 = xPtr->sig.v0;
+ roundBits = sigX0 & 0x7F;
+ sigX0 -= roundBits;
+ if ( roundBits ) {
+ if ( exact ) slowfloat_exceptionFlags |= softfloat_flag_inexact;
+ if ( isTiny ) slowfloat_exceptionFlags |= softfloat_flag_underflow;
+ switch ( roundingMode ) {
+ case softfloat_round_near_even:
+ if ( roundBits < 0x40 ) goto noIncrement;
+ if ( (roundBits == 0x40) && ! (sigX0 & 0x80) ) goto noIncrement;
+ break;
+ case softfloat_round_minMag:
+ goto noIncrement;
+ case softfloat_round_min:
+ if ( ! xPtr->sign ) goto noIncrement;
+ break;
+ case softfloat_round_max:
+ if ( xPtr->sign ) goto noIncrement;
+ break;
+ case softfloat_round_near_maxMag:
+ if ( roundBits < 0x40 ) goto noIncrement;
+ break;
+ }
+ sigX0 += 0x80;
+ sigX64 = xPtr->sig.v64 + ! sigX0;
+ if ( sigX64 == UINT64_C( 0x0100000000000000 ) ) {
+ ++xPtr->exp;
+ sigX64 = UINT64_C( 0x0080000000000000 );
+ }
+ xPtr->sig.v64 = sigX64;
+ }
+ noIncrement:
+ xPtr->sig.v0 = sigX0;
+
+}
+
+static void ui32ToFloatX( uint_fast32_t a, struct floatX *xPtr )
+{
+ uint_fast64_t sig64;
+ int_fast32_t exp;
+
+ xPtr->isNaN = false;
+ xPtr->isInf = false;
+ xPtr->sign = false;
+ sig64 = a;
+ if ( a ) {
+ xPtr->isZero = false;
+ exp = 31;
+ sig64 <<= 24;
+ while ( sig64 < UINT64_C( 0x0080000000000000 ) ) {
+ --exp;
+ sig64 <<= 1;
+ }
+ xPtr->exp = exp;
+ } else {
+ xPtr->isZero = true;
+ }
+ xPtr->sig.v64 = sig64;
+ xPtr->sig.v0 = 0;
+
+}
+
+static
+ uint_fast32_t
+ floatXToUI32(
+ const struct floatX *xPtr, uint_fast8_t roundingMode, bool exact )
+{
+ uint_fast8_t savedExceptionFlags;
+ struct floatX x;
+ int_fast32_t shiftCount;
+ uint_fast32_t z;
+
+ if ( xPtr->isInf || xPtr->isNaN ) {
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ return 0xFFFFFFFF;
+ }
+ if ( xPtr->isZero ) return 0;
+ savedExceptionFlags = slowfloat_exceptionFlags;
+ x = *xPtr;
+ shiftCount = 52 - x.exp;
+ if ( 56 < shiftCount ) {
+ x.sig.v64 = 0;
+ x.sig.v0 = 1;
+ } else {
+ while ( 0 < shiftCount ) {
+ x.sig = shortShiftRightJam128( x.sig, 1 );
+ --shiftCount;
+ }
+ }
+ roundFloatXTo53( false, &x, roundingMode, exact );
+ x.sig = shortShiftRightJam128( x.sig, 3 );
+ z = x.sig.v64;
+ if ( (shiftCount < 0) || x.sig.v64>>32 || (x.sign && z) ) {
+ slowfloat_exceptionFlags =
+ savedExceptionFlags | softfloat_flag_invalid;
+ return 0xFFFFFFFF;
+ }
+ return z;
+
+}
+
+static void ui64ToFloatX( uint_fast64_t a, struct floatX *xPtr )
+{
+ struct uint128 sig;
+ int_fast32_t exp;
+
+ xPtr->isNaN = false;
+ xPtr->isInf = false;
+ xPtr->sign = false;
+ sig.v64 = 0;
+ sig.v0 = a;
+ if ( a ) {
+ xPtr->isZero = false;
+ exp = 63;
+ sig = shortShiftLeft128( sig, 56 );
+ while ( sig.v64 < UINT64_C( 0x0080000000000000 ) ) {
+ --exp;
+ sig = shortShiftLeft128( sig, 1 );
+ }
+ xPtr->exp = exp;
+ } else {
+ xPtr->isZero = true;
+ }
+ xPtr->sig = sig;
+
+}
+
+static
+ uint_fast64_t
+ floatXToUI64(
+ const struct floatX *xPtr, uint_fast8_t roundingMode, bool exact )
+{
+ uint_fast8_t savedExceptionFlags;
+ struct floatX x;
+ int_fast32_t shiftCount;
+ uint_fast64_t z;
+
+ if ( xPtr->isInf || xPtr->isNaN ) {
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ return UINT64_C( 0xFFFFFFFFFFFFFFFF );
+ }
+ if ( xPtr->isZero ) return 0;
+ savedExceptionFlags = slowfloat_exceptionFlags;
+ x = *xPtr;
+ shiftCount = 112 - x.exp;
+ if ( 116 < shiftCount ) {
+ x.sig.v64 = 0;
+ x.sig.v0 = 1;
+ } else {
+ while ( 0 < shiftCount ) {
+ x.sig = shortShiftRightJam128( x.sig, 1 );
+ --shiftCount;
+ }
+ }
+ roundFloatXTo113( false, &x, roundingMode, exact );
+ x.sig = shortShiftRightJam128( x.sig, 7 );
+ z = x.sig.v0;
+ if ( (shiftCount < 0) || x.sig.v64 || (x.sign && z) ) {
+ slowfloat_exceptionFlags =
+ savedExceptionFlags | softfloat_flag_invalid;
+ return UINT64_C( 0xFFFFFFFFFFFFFFFF );
+ }
+ return z;
+
+}
+
+static void i32ToFloatX( int_fast32_t a, struct floatX *xPtr )
+{
+ bool sign;
+ uint_fast64_t sig64;
+ int_fast32_t exp;
+
+ xPtr->isNaN = false;
+ xPtr->isInf = false;
+ sign = (a < 0);
+ xPtr->sign = sign;
+ sig64 = sign ? -(uint64_t) a : a;
+ if ( a ) {
+ xPtr->isZero = false;
+ exp = 31;
+ sig64 <<= 24;
+ while ( sig64 < UINT64_C( 0x0080000000000000 ) ) {
+ --exp;
+ sig64 <<= 1;
+ }
+ xPtr->exp = exp;
+ } else {
+ xPtr->isZero = true;
+ }
+ xPtr->sig.v64 = sig64;
+ xPtr->sig.v0 = 0;
+
+}
+
+static
+ int_fast32_t
+ floatXToI32(
+ const struct floatX *xPtr, uint_fast8_t roundingMode, bool exact )
+{
+ uint_fast8_t savedExceptionFlags;
+ struct floatX x;
+ int_fast32_t shiftCount;
+ union { uint32_t ui; int32_t i; } uZ;
+
+ if ( xPtr->isInf || xPtr->isNaN ) {
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ return (xPtr->isInf & xPtr->sign) ? -0x7FFFFFFF - 1 : 0x7FFFFFFF;
+ }
+ if ( xPtr->isZero ) return 0;
+ savedExceptionFlags = slowfloat_exceptionFlags;
+ x = *xPtr;
+ shiftCount = 52 - x.exp;
+ if ( 56 < shiftCount ) {
+ x.sig.v64 = 0;
+ x.sig.v0 = 1;
+ } else {
+ while ( 0 < shiftCount ) {
+ x.sig = shortShiftRightJam128( x.sig, 1 );
+ --shiftCount;
+ }
+ }
+ roundFloatXTo53( false, &x, roundingMode, exact );
+ x.sig = shortShiftRightJam128( x.sig, 3 );
+ uZ.ui = x.sig.v64;
+ if ( x.sign ) uZ.ui = -uZ.ui;
+ if (
+ (shiftCount < 0) || x.sig.v64>>32
+ || ((uZ.i != 0) && (x.sign != (uZ.i < 0)))
+ ) {
+ slowfloat_exceptionFlags =
+ savedExceptionFlags | softfloat_flag_invalid;
+ return x.sign ? -0x7FFFFFFF - 1 : 0x7FFFFFFF;
+ }
+ return uZ.i;
+
+}
+
+static void i64ToFloatX( int_fast64_t a, struct floatX *xPtr )
+{
+ bool sign;
+ struct uint128 sig;
+ int_fast32_t exp;
+
+ xPtr->isNaN = false;
+ xPtr->isInf = false;
+ sign = (a < 0);
+ xPtr->sign = sign;
+ sig.v64 = 0;
+ sig.v0 = sign ? -(uint_fast64_t) a : a;
+ if ( a ) {
+ xPtr->isZero = false;
+ exp = 63;
+ sig = shortShiftLeft128( sig, 56 );
+ while ( sig.v64 < UINT64_C( 0x0080000000000000 ) ) {
+ --exp;
+ sig = shortShiftLeft128( sig, 1 );
+ }
+ xPtr->exp = exp;
+ } else {
+ xPtr->isZero = true;
+ }
+ xPtr->sig = sig;
+
+}
+
+static
+ int_fast64_t
+ floatXToI64(
+ const struct floatX *xPtr, uint_fast8_t roundingMode, bool exact )
+{
+ uint_fast8_t savedExceptionFlags;
+ struct floatX x;
+ int_fast32_t shiftCount;
+ union { uint64_t ui; int64_t i; } uZ;
+
+ if ( xPtr->isInf || xPtr->isNaN ) {
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ return
+ (xPtr->isInf & xPtr->sign) ? -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1
+ : INT64_C( 0x7FFFFFFFFFFFFFFF );
+ }
+ if ( xPtr->isZero ) return 0;
+ savedExceptionFlags = slowfloat_exceptionFlags;
+ x = *xPtr;
+ shiftCount = 112 - x.exp;
+ if ( 116 < shiftCount ) {
+ x.sig.v64 = 0;
+ x.sig.v0 = 1;
+ } else {
+ while ( 0 < shiftCount ) {
+ x.sig = shortShiftRightJam128( x.sig, 1 );
+ --shiftCount;
+ }
+ }
+ roundFloatXTo113( false, &x, roundingMode, exact );
+ x.sig = shortShiftRightJam128( x.sig, 7 );
+ uZ.ui = x.sig.v0;
+ if ( x.sign ) uZ.ui = -uZ.ui;
+ if (
+ (shiftCount < 0) || x.sig.v64
+ || ((uZ.i != 0) && (x.sign != (uZ.i < 0)))
+ ) {
+ slowfloat_exceptionFlags =
+ savedExceptionFlags | softfloat_flag_invalid;
+ return
+ x.sign ? -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1
+ : INT64_C( 0x7FFFFFFFFFFFFFFF );
+ }
+ return uZ.i;
+
+}
+
+static void f32ToFloatX( float32_t a, struct floatX *xPtr )
+{
+ union ui32_f32 uA;
+ uint_fast32_t uiA;
+ int_fast16_t exp;
+ uint_fast64_t sig64;
+
+ uA.f = a;
+ uiA = uA.ui;
+ xPtr->isNaN = false;
+ xPtr->isInf = false;
+ xPtr->isZero = false;
+ xPtr->sign = ((uiA & 0x80000000) != 0);
+ exp = uiA>>23 & 0xFF;
+ sig64 = uiA & 0x007FFFFF;
+ sig64 <<= 32;
+ if ( exp == 0xFF ) {
+ if ( sig64 ) {
+ xPtr->isNaN = true;
+ } else {
+ xPtr->isInf = true;
+ }
+ } else if ( ! exp ) {
+ if ( ! sig64 ) {
+ xPtr->isZero = true;
+ } else {
+ exp = 1 - 0x7F;
+ do {
+ --exp;
+ sig64 <<= 1;
+ } while ( sig64 < UINT64_C( 0x0080000000000000 ) );
+ xPtr->exp = exp;
+ }
+ } else {
+ xPtr->exp = exp - 0x7F;
+ sig64 |= UINT64_C( 0x0080000000000000 );
+ }
+ xPtr->sig.v64 = sig64;
+ xPtr->sig.v0 = 0;
+
+}
+
+static float32_t floatXToF32( const struct floatX *xPtr )
+{
+ uint_fast32_t uiZ;
+ struct floatX x, savedX;
+ bool isTiny;
+ int_fast32_t exp;
+ union ui32_f32 uZ;
+
+ if ( xPtr->isNaN ) {
+ uiZ = 0xFFFFFFFF;
+ goto uiZ;
+ }
+ if ( xPtr->isInf ) {
+ uiZ = xPtr->sign ? 0xFF800000 : 0x7F800000;
+ goto uiZ;
+ }
+ if ( xPtr->isZero ) {
+ uiZ = xPtr->sign ? 0x80000000 : 0;
+ goto uiZ;
+ }
+ x = *xPtr;
+ while ( UINT64_C( 0x0100000000000000 ) <= x.sig.v64 ) {
+ ++x.exp;
+ x.sig = shortShiftRightJam128( x.sig, 1 );
+ }
+ while ( x.sig.v64 < UINT64_C( 0x0080000000000000 ) ) {
+ --x.exp;
+ x.sig = shortShiftLeft128( x.sig, 1 );
+ }
+ savedX = x;
+ isTiny =
+ (slowfloat_detectTininess == softfloat_tininess_beforeRounding)
+ && (x.exp + 0x7F <= 0);
+ roundFloatXTo24( isTiny, &x, slowfloat_roundingMode, true );
+ exp = x.exp + 0x7F;
+ if ( 0xFF <= exp ) {
+ slowfloat_exceptionFlags |=
+ softfloat_flag_overflow | softfloat_flag_inexact;
+ if ( x.sign ) {
+ switch ( slowfloat_roundingMode ) {
+ case softfloat_round_near_even:
+ case softfloat_round_min:
+ case softfloat_round_near_maxMag:
+ uiZ = 0xFF800000;
+ break;
+ case softfloat_round_minMag:
+ case softfloat_round_max:
+ uiZ = 0xFF7FFFFF;
+ break;
+ }
+ } else {
+ switch ( slowfloat_roundingMode ) {
+ case softfloat_round_near_even:
+ case softfloat_round_max:
+ case softfloat_round_near_maxMag:
+ uiZ = 0x7F800000;
+ break;
+ case softfloat_round_minMag:
+ case softfloat_round_min:
+ uiZ = 0x7F7FFFFF;
+ break;
+ }
+ }
+ goto uiZ;
+ }
+ if ( exp <= 0 ) {
+ isTiny = true;
+ x = savedX;
+ exp = x.exp + 0x7F;
+ if ( exp < -27 ) {
+ x.sig.v0 = (x.sig.v64 != 0) || (x.sig.v0 != 0);
+ x.sig.v64 = 0;
+ } else {
+ while ( exp <= 0 ) {
+ ++exp;
+ x.sig = shortShiftRightJam128( x.sig, 1 );
+ }
+ }
+ roundFloatXTo24( isTiny, &x, slowfloat_roundingMode, true );
+ exp = (UINT64_C( 0x0080000000000000 ) <= x.sig.v64) ? 1 : 0;
+ }
+ uiZ = (uint_fast32_t) exp<<23;
+ if ( x.sign ) uiZ |= 0x80000000;
+ uiZ |= x.sig.v64>>32 & 0x007FFFFF;
+ uiZ:
+ uZ.ui = uiZ;
+ return uZ.f;
+
+}
+
+static void f64ToFloatX( float64_t a, struct floatX *xPtr )
+{
+ union ui64_f64 uA;
+ uint_fast64_t uiA;
+ int_fast16_t exp;
+ uint_fast64_t sig64;
+
+ uA.f = a;
+ uiA = uA.ui;
+ xPtr->isNaN = false;
+ xPtr->isInf = false;
+ xPtr->isZero = false;
+ xPtr->sign = ((uiA & UINT64_C( 0x8000000000000000 )) != 0);
+ exp = uiA>>52 & 0x7FF;
+ sig64 = uiA & UINT64_C( 0x000FFFFFFFFFFFFF );
+ if ( exp == 0x7FF ) {
+ if ( sig64 ) {
+ xPtr->isNaN = true;
+ } else {
+ xPtr->isInf = true;
+ }
+ } else if ( ! exp ) {
+ if ( ! sig64 ) {
+ xPtr->isZero = true;
+ } else {
+ exp = 1 - 0x3FF;
+ do {
+ --exp;
+ sig64 <<= 1;
+ } while ( sig64 < UINT64_C( 0x0010000000000000 ) );
+ xPtr->exp = exp;
+ }
+ } else {
+ xPtr->exp = exp - 0x3FF;
+ sig64 |= UINT64_C( 0x0010000000000000 );
+ }
+ xPtr->sig.v64 = sig64<<3;
+ xPtr->sig.v0 = 0;
+
+}
+
+static float64_t floatXToF64( const struct floatX *xPtr )
+{
+ uint_fast64_t uiZ;
+ struct floatX x, savedX;
+ bool isTiny;
+ int_fast32_t exp;
+ union ui64_f64 uZ;
+
+ if ( xPtr->isNaN ) {
+ uiZ = UINT64_C( 0xFFFFFFFFFFFFFFFF );
+ goto uiZ;
+ }
+ if ( xPtr->isInf ) {
+ uiZ =
+ xPtr->sign ? UINT64_C( 0xFFF0000000000000 )
+ : UINT64_C( 0x7FF0000000000000 );
+ goto uiZ;
+ }
+ if ( xPtr->isZero ) {
+ uiZ = xPtr->sign ? UINT64_C( 0x8000000000000000 ) : 0;
+ goto uiZ;
+ }
+ x = *xPtr;
+ while ( UINT64_C( 0x0100000000000000 ) <= x.sig.v64 ) {
+ ++x.exp;
+ x.sig = shortShiftRightJam128( x.sig, 1 );
+ }
+ while ( x.sig.v64 < UINT64_C( 0x0080000000000000 ) ) {
+ --x.exp;
+ x.sig = shortShiftLeft128( x.sig, 1 );
+ }
+ savedX = x;
+ isTiny =
+ (slowfloat_detectTininess == softfloat_tininess_beforeRounding)
+ && (x.exp + 0x3FF <= 0);
+ roundFloatXTo53( isTiny, &x, slowfloat_roundingMode, true );
+ exp = x.exp + 0x3FF;
+ if ( 0x7FF <= exp ) {
+ slowfloat_exceptionFlags |=
+ softfloat_flag_overflow | softfloat_flag_inexact;
+ if ( x.sign ) {
+ switch ( slowfloat_roundingMode ) {
+ case softfloat_round_near_even:
+ case softfloat_round_min:
+ case softfloat_round_near_maxMag:
+ uiZ = UINT64_C( 0xFFF0000000000000 );
+ break;
+ case softfloat_round_minMag:
+ case softfloat_round_max:
+ uiZ = UINT64_C( 0xFFEFFFFFFFFFFFFF );
+ break;
+ }
+ } else {
+ switch ( slowfloat_roundingMode ) {
+ case softfloat_round_near_even:
+ case softfloat_round_max:
+ case softfloat_round_near_maxMag:
+ uiZ = UINT64_C( 0x7FF0000000000000 );
+ break;
+ case softfloat_round_minMag:
+ case softfloat_round_min:
+ uiZ = UINT64_C( 0x7FEFFFFFFFFFFFFF );
+ break;
+ }
+ }
+ goto uiZ;
+ }
+ if ( exp <= 0 ) {
+ isTiny = true;
+ x = savedX;
+ exp = x.exp + 0x3FF;
+ if ( exp < -56 ) {
+ x.sig.v0 = (x.sig.v64 != 0) || (x.sig.v0 != 0);
+ x.sig.v64 = 0;
+ } else {
+ while ( exp <= 0 ) {
+ ++exp;
+ x.sig = shortShiftRightJam128( x.sig, 1 );
+ }
+ }
+ roundFloatXTo53( isTiny, &x, slowfloat_roundingMode, true );
+ exp = (UINT64_C( 0x0080000000000000 ) <= x.sig.v64) ? 1 : 0;
+ }
+ uiZ = (uint_fast64_t) exp<<52;
+ if ( x.sign ) uiZ |= UINT64_C( 0x8000000000000000 );
+ uiZ |= x.sig.v64>>3 & UINT64_C( 0x000FFFFFFFFFFFFF );
+ uiZ:
+ uZ.ui = uiZ;
+ return uZ.f;
+
+}
+
+#ifdef EXTFLOAT80
+
+static void extF80MToFloatX( const extFloat80_t *aPtr, struct floatX *xPtr )
+{
+ const struct extFloat80M *aSPtr;
+ uint_fast16_t uiA64;
+ int_fast32_t exp;
+ struct uint128 sig;
+
+ aSPtr = (const struct extFloat80M *) aPtr;
+ xPtr->isNaN = false;
+ xPtr->isInf = false;
+ xPtr->isZero = false;
+ uiA64 = aSPtr->signExp;
+ xPtr->sign = ((uiA64 & 0x8000) != 0);
+ exp = uiA64 & 0x7FFF;
+ sig.v64 = 0;
+ sig.v0 = aSPtr->signif;
+ if ( exp == 0x7FFF ) {
+ if ( sig.v0 & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) {
+ xPtr->isNaN = true;
+ } else {
+ xPtr->isInf = true;
+ }
+ } else {
+ if ( ! exp ) ++exp;
+ exp -= 0x3FFF;
+ if ( ! (sig.v0 & UINT64_C( 0x8000000000000000 )) ) {
+ if ( ! sig.v0 ) {
+ xPtr->isZero = true;
+ } else {
+ do {
+ --exp;
+ sig.v0 <<= 1;
+ } while ( sig.v0 < UINT64_C( 0x8000000000000000 ) );
+ }
+ }
+ xPtr->exp = exp;
+ }
+ xPtr->sig = shortShiftLeft128( sig, 56 );
+
+}
+
+static void floatXToExtF80M( const struct floatX *xPtr, extFloat80_t *zPtr )
+{
+ struct extFloat80M *zSPtr;
+ struct floatX x, savedX;
+ bool isTiny;
+ int_fast32_t exp;
+ uint_fast64_t uiZ0;
+ uint_fast16_t uiZ64;
+
+ zSPtr = (struct extFloat80M *) zPtr;
+ if ( xPtr->isNaN ) {
+ zSPtr->signExp = 0xFFFF;
+ zSPtr->signif = UINT64_C( 0xFFFFFFFFFFFFFFFF );
+ return;
+ }
+ if ( xPtr->isInf ) {
+ zSPtr->signExp = xPtr->sign ? 0xFFFF : 0x7FFF;
+ zSPtr->signif = UINT64_C( 0x8000000000000000 );
+ return;
+ }
+ if ( xPtr->isZero ) {
+ zSPtr->signExp = xPtr->sign ? 0x8000 : 0;
+ zSPtr->signif = 0;
+ return;
+ }
+ x = *xPtr;
+ while ( UINT64_C( 0x0100000000000000 ) <= x.sig.v64 ) {
+ ++x.exp;
+ x.sig = shortShiftRightJam128( x.sig, 1 );
+ }
+ while ( x.sig.v64 < UINT64_C( 0x0080000000000000 ) ) {
+ --x.exp;
+ x.sig = shortShiftLeft128( x.sig, 1 );
+ }
+ savedX = x;
+ isTiny =
+ (slowfloat_detectTininess == softfloat_tininess_beforeRounding)
+ && (x.exp + 0x3FFF <= 0);
+ switch ( slow_extF80_roundingPrecision ) {
+ case 32:
+ roundFloatXTo24( isTiny, &x, slowfloat_roundingMode, true );
+ break;
+ case 64:
+ roundFloatXTo53( isTiny, &x, slowfloat_roundingMode, true );
+ break;
+ default:
+ roundFloatXTo64( isTiny, &x, slowfloat_roundingMode, true );
+ break;
+ }
+ exp = x.exp + 0x3FFF;
+ if ( 0x7FFF <= exp ) {
+ slowfloat_exceptionFlags |=
+ softfloat_flag_overflow | softfloat_flag_inexact;
+ if ( x.sign ) {
+ switch ( slowfloat_roundingMode ) {
+ case softfloat_round_near_even:
+ case softfloat_round_min:
+ case softfloat_round_near_maxMag:
+ zSPtr->signExp = 0xFFFF;
+ zSPtr->signif = UINT64_C( 0x8000000000000000 );
+ break;
+ case softfloat_round_minMag:
+ case softfloat_round_max:
+ switch ( slow_extF80_roundingPrecision ) {
+ case 32:
+ uiZ0 = UINT64_C( 0xFFFFFF0000000000 );
+ break;
+ case 64:
+ uiZ0 = UINT64_C( 0xFFFFFFFFFFFFF800 );
+ break;
+ default:
+ uiZ0 = UINT64_C( 0xFFFFFFFFFFFFFFFF );
+ break;
+ }
+ zSPtr->signExp = 0xFFFE;
+ zSPtr->signif = uiZ0;
+ break;
+ }
+ } else {
+ switch ( slowfloat_roundingMode ) {
+ case softfloat_round_near_even:
+ case softfloat_round_max:
+ case softfloat_round_near_maxMag:
+ zSPtr->signExp = 0x7FFF;
+ zSPtr->signif = UINT64_C( 0x8000000000000000 );
+ break;
+ case softfloat_round_minMag:
+ case softfloat_round_min:
+ switch ( slow_extF80_roundingPrecision ) {
+ case 32:
+ uiZ0 = UINT64_C( 0xFFFFFF0000000000 );
+ break;
+ case 64:
+ uiZ0 = UINT64_C( 0xFFFFFFFFFFFFF800 );
+ break;
+ default:
+ uiZ0 = UINT64_C( 0xFFFFFFFFFFFFFFFF );
+ break;
+ }
+ zSPtr->signExp = 0x7FFE;
+ zSPtr->signif = uiZ0;
+ break;
+ }
+ }
+ return;
+ }
+ if ( exp <= 0 ) {
+ isTiny = true;
+ x = savedX;
+ exp = x.exp + 0x3FFF;
+ if ( exp < -70 ) {
+ x.sig.v0 = (x.sig.v64 != 0) || (x.sig.v0 != 0);
+ x.sig.v64 = 0;
+ } else {
+ while ( exp <= 0 ) {
+ ++exp;
+ x.sig = shortShiftRightJam128( x.sig, 1 );
+ }
+ }
+ switch ( slow_extF80_roundingPrecision ) {
+ case 32:
+ roundFloatXTo24( isTiny, &x, slowfloat_roundingMode, true );
+ break;
+ case 64:
+ roundFloatXTo53( isTiny, &x, slowfloat_roundingMode, true );
+ break;
+ default:
+ roundFloatXTo64( isTiny, &x, slowfloat_roundingMode, true );
+ break;
+ }
+ exp = (UINT64_C( 0x0080000000000000 ) <= x.sig.v64) ? 1 : 0;
+ }
+ uiZ64 = exp;
+ if ( x.sign ) uiZ64 |= 0x8000;
+ zSPtr->signExp = uiZ64;
+ zSPtr->signif = shortShiftRightJam128( x.sig, 56 ).v0;
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+static void f128MToFloatX( const float128_t *aPtr, struct floatX *xPtr )
+{
+ const struct uint128 *uiAPtr;
+ uint_fast64_t uiA64;
+ int_fast32_t exp;
+ struct uint128 sig;
+
+ uiAPtr = (const struct uint128 *) aPtr;
+ xPtr->isNaN = false;
+ xPtr->isInf = false;
+ xPtr->isZero = false;
+ uiA64 = uiAPtr->v64;
+ xPtr->sign = ((uiA64 & UINT64_C( 0x8000000000000000 )) != 0);
+ exp = uiA64>>48 & 0x7FFF;
+ sig.v64 = uiA64 & UINT64_C( 0x0000FFFFFFFFFFFF );
+ sig.v0 = uiAPtr->v0;
+ if ( exp == 0x7FFF ) {
+ if ( sig.v64 || sig.v0 ) {
+ xPtr->isNaN = true;
+ } else {
+ xPtr->isInf = true;
+ }
+ } else if ( ! exp ) {
+ if ( ! sig.v64 && ! sig.v0 ) {
+ xPtr->isZero = true;
+ } else {
+ exp = 1 - 0x3FFF;
+ do {
+ --exp;
+ sig = shortShiftLeft128( sig, 1 );
+ } while ( sig.v64 < UINT64_C( 0x0001000000000000 ) );
+ xPtr->exp = exp;
+ }
+ } else {
+ xPtr->exp = exp - 0x3FFF;
+ sig.v64 |= UINT64_C( 0x0001000000000000 );
+ }
+ xPtr->sig = shortShiftLeft128( sig, 7 );
+
+}
+
+static void floatXToF128M( const struct floatX *xPtr, float128_t *zPtr )
+{
+ struct uint128 *uiZPtr;
+ struct floatX x, savedX;
+ bool isTiny;
+ int_fast32_t exp;
+ uint_fast64_t uiZ64;
+
+ uiZPtr = (struct uint128 *) zPtr;
+ if ( xPtr->isNaN ) {
+ uiZPtr->v64 = uiZPtr->v0 = UINT64_C( 0xFFFFFFFFFFFFFFFF );
+ return;
+ }
+ if ( xPtr->isInf ) {
+ uiZPtr->v64 =
+ xPtr->sign ? UINT64_C( 0xFFFF000000000000 )
+ : UINT64_C( 0x7FFF000000000000 );
+ uiZPtr->v0 = 0;
+ return;
+ }
+ if ( xPtr->isZero ) {
+ uiZPtr->v64 = xPtr->sign ? UINT64_C( 0x8000000000000000 ) : 0;
+ uiZPtr->v0 = 0;
+ return;
+ }
+ x = *xPtr;
+ while ( UINT64_C( 0x0100000000000000 ) <= x.sig.v64 ) {
+ ++x.exp;
+ x.sig = shortShiftRightJam128( x.sig, 1 );
+ }
+ while ( x.sig.v64 < UINT64_C( 0x0080000000000000 ) ) {
+ --x.exp;
+ x.sig = shortShiftLeft128( x.sig, 1 );
+ }
+ savedX = x;
+ isTiny =
+ (slowfloat_detectTininess == softfloat_tininess_beforeRounding)
+ && (x.exp + 0x3FFF <= 0);
+ roundFloatXTo113( isTiny, &x, slowfloat_roundingMode, true );
+ exp = x.exp + 0x3FFF;
+ if ( 0x7FFF <= exp ) {
+ slowfloat_exceptionFlags |=
+ softfloat_flag_overflow | softfloat_flag_inexact;
+ if ( x.sign ) {
+ switch ( slowfloat_roundingMode ) {
+ case softfloat_round_near_even:
+ case softfloat_round_min:
+ case softfloat_round_near_maxMag:
+ uiZPtr->v64 = UINT64_C( 0xFFFF000000000000 );
+ uiZPtr->v0 = 0;
+ break;
+ case softfloat_round_minMag:
+ case softfloat_round_max:
+ uiZPtr->v64 = UINT64_C( 0xFFFEFFFFFFFFFFFF );
+ uiZPtr->v0 = UINT64_C( 0xFFFFFFFFFFFFFFFF );
+ break;
+ }
+ } else {
+ switch ( slowfloat_roundingMode ) {
+ case softfloat_round_near_even:
+ case softfloat_round_max:
+ case softfloat_round_near_maxMag:
+ uiZPtr->v64 = UINT64_C( 0x7FFF000000000000 );
+ uiZPtr->v0 = 0;
+ break;
+ case softfloat_round_minMag:
+ case softfloat_round_min:
+ uiZPtr->v64 = UINT64_C( 0x7FFEFFFFFFFFFFFF );
+ uiZPtr->v0 = UINT64_C( 0xFFFFFFFFFFFFFFFF );
+ break;
+ }
+ }
+ return;
+ }
+ if ( exp <= 0 ) {
+ isTiny = true;
+ x = savedX;
+ exp = x.exp + 0x3FFF;
+ if ( exp < -120 ) {
+ x.sig.v0 = (x.sig.v64 != 0) || (x.sig.v0 != 0);
+ x.sig.v64 = 0;
+ } else {
+ while ( exp <= 0 ) {
+ ++exp;
+ x.sig = shortShiftRightJam128( x.sig, 1 );
+ }
+ }
+ roundFloatXTo113( isTiny, &x, slowfloat_roundingMode, true );
+ exp = (UINT64_C( 0x0080000000000000 ) <= x.sig.v64) ? 1 : 0;
+ }
+ uiZ64 = (uint_fast64_t) exp<<48;
+ if ( x.sign ) uiZ64 |= UINT64_C( 0x8000000000000000 );
+ x.sig = shortShiftRightJam128( x.sig, 7 );
+ uiZPtr->v64 = uiZ64 | x.sig.v64 & UINT64_C( 0x0000FFFFFFFFFFFF );
+ uiZPtr->v0 = x.sig.v0;
+
+}
+
+#endif
+
+static void floatXInvalid( struct floatX *xPtr )
+{
+
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ *xPtr = floatXNaN;
+
+}
+
+static
+ void
+ floatXRoundToInt(
+ struct floatX *xPtr, uint_fast8_t roundingMode, bool exact )
+{
+ int_fast32_t exp, shiftCount;
+ struct uint128 sig;
+
+ if ( xPtr->isNaN || xPtr->isInf ) return;
+ exp = xPtr->exp;
+ shiftCount = 112 - exp;
+ if ( shiftCount <= 0 ) return;
+ if ( 119 < shiftCount ) {
+ xPtr->exp = 112;
+ xPtr->sig.v64 = 0;
+ xPtr->sig.v0 = ! xPtr->isZero;
+ } else {
+ sig = xPtr->sig;
+ while ( 0 < shiftCount ) {
+ ++exp;
+ sig = shortShiftRightJam128( sig, 1 );
+ --shiftCount;
+ }
+ xPtr->exp = exp;
+ xPtr->sig = sig;
+ }
+ roundFloatXTo113( false, xPtr, roundingMode, exact );
+ if ( ! xPtr->sig.v64 && ! xPtr->sig.v0 ) xPtr->isZero = true;
+
+}
+
+static void floatXAdd( struct floatX *xPtr, const struct floatX *yPtr )
+{
+ int_fast32_t expX, expY, expDiff;
+ struct uint128 sigY;
+
+ if ( xPtr->isNaN ) return;
+ if ( yPtr->isNaN ) goto copyY;
+ if ( xPtr->isInf && yPtr->isInf ) {
+ if ( xPtr->sign != yPtr->sign ) floatXInvalid( xPtr );
+ return;
+ }
+ if ( xPtr->isInf ) return;
+ if ( yPtr->isInf ) goto copyY;
+ if ( xPtr->isZero && yPtr->isZero ) {
+ if ( xPtr->sign == yPtr->sign ) return;
+ goto completeCancellation;
+ }
+ expX = xPtr->exp;
+ expY = yPtr->exp;
+ if (
+ (xPtr->sign != yPtr->sign) && (expX == expY)
+ && eq128( xPtr->sig, yPtr->sig )
+ ) {
+ completeCancellation:
+ if (slowfloat_roundingMode == softfloat_round_min) {
+ *xPtr = floatXNegativeZero;
+ } else {
+ *xPtr = floatXPositiveZero;
+ }
+ return;
+ }
+ if ( xPtr->isZero ) goto copyY;
+ if ( yPtr->isZero ) return;
+ expDiff = expX - expY;
+ if ( expDiff < 0 ) {
+ xPtr->exp = expY;
+ if ( expDiff < -120 ) {
+ xPtr->sig.v64 = 0;
+ xPtr->sig.v0 = 1;
+ } else {
+ while ( expDiff < 0 ) {
+ ++expDiff;
+ xPtr->sig = shortShiftRightJam128( xPtr->sig, 1 );
+ }
+ }
+ if ( xPtr->sign != yPtr->sign ) xPtr->sig = neg128( xPtr->sig );
+ xPtr->sign = yPtr->sign;
+ xPtr->sig = add128( xPtr->sig, yPtr->sig );
+ } else {
+ sigY = yPtr->sig;
+ if ( 120 < expDiff ) {
+ sigY.v64 = 0;
+ sigY.v0 = 1;
+ } else {
+ while ( 0 < expDiff ) {
+ --expDiff;
+ sigY = shortShiftRightJam128( sigY, 1 );
+ }
+ }
+ if ( xPtr->sign != yPtr->sign ) sigY = neg128( sigY );
+ xPtr->sig = add128( xPtr->sig, sigY );
+ }
+ if ( xPtr->sig.v64 & UINT64_C( 0x8000000000000000 ) ) {
+ xPtr->sign = ! xPtr->sign;
+ xPtr->sig = neg128( xPtr->sig );
+ }
+ return;
+ copyY:
+ *xPtr = *yPtr;
+
+}
+
+static void floatXMul( struct floatX *xPtr, const struct floatX *yPtr )
+{
+ struct uint128 sig;
+ int bitNum;
+
+ if ( xPtr->isNaN ) return;
+ if ( yPtr->isNaN ) {
+ xPtr->isNaN = true;
+ xPtr->isInf = false;
+ xPtr->isZero = false;
+ xPtr->sign = yPtr->sign;
+ return;
+ }
+ if ( yPtr->sign ) xPtr->sign = ! xPtr->sign;
+ if ( xPtr->isInf ) {
+ if ( yPtr->isZero ) floatXInvalid( xPtr );
+ return;
+ }
+ if ( yPtr->isInf ) {
+ if ( xPtr->isZero ) {
+ floatXInvalid( xPtr );
+ return;
+ }
+ xPtr->isInf = true;
+ return;
+ }
+ if ( xPtr->isZero || yPtr->isZero ) {
+ if ( xPtr->sign ) {
+ *xPtr = floatXNegativeZero;
+ } else {
+ *xPtr = floatXPositiveZero;
+ }
+ return;
+ }
+ xPtr->exp += yPtr->exp;
+ sig.v64 = 0;
+ sig.v0 = 0;
+ for ( bitNum = 0; bitNum < 120; ++bitNum ) {
+ sig = shortShiftRightJam128( sig, 1 );
+ if ( xPtr->sig.v0 & 1 ) sig = add128( sig, yPtr->sig );
+ xPtr->sig = shortShiftRight128( xPtr->sig, 1 );
+ }
+ if ( UINT64_C( 0x0100000000000000 ) <= sig.v64 ) {
+ ++xPtr->exp;
+ sig = shortShiftRightJam128( sig, 1 );
+ }
+ xPtr->sig = sig;
+
+}
+
+static void floatXDiv( struct floatX *xPtr, const struct floatX *yPtr )
+{
+ struct uint128 sig, negSigY;
+ int bitNum;
+
+ if ( xPtr->isNaN ) return;
+ if ( yPtr->isNaN ) {
+ xPtr->isNaN = true;
+ xPtr->isInf = false;
+ xPtr->isZero = false;
+ xPtr->sign = yPtr->sign;
+ return;
+ }
+ if ( yPtr->sign ) xPtr->sign = ! xPtr->sign;
+ if ( xPtr->isInf ) {
+ if ( yPtr->isInf ) floatXInvalid( xPtr );
+ return;
+ }
+ if ( yPtr->isZero ) {
+ if ( xPtr->isZero ) {
+ floatXInvalid( xPtr );
+ return;
+ }
+ slowfloat_exceptionFlags |= softfloat_flag_infinite;
+ xPtr->isInf = true;
+ return;
+ }
+ if ( xPtr->isZero || yPtr->isInf ) {
+ if ( xPtr->sign ) {
+ *xPtr = floatXNegativeZero;
+ } else {
+ *xPtr = floatXPositiveZero;
+ }
+ return;
+ }
+ xPtr->exp -= yPtr->exp + 1;
+ sig.v64 = 0;
+ sig.v0 = 0;
+ negSigY = neg128( yPtr->sig );
+ for ( bitNum = 0; bitNum < 120; ++bitNum ) {
+ if ( le128( yPtr->sig, xPtr->sig ) ) {
+ sig.v0 |= 1;
+ xPtr->sig = add128( xPtr->sig, negSigY );
+ }
+ xPtr->sig = shortShiftLeft128( xPtr->sig, 1 );
+ sig = shortShiftLeft128( sig, 1 );
+ }
+ if ( xPtr->sig.v64 || xPtr->sig.v0 ) sig.v0 |= 1;
+ xPtr->sig = sig;
+
+}
+
+static void floatXRem( struct floatX *xPtr, const struct floatX *yPtr )
+{
+ int_fast32_t expX, expY;
+ struct uint128 sigY, negSigY;
+ bool lastQuotientBit;
+ struct uint128 savedSigX;
+
+ if ( xPtr->isNaN ) return;
+ if ( yPtr->isNaN ) {
+ xPtr->isNaN = true;
+ xPtr->isInf = false;
+ xPtr->isZero = false;
+ xPtr->sign = yPtr->sign;
+ return;
+ }
+ if ( xPtr->isInf || yPtr->isZero ) {
+ floatXInvalid( xPtr );
+ return;
+ }
+ if ( xPtr->isZero || yPtr->isInf ) return;
+ expX = xPtr->exp;
+ expY = yPtr->exp - 1;
+ if ( expX < expY ) return;
+ sigY = shortShiftLeft128( yPtr->sig, 1 );
+ negSigY = neg128( sigY );
+ while ( expY < expX ) {
+ --expX;
+ if ( le128( sigY, xPtr->sig ) ) {
+ xPtr->sig = add128( xPtr->sig, negSigY );
+ }
+ xPtr->sig = shortShiftLeft128( xPtr->sig, 1 );
+ }
+ xPtr->exp = expX;
+ lastQuotientBit = le128( sigY, xPtr->sig );
+ if ( lastQuotientBit ) xPtr->sig = add128( xPtr->sig, negSigY );
+ savedSigX = xPtr->sig;
+ xPtr->sig = neg128( add128( xPtr->sig, negSigY ) );
+ if ( lt128( xPtr->sig, savedSigX ) ) {
+ xPtr->sign = ! xPtr->sign;
+ } else if ( lt128( savedSigX, xPtr->sig ) ) {
+ goto restoreSavedSigX;
+ } else {
+ if ( lastQuotientBit ) {
+ xPtr->sign = ! xPtr->sign;
+ } else {
+ restoreSavedSigX:
+ xPtr->sig = savedSigX;
+ }
+ }
+ if ( ! xPtr->sig.v64 && ! xPtr->sig.v0 ) xPtr->isZero = true;
+
+}
+
+static void floatXSqrt( struct floatX *xPtr )
+{
+ struct uint128 sig, bitSig;
+ int bitNum;
+ struct uint128 savedSigX;
+
+ if ( xPtr->isNaN || xPtr->isZero ) return;
+ if ( xPtr->sign ) {
+ floatXInvalid( xPtr );
+ return;
+ }
+ if ( xPtr->isInf ) return;
+ if ( ! (xPtr->exp & 1) ) xPtr->sig = shortShiftRightJam128( xPtr->sig, 1 );
+ xPtr->exp >>= 1;
+ sig.v64 = 0;
+ sig.v0 = 0;
+ bitSig.v64 = UINT64_C( 0x0080000000000000 );
+ bitSig.v0 = 0;
+ for ( bitNum = 0; bitNum < 120; ++bitNum ) {
+ savedSigX = xPtr->sig;
+ xPtr->sig = add128( xPtr->sig, neg128( sig ) );
+ xPtr->sig = shortShiftLeft128( xPtr->sig, 1 );
+ xPtr->sig = add128( xPtr->sig, neg128( bitSig ) );
+ if ( xPtr->sig.v64 & UINT64_C( 0x8000000000000000 ) ) {
+ xPtr->sig = shortShiftLeft128( savedSigX, 1 );
+ } else {
+ sig.v64 |= bitSig.v64;
+ sig.v0 |= bitSig.v0;
+ }
+ bitSig = shortShiftRightJam128( bitSig, 1 );
+ }
+ if ( xPtr->sig.v64 || xPtr->sig.v0 ) sig.v0 |= 1;
+ xPtr->sig = sig;
+
+}
+
+static bool floatXEq( const struct floatX *xPtr, const struct floatX *yPtr )
+{
+
+ if ( xPtr->isNaN || yPtr->isNaN ) return false;
+ if ( xPtr->isZero && yPtr->isZero ) return true;
+ if ( xPtr->sign != yPtr->sign ) return false;
+ if ( xPtr->isInf || yPtr->isInf ) return xPtr->isInf && yPtr->isInf;
+ return ( xPtr->exp == yPtr->exp ) && eq128( xPtr->sig, yPtr->sig );
+
+}
+
+static bool floatXLe( const struct floatX *xPtr, const struct floatX *yPtr )
+{
+
+ if ( xPtr->isNaN || yPtr->isNaN ) return false;
+ if ( xPtr->isZero && yPtr->isZero ) return true;
+ if ( xPtr->sign != yPtr->sign ) return xPtr->sign;
+ if ( xPtr->sign ) {
+ if ( xPtr->isInf || yPtr->isZero ) return true;
+ if ( yPtr->isInf || xPtr->isZero ) return false;
+ if ( yPtr->exp < xPtr->exp ) return true;
+ if ( xPtr->exp < yPtr->exp ) return false;
+ return le128( yPtr->sig, xPtr->sig );
+ } else {
+ if ( yPtr->isInf || xPtr->isZero ) return true;
+ if ( xPtr->isInf || yPtr->isZero ) return false;
+ if ( xPtr->exp < yPtr->exp ) return true;
+ if ( yPtr->exp < xPtr->exp ) return false;
+ return le128( xPtr->sig, yPtr->sig );
+ }
+
+}
+
+static bool floatXLt( const struct floatX *xPtr, const struct floatX *yPtr )
+{
+
+ if ( xPtr->isNaN || yPtr->isNaN ) return false;
+ if ( xPtr->isZero && yPtr->isZero ) return false;
+ if ( xPtr->sign != yPtr->sign ) return xPtr->sign;
+ if ( xPtr->isInf && yPtr->isInf ) return false;
+ if ( xPtr->sign ) {
+ if ( xPtr->isInf || yPtr->isZero ) return true;
+ if ( yPtr->isInf || xPtr->isZero ) return false;
+ if ( yPtr->exp < xPtr->exp ) return true;
+ if ( xPtr->exp < yPtr->exp ) return false;
+ return lt128( yPtr->sig, xPtr->sig );
+ } else {
+ if ( yPtr->isInf || xPtr->isZero ) return true;
+ if ( xPtr->isInf || yPtr->isZero ) return false;
+ if ( xPtr->exp < yPtr->exp ) return true;
+ if ( yPtr->exp < xPtr->exp ) return false;
+ return lt128( xPtr->sig, yPtr->sig );
+ }
+
+}
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+
+#if defined EXTFLOAT80 || defined FLOAT128
+
+#ifdef LITTLEENDIAN
+struct uint256 { uint64_t v0, v64, v128, v192; };
+#else
+struct uint256 { uint64_t v192, v128 v64, v0; };
+#endif
+
+static bool eq256M( const struct uint256 *aPtr, const struct uint256 *bPtr )
+{
+
+ return
+ (aPtr->v192 == bPtr->v192) && (aPtr->v128 == bPtr->v128)
+ && (aPtr->v64 == bPtr->v64) && (aPtr->v0 == bPtr->v0);
+
+}
+
+static void shiftLeft1256M( struct uint256 *ptr )
+{
+ uint64_t dword1, dword2;
+
+ dword1 = ptr->v128;
+ ptr->v192 = ptr->v192<<1 | dword1>>63;
+ dword2 = ptr->v64;
+ ptr->v128 = dword1<<1 | dword2>>63;
+ dword1 = ptr->v0;
+ ptr->v64 = dword2<<1 | dword1>>63;
+ ptr->v0 = dword1<<1;
+
+}
+
+static void shiftRight1256M( struct uint256 *ptr )
+{
+ uint64_t dword1, dword2;
+
+ dword1 = ptr->v64;
+ ptr->v0 = dword1<<63 | ptr->v0>>1;
+ dword2 = ptr->v128;
+ ptr->v64 = dword2<<63 | dword1>>1;
+ dword1 = ptr->v192;
+ ptr->v128 = dword1<<63 | dword2>>1;
+ ptr->v192 = dword1>>1;
+
+}
+
+static void shiftRight1Jam256M( struct uint256 *ptr )
+{
+ int extra;
+
+ extra = ptr->v0 & 1;
+ shiftRight1256M( ptr );
+ ptr->v0 |= extra;
+
+}
+
+static void neg256M( struct uint256 *ptr )
+{
+ uint64_t v64, v0, v128;
+
+ v64 = ptr->v64;
+ v0 = ptr->v0;
+ if ( v64 | v0 ) {
+ ptr->v192 = ~ptr->v192;
+ ptr->v128 = ~ptr->v128;
+ if ( v0 ) {
+ ptr->v64 = ~v64;
+ ptr->v0 = -v0;
+ } else {
+ ptr->v64 = -v64;
+ }
+ } else {
+ v128 = ptr->v128;
+ if ( v128 ) {
+ ptr->v192 = ~ptr->v192;
+ ptr->v128 = -v128;
+ } else {
+ ptr->v192 = -ptr->v192;
+ }
+ }
+
+}
+
+static void add256M( struct uint256 *aPtr, const struct uint256 *bPtr )
+{
+ uint64_t dwordA, dwordZ;
+ unsigned int carry1, carry2;
+
+ dwordA = aPtr->v0;
+ dwordZ = dwordA + bPtr->v0;
+ carry1 = (dwordZ < dwordA);
+ aPtr->v0 = dwordZ;
+ dwordA = aPtr->v64;
+ dwordZ = dwordA + bPtr->v64;
+ carry2 = (dwordZ < dwordA);
+ dwordZ += carry1;
+ carry2 += (dwordZ < carry1);
+ aPtr->v64 = dwordZ;
+ dwordA = aPtr->v128;
+ dwordZ = dwordA + bPtr->v128;
+ carry1 = (dwordZ < dwordA);
+ dwordZ += carry2;
+ carry1 += (dwordZ < carry2);
+ aPtr->v128 = dwordZ;
+ aPtr->v192 = aPtr->v192 + bPtr->v192 + carry1;
+
+}
+
+struct floatX256 {
+ bool isNaN;
+ bool isInf;
+ bool isZero;
+ bool sign;
+ int_fast32_t exp;
+ struct uint256 sig;
+};
+
+static const struct floatX256 floatX256NaN =
+ { true, false, false, false, 0, { 0, 0, 0, 0 } };
+static const struct floatX256 floatX256PositiveZero =
+ { false, false, true, false, 0, { 0, 0, 0, 0 } };
+static const struct floatX256 floatX256NegativeZero =
+ { false, false, true, true, 0, { 0, 0, 0, 0 } };
+
+#ifdef FLOAT128
+
+static void f128MToFloatX256( const float128_t *aPtr, struct floatX256 *xPtr )
+{
+ struct floatX x;
+
+ f128MToFloatX( aPtr, &x );
+ xPtr->isNaN = x.isNaN;
+ xPtr->isInf = x.isInf;
+ xPtr->isZero = x.isZero;
+ xPtr->sign = x.sign;
+ xPtr->exp = x.exp;
+ xPtr->sig.v192 = x.sig.v64;
+ xPtr->sig.v128 = x.sig.v0;
+ xPtr->sig.v64 = 0;
+ xPtr->sig.v0 = 0;
+
+}
+
+static void floatX256ToF128M( const struct floatX256 *xPtr, float128_t *zPtr )
+{
+ struct floatX x;
+ int_fast32_t expZ;
+ struct uint256 sig;
+
+ x.isNaN = xPtr->isNaN;
+ x.isInf = xPtr->isInf;
+ x.isZero = xPtr->isZero;
+ x.sign = xPtr->sign;
+ if ( ! (x.isNaN | x.isInf | x.isZero) ) {
+ expZ = xPtr->exp;
+ sig = xPtr->sig;
+ while ( ! sig.v192 ) {
+ expZ -= 64;
+ sig.v192 = sig.v128;
+ sig.v128 = sig.v64;
+ sig.v64 = sig.v0;
+ sig.v0 = 0;
+ }
+ while ( sig.v192 < UINT64_C( 0x0100000000000000 ) ) {
+ --expZ;
+ shiftLeft1256M( &sig );
+ }
+ x.exp = expZ;
+ x.sig.v64 = sig.v192;
+ x.sig.v0 = sig.v128 | ((sig.v64 | sig.v0) != 0);
+ }
+ floatXToF128M( &x, zPtr );
+
+}
+
+#endif
+
+static void floatX256Invalid( struct floatX256 *xPtr )
+{
+
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ *xPtr = floatX256NaN;
+
+}
+
+static
+ void floatX256Add( struct floatX256 *xPtr, const struct floatX256 *yPtr )
+{
+ int_fast32_t expX, expY, expDiff;
+ struct uint256 sigY;
+
+ if ( xPtr->isNaN ) return;
+ if ( yPtr->isNaN ) goto copyY;
+ if ( xPtr->isInf && yPtr->isInf ) {
+ if ( xPtr->sign != yPtr->sign ) floatX256Invalid( xPtr );
+ return;
+ }
+ if ( xPtr->isInf ) return;
+ if ( yPtr->isInf ) goto copyY;
+ if ( xPtr->isZero && yPtr->isZero ) {
+ if ( xPtr->sign == yPtr->sign ) return;
+ goto completeCancellation;
+ }
+ expX = xPtr->exp;
+ expY = yPtr->exp;
+ if (
+ (xPtr->sign != yPtr->sign) && (expX == expY)
+ && eq256M( &xPtr->sig, &yPtr->sig )
+ ) {
+ completeCancellation:
+ if (slowfloat_roundingMode == softfloat_round_min) {
+ *xPtr = floatX256NegativeZero;
+ } else {
+ *xPtr = floatX256PositiveZero;
+ }
+ return;
+ }
+ if ( xPtr->isZero ) goto copyY;
+ if ( yPtr->isZero ) return;
+ expDiff = expX - expY;
+ if ( expDiff < 0 ) {
+ xPtr->exp = expY;
+ if ( expDiff < -248 ) {
+ xPtr->sig.v192 = 0;
+ xPtr->sig.v128 = 0;
+ xPtr->sig.v64 = 0;
+ xPtr->sig.v0 = 1;
+ } else {
+ while ( expDiff < 0 ) {
+ ++expDiff;
+ shiftRight1Jam256M( &xPtr->sig );
+ }
+ }
+ if ( xPtr->sign != yPtr->sign ) neg256M( &xPtr->sig );
+ xPtr->sign = yPtr->sign;
+ add256M( &xPtr->sig, &yPtr->sig );
+ } else {
+ sigY = yPtr->sig;
+ if ( 248 < expDiff ) {
+ sigY.v192 = 0;
+ sigY.v128 = 0;
+ sigY.v64 = 0;
+ sigY.v0 = 1;
+ } else {
+ while ( 0 < expDiff ) {
+ --expDiff;
+ shiftRight1Jam256M( &sigY );
+ }
+ }
+ if ( xPtr->sign != yPtr->sign ) neg256M( &sigY );
+ add256M( &xPtr->sig, &sigY );
+ }
+ if ( xPtr->sig.v192 & UINT64_C( 0x8000000000000000 ) ) {
+ xPtr->sign = ! xPtr->sign;
+ neg256M( &xPtr->sig );
+ }
+ return;
+ copyY:
+ *xPtr = *yPtr;
+
+}
+
+static
+ void floatX256Mul( struct floatX256 *xPtr, const struct floatX256 *yPtr )
+{
+ struct uint256 sig;
+ int bitNum;
+
+ if ( xPtr->isNaN ) return;
+ if ( yPtr->isNaN ) {
+ xPtr->isNaN = true;
+ xPtr->isInf = false;
+ xPtr->isZero = false;
+ xPtr->sign = yPtr->sign;
+ return;
+ }
+ if ( yPtr->sign ) xPtr->sign = ! xPtr->sign;
+ if ( xPtr->isInf ) {
+ if ( yPtr->isZero ) floatX256Invalid( xPtr );
+ return;
+ }
+ if ( yPtr->isInf ) {
+ if ( xPtr->isZero ) {
+ floatX256Invalid( xPtr );
+ return;
+ }
+ xPtr->isInf = true;
+ return;
+ }
+ if ( xPtr->isZero || yPtr->isZero ) {
+ if ( xPtr->sign ) {
+ *xPtr = floatX256NegativeZero;
+ } else {
+ *xPtr = floatX256PositiveZero;
+ }
+ return;
+ }
+ xPtr->exp += yPtr->exp;
+ sig.v192 = 0;
+ sig.v128 = 0;
+ sig.v64 = 0;
+ sig.v0 = 0;
+ for ( bitNum = 0; bitNum < 248; ++bitNum ) {
+ shiftRight1Jam256M( &sig );
+ if ( xPtr->sig.v0 & 1 ) add256M( &sig, &yPtr->sig );
+ shiftRight1256M( &xPtr->sig );
+ }
+ if ( UINT64_C( 0x0100000000000000 ) <= sig.v192 ) {
+ ++xPtr->exp;
+ shiftRight1Jam256M( &sig );
+ }
+ xPtr->sig = sig;
+
+}
+
+#endif
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+
+float32_t slow_ui32_to_f32( uint32_t a )
+{
+ struct floatX x;
+
+ ui32ToFloatX( a, &x );
+ return floatXToF32( &x );
+
+}
+
+float64_t slow_ui32_to_f64( uint32_t a )
+{
+ struct floatX x;
+
+ ui32ToFloatX( a, &x );
+ return floatXToF64( &x );
+
+}
+
+#ifdef EXTFLOAT80
+
+void slow_ui32_to_extF80M( uint32_t a, extFloat80_t *zPtr )
+{
+ struct floatX x;
+
+ ui32ToFloatX( a, &x );
+ floatXToExtF80M( &x, zPtr );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+void slow_ui32_to_f128M( uint32_t a, float128_t *zPtr )
+{
+ struct floatX x;
+
+ ui32ToFloatX( a, &x );
+ floatXToF128M( &x, zPtr );
+
+}
+
+#endif
+
+float32_t slow_ui64_to_f32( uint64_t a )
+{
+ struct floatX x;
+
+ ui64ToFloatX( a, &x );
+ return floatXToF32( &x );
+
+}
+
+float64_t slow_ui64_to_f64( uint64_t a )
+{
+ struct floatX x;
+
+ ui64ToFloatX( a, &x );
+ return floatXToF64( &x );
+
+}
+
+#ifdef EXTFLOAT80
+
+void slow_ui64_to_extF80M( uint64_t a, extFloat80_t *zPtr )
+{
+ struct floatX x;
+
+ ui64ToFloatX( a, &x );
+ floatXToExtF80M( &x, zPtr );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+void slow_ui64_to_f128M( uint64_t a, float128_t *zPtr )
+{
+ struct floatX x;
+
+ ui64ToFloatX( a, &x );
+ floatXToF128M( &x, zPtr );
+
+}
+
+#endif
+
+float32_t slow_i32_to_f32( int32_t a )
+{
+ struct floatX x;
+
+ i32ToFloatX( a, &x );
+ return floatXToF32( &x );
+
+}
+
+float64_t slow_i32_to_f64( int32_t a )
+{
+ struct floatX x;
+
+ i32ToFloatX( a, &x );
+ return floatXToF64( &x );
+
+}
+
+#ifdef EXTFLOAT80
+
+void slow_i32_to_extF80M( int32_t a, extFloat80_t *zPtr )
+{
+ struct floatX x;
+
+ i32ToFloatX( a, &x );
+ floatXToExtF80M( &x, zPtr );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+void slow_i32_to_f128M( int32_t a, float128_t *zPtr )
+{
+ struct floatX x;
+
+ i32ToFloatX( a, &x );
+ floatXToF128M( &x, zPtr );
+
+}
+
+#endif
+
+float32_t slow_i64_to_f32( int64_t a )
+{
+ struct floatX x;
+
+ i64ToFloatX( a, &x );
+ return floatXToF32( &x );
+
+}
+
+float64_t slow_i64_to_f64( int64_t a )
+{
+ struct floatX x;
+
+ i64ToFloatX( a, &x );
+ return floatXToF64( &x );
+
+}
+
+#ifdef EXTFLOAT80
+
+void slow_i64_to_extF80M( int64_t a, extFloat80_t *zPtr )
+{
+ struct floatX x;
+
+ i64ToFloatX( a, &x );
+ floatXToExtF80M( &x, zPtr );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+void slow_i64_to_f128M( int64_t a, float128_t *zPtr )
+{
+ struct floatX x;
+
+ i64ToFloatX( a, &x );
+ floatXToF128M( &x, zPtr );
+
+}
+
+#endif
+
+uint_fast32_t
+ slow_f32_to_ui32( float32_t a, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ f32ToFloatX( a, &x );
+ return floatXToUI32( &x, roundingMode, exact );
+
+}
+
+uint_fast64_t
+ slow_f32_to_ui64( float32_t a, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ f32ToFloatX( a, &x );
+ return floatXToUI64( &x, roundingMode, exact );
+
+}
+
+int_fast32_t
+ slow_f32_to_i32( float32_t a, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ f32ToFloatX( a, &x );
+ return floatXToI32( &x, roundingMode, exact );
+
+}
+
+int_fast64_t
+ slow_f32_to_i64( float32_t a, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ f32ToFloatX( a, &x );
+ return floatXToI64( &x, roundingMode, exact );
+
+}
+
+uint_fast32_t slow_f32_to_ui32_r_minMag( float32_t a, bool exact )
+{
+ struct floatX x;
+
+ f32ToFloatX( a, &x );
+ return floatXToUI32( &x, softfloat_round_minMag, exact );
+
+}
+
+uint_fast64_t slow_f32_to_ui64_r_minMag( float32_t a, bool exact )
+{
+ struct floatX x;
+
+ f32ToFloatX( a, &x );
+ return floatXToUI64( &x, softfloat_round_minMag, exact );
+
+}
+
+int_fast32_t slow_f32_to_i32_r_minMag( float32_t a, bool exact )
+{
+ struct floatX x;
+
+ f32ToFloatX( a, &x );
+ return floatXToI32( &x, softfloat_round_minMag, exact );
+
+}
+
+int_fast64_t slow_f32_to_i64_r_minMag( float32_t a, bool exact )
+{
+ struct floatX x;
+
+ f32ToFloatX( a, &x );
+ return floatXToI64( &x, softfloat_round_minMag, exact );
+
+}
+
+float64_t slow_f32_to_f64( float32_t a )
+{
+ struct floatX x;
+
+ f32ToFloatX( a, &x );
+ return floatXToF64( &x );
+
+}
+
+#ifdef EXTFLOAT80
+
+void slow_f32_to_extF80M( float32_t a, extFloat80_t *zPtr )
+{
+ struct floatX x;
+
+ f32ToFloatX( a, &x );
+ floatXToExtF80M( &x, zPtr );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+void slow_f32_to_f128M( float32_t a, float128_t *zPtr )
+{
+ struct floatX x;
+
+ f32ToFloatX( a, &x );
+ floatXToF128M( &x, zPtr );
+
+}
+
+#endif
+
+float32_t
+ slow_f32_roundToInt( float32_t a, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ f32ToFloatX( a, &x );
+ floatXRoundToInt( &x, roundingMode, exact );
+ return floatXToF32( &x );
+
+}
+
+float32_t slow_f32_add( float32_t a, float32_t b )
+{
+ struct floatX x, y;
+
+ f32ToFloatX( a, &x );
+ f32ToFloatX( b, &y );
+ floatXAdd( &x, &y );
+ return floatXToF32( &x );
+
+}
+
+float32_t slow_f32_sub( float32_t a, float32_t b )
+{
+ struct floatX x, y;
+
+ f32ToFloatX( a, &x );
+ f32ToFloatX( b, &y );
+ y.sign = ! y.sign;
+ floatXAdd( &x, &y );
+ return floatXToF32( &x );
+
+
+}
+
+float32_t slow_f32_mul( float32_t a, float32_t b )
+{
+ struct floatX x, y;
+
+ f32ToFloatX( a, &x );
+ f32ToFloatX( b, &y );
+ floatXMul( &x, &y );
+ return floatXToF32( &x );
+
+}
+
+float32_t slow_f32_mulAdd( float32_t a, float32_t b, float32_t c )
+{
+ struct floatX x, y;
+
+ f32ToFloatX( a, &x );
+ f32ToFloatX( b, &y );
+ floatXMul( &x, &y );
+ f32ToFloatX( c, &y );
+ floatXAdd( &x, &y );
+ return floatXToF32( &x );
+
+}
+
+float32_t slow_f32_div( float32_t a, float32_t b )
+{
+ struct floatX x, y;
+
+ f32ToFloatX( a, &x );
+ f32ToFloatX( b, &y );
+ floatXDiv( &x, &y );
+ return floatXToF32( &x );
+
+}
+
+float32_t slow_f32_rem( float32_t a, float32_t b )
+{
+ struct floatX x, y;
+
+ f32ToFloatX( a, &x );
+ f32ToFloatX( b, &y );
+ floatXRem( &x, &y );
+ return floatXToF32( &x );
+
+}
+
+float32_t slow_f32_sqrt( float32_t a )
+{
+ struct floatX x;
+
+ f32ToFloatX( a, &x );
+ floatXSqrt( &x );
+ return floatXToF32( &x );
+
+}
+
+bool slow_f32_eq( float32_t a, float32_t b )
+{
+ struct floatX x, y;
+
+ f32ToFloatX( a, &x );
+ f32ToFloatX( b, &y );
+ return floatXEq( &x, &y );
+
+}
+
+bool slow_f32_le( float32_t a, float32_t b )
+{
+ struct floatX x, y;
+
+ f32ToFloatX( a, &x );
+ f32ToFloatX( b, &y );
+ if ( x.isNaN || y.isNaN ) {
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ }
+ return floatXLe( &x, &y );
+
+}
+
+bool slow_f32_lt( float32_t a, float32_t b )
+{
+ struct floatX x, y;
+
+ f32ToFloatX( a, &x );
+ f32ToFloatX( b, &y );
+ if ( x.isNaN || y.isNaN ) {
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ }
+ return floatXLt( &x, &y );
+
+}
+
+bool slow_f32_eq_signaling( float32_t a, float32_t b )
+{
+ struct floatX x, y;
+
+ f32ToFloatX( a, &x );
+ f32ToFloatX( b, &y );
+ if ( x.isNaN || y.isNaN ) {
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ }
+ return floatXEq( &x, &y );
+
+}
+
+bool slow_f32_le_quiet( float32_t a, float32_t b )
+{
+ struct floatX x, y;
+
+ f32ToFloatX( a, &x );
+ f32ToFloatX( b, &y );
+ return floatXLe( &x, &y );
+
+}
+
+bool slow_f32_lt_quiet( float32_t a, float32_t b )
+{
+ struct floatX x, y;
+
+ f32ToFloatX( a, &x );
+ f32ToFloatX( b, &y );
+ return floatXLt( &x, &y );
+
+}
+
+uint_fast32_t
+ slow_f64_to_ui32( float64_t a, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ f64ToFloatX( a, &x );
+ return floatXToUI32( &x, roundingMode, exact );
+
+}
+
+uint_fast64_t
+ slow_f64_to_ui64( float64_t a, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ f64ToFloatX( a, &x );
+ return floatXToUI64( &x, roundingMode, exact );
+
+}
+
+int_fast32_t
+ slow_f64_to_i32( float64_t a, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ f64ToFloatX( a, &x );
+ return floatXToI32( &x, roundingMode, exact );
+
+}
+
+int_fast64_t
+ slow_f64_to_i64( float64_t a, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ f64ToFloatX( a, &x );
+ return floatXToI64( &x, roundingMode, exact );
+
+}
+
+uint_fast32_t slow_f64_to_ui32_r_minMag( float64_t a, bool exact )
+{
+ struct floatX x;
+
+ f64ToFloatX( a, &x );
+ return floatXToUI32( &x, softfloat_round_minMag, exact );
+
+}
+
+uint_fast64_t slow_f64_to_ui64_r_minMag( float64_t a, bool exact )
+{
+ struct floatX x;
+
+ f64ToFloatX( a, &x );
+ return floatXToUI64( &x, softfloat_round_minMag, exact );
+
+}
+
+int_fast32_t slow_f64_to_i32_r_minMag( float64_t a, bool exact )
+{
+ struct floatX x;
+
+ f64ToFloatX( a, &x );
+ return floatXToI32( &x, softfloat_round_minMag, exact );
+
+}
+
+int_fast64_t slow_f64_to_i64_r_minMag( float64_t a, bool exact )
+{
+ struct floatX x;
+
+ f64ToFloatX( a, &x );
+ return floatXToI64( &x, softfloat_round_minMag, exact );
+
+}
+
+float32_t slow_f64_to_f32( float64_t a )
+{
+ struct floatX x;
+
+ f64ToFloatX( a, &x );
+ return floatXToF32( &x );
+
+}
+
+#ifdef EXTFLOAT80
+
+void slow_f64_to_extF80M( float64_t a, extFloat80_t *zPtr )
+{
+ struct floatX x;
+
+ f64ToFloatX( a, &x );
+ floatXToExtF80M( &x, zPtr );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+void slow_f64_to_f128M( float64_t a, float128_t *zPtr )
+{
+ struct floatX x;
+
+ f64ToFloatX( a, &x );
+ floatXToF128M( &x, zPtr );
+
+}
+
+#endif
+
+float64_t
+ slow_f64_roundToInt( float64_t a, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ f64ToFloatX( a, &x );
+ floatXRoundToInt( &x, roundingMode, exact );
+ return floatXToF64( &x );
+
+}
+
+float64_t slow_f64_add( float64_t a, float64_t b )
+{
+ struct floatX x, y;
+
+ f64ToFloatX( a, &x );
+ f64ToFloatX( b, &y );
+ floatXAdd( &x, &y );
+ return floatXToF64( &x );
+
+}
+
+float64_t slow_f64_sub( float64_t a, float64_t b )
+{
+ struct floatX x, y;
+
+ f64ToFloatX( a, &x );
+ f64ToFloatX( b, &y );
+ y.sign = ! y.sign;
+ floatXAdd( &x, &y );
+ return floatXToF64( &x );
+
+}
+
+float64_t slow_f64_mul( float64_t a, float64_t b )
+{
+ struct floatX x, y;
+
+ f64ToFloatX( a, &x );
+ f64ToFloatX( b, &y );
+ floatXMul( &x, &y );
+ return floatXToF64( &x );
+
+}
+
+float64_t slow_f64_mulAdd( float64_t a, float64_t b, float64_t c )
+{
+ struct floatX x, y;
+
+ f64ToFloatX( a, &x );
+ f64ToFloatX( b, &y );
+ floatXMul( &x, &y );
+ f64ToFloatX( c, &y );
+ floatXAdd( &x, &y );
+ return floatXToF64( &x );
+
+}
+
+float64_t slow_f64_div( float64_t a, float64_t b )
+{
+ struct floatX x, y;
+
+ f64ToFloatX( a, &x );
+ f64ToFloatX( b, &y );
+ floatXDiv( &x, &y );
+ return floatXToF64( &x );
+
+}
+
+float64_t slow_f64_rem( float64_t a, float64_t b )
+{
+ struct floatX x, y;
+
+ f64ToFloatX( a, &x );
+ f64ToFloatX( b, &y );
+ floatXRem( &x, &y );
+ return floatXToF64( &x );
+
+}
+
+float64_t slow_f64_sqrt( float64_t a )
+{
+ struct floatX x;
+
+ f64ToFloatX( a, &x );
+ floatXSqrt( &x );
+ return floatXToF64( &x );
+
+}
+
+bool slow_f64_eq( float64_t a, float64_t b )
+{
+ struct floatX x, y;
+
+ f64ToFloatX( a, &x );
+ f64ToFloatX( b, &y );
+ return floatXEq( &x, &y );
+
+}
+
+bool slow_f64_le( float64_t a, float64_t b )
+{
+ struct floatX x, y;
+
+ f64ToFloatX( a, &x );
+ f64ToFloatX( b, &y );
+ if ( x.isNaN || y.isNaN ) {
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ }
+ return floatXLe( &x, &y );
+
+}
+
+bool slow_f64_lt( float64_t a, float64_t b )
+{
+ struct floatX x, y;
+
+ f64ToFloatX( a, &x );
+ f64ToFloatX( b, &y );
+ if ( x.isNaN || y.isNaN ) {
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ }
+ return floatXLt( &x, &y );
+
+}
+
+bool slow_f64_eq_signaling( float64_t a, float64_t b )
+{
+ struct floatX x, y;
+
+ f64ToFloatX( a, &x );
+ f64ToFloatX( b, &y );
+ if ( x.isNaN || y.isNaN ) {
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ }
+ return floatXEq( &x, &y );
+
+}
+
+bool slow_f64_le_quiet( float64_t a, float64_t b )
+{
+ struct floatX x, y;
+
+ f64ToFloatX( a, &x );
+ f64ToFloatX( b, &y );
+ return floatXLe( &x, &y );
+
+}
+
+bool slow_f64_lt_quiet( float64_t a, float64_t b )
+{
+ struct floatX x, y;
+
+ f64ToFloatX( a, &x );
+ f64ToFloatX( b, &y );
+ return floatXLt( &x, &y );
+
+}
+
+#ifdef EXTFLOAT80
+
+uint_fast32_t
+ slow_extF80M_to_ui32(
+ const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ extF80MToFloatX( aPtr, &x );
+ return floatXToUI32( &x, roundingMode, exact );
+
+}
+
+uint_fast64_t
+ slow_extF80M_to_ui64(
+ const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ extF80MToFloatX( aPtr, &x );
+ return floatXToUI64( &x, roundingMode, exact );
+
+}
+
+int_fast32_t
+ slow_extF80M_to_i32(
+ const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ extF80MToFloatX( aPtr, &x );
+ return floatXToI32( &x, roundingMode, exact );
+
+}
+
+int_fast64_t
+ slow_extF80M_to_i64(
+ const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ extF80MToFloatX( aPtr, &x );
+ return floatXToI64( &x, roundingMode, exact );
+
+}
+
+uint_fast32_t
+ slow_extF80M_to_ui32_r_minMag( const extFloat80_t *aPtr, bool exact )
+{
+ struct floatX x;
+
+ extF80MToFloatX( aPtr, &x );
+ return floatXToUI32( &x, softfloat_round_minMag, exact );
+
+}
+
+uint_fast64_t
+ slow_extF80M_to_ui64_r_minMag( const extFloat80_t *aPtr, bool exact )
+{
+ struct floatX x;
+
+ extF80MToFloatX( aPtr, &x );
+ return floatXToUI64( &x, softfloat_round_minMag, exact );
+
+}
+
+int_fast32_t
+ slow_extF80M_to_i32_r_minMag( const extFloat80_t *aPtr, bool exact )
+{
+ struct floatX x;
+
+ extF80MToFloatX( aPtr, &x );
+ return floatXToI32( &x, softfloat_round_minMag, exact );
+
+}
+
+int_fast64_t
+ slow_extF80M_to_i64_r_minMag( const extFloat80_t *aPtr, bool exact )
+{
+ struct floatX x;
+
+ extF80MToFloatX( aPtr, &x );
+ return floatXToI64( &x, softfloat_round_minMag, exact );
+
+}
+
+float32_t slow_extF80M_to_f32( const extFloat80_t *aPtr )
+{
+ struct floatX x;
+
+ extF80MToFloatX( aPtr, &x );
+ return floatXToF32( &x );
+
+}
+
+float64_t slow_extF80M_to_f64( const extFloat80_t *aPtr )
+{
+ struct floatX x;
+
+ extF80MToFloatX( aPtr, &x );
+ return floatXToF64( &x );
+
+}
+
+#ifdef FLOAT128
+
+void slow_extF80M_to_f128M( const extFloat80_t *aPtr, float128_t *zPtr )
+{
+ struct floatX x;
+
+ extF80MToFloatX( aPtr, &x );
+ floatXToF128M( &x, zPtr );
+
+}
+
+#endif
+
+void
+ slow_extF80M_roundToInt(
+ const extFloat80_t *aPtr,
+ uint_fast8_t roundingMode,
+ bool exact,
+ extFloat80_t *zPtr
+ )
+{
+ struct floatX x;
+
+ extF80MToFloatX( aPtr, &x );
+ floatXRoundToInt( &x, roundingMode, exact );
+ floatXToExtF80M( &x, zPtr );
+
+}
+
+void
+ slow_extF80M_add(
+ const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr )
+{
+ struct floatX x, y;
+
+ extF80MToFloatX( aPtr, &x );
+ extF80MToFloatX( bPtr, &y );
+ floatXAdd( &x, &y );
+ floatXToExtF80M( &x, zPtr );
+
+}
+
+void
+ slow_extF80M_sub(
+ const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr )
+{
+ struct floatX x, y;
+
+ extF80MToFloatX( aPtr, &x );
+ extF80MToFloatX( bPtr, &y );
+ y.sign = ! y.sign;
+ floatXAdd( &x, &y );
+ floatXToExtF80M( &x, zPtr );
+
+}
+
+void
+ slow_extF80M_mul(
+ const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr )
+{
+ struct floatX x, y;
+
+ extF80MToFloatX( aPtr, &x );
+ extF80MToFloatX( bPtr, &y );
+ floatXMul( &x, &y );
+ floatXToExtF80M( &x, zPtr );
+
+}
+
+void
+ slow_extF80M_div(
+ const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr )
+{
+ struct floatX x, y;
+
+ extF80MToFloatX( aPtr, &x );
+ extF80MToFloatX( bPtr, &y );
+ floatXDiv( &x, &y );
+ floatXToExtF80M( &x, zPtr );
+
+}
+
+void
+ slow_extF80M_rem(
+ const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr )
+{
+ struct floatX x, y;
+
+ extF80MToFloatX( aPtr, &x );
+ extF80MToFloatX( bPtr, &y );
+ floatXRem( &x, &y );
+ floatXToExtF80M( &x, zPtr );
+
+}
+
+void slow_extF80M_sqrt( const extFloat80_t *aPtr, extFloat80_t *zPtr )
+{
+ struct floatX x;
+
+ extF80MToFloatX( aPtr, &x );
+ floatXSqrt( &x );
+ floatXToExtF80M( &x, zPtr );
+
+}
+
+bool slow_extF80M_eq( const extFloat80_t *aPtr, const extFloat80_t *bPtr )
+{
+ struct floatX x, y;
+
+ extF80MToFloatX( aPtr, &x );
+ extF80MToFloatX( bPtr, &y );
+ return floatXEq( &x, &y );
+
+}
+
+bool slow_extF80M_le( const extFloat80_t *aPtr, const extFloat80_t *bPtr )
+{
+ struct floatX x, y;
+
+ extF80MToFloatX( aPtr, &x );
+ extF80MToFloatX( bPtr, &y );
+ if ( x.isNaN || y.isNaN ) {
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ }
+ return floatXLe( &x, &y );
+
+}
+
+bool slow_extF80M_lt( const extFloat80_t *aPtr, const extFloat80_t *bPtr )
+{
+ struct floatX x, y;
+
+ extF80MToFloatX( aPtr, &x );
+ extF80MToFloatX( bPtr, &y );
+ if ( x.isNaN || y.isNaN ) {
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ }
+ return floatXLt( &x, &y );
+
+}
+
+bool
+ slow_extF80M_eq_signaling(
+ const extFloat80_t *aPtr, const extFloat80_t *bPtr )
+{
+ struct floatX x, y;
+
+ extF80MToFloatX( aPtr, &x );
+ extF80MToFloatX( bPtr, &y );
+ if ( x.isNaN || y.isNaN ) {
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ }
+ return floatXEq( &x, &y );
+
+}
+
+bool slow_extF80M_le_quiet( const extFloat80_t *aPtr, const extFloat80_t *bPtr )
+{
+ struct floatX x, y;
+
+ extF80MToFloatX( aPtr, &x );
+ extF80MToFloatX( bPtr, &y );
+ return floatXLe( &x, &y );
+
+}
+
+bool slow_extF80M_lt_quiet( const extFloat80_t *aPtr, const extFloat80_t *bPtr )
+{
+ struct floatX x, y;
+
+ extF80MToFloatX( aPtr, &x );
+ extF80MToFloatX( bPtr, &y );
+ return floatXLt( &x, &y );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+uint_fast32_t
+ slow_f128M_to_ui32(
+ const float128_t *aPtr, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ f128MToFloatX( aPtr, &x );
+ return floatXToUI32( &x, roundingMode, exact );
+
+}
+
+uint_fast64_t
+ slow_f128M_to_ui64(
+ const float128_t *aPtr, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ f128MToFloatX( aPtr, &x );
+ return floatXToUI64( &x, roundingMode, exact );
+
+}
+
+int_fast32_t
+ slow_f128M_to_i32(
+ const float128_t *aPtr, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ f128MToFloatX( aPtr, &x );
+ return floatXToI32( &x, roundingMode, exact );
+
+}
+
+int_fast64_t
+ slow_f128M_to_i64(
+ const float128_t *aPtr, uint_fast8_t roundingMode, bool exact )
+{
+ struct floatX x;
+
+ f128MToFloatX( aPtr, &x );
+ return floatXToI64( &x, roundingMode, exact );
+
+}
+
+uint_fast32_t slow_f128M_to_ui32_r_minMag( const float128_t *aPtr, bool exact )
+{
+ struct floatX x;
+
+ f128MToFloatX( aPtr, &x );
+ return floatXToUI32( &x, softfloat_round_minMag, exact );
+
+}
+
+uint_fast64_t slow_f128M_to_ui64_r_minMag( const float128_t *aPtr, bool exact )
+{
+ struct floatX x;
+
+ f128MToFloatX( aPtr, &x );
+ return floatXToUI64( &x, softfloat_round_minMag, exact );
+
+}
+
+int_fast32_t slow_f128M_to_i32_r_minMag( const float128_t *aPtr, bool exact )
+{
+ struct floatX x;
+
+ f128MToFloatX( aPtr, &x );
+ return floatXToI32( &x, softfloat_round_minMag, exact );
+
+}
+
+int_fast64_t slow_f128M_to_i64_r_minMag( const float128_t *aPtr, bool exact )
+{
+ struct floatX x;
+
+ f128MToFloatX( aPtr, &x );
+ return floatXToI64( &x, softfloat_round_minMag, exact );
+
+}
+
+float32_t slow_f128M_to_f32( const float128_t *aPtr )
+{
+ struct floatX x;
+
+ f128MToFloatX( aPtr, &x );
+ return floatXToF32( &x );
+
+}
+
+float64_t slow_f128M_to_f64( const float128_t *aPtr )
+{
+ struct floatX x;
+
+ f128MToFloatX( aPtr, &x );
+ return floatXToF64( &x );
+
+}
+
+#ifdef EXTFLOAT80
+
+void slow_f128M_to_extF80M( const float128_t *aPtr, extFloat80_t *zPtr )
+{
+ struct floatX x;
+
+ f128MToFloatX( aPtr, &x );
+ floatXToExtF80M( &x, zPtr );
+
+}
+
+#endif
+
+void
+ slow_f128M_roundToInt(
+ const float128_t *aPtr,
+ uint_fast8_t roundingMode,
+ bool exact,
+ float128_t *zPtr
+ )
+{
+ struct floatX x;
+
+ f128MToFloatX( aPtr, &x );
+ floatXRoundToInt( &x, roundingMode, exact );
+ floatXToF128M( &x, zPtr );
+
+}
+
+void
+ slow_f128M_add(
+ const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
+{
+ struct floatX x, y;
+
+ f128MToFloatX( aPtr, &x );
+ f128MToFloatX( bPtr, &y );
+ floatXAdd( &x, &y );
+ floatXToF128M( &x, zPtr );
+
+}
+
+void
+ slow_f128M_sub(
+ const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
+{
+ struct floatX x, y;
+
+ f128MToFloatX( aPtr, &x );
+ f128MToFloatX( bPtr, &y );
+ y.sign = ! y.sign;
+ floatXAdd( &x, &y );
+ floatXToF128M( &x, zPtr );
+
+}
+
+void
+ slow_f128M_mul(
+ const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
+{
+ struct floatX x, y;
+
+ f128MToFloatX( aPtr, &x );
+ f128MToFloatX( bPtr, &y );
+ floatXMul( &x, &y );
+ floatXToF128M( &x, zPtr );
+
+}
+
+void
+ slow_f128M_mulAdd(
+ const float128_t *aPtr,
+ const float128_t *bPtr,
+ const float128_t *cPtr,
+ float128_t *zPtr
+ )
+{
+ struct floatX256 x, y;
+
+ f128MToFloatX256( aPtr, &x );
+ f128MToFloatX256( bPtr, &y );
+ floatX256Mul( &x, &y );
+ f128MToFloatX256( cPtr, &y );
+ floatX256Add( &x, &y );
+ floatX256ToF128M( &x, zPtr );
+
+}
+
+void
+ slow_f128M_div(
+ const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
+{
+ struct floatX x, y;
+
+ f128MToFloatX( aPtr, &x );
+ f128MToFloatX( bPtr, &y );
+ floatXDiv( &x, &y );
+ floatXToF128M( &x, zPtr );
+
+}
+
+void
+ slow_f128M_rem(
+ const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr )
+{
+ struct floatX x, y;
+
+ f128MToFloatX( aPtr, &x );
+ f128MToFloatX( bPtr, &y );
+ floatXRem( &x, &y );
+ floatXToF128M( &x, zPtr );
+
+}
+
+void slow_f128M_sqrt( const float128_t *aPtr, float128_t *zPtr )
+{
+ struct floatX x;
+
+ f128MToFloatX( aPtr, &x );
+ floatXSqrt( &x );
+ floatXToF128M( &x, zPtr );
+
+}
+
+bool slow_f128M_eq( const float128_t *aPtr, const float128_t *bPtr )
+{
+ struct floatX x, y;
+
+ f128MToFloatX( aPtr, &x );
+ f128MToFloatX( bPtr, &y );
+ return floatXEq( &x, &y );
+
+}
+
+bool slow_f128M_le( const float128_t *aPtr, const float128_t *bPtr )
+{
+ struct floatX x, y;
+
+ f128MToFloatX( aPtr, &x );
+ f128MToFloatX( bPtr, &y );
+ if ( x.isNaN || y.isNaN ) {
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ }
+ return floatXLe( &x, &y );
+
+}
+
+bool slow_f128M_lt( const float128_t *aPtr, const float128_t *bPtr )
+{
+ struct floatX x, y;
+
+ f128MToFloatX( aPtr, &x );
+ f128MToFloatX( bPtr, &y );
+ if ( x.isNaN || y.isNaN ) {
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ }
+ return floatXLt( &x, &y );
+
+}
+
+bool slow_f128M_eq_signaling( const float128_t *aPtr, const float128_t *bPtr )
+{
+ struct floatX x, y;
+
+ f128MToFloatX( aPtr, &x );
+ f128MToFloatX( bPtr, &y );
+ if ( x.isNaN || y.isNaN ) {
+ slowfloat_exceptionFlags |= softfloat_flag_invalid;
+ }
+ return floatXEq( &x, &y );
+
+}
+
+bool slow_f128M_le_quiet( const float128_t *aPtr, const float128_t *bPtr )
+{
+ struct floatX x, y;
+
+ f128MToFloatX( aPtr, &x );
+ f128MToFloatX( bPtr, &y );
+ return floatXLe( &x, &y );
+
+}
+
+bool slow_f128M_lt_quiet( const float128_t *aPtr, const float128_t *bPtr )
+{
+ struct floatX x, y;
+
+ f128MToFloatX( aPtr, &x );
+ f128MToFloatX( bPtr, &y );
+ return floatXLt( &x, &y );
+
+}
+
+#endif
+