|
@@ -2967,3 +2967,154 @@ floatx80 floatx80_mul( struct roundingData *roundData, floatx80 a, floatx80 b )
|
|
}
|
|
}
|
|
zExp = aExp + bExp - 0x3FFE;
|
|
zExp = aExp + bExp - 0x3FFE;
|
|
mul64To128( aSig, bSig, &zSig0, &zSig1 );
|
|
mul64To128( aSig, bSig, &zSig0, &zSig1 );
|
|
|
|
+ if ( 0 < (sbits64) zSig0 ) {
|
|
|
|
+ shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 );
|
|
|
|
+ --zExp;
|
|
|
|
+ }
|
|
|
|
+ return
|
|
|
|
+ roundAndPackFloatx80(
|
|
|
|
+ roundData, zSign, zExp, zSig0, zSig1 );
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+-------------------------------------------------------------------------------
|
|
|
|
+Returns the result of dividing the extended double-precision floating-point
|
|
|
|
+value `a' by the corresponding value `b'. The operation is performed
|
|
|
|
+according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
|
|
|
|
+-------------------------------------------------------------------------------
|
|
|
|
+*/
|
|
|
|
+floatx80 floatx80_div( struct roundingData *roundData, floatx80 a, floatx80 b )
|
|
|
|
+{
|
|
|
|
+ flag aSign, bSign, zSign;
|
|
|
|
+ int32 aExp, bExp, zExp;
|
|
|
|
+ bits64 aSig, bSig, zSig0, zSig1;
|
|
|
|
+ bits64 rem0, rem1, rem2, term0, term1, term2;
|
|
|
|
+ floatx80 z;
|
|
|
|
+
|
|
|
|
+ aSig = extractFloatx80Frac( a );
|
|
|
|
+ aExp = extractFloatx80Exp( a );
|
|
|
|
+ aSign = extractFloatx80Sign( a );
|
|
|
|
+ bSig = extractFloatx80Frac( b );
|
|
|
|
+ bExp = extractFloatx80Exp( b );
|
|
|
|
+ bSign = extractFloatx80Sign( b );
|
|
|
|
+ zSign = aSign ^ bSign;
|
|
|
|
+ if ( aExp == 0x7FFF ) {
|
|
|
|
+ if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b );
|
|
|
|
+ if ( bExp == 0x7FFF ) {
|
|
|
|
+ if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
|
|
|
|
+ goto invalid;
|
|
|
|
+ }
|
|
|
|
+ return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
|
|
|
|
+ }
|
|
|
|
+ if ( bExp == 0x7FFF ) {
|
|
|
|
+ if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
|
|
|
|
+ return packFloatx80( zSign, 0, 0 );
|
|
|
|
+ }
|
|
|
|
+ if ( bExp == 0 ) {
|
|
|
|
+ if ( bSig == 0 ) {
|
|
|
|
+ if ( ( aExp | aSig ) == 0 ) {
|
|
|
|
+ invalid:
|
|
|
|
+ roundData->exception |= float_flag_invalid;
|
|
|
|
+ z.low = floatx80_default_nan_low;
|
|
|
|
+ z.high = floatx80_default_nan_high;
|
|
|
|
+ z.__padding = 0;
|
|
|
|
+ return z;
|
|
|
|
+ }
|
|
|
|
+ roundData->exception |= float_flag_divbyzero;
|
|
|
|
+ return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
|
|
|
|
+ }
|
|
|
|
+ normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
|
|
|
|
+ }
|
|
|
|
+ if ( aExp == 0 ) {
|
|
|
|
+ if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
|
|
|
|
+ normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
|
|
|
|
+ }
|
|
|
|
+ zExp = aExp - bExp + 0x3FFE;
|
|
|
|
+ rem1 = 0;
|
|
|
|
+ if ( bSig <= aSig ) {
|
|
|
|
+ shift128Right( aSig, 0, 1, &aSig, &rem1 );
|
|
|
|
+ ++zExp;
|
|
|
|
+ }
|
|
|
|
+ zSig0 = estimateDiv128To64( aSig, rem1, bSig );
|
|
|
|
+ mul64To128( bSig, zSig0, &term0, &term1 );
|
|
|
|
+ sub128( aSig, rem1, term0, term1, &rem0, &rem1 );
|
|
|
|
+ while ( (sbits64) rem0 < 0 ) {
|
|
|
|
+ --zSig0;
|
|
|
|
+ add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
|
|
|
|
+ }
|
|
|
|
+ zSig1 = estimateDiv128To64( rem1, 0, bSig );
|
|
|
|
+ if ( (bits64) ( zSig1<<1 ) <= 8 ) {
|
|
|
|
+ mul64To128( bSig, zSig1, &term1, &term2 );
|
|
|
|
+ sub128( rem1, 0, term1, term2, &rem1, &rem2 );
|
|
|
|
+ while ( (sbits64) rem1 < 0 ) {
|
|
|
|
+ --zSig1;
|
|
|
|
+ add128( rem1, rem2, 0, bSig, &rem1, &rem2 );
|
|
|
|
+ }
|
|
|
|
+ zSig1 |= ( ( rem1 | rem2 ) != 0 );
|
|
|
|
+ }
|
|
|
|
+ return
|
|
|
|
+ roundAndPackFloatx80(
|
|
|
|
+ roundData, zSign, zExp, zSig0, zSig1 );
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+-------------------------------------------------------------------------------
|
|
|
|
+Returns the remainder of the extended double-precision floating-point value
|
|
|
|
+`a' with respect to the corresponding value `b'. The operation is performed
|
|
|
|
+according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
|
|
|
|
+-------------------------------------------------------------------------------
|
|
|
|
+*/
|
|
|
|
+floatx80 floatx80_rem( struct roundingData *roundData, floatx80 a, floatx80 b )
|
|
|
|
+{
|
|
|
|
+ flag aSign, bSign, zSign;
|
|
|
|
+ int32 aExp, bExp, expDiff;
|
|
|
|
+ bits64 aSig0, aSig1, bSig;
|
|
|
|
+ bits64 q, term0, term1, alternateASig0, alternateASig1;
|
|
|
|
+ floatx80 z;
|
|
|
|
+
|
|
|
|
+ aSig0 = extractFloatx80Frac( a );
|
|
|
|
+ aExp = extractFloatx80Exp( a );
|
|
|
|
+ aSign = extractFloatx80Sign( a );
|
|
|
|
+ bSig = extractFloatx80Frac( b );
|
|
|
|
+ bExp = extractFloatx80Exp( b );
|
|
|
|
+ bSign = extractFloatx80Sign( b );
|
|
|
|
+ if ( aExp == 0x7FFF ) {
|
|
|
|
+ if ( (bits64) ( aSig0<<1 )
|
|
|
|
+ || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) {
|
|
|
|
+ return propagateFloatx80NaN( a, b );
|
|
|
|
+ }
|
|
|
|
+ goto invalid;
|
|
|
|
+ }
|
|
|
|
+ if ( bExp == 0x7FFF ) {
|
|
|
|
+ if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
|
|
|
|
+ return a;
|
|
|
|
+ }
|
|
|
|
+ if ( bExp == 0 ) {
|
|
|
|
+ if ( bSig == 0 ) {
|
|
|
|
+ invalid:
|
|
|
|
+ roundData->exception |= float_flag_invalid;
|
|
|
|
+ z.low = floatx80_default_nan_low;
|
|
|
|
+ z.high = floatx80_default_nan_high;
|
|
|
|
+ z.__padding = 0;
|
|
|
|
+ return z;
|
|
|
|
+ }
|
|
|
|
+ normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
|
|
|
|
+ }
|
|
|
|
+ if ( aExp == 0 ) {
|
|
|
|
+ if ( (bits64) ( aSig0<<1 ) == 0 ) return a;
|
|
|
|
+ normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
|
|
|
|
+ }
|
|
|
|
+ bSig |= LIT64( 0x8000000000000000 );
|
|
|
|
+ zSign = aSign;
|
|
|
|
+ expDiff = aExp - bExp;
|
|
|
|
+ aSig1 = 0;
|
|
|
|
+ if ( expDiff < 0 ) {
|
|
|
|
+ if ( expDiff < -1 ) return a;
|
|
|
|
+ shift128Right( aSig0, 0, 1, &aSig0, &aSig1 );
|
|
|
|
+ expDiff = 0;
|
|
|
|
+ }
|
|
|
|
+ q = ( bSig <= aSig0 );
|
|
|
|
+ if ( q ) aSig0 -= bSig;
|
|
|
|
+ expDiff -= 64;
|