|
@@ -961,3 +961,108 @@ floatx80 float32_to_floatx80( float32 a )
|
|
|
-------------------------------------------------------------------------------
|
|
|
Rounds the single-precision floating-point value `a' to an integer, and
|
|
|
returns the result as a single-precision floating-point value. The
|
|
|
+operation is performed according to the IEC/IEEE Standard for Binary
|
|
|
+Floating-point Arithmetic.
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+*/
|
|
|
+float32 float32_round_to_int( struct roundingData *roundData, float32 a )
|
|
|
+{
|
|
|
+ flag aSign;
|
|
|
+ int16 aExp;
|
|
|
+ bits32 lastBitMask, roundBitsMask;
|
|
|
+ int8 roundingMode;
|
|
|
+ float32 z;
|
|
|
+
|
|
|
+ aExp = extractFloat32Exp( a );
|
|
|
+ if ( 0x96 <= aExp ) {
|
|
|
+ if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) {
|
|
|
+ return propagateFloat32NaN( a, a );
|
|
|
+ }
|
|
|
+ return a;
|
|
|
+ }
|
|
|
+ roundingMode = roundData->mode;
|
|
|
+ if ( aExp <= 0x7E ) {
|
|
|
+ if ( (bits32) ( a<<1 ) == 0 ) return a;
|
|
|
+ roundData->exception |= float_flag_inexact;
|
|
|
+ aSign = extractFloat32Sign( a );
|
|
|
+ switch ( roundingMode ) {
|
|
|
+ case float_round_nearest_even:
|
|
|
+ if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) {
|
|
|
+ return packFloat32( aSign, 0x7F, 0 );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case float_round_down:
|
|
|
+ return aSign ? 0xBF800000 : 0;
|
|
|
+ case float_round_up:
|
|
|
+ return aSign ? 0x80000000 : 0x3F800000;
|
|
|
+ }
|
|
|
+ return packFloat32( aSign, 0, 0 );
|
|
|
+ }
|
|
|
+ lastBitMask = 1;
|
|
|
+ lastBitMask <<= 0x96 - aExp;
|
|
|
+ roundBitsMask = lastBitMask - 1;
|
|
|
+ z = a;
|
|
|
+ if ( roundingMode == float_round_nearest_even ) {
|
|
|
+ z += lastBitMask>>1;
|
|
|
+ if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
|
|
|
+ }
|
|
|
+ else if ( roundingMode != float_round_to_zero ) {
|
|
|
+ if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) {
|
|
|
+ z += roundBitsMask;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ z &= ~ roundBitsMask;
|
|
|
+ if ( z != a ) roundData->exception |= float_flag_inexact;
|
|
|
+ return z;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Returns the result of adding the absolute values of the single-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 float32 addFloat32Sigs( 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 <<= 6;
|
|
|
+ bSig <<= 6;
|
|
|
+ if ( 0 < expDiff ) {
|
|
|
+ if ( aExp == 0xFF ) {
|
|
|
+ if ( aSig ) return propagateFloat32NaN( a, b );
|
|
|
+ return a;
|
|
|
+ }
|
|
|
+ if ( bExp == 0 ) {
|
|
|
+ --expDiff;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ bSig |= 0x20000000;
|
|
|
+ }
|
|
|
+ shift32RightJamming( bSig, expDiff, &bSig );
|
|
|
+ zExp = aExp;
|
|
|
+ }
|
|
|
+ else if ( expDiff < 0 ) {
|
|
|
+ if ( bExp == 0xFF ) {
|
|
|
+ if ( bSig ) return propagateFloat32NaN( a, b );
|
|
|
+ return packFloat32( zSign, 0xFF, 0 );
|
|
|
+ }
|
|
|
+ if ( aExp == 0 ) {
|
|
|
+ ++expDiff;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ aSig |= 0x20000000;
|
|
|
+ }
|
|
|
+ shift32RightJamming( aSig, - expDiff, &aSig );
|
|
|
+ zExp = bExp;
|