qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion o


From: Maciej W. Rozycki
Subject: [Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion operations
Date: Tue, 9 Dec 2014 01:54:40 +0000
User-agent: Alpine 1.10 (DEB 962 2008-03-14)

Fix sNaN handling in floating-point format conversion operations, that 
are classified by the IEEE 754-2008 standard as general-computational 
operations [1]:

"5.4 formatOf general-computational operations

"5.4.2 Conversion operations for floating-point formats and decimal 
character sequences

"Implementations shall provide the following formatOf conversion 
operations from all supported floating-point formats to all supported 
floating-point formats, as well as conversions to and from decimal 
character sequences.  These operations shall not propagate non-canonical 
results.  Some format conversion operations produce results in a 
different radix than the operands."

according to the quietening requirement [2] set by the same standard:

"7.2 Invalid operation

"For operations producing results in floating-point format, the default 
result of an operation that signals the invalid operation exception 
shall be a quiet NaN that should provide some diagnostic information 
(see 6.2).

"These operations are:
    a)   any general-computational or signaling-computational operation 
         on a signaling NaN (see 6.2), except for some conversions (see 
         5.12)"

and the reference above is [3]:

"5.12 Details of conversion between floating-point data and external 
character sequences"

so does not apply to conversions a pair of floating-point formats.

Therefore quieten any sNaN encountered in floating-point format 
conversions, in the usual manner.

References:

[1] "IEEE Standard for Floating-Point Arithmetic", IEEE Computer 
    Society, IEEE Std 754-2008, 29 August 2008, pp. 21-22

[2] same, p. 37

[3] same, p. 30

Signed-off-by: Maciej W. Rozycki <address@hidden>
---
 This is in particular how MIPS hardware operates, other processors 
supposedly do the same if they claim compliance to IEEE 754.

 Please apply.

qemu-softfloat-convert-snan.diff
Index: qemu-git-trunk/fpu/softfloat.c
===================================================================
--- qemu-git-trunk.orig/fpu/softfloat.c 2014-10-24 22:03:48.000000000 +0100
+++ qemu-git-trunk/fpu/softfloat.c      2014-11-03 01:45:15.488923310 +0000
@@ -1711,7 +1711,11 @@ float64 float32_to_float64( float32 a ST
     aExp = extractFloat32Exp( a );
     aSign = extractFloat32Sign( a );
     if ( aExp == 0xFF ) {
-        if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a 
STATUS_VAR ) STATUS_VAR );
+        if (aSig) {
+            return float64_maybe_silence_nan(
+                commonNaNToFloat64(float32ToCommonNaN(a STATUS_VAR)
+                                   STATUS_VAR));
+        }
         return packFloat64( aSign, 0x7FF, 0 );
     }
     if ( aExp == 0 ) {
@@ -1741,7 +1745,11 @@ floatx80 float32_to_floatx80( float32 a 
     aExp = extractFloat32Exp( a );
     aSign = extractFloat32Sign( a );
     if ( aExp == 0xFF ) {
-        if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a 
STATUS_VAR ) STATUS_VAR );
+        if (aSig) {
+            return floatx80_maybe_silence_nan(
+                commonNaNToFloatx80(float32ToCommonNaN(a STATUS_VAR)
+                                    STATUS_VAR));
+        }
         return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
     }
     if ( aExp == 0 ) {
@@ -1771,7 +1779,11 @@ float128 float32_to_float128( float32 a 
     aExp = extractFloat32Exp( a );
     aSign = extractFloat32Sign( a );
     if ( aExp == 0xFF ) {
-        if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a 
STATUS_VAR ) STATUS_VAR );
+        if (aSig) {
+            return float128_maybe_silence_nan(
+                commonNaNToFloat128(float32ToCommonNaN(a STATUS_VAR)
+                                    STATUS_VAR));
+        }
         return packFloat128( aSign, 0x7FFF, 0, 0 );
     }
     if ( aExp == 0 ) {
@@ -3151,7 +3163,11 @@ float32 float64_to_float32( float64 a ST
     aExp = extractFloat64Exp( a );
     aSign = extractFloat64Sign( a );
     if ( aExp == 0x7FF ) {
-        if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a 
STATUS_VAR ) STATUS_VAR );
+        if (aSig) {
+            return float32_maybe_silence_nan(
+                commonNaNToFloat32(float64ToCommonNaN(a STATUS_VAR)
+                                   STATUS_VAR));
+        }
         return packFloat32( aSign, 0xFF, 0 );
     }
     shift64RightJamming( aSig, 22, &aSig );
@@ -3318,7 +3334,9 @@ float32 float16_to_float32(float16 a, fl
 
     if (aExp == 0x1f && ieee) {
         if (aSig) {
-            return commonNaNToFloat32(float16ToCommonNaN(a STATUS_VAR) 
STATUS_VAR);
+            return float32_maybe_silence_nan(
+                commonNaNToFloat32(float16ToCommonNaN(a STATUS_VAR)
+                                   STATUS_VAR));
         }
         return packFloat32(aSign, 0xff, 0);
     }
@@ -3351,8 +3369,9 @@ float16 float32_to_float16(float32 a, fl
                 float_raise(float_flag_invalid STATUS_VAR);
                 return packFloat16(aSign, 0, 0);
             }
-            return commonNaNToFloat16(
-                float32ToCommonNaN(a STATUS_VAR) STATUS_VAR);
+            return float16_maybe_silence_nan(
+                commonNaNToFloat16(float32ToCommonNaN(a STATUS_VAR)
+                                   STATUS_VAR));
         }
         /* Infinity */
         if (!ieee) {
@@ -3389,8 +3408,9 @@ float64 float16_to_float64(float16 a, fl
 
     if (aExp == 0x1f && ieee) {
         if (aSig) {
-            return commonNaNToFloat64(
-                float16ToCommonNaN(a STATUS_VAR) STATUS_VAR);
+            return float64_maybe_silence_nan(
+                commonNaNToFloat64(float16ToCommonNaN(a STATUS_VAR)
+                                   STATUS_VAR));
         }
         return packFloat64(aSign, 0x7ff, 0);
     }
@@ -3424,8 +3444,9 @@ float16 float64_to_float16(float64 a, fl
                 float_raise(float_flag_invalid STATUS_VAR);
                 return packFloat16(aSign, 0, 0);
             }
-            return commonNaNToFloat16(
-                float64ToCommonNaN(a STATUS_VAR) STATUS_VAR);
+            return float16_maybe_silence_nan(
+                commonNaNToFloat16(float64ToCommonNaN(a STATUS_VAR)
+                                   STATUS_VAR));
         }
         /* Infinity */
         if (!ieee) {
@@ -3470,7 +3491,11 @@ floatx80 float64_to_floatx80( float64 a 
     aExp = extractFloat64Exp( a );
     aSign = extractFloat64Sign( a );
     if ( aExp == 0x7FF ) {
-        if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a 
STATUS_VAR ) STATUS_VAR );
+        if (aSig) {
+            return floatx80_maybe_silence_nan(
+                commonNaNToFloatx80(float64ToCommonNaN(a STATUS_VAR)
+                                    STATUS_VAR));
+        }
         return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
     }
     if ( aExp == 0 ) {
@@ -3501,7 +3526,11 @@ float128 float64_to_float128( float64 a 
     aExp = extractFloat64Exp( a );
     aSign = extractFloat64Sign( a );
     if ( aExp == 0x7FF ) {
-        if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a 
STATUS_VAR ) STATUS_VAR );
+        if (aSig) {
+            return float128_maybe_silence_nan(
+                commonNaNToFloat128(float64ToCommonNaN(a STATUS_VAR)
+                                    STATUS_VAR));
+        }
         return packFloat128( aSign, 0x7FFF, 0, 0 );
     }
     if ( aExp == 0 ) {
@@ -4759,8 +4788,10 @@ float32 floatx80_to_float32( floatx80 a 
     aExp = extractFloatx80Exp( a );
     aSign = extractFloatx80Sign( a );
     if ( aExp == 0x7FFF ) {
-        if ( (uint64_t) ( aSig<<1 ) ) {
-            return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR ) 
STATUS_VAR );
+        if ((uint64_t)(aSig << 1)) {
+            return float32_maybe_silence_nan(
+                commonNaNToFloat32(floatx80ToCommonNaN(a STATUS_VAR)
+                                   STATUS_VAR));
         }
         return packFloat32( aSign, 0xFF, 0 );
     }
@@ -4787,8 +4818,10 @@ float64 floatx80_to_float64( floatx80 a 
     aExp = extractFloatx80Exp( a );
     aSign = extractFloatx80Sign( a );
     if ( aExp == 0x7FFF ) {
-        if ( (uint64_t) ( aSig<<1 ) ) {
-            return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR ) 
STATUS_VAR );
+        if ((uint64_t)(aSig << 1)) {
+            return float64_maybe_silence_nan(
+                commonNaNToFloat64(floatx80ToCommonNaN(a STATUS_VAR)
+                                   STATUS_VAR));
         }
         return packFloat64( aSign, 0x7FF, 0 );
     }
@@ -4814,8 +4847,9 @@ float128 floatx80_to_float128( floatx80 
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
     aSign = extractFloatx80Sign( a );
-    if ( ( aExp == 0x7FFF ) && (uint64_t) ( aSig<<1 ) ) {
-        return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR ) 
STATUS_VAR );
+    if (aExp == 0x7FFF && (uint64_t)(aSig << 1)) {
+        return float128_maybe_silence_nan(
+            commonNaNToFloat128(floatx80ToCommonNaN(a STATUS_VAR) STATUS_VAR));
     }
     shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 );
     return packFloat128( aSign, aExp, zSig0, zSig1 );
@@ -5832,8 +5866,10 @@ float32 float128_to_float32( float128 a 
     aExp = extractFloat128Exp( a );
     aSign = extractFloat128Sign( a );
     if ( aExp == 0x7FFF ) {
-        if ( aSig0 | aSig1 ) {
-            return commonNaNToFloat32( float128ToCommonNaN( a STATUS_VAR ) 
STATUS_VAR );
+        if (aSig0 | aSig1) {
+            return float32_maybe_silence_nan(
+                commonNaNToFloat32(float128ToCommonNaN(a STATUS_VAR)
+                                   STATUS_VAR));
         }
         return packFloat32( aSign, 0xFF, 0 );
     }
@@ -5866,8 +5902,10 @@ float64 float128_to_float64( float128 a 
     aExp = extractFloat128Exp( a );
     aSign = extractFloat128Sign( a );
     if ( aExp == 0x7FFF ) {
-        if ( aSig0 | aSig1 ) {
-            return commonNaNToFloat64( float128ToCommonNaN( a STATUS_VAR ) 
STATUS_VAR );
+        if (aSig0 | aSig1) {
+            return float64_maybe_silence_nan(
+                commonNaNToFloat64(float128ToCommonNaN(a STATUS_VAR)
+                                   STATUS_VAR));
         }
         return packFloat64( aSign, 0x7FF, 0 );
     }
@@ -5899,8 +5937,10 @@ floatx80 float128_to_floatx80( float128 
     aExp = extractFloat128Exp( a );
     aSign = extractFloat128Sign( a );
     if ( aExp == 0x7FFF ) {
-        if ( aSig0 | aSig1 ) {
-            return commonNaNToFloatx80( float128ToCommonNaN( a STATUS_VAR ) 
STATUS_VAR );
+        if (aSig0 | aSig1) {
+            return floatx80_maybe_silence_nan(
+                commonNaNToFloatx80(float128ToCommonNaN(a STATUS_VAR)
+                                    STATUS_VAR));
         }
         return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
     }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]