Add strict checking mode for softfp code.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3688 c046a42c-6fe2-441c-8c8c-71466251a162
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 8f9dd5c..18c6dd5 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -66,9 +66,9 @@
 | The pattern for a default generated single-precision NaN.
 *----------------------------------------------------------------------------*/
 #if SNAN_BIT_IS_ONE
-#define float32_default_nan 0x7FBFFFFF
+#define float32_default_nan make_float32(0x7FBFFFFF)
 #else
-#define float32_default_nan 0xFFC00000
+#define float32_default_nan make_float32(0xFFC00000)
 #endif
 
 /*----------------------------------------------------------------------------
@@ -76,8 +76,9 @@
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-int float32_is_nan( float32 a )
+int float32_is_nan( float32 a_ )
 {
+    uint32_t a = float32_val(a_);
 #if SNAN_BIT_IS_ONE
     return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
 #else
@@ -90,8 +91,9 @@
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-int float32_is_signaling_nan( float32 a )
+int float32_is_signaling_nan( float32 a_ )
 {
+    uint32_t a = float32_val(a_);
 #if SNAN_BIT_IS_ONE
     return ( 0xFF800000 <= (bits32) ( a<<1 ) );
 #else
@@ -110,9 +112,9 @@
     commonNaNT z;
 
     if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
-    z.sign = a>>31;
+    z.sign = float32_val(a)>>31;
     z.low = 0;
-    z.high = ( (bits64) a )<<41;
+    z.high = ( (bits64) float32_val(a) )<<41;
     return z;
 }
 
@@ -123,7 +125,8 @@
 
 static float32 commonNaNToFloat32( commonNaNT a )
 {
-    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
+    return make_float32(
+        ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ) );
 }
 
 /*----------------------------------------------------------------------------
@@ -135,42 +138,52 @@
 static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
 {
     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+    bits32 av, bv, res;
 
     aIsNaN = float32_is_nan( a );
     aIsSignalingNaN = float32_is_signaling_nan( a );
     bIsNaN = float32_is_nan( b );
     bIsSignalingNaN = float32_is_signaling_nan( b );
+    av = float32_val(a);
+    bv = float32_val(b);
 #if SNAN_BIT_IS_ONE
-    a &= ~0x00400000;
-    b &= ~0x00400000;
+    av &= ~0x00400000;
+    bv &= ~0x00400000;
 #else
-    a |= 0x00400000;
-    b |= 0x00400000;
+    av |= 0x00400000;
+    bv |= 0x00400000;
 #endif
     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
     if ( aIsSignalingNaN ) {
         if ( bIsSignalingNaN ) goto returnLargerSignificand;
-        return bIsNaN ? b : a;
+        res = bIsNaN ? bv : av;
     }
     else if ( aIsNaN ) {
-        if ( bIsSignalingNaN | ! bIsNaN ) return a;
+        if ( bIsSignalingNaN | ! bIsNaN )
+            res = av;
+        else {
  returnLargerSignificand:
-        if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b;
-        if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a;
-        return ( a < b ) ? a : b;
+            if ( (bits32) ( av<<1 ) < (bits32) ( bv<<1 ) )
+                res = bv;
+            else if ( (bits32) ( bv<<1 ) < (bits32) ( av<<1 ) )
+                res = av;
+            else
+                res = ( av < bv ) ? av : bv;
+        }
     }
     else {
-        return b;
+        res = bv;
     }
+    return make_float32(res);
 }
 
 /*----------------------------------------------------------------------------
 | The pattern for a default generated double-precision NaN.
 *----------------------------------------------------------------------------*/
 #if SNAN_BIT_IS_ONE
-#define float64_default_nan LIT64( 0x7FF7FFFFFFFFFFFF )
+#define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
 #else
-#define float64_default_nan LIT64( 0xFFF8000000000000 )
+#define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
 #endif
 
 /*----------------------------------------------------------------------------
@@ -178,8 +191,9 @@
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-int float64_is_nan( float64 a )
+int float64_is_nan( float64 a_ )
 {
+    bits64 a = float64_val(a_);
 #if SNAN_BIT_IS_ONE
     return
            ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
@@ -194,8 +208,9 @@
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-int float64_is_signaling_nan( float64 a )
+int float64_is_signaling_nan( float64 a_ )
 {
+    bits64 a = float64_val(a_);
 #if SNAN_BIT_IS_ONE
     return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
 #else
@@ -216,9 +231,9 @@
     commonNaNT z;
 
     if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
-    z.sign = a>>63;
+    z.sign = float64_val(a)>>63;
     z.low = 0;
-    z.high = a<<12;
+    z.high = float64_val(a)<<12;
     return z;
 }
 
@@ -229,10 +244,10 @@
 
 static float64 commonNaNToFloat64( commonNaNT a )
 {
-    return
+    return make_float64(
           ( ( (bits64) a.sign )<<63 )
         | LIT64( 0x7FF8000000000000 )
-        | ( a.high>>12 );
+        | ( a.high>>12 ));
 }
 
 /*----------------------------------------------------------------------------
@@ -244,33 +259,43 @@
 static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
 {
     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+    bits64 av, bv, res;
 
     aIsNaN = float64_is_nan( a );
     aIsSignalingNaN = float64_is_signaling_nan( a );
     bIsNaN = float64_is_nan( b );
     bIsSignalingNaN = float64_is_signaling_nan( b );
+    av = float64_val(a);
+    bv = float64_val(b);
 #if SNAN_BIT_IS_ONE
-    a &= ~LIT64( 0x0008000000000000 );
-    b &= ~LIT64( 0x0008000000000000 );
+    av &= ~LIT64( 0x0008000000000000 );
+    bv &= ~LIT64( 0x0008000000000000 );
 #else
-    a |= LIT64( 0x0008000000000000 );
-    b |= LIT64( 0x0008000000000000 );
+    av |= LIT64( 0x0008000000000000 );
+    bv |= LIT64( 0x0008000000000000 );
 #endif
     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
     if ( aIsSignalingNaN ) {
         if ( bIsSignalingNaN ) goto returnLargerSignificand;
-        return bIsNaN ? b : a;
+        res = bIsNaN ? bv : av;
     }
     else if ( aIsNaN ) {
-        if ( bIsSignalingNaN | ! bIsNaN ) return a;
+        if ( bIsSignalingNaN | ! bIsNaN )
+            res = av;
+        else {
  returnLargerSignificand:
-        if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b;
-        if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a;
-        return ( a < b ) ? a : b;
+            if ( (bits64) ( av<<1 ) < (bits64) ( bv<<1 ) )
+                res = bv;
+            else if ( (bits64) ( bv<<1 ) < (bits64) ( av<<1 ) )
+                res = av;
+            else
+                res = ( av < bv ) ? av : bv;
+        }
     }
     else {
-        return b;
+        res = bv;
     }
+    return make_float64(res);
 }
 
 #ifdef FLOATX80
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 8ebb692..f6cbd29 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -175,7 +175,7 @@
 INLINE bits32 extractFloat32Frac( float32 a )
 {
 
-    return a & 0x007FFFFF;
+    return float32_val(a) & 0x007FFFFF;
 
 }
 
@@ -186,7 +186,7 @@
 INLINE int16 extractFloat32Exp( float32 a )
 {
 
-    return ( a>>23 ) & 0xFF;
+    return ( float32_val(a)>>23 ) & 0xFF;
 
 }
 
@@ -197,7 +197,7 @@
 INLINE flag extractFloat32Sign( float32 a )
 {
 
-    return a>>31;
+    return float32_val(a)>>31;
 
 }
 
@@ -233,7 +233,8 @@
 INLINE float32 packFloat32( flag zSign, int16 zExp, bits32 zSig )
 {
 
-    return ( ( (bits32) zSign )<<31 ) + ( ( (bits32) zExp )<<23 ) + zSig;
+    return make_float32(
+          ( ( (bits32) zSign )<<31 ) + ( ( (bits32) zExp )<<23 ) + zSig);
 
 }
 
@@ -290,7 +291,7 @@
                   && ( (sbits32) ( zSig + roundIncrement ) < 0 ) )
            ) {
             float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
-            return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 );
+            return packFloat32( zSign, 0xFF, - ( roundIncrement == 0 ));
         }
         if ( zExp < 0 ) {
             isTiny =
@@ -337,7 +338,7 @@
 INLINE bits64 extractFloat64Frac( float64 a )
 {
 
-    return a & LIT64( 0x000FFFFFFFFFFFFF );
+    return float64_val(a) & LIT64( 0x000FFFFFFFFFFFFF );
 
 }
 
@@ -348,7 +349,7 @@
 INLINE int16 extractFloat64Exp( float64 a )
 {
 
-    return ( a>>52 ) & 0x7FF;
+    return ( float64_val(a)>>52 ) & 0x7FF;
 
 }
 
@@ -359,7 +360,7 @@
 INLINE flag extractFloat64Sign( float64 a )
 {
 
-    return a>>63;
+    return float64_val(a)>>63;
 
 }
 
@@ -395,7 +396,8 @@
 INLINE float64 packFloat64( flag zSign, int16 zExp, bits64 zSig )
 {
 
-    return ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<52 ) + zSig;
+    return make_float64(
+        ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<52 ) + zSig);
 
 }
 
@@ -452,7 +454,7 @@
                   && ( (sbits64) ( zSig + roundIncrement ) < 0 ) )
            ) {
             float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
-            return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 );
+            return packFloat64( zSign, 0x7FF, - ( roundIncrement == 0 ));
         }
         if ( zExp < 0 ) {
             isTiny =
@@ -1050,7 +1052,7 @@
 {
     flag zSign;
 
-    if ( a == 0 ) return 0;
+    if ( a == 0 ) return float32_zero;
     if ( a == (sbits32) 0x80000000 ) return packFloat32( 1, 0x9E, 0 );
     zSign = ( a < 0 );
     return normalizeRoundAndPackFloat32( zSign, 0x9C, zSign ? - a : a STATUS_VAR );
@@ -1070,7 +1072,7 @@
     int8 shiftCount;
     bits64 zSig;
 
-    if ( a == 0 ) return 0;
+    if ( a == 0 ) return float64_zero;
     zSign = ( a < 0 );
     absA = zSign ? - a : a;
     shiftCount = countLeadingZeros32( absA ) + 21;
@@ -1144,7 +1146,7 @@
     uint64 absA;
     int8 shiftCount;
 
-    if ( a == 0 ) return 0;
+    if ( a == 0 ) return float32_zero;
     zSign = ( a < 0 );
     absA = zSign ? - a : a;
     shiftCount = countLeadingZeros64( absA ) - 40;
@@ -1168,7 +1170,7 @@
 {
     int8 shiftCount;
 
-    if ( a == 0 ) return 0;
+    if ( a == 0 ) return float32_zero;
     shiftCount = countLeadingZeros64( a ) - 40;
     if ( 0 <= shiftCount ) {
         return packFloat32( 1 > 0, 0x95 - shiftCount, a<<shiftCount );
@@ -1195,7 +1197,7 @@
 {
     flag zSign;
 
-    if ( a == 0 ) return 0;
+    if ( a == 0 ) return float64_zero;
     if ( a == (sbits64) LIT64( 0x8000000000000000 ) ) {
         return packFloat64( 1, 0x43E, 0 );
     }
@@ -1206,7 +1208,7 @@
 
 float64 uint64_to_float64( uint64 a STATUS_PARAM )
 {
-    if ( a == 0 ) return 0;
+    if ( a == 0 ) return float64_zero;
     return normalizeRoundAndPackFloat64( 0, 0x43C, a STATUS_VAR );
 
 }
@@ -1325,7 +1327,7 @@
     aSign = extractFloat32Sign( a );
     shiftCount = aExp - 0x9E;
     if ( 0 <= shiftCount ) {
-        if ( a != 0xCF000000 ) {
+        if ( float32_val(a) != 0xCF000000 ) {
             float_raise( float_flag_invalid STATUS_VAR);
             if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) return 0x7FFFFFFF;
         }
@@ -1404,7 +1406,7 @@
     aSign = extractFloat32Sign( a );
     shiftCount = aExp - 0xBE;
     if ( 0 <= shiftCount ) {
-        if ( a != 0xDF000000 ) {
+        if ( float32_val(a) != 0xDF000000 ) {
             float_raise( float_flag_invalid STATUS_VAR);
             if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) {
                 return LIT64( 0x7FFFFFFFFFFFFFFF );
@@ -1535,7 +1537,7 @@
     int16 aExp;
     bits32 lastBitMask, roundBitsMask;
     int8 roundingMode;
-    float32 z;
+    bits32 z;
 
     aExp = extractFloat32Exp( a );
     if ( 0x96 <= aExp ) {
@@ -1545,7 +1547,7 @@
         return a;
     }
     if ( aExp <= 0x7E ) {
-        if ( (bits32) ( a<<1 ) == 0 ) return a;
+        if ( (bits32) ( float32_val(a)<<1 ) == 0 ) return a;
         STATUS(float_exception_flags) |= float_flag_inexact;
         aSign = extractFloat32Sign( a );
         switch ( STATUS(float_rounding_mode) ) {
@@ -1555,29 +1557,29 @@
             }
             break;
          case float_round_down:
-            return aSign ? 0xBF800000 : 0;
+            return make_float32(aSign ? 0xBF800000 : 0);
          case float_round_up:
-            return aSign ? 0x80000000 : 0x3F800000;
+            return make_float32(aSign ? 0x80000000 : 0x3F800000);
         }
         return packFloat32( aSign, 0, 0 );
     }
     lastBitMask = 1;
     lastBitMask <<= 0x96 - aExp;
     roundBitsMask = lastBitMask - 1;
-    z = a;
+    z = float32_val(a);
     roundingMode = STATUS(float_rounding_mode);
     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 ) ) {
+        if ( extractFloat32Sign( make_float32(z) ) ^ ( roundingMode == float_round_up ) ) {
             z += roundBitsMask;
         }
     }
     z &= ~ roundBitsMask;
-    if ( z != a ) STATUS(float_exception_flags) |= float_flag_inexact;
-    return z;
+    if ( z != float32_val(a) ) STATUS(float_exception_flags) |= float_flag_inexact;
+    return make_float32(z);
 
 }
 
@@ -2008,7 +2010,7 @@
     aExp = extractFloat32Exp( a );
     aSign = extractFloat32Sign( a );
     if ( aExp == 0xFF ) {
-        if ( aSig ) return propagateFloat32NaN( a, 0 STATUS_VAR );
+        if ( aSig ) return propagateFloat32NaN( a, float32_zero STATUS_VAR );
         if ( ! aSign ) return a;
         float_raise( float_flag_invalid STATUS_VAR);
         return float32_default_nan;
@@ -2019,7 +2021,7 @@
         return float32_default_nan;
     }
     if ( aExp == 0 ) {
-        if ( aSig == 0 ) return 0;
+        if ( aSig == 0 ) return float32_zero;
         normalizeFloat32Subnormal( aSig, &aExp, &aSig );
     }
     zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E;
@@ -2062,7 +2064,8 @@
         }
         return 0;
     }
-    return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
+    return ( float32_val(a) == float32_val(b) ) ||
+            ( (bits32) ( ( float32_val(a) | float32_val(b) )<<1 ) == 0 );
 
 }
 
@@ -2076,6 +2079,7 @@
 int float32_le( float32 a, float32 b STATUS_PARAM )
 {
     flag aSign, bSign;
+    bits32 av, bv;
 
     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
@@ -2085,8 +2089,10 @@
     }
     aSign = extractFloat32Sign( a );
     bSign = extractFloat32Sign( b );
-    if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
-    return ( a == b ) || ( aSign ^ ( a < b ) );
+    av = float32_val(a);
+    bv = float32_val(b);
+    if ( aSign != bSign ) return aSign || ( (bits32) ( ( av | bv )<<1 ) == 0 );
+    return ( av == bv ) || ( aSign ^ ( av < bv ) );
 
 }
 
@@ -2099,6 +2105,7 @@
 int float32_lt( float32 a, float32 b STATUS_PARAM )
 {
     flag aSign, bSign;
+    bits32 av, bv;
 
     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
@@ -2108,8 +2115,10 @@
     }
     aSign = extractFloat32Sign( a );
     bSign = extractFloat32Sign( b );
-    if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
-    return ( a != b ) && ( aSign ^ ( a < b ) );
+    av = float32_val(a);
+    bv = float32_val(b);
+    if ( aSign != bSign ) return aSign && ( (bits32) ( ( av | bv )<<1 ) != 0 );
+    return ( av != bv ) && ( aSign ^ ( av < bv ) );
 
 }
 
@@ -2122,6 +2131,7 @@
 
 int float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
 {
+    bits32 av, bv;
 
     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
@@ -2129,7 +2139,9 @@
         float_raise( float_flag_invalid STATUS_VAR);
         return 0;
     }
-    return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
+    av = float32_val(a);
+    bv = float32_val(b);
+    return ( av == bv ) || ( (bits32) ( ( av | bv )<<1 ) == 0 );
 
 }
 
@@ -2143,6 +2155,7 @@
 int float32_le_quiet( float32 a, float32 b STATUS_PARAM )
 {
     flag aSign, bSign;
+    bits32 av, bv;
 
     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
@@ -2154,8 +2167,10 @@
     }
     aSign = extractFloat32Sign( a );
     bSign = extractFloat32Sign( b );
-    if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
-    return ( a == b ) || ( aSign ^ ( a < b ) );
+    av = float32_val(a);
+    bv = float32_val(b);
+    if ( aSign != bSign ) return aSign || ( (bits32) ( ( av | bv )<<1 ) == 0 );
+    return ( av == bv ) || ( aSign ^ ( av < bv ) );
 
 }
 
@@ -2169,6 +2184,7 @@
 int float32_lt_quiet( float32 a, float32 b STATUS_PARAM )
 {
     flag aSign, bSign;
+    bits32 av, bv;
 
     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
@@ -2180,8 +2196,10 @@
     }
     aSign = extractFloat32Sign( a );
     bSign = extractFloat32Sign( b );
-    if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
-    return ( a != b ) && ( aSign ^ ( a < b ) );
+    av = float32_val(a);
+    bv = float32_val(b);
+    if ( aSign != bSign ) return aSign && ( (bits32) ( ( av | bv )<<1 ) != 0 );
+    return ( av != bv ) && ( aSign ^ ( av < bv ) );
 
 }
 
@@ -2324,7 +2342,7 @@
     shiftCount = aExp - 0x433;
     if ( 0 <= shiftCount ) {
         if ( 0x43E <= aExp ) {
-            if ( a != LIT64( 0xC3E0000000000000 ) ) {
+            if ( float64_val(a) != LIT64( 0xC3E0000000000000 ) ) {
                 float_raise( float_flag_invalid STATUS_VAR);
                 if (    ! aSign
                      || (    ( aExp == 0x7FF )
@@ -2464,7 +2482,7 @@
     int16 aExp;
     bits64 lastBitMask, roundBitsMask;
     int8 roundingMode;
-    float64 z;
+    bits64 z;
 
     aExp = extractFloat64Exp( a );
     if ( 0x433 <= aExp ) {
@@ -2474,7 +2492,7 @@
         return a;
     }
     if ( aExp < 0x3FF ) {
-        if ( (bits64) ( a<<1 ) == 0 ) return a;
+        if ( (bits64) ( float64_val(a)<<1 ) == 0 ) return a;
         STATUS(float_exception_flags) |= float_flag_inexact;
         aSign = extractFloat64Sign( a );
         switch ( STATUS(float_rounding_mode) ) {
@@ -2484,30 +2502,31 @@
             }
             break;
          case float_round_down:
-            return aSign ? LIT64( 0xBFF0000000000000 ) : 0;
+            return make_float64(aSign ? LIT64( 0xBFF0000000000000 ) : 0);
          case float_round_up:
-            return
-            aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 );
+            return make_float64(
+            aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 ));
         }
         return packFloat64( aSign, 0, 0 );
     }
     lastBitMask = 1;
     lastBitMask <<= 0x433 - aExp;
     roundBitsMask = lastBitMask - 1;
-    z = a;
+    z = float64_val(a);
     roundingMode = STATUS(float_rounding_mode);
     if ( roundingMode == float_round_nearest_even ) {
         z += lastBitMask>>1;
         if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
     }
     else if ( roundingMode != float_round_to_zero ) {
-        if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) {
+        if ( extractFloat64Sign( make_float64(z) ) ^ ( roundingMode == float_round_up ) ) {
             z += roundBitsMask;
         }
     }
     z &= ~ roundBitsMask;
-    if ( z != a ) STATUS(float_exception_flags) |= float_flag_inexact;
-    return z;
+    if ( z != float64_val(a) )
+        STATUS(float_exception_flags) |= float_flag_inexact;
+    return make_float64(z);
 
 }
 
@@ -2951,7 +2970,7 @@
         return float64_default_nan;
     }
     if ( aExp == 0 ) {
-        if ( aSig == 0 ) return 0;
+        if ( aSig == 0 ) return float64_zero;
         normalizeFloat64Subnormal( aSig, &aExp, &aSig );
     }
     zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE;
@@ -2982,6 +3001,7 @@
 
 int float64_eq( float64 a, float64 b STATUS_PARAM )
 {
+    bits64 av, bv;
 
     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
@@ -2991,7 +3011,9 @@
         }
         return 0;
     }
-    return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 );
+    av = float64_val(a);
+    bv = float64_val(a);
+    return ( av == bv ) || ( (bits64) ( ( av | bv )<<1 ) == 0 );
 
 }
 
@@ -3005,6 +3027,7 @@
 int float64_le( float64 a, float64 b STATUS_PARAM )
 {
     flag aSign, bSign;
+    bits64 av, bv;
 
     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
@@ -3014,8 +3037,10 @@
     }
     aSign = extractFloat64Sign( a );
     bSign = extractFloat64Sign( b );
-    if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 );
-    return ( a == b ) || ( aSign ^ ( a < b ) );
+    av = float64_val(a);
+    bv = float64_val(a);
+    if ( aSign != bSign ) return aSign || ( (bits64) ( ( av | bv )<<1 ) == 0 );
+    return ( av == bv ) || ( aSign ^ ( av < bv ) );
 
 }
 
@@ -3028,6 +3053,7 @@
 int float64_lt( float64 a, float64 b STATUS_PARAM )
 {
     flag aSign, bSign;
+    bits64 av, bv;
 
     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
@@ -3037,8 +3063,10 @@
     }
     aSign = extractFloat64Sign( a );
     bSign = extractFloat64Sign( b );
-    if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 );
-    return ( a != b ) && ( aSign ^ ( a < b ) );
+    av = float64_val(a);
+    bv = float64_val(a);
+    if ( aSign != bSign ) return aSign && ( (bits64) ( ( av | bv )<<1 ) != 0 );
+    return ( av != bv ) && ( aSign ^ ( av < bv ) );
 
 }
 
@@ -3051,6 +3079,7 @@
 
 int float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
 {
+    bits64 av, bv;
 
     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
@@ -3058,7 +3087,9 @@
         float_raise( float_flag_invalid STATUS_VAR);
         return 0;
     }
-    return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 );
+    av = float64_val(a);
+    bv = float64_val(a);
+    return ( av == bv ) || ( (bits64) ( ( av | bv )<<1 ) == 0 );
 
 }
 
@@ -3072,6 +3103,7 @@
 int float64_le_quiet( float64 a, float64 b STATUS_PARAM )
 {
     flag aSign, bSign;
+    bits64 av, bv;
 
     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
@@ -3083,8 +3115,10 @@
     }
     aSign = extractFloat64Sign( a );
     bSign = extractFloat64Sign( b );
-    if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 );
-    return ( a == b ) || ( aSign ^ ( a < b ) );
+    av = float64_val(a);
+    bv = float64_val(a);
+    if ( aSign != bSign ) return aSign || ( (bits64) ( ( av | bv )<<1 ) == 0 );
+    return ( av == bv ) || ( aSign ^ ( av < bv ) );
 
 }
 
@@ -3098,6 +3132,7 @@
 int float64_lt_quiet( float64 a, float64 b STATUS_PARAM )
 {
     flag aSign, bSign;
+    bits64 av, bv;
 
     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
@@ -3109,8 +3144,10 @@
     }
     aSign = extractFloat64Sign( a );
     bSign = extractFloat64Sign( b );
-    if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 );
-    return ( a != b ) && ( aSign ^ ( a < b ) );
+    av = float64_val(a);
+    bv = float64_val(a);
+    if ( aSign != bSign ) return aSign && ( (bits64) ( ( av | bv )<<1 ) != 0 );
+    return ( av != bv ) && ( aSign ^ ( av < bv ) );
 
 }
 
@@ -5310,12 +5347,14 @@
     return res;
 }
 
+/* FIXME: This looks broken.  */
 uint64_t float64_to_uint64 (float64 a STATUS_PARAM)
 {
     int64_t v;
 
-    v = int64_to_float64(INT64_MIN STATUS_VAR);
-    v = float64_to_int64((a + v) STATUS_VAR);
+    v = float64_val(int64_to_float64(INT64_MIN STATUS_VAR));
+    v += float64_val(a);
+    v = float64_to_int64(make_float64(v) STATUS_VAR);
 
     return v - INT64_MIN;
 }
@@ -5324,8 +5363,9 @@
 {
     int64_t v;
 
-    v = int64_to_float64(INT64_MIN STATUS_VAR);
-    v = float64_to_int64_round_to_zero((a + v) STATUS_VAR);
+    v = float64_val(int64_to_float64(INT64_MIN STATUS_VAR));
+    v += float64_val(a);
+    v = float64_to_int64_round_to_zero(make_float64(v) STATUS_VAR);
 
     return v - INT64_MIN;
 }
@@ -5335,6 +5375,7 @@
                                       int is_quiet STATUS_PARAM )            \
 {                                                                            \
     flag aSign, bSign;                                                       \
+    bits ## s av, bv;                                                        \
                                                                              \
     if (( ( extractFloat ## s ## Exp( a ) == nan_exp ) &&                    \
          extractFloat ## s ## Frac( a ) ) ||                                 \
@@ -5349,18 +5390,20 @@
     }                                                                        \
     aSign = extractFloat ## s ## Sign( a );                                  \
     bSign = extractFloat ## s ## Sign( b );                                  \
+    av = float ## s ## _val(a);                                              \
+    bv = float ## s ## _val(a);                                              \
     if ( aSign != bSign ) {                                                  \
-        if ( (bits ## s) ( ( a | b )<<1 ) == 0 ) {                           \
+        if ( (bits ## s) ( ( av | bv )<<1 ) == 0 ) {                         \
             /* zero case */                                                  \
             return float_relation_equal;                                     \
         } else {                                                             \
             return 1 - (2 * aSign);                                          \
         }                                                                    \
     } else {                                                                 \
-        if (a == b) {                                                        \
+        if (av == bv) {                                                      \
             return float_relation_equal;                                     \
         } else {                                                             \
-            return 1 - 2 * (aSign ^ ( a < b ));                              \
+            return 1 - 2 * (aSign ^ ( av < bv ));                            \
         }                                                                    \
     }                                                                        \
 }                                                                            \
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index f0261fb..84cffdd 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -111,8 +111,31 @@
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE floating-point types.
 *----------------------------------------------------------------------------*/
+/* Use structures for soft-float types.  This prevents accidentally mixing
+   them with native int/float types.  A sufficiently clever compiler and
+   sane ABI should be able to see though these structs.  However
+   x86/gcc 3.x seems to struggle a bit, so leave them disabled by default.  */
+//#define USE_SOFTFLOAT_STRUCT_TYPES
+#ifdef USE_SOFTFLOAT_STRUCT_TYPES
+typedef struct {
+    uint32_t v;
+} float32;
+/* The cast ensures an error if the wrong type is passed.  */
+#define float32_val(x) (((float32)(x)).v)
+#define make_float32(x) __extension__ ({ float32 f32_val = {x}; f32_val; })
+typedef struct {
+    uint64_t v;
+} float64;
+#define float64_val(x) (((float64)(x)).v)
+#define make_float64(x) __extension__ ({ float64 f64_val = {x}; f64_val; })
+#else
 typedef uint32_t float32;
 typedef uint64_t float64;
+#define float32_val(x) (x)
+#define float64_val(x) (x)
+#define make_float32(x) (x)
+#define make_float64(x) (x)
+#endif
 #ifdef FLOATX80
 typedef struct {
     uint64_t low;
@@ -248,14 +271,16 @@
 
 INLINE float32 float32_abs(float32 a)
 {
-    return a & 0x7fffffff;
+    return make_float32(float32_val(a) & 0x7fffffff);
 }
 
 INLINE float32 float32_chs(float32 a)
 {
-    return a ^ 0x80000000;
+    return make_float32(float32_val(a) ^ 0x80000000);
 }
 
+#define float32_zero make_float32(0)
+
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE double-precision conversion routines.
 *----------------------------------------------------------------------------*/
@@ -300,14 +325,16 @@
 
 INLINE float64 float64_abs(float64 a)
 {
-    return a & 0x7fffffffffffffffLL;
+    return make_float64(float64_val(a) & 0x7fffffffffffffffLL);
 }
 
 INLINE float64 float64_chs(float64 a)
 {
-    return a ^ 0x8000000000000000LL;
+    return make_float64(float64_val(a) ^ 0x8000000000000000LL);
 }
 
+#define float64_zero make_float64(0)
+
 #ifdef FLOATX80
 
 /*----------------------------------------------------------------------------
diff --git a/target-arm/nwfpe/double_cpdo.c b/target-arm/nwfpe/double_cpdo.c
index dbd496e..b5320c8 100644
--- a/target-arm/nwfpe/double_cpdo.c
+++ b/target-arm/nwfpe/double_cpdo.c
@@ -38,7 +38,7 @@
 unsigned int DoubleCPDO(const unsigned int opcode)
 {
    FPA11 *fpa11 = GET_FPA11();
-   float64 rFm, rFn = 0;
+   float64 rFm, rFn = float64_zero;
    unsigned int Fd, Fm, Fn, nRc = 1;
 
    //printk("DoubleCPDO(0x%08x)\n",opcode);
diff --git a/target-arm/nwfpe/single_cpdo.c b/target-arm/nwfpe/single_cpdo.c
index 1482f47..65043bc 100644
--- a/target-arm/nwfpe/single_cpdo.c
+++ b/target-arm/nwfpe/single_cpdo.c
@@ -38,7 +38,7 @@
 unsigned int SingleCPDO(const unsigned int opcode)
 {
    FPA11 *fpa11 = GET_FPA11();
-   float32 rFm, rFn = 0;
+   float32 rFm, rFn = float32_zero;
    unsigned int Fd, Fm, Fn, nRc = 1;
 
    Fm = getFm(opcode);
@@ -128,13 +128,11 @@
       break;
 
       case MNF_CODE:
-         rFm ^= 0x80000000;
-         fpa11->fpreg[Fd].fSingle = rFm;
+         fpa11->fpreg[Fd].fSingle = float32_chs(rFm);
       break;
 
       case ABS_CODE:
-         rFm &= 0x7fffffff;
-         fpa11->fpreg[Fd].fSingle = rFm;
+         fpa11->fpreg[Fd].fSingle = float32_abs(rFm);
       break;
 
       case RND_CODE:
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 460ef3c..f6b0cd6 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -255,7 +255,7 @@
         /* +/-inf compares equal against itself, but sub returns nan.  */
         if (!float64_is_nan(src0)
             && !float64_is_nan(src1)) {
-            res = 0;
+            res = float64_zero;
             if (float64_lt_quiet(src0, res, &env->fp_status))
                 res = float64_chs(res);
         }
diff --git a/target-m68k/op.c b/target-m68k/op.c
index 8600f43..140c71d 100644
--- a/target-m68k/op.c
+++ b/target-m68k/op.c
@@ -108,7 +108,7 @@
 
 OP(zerof64)
 {
-    set_opf64(PARAM1, 0);
+    set_opf64(PARAM1, float64_zero);
     FORCE_RET();
 }
 
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 4391e55..0323021 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -624,10 +624,10 @@
 
 /* Complex FPU operations which may need stack space. */
 
-#define FLOAT_ONE32 (0x3f8 << 20)
-#define FLOAT_ONE64 (0x3ffULL << 52)
-#define FLOAT_TWO32 (1 << 30)
-#define FLOAT_TWO64 (1ULL << 62)
+#define FLOAT_ONE32 make_float32(0x3f8 << 20)
+#define FLOAT_ONE64 make_float64(0x3ffULL << 52)
+#define FLOAT_TWO32 make_float32(1 << 30)
+#define FLOAT_TWO64 make_float64(1ULL << 62)
 #define FLOAT_QNAN32 0x7fbfffff
 #define FLOAT_QNAN64 0x7ff7ffffffffffffULL
 #define FLOAT_SNAN32 0x7fffffff