qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH] Fix NaN handling in softfloat


From: Aurelien Jarno
Subject: Re: [Qemu-devel] [PATCH] Fix NaN handling in softfloat
Date: Wed, 21 Nov 2007 16:49:22 +0100
User-agent: Mutt/1.5.13 (2006-08-11)

> I have looked quickly at your patch, it looks like the right approach to
> define target specific things at only one place in the file. I will get
> a closer tomorrow.
> 

Sorry I have been busy with real life stuff, and haven't looked at your
patch. I have seen you have committed it.

I have rebased the patch I already posted against the current CVS, it is
less intrusive now. It defines float32_default_nan and 
float64_default_nan for the various targets, as it varies even within 
targets which have the same convention for the SNAN bit.

It also keeps the mantissa when converting FP numbers, so that qNaN are
not changed into sNaN on MIPS and HPPA. If the mantissa becames zero a
new NaN number is generated.

It finally fixes an off-by-one in the extended double precision
format (aka floatx80), the mantissa is 64-bit long and not 63-bit
long.

With this patch applied all the glibc 2.7 floating point tests
are successfull on MIPS and MIPSEL.


Index: fpu/softfloat-specialize.h
===================================================================
RCS file: /sources/qemu/qemu/fpu/softfloat-specialize.h,v
retrieving revision 1.5
diff -u -d -p -r1.5 softfloat-specialize.h
--- fpu/softfloat-specialize.h  18 Nov 2007 14:33:23 -0000      1.5
+++ fpu/softfloat-specialize.h  20 Nov 2007 23:18:44 -0000
@@ -65,7 +65,13 @@ typedef struct {
 /*----------------------------------------------------------------------------
 | The pattern for a default generated single-precision NaN.
 *----------------------------------------------------------------------------*/
-#if SNAN_BIT_IS_ONE
+#if defined(TARGET_SPARC)
+#define float32_default_nan make_float32(0x7FFFFFFF)
+#elif defined(TARGET_POWERPC)
+#define float32_default_nan make_float32(0x7FC00000)
+#elif defined(TARGET_HPPA)
+#define float32_default_nan make_float32(0x7FA00000)
+#elif SNAN_BIT_IS_ONE
 #define float32_default_nan make_float32(0x7FBFFFFF)
 #else
 #define float32_default_nan make_float32(0xFFC00000)
@@ -125,8 +131,12 @@ static commonNaNT float32ToCommonNaN( fl
 
 static float32 commonNaNToFloat32( commonNaNT a )
 {
-    return make_float32(
-        ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ) );
+    bits32 mantissa = a.high>>41;
+    if ( mantissa )
+        return make_float32(
+            ( ( (bits32) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
+    else
+        return float32_default_nan;
 }
 
 /*----------------------------------------------------------------------------
@@ -180,7 +190,13 @@ static float32 propagateFloat32NaN( floa
 /*----------------------------------------------------------------------------
 | The pattern for a default generated double-precision NaN.
 *----------------------------------------------------------------------------*/
-#if SNAN_BIT_IS_ONE
+#if defined(TARGET_SPARC)
+#define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF ))
+#elif defined(TARGET_POWERPC)
+#define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 ))
+#elif defined(TARGET_HPPA)
+#define float64_default_nan make_float64(LIT64( 0x7FF4000000000000 ))
+#elif SNAN_BIT_IS_ONE
 #define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
 #else
 #define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
@@ -244,10 +260,15 @@ static commonNaNT float64ToCommonNaN( fl
 
 static float64 commonNaNToFloat64( commonNaNT a )
 {
-    return make_float64(
-          ( ( (bits64) a.sign )<<63 )
-        | LIT64( 0x7FF8000000000000 )
-        | ( a.high>>12 ));
+    bits64 mantissa = a.high>>12;
+
+    if ( mantissa )
+        return make_float64(
+              ( ( (bits64) a.sign )<<63 )
+            | LIT64( 0x7FF0000000000000 )
+            | ( a.high>>12 ));
+    else
+        return float64_default_nan;
 }
 
 /*----------------------------------------------------------------------------
@@ -366,7 +387,7 @@ static commonNaNT floatx80ToCommonNaN( f
     if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid 
STATUS_VAR);
     z.sign = a.high>>15;
     z.low = 0;
-    z.high = a.low<<1;
+    z.high = a.low;
     return z;
 }
 
@@ -379,7 +400,10 @@ static floatx80 commonNaNToFloatx80( com
 {
     floatx80 z;
 
-    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
+    if (a.high)
+        z.low = a.high;
+    else
+        z.low = floatx80_default_nan_low;
     z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
     return z;
 }
@@ -500,7 +524,7 @@ static float128 commonNaNToFloat128( com
     float128 z;
 
     shift128Right( a.high, a.low, 16, &z.high, &z.low );
-    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
+    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF000000000000 );
     return z;
 }
 

-- 
  .''`.  Aurelien Jarno             | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   address@hidden         | address@hidden
   `-    people.debian.org/~aurel32 | www.aurel32.net




reply via email to

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