|
@@ -1066,3 +1066,196 @@ static float32 addFloat32Sigs( struct roundingData *roundData, float32 a, float3
|
|
|
}
|
|
|
shift32RightJamming( aSig, - expDiff, &aSig );
|
|
|
zExp = bExp;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if ( aExp == 0xFF ) {
|
|
|
+ if ( aSig | bSig ) return propagateFloat32NaN( a, b );
|
|
|
+ return a;
|
|
|
+ }
|
|
|
+ if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 );
|
|
|
+ zSig = 0x40000000 + aSig + bSig;
|
|
|
+ zExp = aExp;
|
|
|
+ goto roundAndPack;
|
|
|
+ }
|
|
|
+ aSig |= 0x20000000;
|
|
|
+ zSig = ( aSig + bSig )<<1;
|
|
|
+ --zExp;
|
|
|
+ if ( (sbits32) zSig < 0 ) {
|
|
|
+ zSig = aSig + bSig;
|
|
|
+ ++zExp;
|
|
|
+ }
|
|
|
+ roundAndPack:
|
|
|
+ return roundAndPackFloat32( roundData, zSign, zExp, zSig );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Returns the result of subtracting the absolute values of the single-
|
|
|
+precision floating-point values `a' and `b'. If `zSign' is true, the
|
|
|
+difference is negated before being returned. `zSign' is ignored if the
|
|
|
+result is a NaN. The subtraction is performed according to the IEC/IEEE
|
|
|
+Standard for Binary Floating-point Arithmetic.
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+*/
|
|
|
+static float32 subFloat32Sigs( struct roundingData *roundData, float32 a, float32 b, flag zSign )
|
|
|
+{
|
|
|
+ int16 aExp, bExp, zExp;
|
|
|
+ bits32 aSig, bSig, zSig;
|
|
|
+ int16 expDiff;
|
|
|
+
|
|
|
+ aSig = extractFloat32Frac( a );
|
|
|
+ aExp = extractFloat32Exp( a );
|
|
|
+ bSig = extractFloat32Frac( b );
|
|
|
+ bExp = extractFloat32Exp( b );
|
|
|
+ expDiff = aExp - bExp;
|
|
|
+ aSig <<= 7;
|
|
|
+ bSig <<= 7;
|
|
|
+ if ( 0 < expDiff ) goto aExpBigger;
|
|
|
+ if ( expDiff < 0 ) goto bExpBigger;
|
|
|
+ if ( aExp == 0xFF ) {
|
|
|
+ if ( aSig | bSig ) return propagateFloat32NaN( a, b );
|
|
|
+ roundData->exception |= float_flag_invalid;
|
|
|
+ return float32_default_nan;
|
|
|
+ }
|
|
|
+ if ( aExp == 0 ) {
|
|
|
+ aExp = 1;
|
|
|
+ bExp = 1;
|
|
|
+ }
|
|
|
+ if ( bSig < aSig ) goto aBigger;
|
|
|
+ if ( aSig < bSig ) goto bBigger;
|
|
|
+ return packFloat32( roundData->mode == float_round_down, 0, 0 );
|
|
|
+ bExpBigger:
|
|
|
+ if ( bExp == 0xFF ) {
|
|
|
+ if ( bSig ) return propagateFloat32NaN( a, b );
|
|
|
+ return packFloat32( zSign ^ 1, 0xFF, 0 );
|
|
|
+ }
|
|
|
+ if ( aExp == 0 ) {
|
|
|
+ ++expDiff;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ aSig |= 0x40000000;
|
|
|
+ }
|
|
|
+ shift32RightJamming( aSig, - expDiff, &aSig );
|
|
|
+ bSig |= 0x40000000;
|
|
|
+ bBigger:
|
|
|
+ zSig = bSig - aSig;
|
|
|
+ zExp = bExp;
|
|
|
+ zSign ^= 1;
|
|
|
+ goto normalizeRoundAndPack;
|
|
|
+ aExpBigger:
|
|
|
+ if ( aExp == 0xFF ) {
|
|
|
+ if ( aSig ) return propagateFloat32NaN( a, b );
|
|
|
+ return a;
|
|
|
+ }
|
|
|
+ if ( bExp == 0 ) {
|
|
|
+ --expDiff;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ bSig |= 0x40000000;
|
|
|
+ }
|
|
|
+ shift32RightJamming( bSig, expDiff, &bSig );
|
|
|
+ aSig |= 0x40000000;
|
|
|
+ aBigger:
|
|
|
+ zSig = aSig - bSig;
|
|
|
+ zExp = aExp;
|
|
|
+ normalizeRoundAndPack:
|
|
|
+ --zExp;
|
|
|
+ return normalizeRoundAndPackFloat32( roundData, zSign, zExp, zSig );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Returns the result of adding the single-precision floating-point values `a'
|
|
|
+and `b'. The operation is performed according to the IEC/IEEE Standard for
|
|
|
+Binary Floating-point Arithmetic.
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+*/
|
|
|
+float32 float32_add( struct roundingData *roundData, float32 a, float32 b )
|
|
|
+{
|
|
|
+ flag aSign, bSign;
|
|
|
+
|
|
|
+ aSign = extractFloat32Sign( a );
|
|
|
+ bSign = extractFloat32Sign( b );
|
|
|
+ if ( aSign == bSign ) {
|
|
|
+ return addFloat32Sigs( roundData, a, b, aSign );
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return subFloat32Sigs( roundData, a, b, aSign );
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Returns the result of subtracting the single-precision floating-point values
|
|
|
+`a' and `b'. The operation is performed according to the IEC/IEEE Standard
|
|
|
+for Binary Floating-point Arithmetic.
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+*/
|
|
|
+float32 float32_sub( struct roundingData *roundData, float32 a, float32 b )
|
|
|
+{
|
|
|
+ flag aSign, bSign;
|
|
|
+
|
|
|
+ aSign = extractFloat32Sign( a );
|
|
|
+ bSign = extractFloat32Sign( b );
|
|
|
+ if ( aSign == bSign ) {
|
|
|
+ return subFloat32Sigs( roundData, a, b, aSign );
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return addFloat32Sigs( roundData, a, b, aSign );
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Returns the result of multiplying the single-precision floating-point values
|
|
|
+`a' and `b'. The operation is performed according to the IEC/IEEE Standard
|
|
|
+for Binary Floating-point Arithmetic.
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+*/
|
|
|
+float32 float32_mul( struct roundingData *roundData, float32 a, float32 b )
|
|
|
+{
|
|
|
+ flag aSign, bSign, zSign;
|
|
|
+ int16 aExp, bExp, zExp;
|
|
|
+ bits32 aSig, bSig;
|
|
|
+ bits64 zSig64;
|
|
|
+ bits32 zSig;
|
|
|
+
|
|
|
+ aSig = extractFloat32Frac( a );
|
|
|
+ aExp = extractFloat32Exp( a );
|
|
|
+ aSign = extractFloat32Sign( a );
|
|
|
+ bSig = extractFloat32Frac( b );
|
|
|
+ bExp = extractFloat32Exp( b );
|
|
|
+ bSign = extractFloat32Sign( b );
|
|
|
+ zSign = aSign ^ bSign;
|
|
|
+ if ( aExp == 0xFF ) {
|
|
|
+ if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
|
|
|
+ return propagateFloat32NaN( a, b );
|
|
|
+ }
|
|
|
+ if ( ( bExp | bSig ) == 0 ) {
|
|
|
+ roundData->exception |= float_flag_invalid;
|
|
|
+ return float32_default_nan;
|
|
|
+ }
|
|
|
+ return packFloat32( zSign, 0xFF, 0 );
|
|
|
+ }
|
|
|
+ if ( bExp == 0xFF ) {
|
|
|
+ if ( bSig ) return propagateFloat32NaN( a, b );
|
|
|
+ if ( ( aExp | aSig ) == 0 ) {
|
|
|
+ roundData->exception |= float_flag_invalid;
|
|
|
+ return float32_default_nan;
|
|
|
+ }
|
|
|
+ return packFloat32( zSign, 0xFF, 0 );
|
|
|
+ }
|
|
|
+ if ( aExp == 0 ) {
|
|
|
+ if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
|
|
|
+ normalizeFloat32Subnormal( aSig, &aExp, &aSig );
|
|
|
+ }
|
|
|
+ if ( bExp == 0 ) {
|
|
|
+ if ( bSig == 0 ) return packFloat32( zSign, 0, 0 );
|
|
|
+ normalizeFloat32Subnormal( bSig, &bExp, &bSig );
|
|
|
+ }
|
|
|
+ zExp = aExp + bExp - 0x7F;
|
|
|
+ aSig = ( aSig | 0x00800000 )<<7;
|