|
@@ -2626,3 +2626,151 @@ float32 floatx80_to_float32( struct roundingData *roundData, floatx80 a )
|
|
|
}
|
|
|
shift64RightJamming( aSig, 33, &aSig );
|
|
|
if ( aExp || aSig ) aExp -= 0x3F81;
|
|
|
+ return roundAndPackFloat32( roundData, aSign, aExp, aSig );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Returns the result of converting the extended double-precision floating-
|
|
|
+point value `a' to the double-precision floating-point format. The
|
|
|
+conversion is performed according to the IEC/IEEE Standard for Binary
|
|
|
+Floating-point Arithmetic.
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+*/
|
|
|
+float64 floatx80_to_float64( struct roundingData *roundData, floatx80 a )
|
|
|
+{
|
|
|
+ flag aSign;
|
|
|
+ int32 aExp;
|
|
|
+ bits64 aSig, zSig;
|
|
|
+
|
|
|
+ aSig = extractFloatx80Frac( a );
|
|
|
+ aExp = extractFloatx80Exp( a );
|
|
|
+ aSign = extractFloatx80Sign( a );
|
|
|
+ if ( aExp == 0x7FFF ) {
|
|
|
+ if ( (bits64) ( aSig<<1 ) ) {
|
|
|
+ return commonNaNToFloat64( floatx80ToCommonNaN( a ) );
|
|
|
+ }
|
|
|
+ return packFloat64( aSign, 0x7FF, 0 );
|
|
|
+ }
|
|
|
+ shift64RightJamming( aSig, 1, &zSig );
|
|
|
+ if ( aExp || aSig ) aExp -= 0x3C01;
|
|
|
+ return roundAndPackFloat64( roundData, aSign, aExp, zSig );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Rounds the extended double-precision floating-point value `a' to an integer,
|
|
|
+and returns the result as an extended quadruple-precision floating-point
|
|
|
+value. The operation is performed according to the IEC/IEEE Standard for
|
|
|
+Binary Floating-point Arithmetic.
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+*/
|
|
|
+floatx80 floatx80_round_to_int( struct roundingData *roundData, floatx80 a )
|
|
|
+{
|
|
|
+ flag aSign;
|
|
|
+ int32 aExp;
|
|
|
+ bits64 lastBitMask, roundBitsMask;
|
|
|
+ int8 roundingMode;
|
|
|
+ floatx80 z;
|
|
|
+
|
|
|
+ aExp = extractFloatx80Exp( a );
|
|
|
+ if ( 0x403E <= aExp ) {
|
|
|
+ if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) {
|
|
|
+ return propagateFloatx80NaN( a, a );
|
|
|
+ }
|
|
|
+ return a;
|
|
|
+ }
|
|
|
+ if ( aExp <= 0x3FFE ) {
|
|
|
+ if ( ( aExp == 0 )
|
|
|
+ && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) {
|
|
|
+ return a;
|
|
|
+ }
|
|
|
+ roundData->exception |= float_flag_inexact;
|
|
|
+ aSign = extractFloatx80Sign( a );
|
|
|
+ switch ( roundData->mode ) {
|
|
|
+ case float_round_nearest_even:
|
|
|
+ if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 )
|
|
|
+ ) {
|
|
|
+ return
|
|
|
+ packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case float_round_down:
|
|
|
+ return
|
|
|
+ aSign ?
|
|
|
+ packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) )
|
|
|
+ : packFloatx80( 0, 0, 0 );
|
|
|
+ case float_round_up:
|
|
|
+ return
|
|
|
+ aSign ? packFloatx80( 1, 0, 0 )
|
|
|
+ : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) );
|
|
|
+ }
|
|
|
+ return packFloatx80( aSign, 0, 0 );
|
|
|
+ }
|
|
|
+ lastBitMask = 1;
|
|
|
+ lastBitMask <<= 0x403E - aExp;
|
|
|
+ roundBitsMask = lastBitMask - 1;
|
|
|
+ z = a;
|
|
|
+ roundingMode = roundData->mode;
|
|
|
+ if ( roundingMode == float_round_nearest_even ) {
|
|
|
+ z.low += lastBitMask>>1;
|
|
|
+ if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
|
|
|
+ }
|
|
|
+ else if ( roundingMode != float_round_to_zero ) {
|
|
|
+ if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) {
|
|
|
+ z.low += roundBitsMask;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ z.low &= ~ roundBitsMask;
|
|
|
+ if ( z.low == 0 ) {
|
|
|
+ ++z.high;
|
|
|
+ z.low = LIT64( 0x8000000000000000 );
|
|
|
+ }
|
|
|
+ if ( z.low != a.low ) roundData->exception |= float_flag_inexact;
|
|
|
+ return z;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Returns the result of adding the absolute values of the extended double-
|
|
|
+precision floating-point values `a' and `b'. If `zSign' is true, the sum is
|
|
|
+negated before being returned. `zSign' is ignored if the result is a NaN.
|
|
|
+The addition is performed according to the IEC/IEEE Standard for Binary
|
|
|
+Floating-point Arithmetic.
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+*/
|
|
|
+static floatx80 addFloatx80Sigs( struct roundingData *roundData, floatx80 a, floatx80 b, flag zSign )
|
|
|
+{
|
|
|
+ int32 aExp, bExp, zExp;
|
|
|
+ bits64 aSig, bSig, zSig0, zSig1;
|
|
|
+ int32 expDiff;
|
|
|
+
|
|
|
+ aSig = extractFloatx80Frac( a );
|
|
|
+ aExp = extractFloatx80Exp( a );
|
|
|
+ bSig = extractFloatx80Frac( b );
|
|
|
+ bExp = extractFloatx80Exp( b );
|
|
|
+ expDiff = aExp - bExp;
|
|
|
+ if ( 0 < expDiff ) {
|
|
|
+ if ( aExp == 0x7FFF ) {
|
|
|
+ if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b );
|
|
|
+ return a;
|
|
|
+ }
|
|
|
+ if ( bExp == 0 ) --expDiff;
|
|
|
+ shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
|
|
|
+ zExp = aExp;
|
|
|
+ }
|
|
|
+ else if ( expDiff < 0 ) {
|
|
|
+ if ( bExp == 0x7FFF ) {
|
|
|
+ if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
|
|
|
+ return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
|
|
|
+ }
|
|
|
+ if ( aExp == 0 ) ++expDiff;
|
|
|
+ shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
|
|
|
+ zExp = bExp;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if ( aExp == 0x7FFF ) {
|
|
|
+ if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
|