All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support
@ 2014-12-09  1:54 Maciej W. Rozycki
  2014-12-09  1:54 ` [Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion operations Maciej W. Rozycki
                   ` (8 more replies)
  0 siblings, 9 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-12-09  1:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: Leon Alrae, Thomas Schwinge, Aurelien Jarno

Hi,

 This patch series comprises changes to QEMU, both the MIPS backend and 
generic SoftFloat support code, to support IEEE 754-2008 features 
introduced to revision 3.50 of the MIPS Architecture as follows.

1. IEEE 754-2008 NaN encoding.

   As many of you have been aware it has been a long practice for software 
   using IEEE 754 floating-point arithmetic run on MIPS processors to use 
   an encoding of Not-a-Number (NaN) data different to one used by 
   software run on other processors.  And as of IEEE 754-2008 revision [1] 
   this encoding does not follow one recommended in the standard, as 
   specified in section 6.2.1, where it is stated that quiet NaNs should 
   have the first bit (d1) of their significand set to 1 while signalling 
   NaNs should have that bit set to 0, but MIPS software interprets the 
   two bits in the opposite manner.

   As from revision 3.50 [2][3] the MIPS Architecture provides for 
   processors that support the IEEE 754-2008 preferred NaN encoding 
   format. 

   A new ELF file header flag has been allocated to be set for 2008-NaN 
   binaries so that hardware can be configured accordingly by whatever 
   means are used to load the binary where support for both the 2008 and 
   legacy NaN encoding is present.  For hardware where only a single NaN 
   encoding is supported the flag can be used to reject incompatible 
   software.

2. IEEE 754-2008 non-arithmetic ABS and NEG instructions.

   As many of you have been aware MIPS ABS.fmt and NEG.fmt instructions 
   have not supported correct standard-compliant operation on a NaN 
   argument as the architecture has considered them arithmetic and 
   required to signal an Invalid Operation exception (that may or may not 
   be trapped; in the latter case a quiet NaN is produced).  As a result 
   in cases where standard compliance is required GCC has to emit longer 
   sequences to move the value given from the FPU to the CPU, use an 
   integer logical operation to adjust the sign bit manually, and then 
   move the result back to FPU.

   As from Sep 2012 the MIPS Architecture provides for processors that
   support the IEEE 754-2008 requirement that operations on bit strings, 
   that among others include ABS and NEG, are non-arithmetic and never 
   signal an exception.

 These features are addressed by this series as follows:

1. NaN data encodings.

   Handling is straightforward, although changes were tedious, spanning 
   many places in the MIPS backend and SoftFloat.  Data variables 
   providing NaN bit patterns are replaced with functions returning same 
   and then all functions and macros involved parametrised so as to select 
   the appropriate bit pattern according to the SoftFloat status state, 
   where a flag is added to select between the NaN formats where 
   applicable.  Credit goes to Thomas for making changes to SoftFloat in 
   self-contained incremental steps.

   The MIPS backend is then updated to handle the hardware side and 
   configure SoftFloat, just as with the other SoftFloat modes, according 
   to the FCSR NAN2008 bit.  This bit is preset according to the processor 
   definition used -- the architecture permits the bit to be either 
   read/write or read-only and, in the latter case, hardwired to 0 or 1 
   according to the interpretation implemented by a given processor.

2. ABS.fmt and NEG.fmt instructions.

   These were incorrectly already implemented as non-arithmetic.  No 
   existing MIPS processor provided this semantics until now, and not with 
   the FCSR ABS2008 bit set to 0.

   The old definitions therefore now serve the new semantics and new 
   implementations have been added to support the expected legacy 
   arithmetic treatment, according to the FCSR ABS2008 bit.  Again, this 
   bit is preset according to the processor definition used and can also 
   be read/write or read-only and if the latter, hardwired to 0 or 1.

 Both the implementation of the CTC1 instruction and the GDB stub have 
been updated to respect the properties of the new FCSR bits.

 I rigorously tested this set of changes by running full GCC, G++ and 
glibc mips-linux-gnu toolchain test suites under Linux (Debian Wheezy) run 
in QEMU in the system emulation mode, for the following multilibs:

-EB
-EB -mips16
-EB -mmicromips
-EB -mabi=n32
-EB -mabi=64

and the -EL variants of same.  Of these standard MIPS o32 testing was
run on a 24Kf processor and n64/n32 testing was run on a 5KEf processor,
using a 32-bit and a 64-bit kernel respectively.  MIPS16 o32 testing was
run on an artificial 5KEf-mips16 processor -- like a real 5KEf one, but
with the MIPS16 ASE enabled, and a 64-bit kernel.  Finally microMIPS o32
testing was run on an artificial 24Kf-micromips processor -- like a real
24Kf one, but with the microMIPS ASE enabled, and a 32-bit kernel built
as microMIPS code itself.  This covered the legacy NaN mode only and 
assured no regression has been introduced by these changes.

 I also rigorously tested this set of changes by running full GCC, G++ and 
glibc mips-linux-gnu toolchain test suites under QEMU in the Linux user 
emulation mode, for the following multilibs:

-EB
-EB -mips16
-EB -mmicromips
-EB -mabi=n32
-EB -mabi=64

-EB -mnan=2008
-EB -mnan=2008 -mips16
-EB -mnan=2008 -mmicromips
-EB -mnan=2008 -mabi=n32
-EB -mnan=2008 -mabi=64

-EB -msoft-float
-EB -msoft-float -mips16
-EB -msoft-float -mmicromips
-EB -msoft-float -mabi=n32
-EB -msoft-float -mabi=64

and the -EL variants of same.  Of those standard MIPS and MIPS16 o32 
testing was run on an artificial 24Kf-nan2008 processor -- like a real 
24Kf one, but with FCSR NAN2008 and ABS2008 bits writable.  Then microMIPS 
o32 testing was run on an artificial 24Kf-micromips-nan2008 processor -- 
like a real 24Kf one, but with the microMIPS ASE enabled and FCSR NAN2008 
and ABS2008 bits writable.  Finally n64/n32 testing was run on a 
5KEf-nan2008 processor -- like a real 5KEf, but with FCSR NAN2008 and 
ABS2008 bits writable.  Soft-float testing was run for a reference to 
ensure no critical errors were observed in hardware floating-point support 
compared to the same code built to use integer support only.

 Besides usual intermittent fluctuations in test results no problems have 
been spotted.  NB the user emulation mode is particularly problematic with 
the glibc test suite.

 Credit goes to Thomas for most of the SoftFloat changes, except from 1/7 
that I wrote from scratch based on his earlier MIPS-only implementation.  
With 2/7 through 6/7 I only ported the original changes to make them apply 
against and work with current trunk, including though not limited to new 
targets such as AArch64 and code such as MIPS MSA support added to QEMU 
since.  In 7/7 I did all the changes related to hardware and Thomas did 
the bits to configure SoftFloat.

 References:

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

[2] "MIPS Architecture For Programmers, Volume I-A: Introduction to the
    MIPS32 Architecture", MIPS Technologies, Inc., Document Number:
    MD00082, Revision 3.50, September 20, 2012

[3] "MIPS Architecture For Programmers, Volume I-A: Introduction to the
    MIPS64 Architecture", MIPS Technologies, Inc., Document Number:
    MD00083, Revision 3.50, September 20, 2012

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion operations
  2014-12-09  1:54 [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support Maciej W. Rozycki
@ 2014-12-09  1:54 ` Maciej W. Rozycki
  2015-01-29 14:51   ` Leon Alrae
  2015-02-05 16:37   ` Peter Maydell
  2014-12-09  1:54 ` [Qemu-devel] [PATCH 2/7] softfloat: Simplify `floatx80ToCommonNaN' function Maciej W. Rozycki
                   ` (7 subsequent siblings)
  8 siblings, 2 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-12-09  1:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: Leon Alrae, Thomas Schwinge, Aurelien Jarno

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 <macro@codesourcery.com>
---
 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 ) );
     }

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [Qemu-devel] [PATCH 2/7] softfloat: Simplify `floatx80ToCommonNaN' function
  2014-12-09  1:54 [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support Maciej W. Rozycki
  2014-12-09  1:54 ` [Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion operations Maciej W. Rozycki
@ 2014-12-09  1:54 ` Maciej W. Rozycki
  2015-01-28 16:15   ` Leon Alrae
  2014-12-09  1:55 ` [Qemu-devel] [PATCH 3/7] softfloat: Convert `*_default_nan' variables into inline functions Maciej W. Rozycki
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-12-09  1:54 UTC (permalink / raw)
  To: qemu-devel; +Cc: Leon Alrae, Thomas Schwinge, Aurelien Jarno

Make the bit shuffling in one place only and replace input if required 
instead.

Signed-off-by: Thomas Schwinge <thomas@codesourcery.com>
Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
qemu-softfloat-floatx80-nan.diff
Index: qemu-git-trunk/fpu/softfloat-specialize.h
===================================================================
--- qemu-git-trunk.orig/fpu/softfloat-specialize.h	2014-11-06 06:08:34.927738779 +0000
+++ qemu-git-trunk/fpu/softfloat-specialize.h	2014-11-20 21:58:09.908941613 +0000
@@ -934,15 +934,14 @@ static commonNaNT floatx80ToCommonNaN( f
     commonNaNT z;
 
     if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
-    if ( a.low >> 63 ) {
-        z.sign = a.high >> 15;
-        z.low = 0;
-        z.high = a.low << 1;
-    } else {
-        z.sign = floatx80_default_nan_high >> 15;
-        z.low = 0;
-        z.high = floatx80_default_nan_low << 1;
+    /* Replace a Pseudo NaN with a default NaN.  */
+    if (!(a.low >> 63)) {
+        a.low = floatx80_default_nan_low;
+        a.high = floatx80_default_nan_high;
     }
+    z.sign = a.high >> 15;
+    z.low = 0;
+    z.high = a.low << 1;
     return z;
 }
 

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [Qemu-devel] [PATCH 3/7] softfloat: Convert `*_default_nan' variables into inline functions
  2014-12-09  1:54 [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support Maciej W. Rozycki
  2014-12-09  1:54 ` [Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion operations Maciej W. Rozycki
  2014-12-09  1:54 ` [Qemu-devel] [PATCH 2/7] softfloat: Simplify `floatx80ToCommonNaN' function Maciej W. Rozycki
@ 2014-12-09  1:55 ` Maciej W. Rozycki
  2014-12-12 19:34   ` [Qemu-devel] [PATCH v2 " Maciej W. Rozycki
  2014-12-09  1:55 ` [Qemu-devel] [PATCH 4/7] softfloat: Add SoftFloat status parameter to `*_nan' functions Maciej W. Rozycki
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-12-09  1:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: Leon Alrae, Thomas Schwinge, Aurelien Jarno

Mechanically replace `*_default_nan' variables with inline functions and 
convert references accordingly.  Use `__inline__' rather than `inline' 
so that the latter does not cause the definitions to become static as a 
result of macro expansion, the functions are best inlined when referred 
to from softfloat.c, but external copies must be also produced for 
external callers.

Signed-off-by: Thomas Schwinge <thomas@codesourcery.com>
Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
 Eventually we might want to move the new inline functions into a 
separate header to be included from softfloat.h instead of softfloat.c, 
but let's make changes one step at a time.

 So for the time being -- please apply.

qemu-softfloat-default-nan-func.diff
Index: qemu-git-trunk/fpu/softfloat-specialize.h
===================================================================
--- qemu-git-trunk.orig/fpu/softfloat-specialize.h	2014-12-02 00:13:12.808049315 +0000
+++ qemu-git-trunk/fpu/softfloat-specialize.h	2014-12-02 00:13:14.309029586 +0000
@@ -51,69 +51,74 @@ these four paragraphs for those parts of
 /*----------------------------------------------------------------------------
 | The pattern for a default generated half-precision NaN.
 *----------------------------------------------------------------------------*/
+inline float16 float16_default_nan(void)
+{
 #if defined(TARGET_ARM)
-const float16 float16_default_nan = const_float16(0x7E00);
+    return const_float16(0x7E00);
 #elif SNAN_BIT_IS_ONE
-const float16 float16_default_nan = const_float16(0x7DFF);
+    return const_float16(0x7DFF);
 #else
-const float16 float16_default_nan = const_float16(0xFE00);
+    return const_float16(0xFE00);
 #endif
+}
 
 /*----------------------------------------------------------------------------
 | The pattern for a default generated single-precision NaN.
 *----------------------------------------------------------------------------*/
+inline float32 float32_default_nan(void)
+{
 #if defined(TARGET_SPARC)
-const float32 float32_default_nan = const_float32(0x7FFFFFFF);
+    return const_float32(0x7FFFFFFF);
 #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
       defined(TARGET_XTENSA)
-const float32 float32_default_nan = const_float32(0x7FC00000);
+    return const_float32(0x7FC00000);
 #elif SNAN_BIT_IS_ONE
-const float32 float32_default_nan = const_float32(0x7FBFFFFF);
+    return const_float32(0x7FBFFFFF);
 #else
-const float32 float32_default_nan = const_float32(0xFFC00000);
+    return const_float32(0xFFC00000);
 #endif
+}
 
 /*----------------------------------------------------------------------------
 | The pattern for a default generated double-precision NaN.
 *----------------------------------------------------------------------------*/
+inline float64 float64_default_nan(void)
+{
 #if defined(TARGET_SPARC)
-const float64 float64_default_nan = const_float64(LIT64( 0x7FFFFFFFFFFFFFFF ));
+    return const_float64(LIT64(0x7FFFFFFFFFFFFFFF));
 #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
-const float64 float64_default_nan = const_float64(LIT64( 0x7FF8000000000000 ));
+    return const_float64(LIT64(0x7FF8000000000000));
 #elif SNAN_BIT_IS_ONE
-const float64 float64_default_nan = const_float64(LIT64( 0x7FF7FFFFFFFFFFFF ));
+    return const_float64(LIT64(0x7FF7FFFFFFFFFFFF));
 #else
-const float64 float64_default_nan = const_float64(LIT64( 0xFFF8000000000000 ));
+    return const_float64(LIT64(0xFFF8000000000000));
 #endif
+}
 
 /*----------------------------------------------------------------------------
 | The pattern for a default generated extended double-precision NaN.
 *----------------------------------------------------------------------------*/
+inline floatx80 floatx80_default_nan(void)
+{
 #if SNAN_BIT_IS_ONE
-#define floatx80_default_nan_high 0x7FFF
-#define floatx80_default_nan_low  LIT64( 0xBFFFFFFFFFFFFFFF )
+    return make_floatx80(0x7FFF, LIT64(0xBFFFFFFFFFFFFFFF));
 #else
-#define floatx80_default_nan_high 0xFFFF
-#define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
+    return make_floatx80(0xFFFF, LIT64(0xC000000000000000));
 #endif
-
-const floatx80 floatx80_default_nan
-    = make_floatx80_init(floatx80_default_nan_high, floatx80_default_nan_low);
+}
 
 /*----------------------------------------------------------------------------
 | The pattern for a default generated quadruple-precision NaN.  The `high' and
 | `low' values hold the most- and least-significant bits, respectively.
 *----------------------------------------------------------------------------*/
+inline float128 float128_default_nan(void)
+{
 #if SNAN_BIT_IS_ONE
-#define float128_default_nan_high LIT64( 0x7FFF7FFFFFFFFFFF )
-#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
+    return make_float128(LIT64(0x7FFF7FFFFFFFFFFF), LIT64(0xFFFFFFFFFFFFFFFF));
 #else
-#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
-#define float128_default_nan_low  LIT64( 0x0000000000000000 )
+    return make_float128(LIT64(0xFFFF800000000000), LIT64(0x0000000000000000));
 #endif
-
-const float128 float128_default_nan
-    = make_float128_init(float128_default_nan_high, float128_default_nan_low);
+}
 
 /*----------------------------------------------------------------------------
 | Raises the exceptions specified by `flags'.  Floating-point traps can be
@@ -186,7 +191,7 @@ float16 float16_maybe_silence_nan(float1
     if (float16_is_signaling_nan(a_)) {
 #if SNAN_BIT_IS_ONE
 #  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-        return float16_default_nan;
+        return float16_default_nan();
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
 #  endif
@@ -226,14 +231,14 @@ static float16 commonNaNToFloat16(common
     uint16_t mantissa = a.high>>54;
 
     if (STATUS(default_nan_mode)) {
-        return float16_default_nan;
+        return float16_default_nan();
     }
 
     if (mantissa) {
         return make_float16(((((uint16_t) a.sign) << 15)
                              | (0x1F << 10) | mantissa));
     } else {
-        return float16_default_nan;
+        return float16_default_nan();
     }
 }
 
@@ -289,7 +294,7 @@ float32 float32_maybe_silence_nan( float
     if (float32_is_signaling_nan(a_)) {
 #if SNAN_BIT_IS_ONE
 #  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-        return float32_default_nan;
+        return float32_default_nan();
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
 #  endif
@@ -329,14 +334,14 @@ static float32 commonNaNToFloat32( commo
     uint32_t mantissa = a.high>>41;
 
     if ( STATUS(default_nan_mode) ) {
-        return float32_default_nan;
+        return float32_default_nan();
     }
 
     if ( mantissa )
         return make_float32(
             ( ( (uint32_t) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
     else
-        return float32_default_nan;
+        return float32_default_nan();
 }
 
 /*----------------------------------------------------------------------------
@@ -576,7 +581,7 @@ static float32 propagateFloat32NaN( floa
     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
 
     if ( STATUS(default_nan_mode) )
-        return float32_default_nan;
+        return float32_default_nan();
 
     if ((uint32_t)(av<<1) < (uint32_t)(bv<<1)) {
         aIsLargerSignificand = 0;
@@ -629,7 +634,7 @@ static float32 propagateFloat32MulAddNaN
         /* Note that this check is after pickNaNMulAdd so that function
          * has an opportunity to set the Invalid flag.
          */
-        return float32_default_nan;
+        return float32_default_nan();
     }
 
     switch (which) {
@@ -641,7 +646,7 @@ static float32 propagateFloat32MulAddNaN
         return float32_maybe_silence_nan(c);
     case 3:
     default:
-        return float32_default_nan;
+        return float32_default_nan();
     }
 }
 
@@ -701,7 +706,7 @@ float64 float64_maybe_silence_nan( float
     if (float64_is_signaling_nan(a_)) {
 #if SNAN_BIT_IS_ONE
 #  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-        return float64_default_nan;
+        return float64_default_nan();
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
 #  endif
@@ -741,7 +746,7 @@ static float64 commonNaNToFloat64( commo
     uint64_t mantissa = a.high>>12;
 
     if ( STATUS(default_nan_mode) ) {
-        return float64_default_nan;
+        return float64_default_nan();
     }
 
     if ( mantissa )
@@ -750,7 +755,7 @@ static float64 commonNaNToFloat64( commo
             | LIT64( 0x7FF0000000000000 )
             | ( a.high>>12 ));
     else
-        return float64_default_nan;
+        return float64_default_nan();
 }
 
 /*----------------------------------------------------------------------------
@@ -775,7 +780,7 @@ static float64 propagateFloat64NaN( floa
     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
 
     if ( STATUS(default_nan_mode) )
-        return float64_default_nan;
+        return float64_default_nan();
 
     if ((uint64_t)(av<<1) < (uint64_t)(bv<<1)) {
         aIsLargerSignificand = 0;
@@ -828,7 +833,7 @@ static float64 propagateFloat64MulAddNaN
         /* Note that this check is after pickNaNMulAdd so that function
          * has an opportunity to set the Invalid flag.
          */
-        return float64_default_nan;
+        return float64_default_nan();
     }
 
     switch (which) {
@@ -840,7 +845,7 @@ static float64 propagateFloat64MulAddNaN
         return float64_maybe_silence_nan(c);
     case 3:
     default:
-        return float64_default_nan;
+        return float64_default_nan();
     }
 }
 
@@ -910,8 +915,7 @@ floatx80 floatx80_maybe_silence_nan( flo
     if (floatx80_is_signaling_nan(a)) {
 #if SNAN_BIT_IS_ONE
 #  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-        a.low = floatx80_default_nan_low;
-        a.high = floatx80_default_nan_high;
+        a = floatx80_default_nan();
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
 #  endif
@@ -936,8 +940,7 @@ static commonNaNT floatx80ToCommonNaN( f
     if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
     /* Replace a Pseudo NaN with a default NaN.  */
     if (!(a.low >> 63)) {
-        a.low = floatx80_default_nan_low;
-        a.high = floatx80_default_nan_high;
+        a = floatx80_default_nan();
     }
     z.sign = a.high >> 15;
     z.low = 0;
@@ -955,17 +958,14 @@ static floatx80 commonNaNToFloatx80( com
     floatx80 z;
 
     if ( STATUS(default_nan_mode) ) {
-        z.low = floatx80_default_nan_low;
-        z.high = floatx80_default_nan_high;
-        return z;
+        return floatx80_default_nan();
     }
 
     if (a.high >> 1) {
         z.low = LIT64( 0x8000000000000000 ) | a.high >> 1;
         z.high = ( ( (uint16_t) a.sign )<<15 ) | 0x7FFF;
     } else {
-        z.low = floatx80_default_nan_low;
-        z.high = floatx80_default_nan_high;
+        z = floatx80_default_nan();
     }
 
     return z;
@@ -990,9 +990,7 @@ static floatx80 propagateFloatx80NaN( fl
     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
 
     if ( STATUS(default_nan_mode) ) {
-        a.low = floatx80_default_nan_low;
-        a.high = floatx80_default_nan_high;
-        return a;
+        return floatx80_default_nan();
     }
 
     if (a.low < b.low) {
@@ -1069,8 +1067,7 @@ float128 float128_maybe_silence_nan( flo
     if (float128_is_signaling_nan(a)) {
 #if SNAN_BIT_IS_ONE
 #  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-        a.low = float128_default_nan_low;
-        a.high = float128_default_nan_high;
+        a = float128_default_nan();
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
 #  endif
@@ -1108,9 +1105,7 @@ static float128 commonNaNToFloat128( com
     float128 z;
 
     if ( STATUS(default_nan_mode) ) {
-        z.low = float128_default_nan_low;
-        z.high = float128_default_nan_high;
-        return z;
+        return float128_default_nan();
     }
 
     shift128Right( a.high, a.low, 16, &z.high, &z.low );
@@ -1137,9 +1132,7 @@ static float128 propagateFloat128NaN( fl
     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
 
     if ( STATUS(default_nan_mode) ) {
-        a.low = float128_default_nan_low;
-        a.high = float128_default_nan_high;
-        return a;
+        return float128_default_nan();
     }
 
     if (lt128(a.high<<1, a.low, b.high<<1, b.low)) {
Index: qemu-git-trunk/fpu/softfloat.c
===================================================================
--- qemu-git-trunk.orig/fpu/softfloat.c	2014-12-02 00:13:11.308044826 +0000
+++ qemu-git-trunk/fpu/softfloat.c	2014-12-02 00:13:14.309029586 +0000
@@ -1979,7 +1979,7 @@ static float32 subFloat32Sigs( float32 a
     if ( aExp == 0xFF ) {
         if ( aSig | bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
         float_raise( float_flag_invalid STATUS_VAR);
-        return float32_default_nan;
+        return float32_default_nan();
     }
     if ( aExp == 0 ) {
         aExp = 1;
@@ -2104,7 +2104,7 @@ float32 float32_mul( float32 a, float32 
         }
         if ( ( bExp | bSig ) == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float32_default_nan;
+            return float32_default_nan();
         }
         return packFloat32( zSign, 0xFF, 0 );
     }
@@ -2112,7 +2112,7 @@ float32 float32_mul( float32 a, float32 
         if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
         if ( ( aExp | aSig ) == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float32_default_nan;
+            return float32_default_nan();
         }
         return packFloat32( zSign, 0xFF, 0 );
     }
@@ -2163,7 +2163,7 @@ float32 float32_div( float32 a, float32 
         if ( bExp == 0xFF ) {
             if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
             float_raise( float_flag_invalid STATUS_VAR);
-            return float32_default_nan;
+            return float32_default_nan();
         }
         return packFloat32( zSign, 0xFF, 0 );
     }
@@ -2175,7 +2175,7 @@ float32 float32_div( float32 a, float32 
         if ( bSig == 0 ) {
             if ( ( aExp | aSig ) == 0 ) {
                 float_raise( float_flag_invalid STATUS_VAR);
-                return float32_default_nan;
+                return float32_default_nan();
             }
             float_raise( float_flag_divbyzero STATUS_VAR);
             return packFloat32( zSign, 0xFF, 0 );
@@ -2229,7 +2229,7 @@ float32 float32_rem( float32 a, float32 
             return propagateFloat32NaN( a, b STATUS_VAR );
         }
         float_raise( float_flag_invalid STATUS_VAR);
-        return float32_default_nan;
+        return float32_default_nan();
     }
     if ( bExp == 0xFF ) {
         if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
@@ -2238,7 +2238,7 @@ float32 float32_rem( float32 a, float32 
     if ( bExp == 0 ) {
         if ( bSig == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float32_default_nan;
+            return float32_default_nan();
         }
         normalizeFloat32Subnormal( bSig, &bExp, &bSig );
     }
@@ -2353,7 +2353,7 @@ float32 float32_muladd(float32 a, float3
 
     if (infzero) {
         float_raise(float_flag_invalid STATUS_VAR);
-        return float32_default_nan;
+        return float32_default_nan();
     }
 
     if (flags & float_muladd_negate_c) {
@@ -2374,7 +2374,7 @@ float32 float32_muladd(float32 a, float3
         if (pInf && (pSign ^ cSign)) {
             /* addition of opposite-signed infinities => InvalidOperation */
             float_raise(float_flag_invalid STATUS_VAR);
-            return float32_default_nan;
+            return float32_default_nan();
         }
         /* Otherwise generate an infinity of the same sign */
         return packFloat32(cSign ^ signflip, 0xff, 0);
@@ -2548,12 +2548,12 @@ float32 float32_sqrt( float32 a STATUS_P
         if ( aSig ) return propagateFloat32NaN( a, float32_zero STATUS_VAR );
         if ( ! aSign ) return a;
         float_raise( float_flag_invalid STATUS_VAR);
-        return float32_default_nan;
+        return float32_default_nan();
     }
     if ( aSign ) {
         if ( ( aExp | aSig ) == 0 ) return a;
         float_raise( float_flag_invalid STATUS_VAR);
-        return float32_default_nan;
+        return float32_default_nan();
     }
     if ( aExp == 0 ) {
         if ( aSig == 0 ) return float32_zero;
@@ -2684,7 +2684,7 @@ float32 float32_log2( float32 a STATUS_P
     }
     if ( aSign ) {
         float_raise( float_flag_invalid STATUS_VAR);
-        return float32_default_nan;
+        return float32_default_nan();
     }
     if ( aExp == 0xFF ) {
         if ( aSig ) return propagateFloat32NaN( a, float32_zero STATUS_VAR );
@@ -3740,7 +3740,7 @@ static float64 subFloat64Sigs( float64 a
     if ( aExp == 0x7FF ) {
         if ( aSig | bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
         float_raise( float_flag_invalid STATUS_VAR);
-        return float64_default_nan;
+        return float64_default_nan();
     }
     if ( aExp == 0 ) {
         aExp = 1;
@@ -3863,7 +3863,7 @@ float64 float64_mul( float64 a, float64 
         }
         if ( ( bExp | bSig ) == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float64_default_nan;
+            return float64_default_nan();
         }
         return packFloat64( zSign, 0x7FF, 0 );
     }
@@ -3871,7 +3871,7 @@ float64 float64_mul( float64 a, float64 
         if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
         if ( ( aExp | aSig ) == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float64_default_nan;
+            return float64_default_nan();
         }
         return packFloat64( zSign, 0x7FF, 0 );
     }
@@ -3924,7 +3924,7 @@ float64 float64_div( float64 a, float64 
         if ( bExp == 0x7FF ) {
             if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
             float_raise( float_flag_invalid STATUS_VAR);
-            return float64_default_nan;
+            return float64_default_nan();
         }
         return packFloat64( zSign, 0x7FF, 0 );
     }
@@ -3936,7 +3936,7 @@ float64 float64_div( float64 a, float64 
         if ( bSig == 0 ) {
             if ( ( aExp | aSig ) == 0 ) {
                 float_raise( float_flag_invalid STATUS_VAR);
-                return float64_default_nan;
+                return float64_default_nan();
             }
             float_raise( float_flag_divbyzero STATUS_VAR);
             return packFloat64( zSign, 0x7FF, 0 );
@@ -3994,7 +3994,7 @@ float64 float64_rem( float64 a, float64 
             return propagateFloat64NaN( a, b STATUS_VAR );
         }
         float_raise( float_flag_invalid STATUS_VAR);
-        return float64_default_nan;
+        return float64_default_nan();
     }
     if ( bExp == 0x7FF ) {
         if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
@@ -4003,7 +4003,7 @@ float64 float64_rem( float64 a, float64 
     if ( bExp == 0 ) {
         if ( bSig == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float64_default_nan;
+            return float64_default_nan();
         }
         normalizeFloat64Subnormal( bSig, &bExp, &bSig );
     }
@@ -4104,7 +4104,7 @@ float64 float64_muladd(float64 a, float6
 
     if (infzero) {
         float_raise(float_flag_invalid STATUS_VAR);
-        return float64_default_nan;
+        return float64_default_nan();
     }
 
     if (flags & float_muladd_negate_c) {
@@ -4125,7 +4125,7 @@ float64 float64_muladd(float64 a, float6
         if (pInf && (pSign ^ cSign)) {
             /* addition of opposite-signed infinities => InvalidOperation */
             float_raise(float_flag_invalid STATUS_VAR);
-            return float64_default_nan;
+            return float64_default_nan();
         }
         /* Otherwise generate an infinity of the same sign */
         return packFloat64(cSign ^ signflip, 0x7ff, 0);
@@ -4321,12 +4321,12 @@ float64 float64_sqrt( float64 a STATUS_P
         if ( aSig ) return propagateFloat64NaN( a, a STATUS_VAR );
         if ( ! aSign ) return a;
         float_raise( float_flag_invalid STATUS_VAR);
-        return float64_default_nan;
+        return float64_default_nan();
     }
     if ( aSign ) {
         if ( ( aExp | aSig ) == 0 ) return a;
         float_raise( float_flag_invalid STATUS_VAR);
-        return float64_default_nan;
+        return float64_default_nan();
     }
     if ( aExp == 0 ) {
         if ( aSig == 0 ) return float64_zero;
@@ -4374,7 +4374,7 @@ float64 float64_log2( float64 a STATUS_P
     }
     if ( aSign ) {
         float_raise( float_flag_invalid STATUS_VAR);
-        return float64_default_nan;
+        return float64_default_nan();
     }
     if ( aExp == 0x7FF ) {
         if ( aSig ) return propagateFloat64NaN( a, float64_zero STATUS_VAR );
@@ -5027,7 +5027,6 @@ static floatx80 subFloatx80Sigs( floatx8
     int32 aExp, bExp, zExp;
     uint64_t aSig, bSig, zSig0, zSig1;
     int32 expDiff;
-    floatx80 z;
 
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
@@ -5041,9 +5040,7 @@ static floatx80 subFloatx80Sigs( floatx8
             return propagateFloatx80NaN( a, b STATUS_VAR );
         }
         float_raise( float_flag_invalid STATUS_VAR);
-        z.low = floatx80_default_nan_low;
-        z.high = floatx80_default_nan_high;
-        return z;
+        return floatx80_default_nan();
     }
     if ( aExp == 0 ) {
         aExp = 1;
@@ -5135,7 +5132,6 @@ floatx80 floatx80_mul( floatx80 a, float
     flag aSign, bSign, zSign;
     int32 aExp, bExp, zExp;
     uint64_t aSig, bSig, zSig0, zSig1;
-    floatx80 z;
 
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
@@ -5157,9 +5153,7 @@ floatx80 floatx80_mul( floatx80 a, float
         if ( ( aExp | aSig ) == 0 ) {
  invalid:
             float_raise( float_flag_invalid STATUS_VAR);
-            z.low = floatx80_default_nan_low;
-            z.high = floatx80_default_nan_high;
-            return z;
+            return floatx80_default_nan();
         }
         return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
     }
@@ -5195,7 +5189,6 @@ floatx80 floatx80_div( floatx80 a, float
     int32 aExp, bExp, zExp;
     uint64_t aSig, bSig, zSig0, zSig1;
     uint64_t rem0, rem1, rem2, term0, term1, term2;
-    floatx80 z;
 
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
@@ -5221,9 +5214,7 @@ floatx80 floatx80_div( floatx80 a, float
             if ( ( aExp | aSig ) == 0 ) {
  invalid:
                 float_raise( float_flag_invalid STATUS_VAR);
-                z.low = floatx80_default_nan_low;
-                z.high = floatx80_default_nan_high;
-                return z;
+                return floatx80_default_nan();
             }
             float_raise( float_flag_divbyzero STATUS_VAR);
             return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
@@ -5275,7 +5266,6 @@ floatx80 floatx80_rem( floatx80 a, float
     int32 aExp, bExp, expDiff;
     uint64_t aSig0, aSig1, bSig;
     uint64_t q, term0, term1, alternateASig0, alternateASig1;
-    floatx80 z;
 
     aSig0 = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
@@ -5297,9 +5287,7 @@ floatx80 floatx80_rem( floatx80 a, float
         if ( bSig == 0 ) {
  invalid:
             float_raise( float_flag_invalid STATUS_VAR);
-            z.low = floatx80_default_nan_low;
-            z.high = floatx80_default_nan_high;
-            return z;
+            return floatx80_default_nan();
         }
         normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
     }
@@ -5371,7 +5359,6 @@ floatx80 floatx80_sqrt( floatx80 a STATU
     int32 aExp, zExp;
     uint64_t aSig0, aSig1, zSig0, zSig1, doubleZSig0;
     uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
-    floatx80 z;
 
     aSig0 = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
@@ -5385,9 +5372,7 @@ floatx80 floatx80_sqrt( floatx80 a STATU
         if ( ( aExp | aSig0 ) == 0 ) return a;
  invalid:
         float_raise( float_flag_invalid STATUS_VAR);
-        z.low = floatx80_default_nan_low;
-        z.high = floatx80_default_nan_high;
-        return z;
+        return floatx80_default_nan();
     }
     if ( aExp == 0 ) {
         if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 );
@@ -6193,7 +6178,6 @@ static float128 subFloat128Sigs( float12
     int32 aExp, bExp, zExp;
     uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1;
     int32 expDiff;
-    float128 z;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
@@ -6211,9 +6195,7 @@ static float128 subFloat128Sigs( float12
             return propagateFloat128NaN( a, b STATUS_VAR );
         }
         float_raise( float_flag_invalid STATUS_VAR);
-        z.low = float128_default_nan_low;
-        z.high = float128_default_nan_high;
-        return z;
+        return float128_default_nan();
     }
     if ( aExp == 0 ) {
         aExp = 1;
@@ -6317,7 +6299,6 @@ float128 float128_mul( float128 a, float
     flag aSign, bSign, zSign;
     int32 aExp, bExp, zExp;
     uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3;
-    float128 z;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
@@ -6341,9 +6322,7 @@ float128 float128_mul( float128 a, float
         if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
  invalid:
             float_raise( float_flag_invalid STATUS_VAR);
-            z.low = float128_default_nan_low;
-            z.high = float128_default_nan_high;
-            return z;
+            return float128_default_nan();
         }
         return packFloat128( zSign, 0x7FFF, 0, 0 );
     }
@@ -6382,7 +6361,6 @@ float128 float128_div( float128 a, float
     int32 aExp, bExp, zExp;
     uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
     uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
-    float128 z;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
@@ -6410,9 +6388,7 @@ float128 float128_div( float128 a, float
             if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
  invalid:
                 float_raise( float_flag_invalid STATUS_VAR);
-                z.low = float128_default_nan_low;
-                z.high = float128_default_nan_high;
-                return z;
+                return float128_default_nan();
             }
             float_raise( float_flag_divbyzero STATUS_VAR);
             return packFloat128( zSign, 0x7FFF, 0, 0 );
@@ -6467,7 +6443,6 @@ float128 float128_rem( float128 a, float
     uint64_t aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2;
     uint64_t allZero, alternateASig0, alternateASig1, sigMean1;
     int64_t sigMean0;
-    float128 z;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
@@ -6491,9 +6466,7 @@ float128 float128_rem( float128 a, float
         if ( ( bSig0 | bSig1 ) == 0 ) {
  invalid:
             float_raise( float_flag_invalid STATUS_VAR);
-            z.low = float128_default_nan_low;
-            z.high = float128_default_nan_high;
-            return z;
+            return float128_default_nan();
         }
         normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
     }
@@ -6575,7 +6548,6 @@ float128 float128_sqrt( float128 a STATU
     int32 aExp, zExp;
     uint64_t aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0;
     uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
-    float128 z;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
@@ -6590,9 +6562,7 @@ float128 float128_sqrt( float128 a STATU
         if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a;
  invalid:
         float_raise( float_flag_invalid STATUS_VAR);
-        z.low = float128_default_nan_low;
-        z.high = float128_default_nan_high;
-        return z;
+        return float128_default_nan();
     }
     if ( aExp == 0 ) {
         if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 );
Index: qemu-git-trunk/include/fpu/softfloat.h
===================================================================
--- qemu-git-trunk.orig/include/fpu/softfloat.h	2014-12-02 00:12:48.308340454 +0000
+++ qemu-git-trunk/include/fpu/softfloat.h	2014-12-02 00:13:14.309029586 +0000
@@ -326,7 +326,7 @@ static inline int float16_is_any_nan(flo
 /*----------------------------------------------------------------------------
 | The pattern for a default generated half-precision NaN.
 *----------------------------------------------------------------------------*/
-extern const float16 float16_default_nan;
+__inline__ float16 float16_default_nan(void);
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE single-precision conversion routines.
@@ -438,7 +438,7 @@ static inline float32 float32_set_sign(f
 /*----------------------------------------------------------------------------
 | The pattern for a default generated single-precision NaN.
 *----------------------------------------------------------------------------*/
-extern const float32 float32_default_nan;
+__inline__ float32 float32_default_nan(void);
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE double-precision conversion routines.
@@ -550,7 +550,7 @@ static inline float64 float64_set_sign(f
 /*----------------------------------------------------------------------------
 | The pattern for a default generated double-precision NaN.
 *----------------------------------------------------------------------------*/
-extern const float64 float64_default_nan;
+__inline__ float64 float64_default_nan(void);
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE extended double-precision conversion routines.
@@ -635,7 +635,7 @@ static inline int floatx80_is_any_nan(fl
 /*----------------------------------------------------------------------------
 | The pattern for a default generated extended double-precision NaN.
 *----------------------------------------------------------------------------*/
-extern const floatx80 floatx80_default_nan;
+__inline__ floatx80 floatx80_default_nan(void);
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE quadruple-precision conversion routines.
@@ -716,6 +716,6 @@ static inline int float128_is_any_nan(fl
 /*----------------------------------------------------------------------------
 | The pattern for a default generated quadruple-precision NaN.
 *----------------------------------------------------------------------------*/
-extern const float128 float128_default_nan;
+__inline__ float128 float128_default_nan(void);
 
 #endif /* !SOFTFLOAT_H */
Index: qemu-git-trunk/target-arm/helper-a64.c
===================================================================
--- qemu-git-trunk.orig/target-arm/helper-a64.c	2014-12-02 00:12:48.308340454 +0000
+++ qemu-git-trunk/target-arm/helper-a64.c	2014-12-02 00:13:14.309029586 +0000
@@ -342,7 +342,7 @@ float32 HELPER(frecpx_f32)(float32 a, vo
             nan = float32_maybe_silence_nan(a);
         }
         if (fpst->default_nan_mode) {
-            nan = float32_default_nan;
+            nan = float32_default_nan();
         }
         return nan;
     }
@@ -371,7 +371,7 @@ float64 HELPER(frecpx_f64)(float64 a, vo
             nan = float64_maybe_silence_nan(a);
         }
         if (fpst->default_nan_mode) {
-            nan = float64_default_nan;
+            nan = float64_default_nan();
         }
         return nan;
     }
Index: qemu-git-trunk/target-arm/helper.c
===================================================================
--- qemu-git-trunk.orig/target-arm/helper.c	2014-12-02 00:12:48.308340454 +0000
+++ qemu-git-trunk/target-arm/helper.c	2014-12-02 00:13:14.309029586 +0000
@@ -5836,7 +5836,7 @@ float32 HELPER(recpe_f32)(float32 input,
             nan = float32_maybe_silence_nan(f32);
         }
         if (fpst->default_nan_mode) {
-            nan =  float32_default_nan;
+            nan = float32_default_nan();
         }
         return nan;
     } else if (float32_is_infinity(f32)) {
@@ -5890,7 +5890,7 @@ float64 HELPER(recpe_f64)(float64 input,
             nan = float64_maybe_silence_nan(f64);
         }
         if (fpst->default_nan_mode) {
-            nan =  float64_default_nan;
+            nan = float64_default_nan();
         }
         return nan;
     } else if (float64_is_infinity(f64)) {
@@ -5997,7 +5997,7 @@ float32 HELPER(rsqrte_f32)(float32 input
             nan = float32_maybe_silence_nan(f32);
         }
         if (s->default_nan_mode) {
-            nan =  float32_default_nan;
+            nan = float32_default_nan();
         }
         return nan;
     } else if (float32_is_zero(f32)) {
@@ -6005,7 +6005,7 @@ float32 HELPER(rsqrte_f32)(float32 input
         return float32_set_sign(float32_infinity, float32_is_neg(f32));
     } else if (float32_is_neg(f32)) {
         float_raise(float_flag_invalid, s);
-        return float32_default_nan;
+        return float32_default_nan();
     } else if (float32_is_infinity(f32)) {
         return float32_zero;
     }
@@ -6061,7 +6061,7 @@ float64 HELPER(rsqrte_f64)(float64 input
             nan = float64_maybe_silence_nan(f64);
         }
         if (s->default_nan_mode) {
-            nan =  float64_default_nan;
+            nan = float64_default_nan();
         }
         return nan;
     } else if (float64_is_zero(f64)) {
@@ -6069,7 +6069,7 @@ float64 HELPER(rsqrte_f64)(float64 input
         return float64_set_sign(float64_infinity, float64_is_neg(f64));
     } else if (float64_is_neg(f64)) {
         float_raise(float_flag_invalid, s);
-        return float64_default_nan;
+        return float64_default_nan();
     } else if (float64_is_infinity(f64)) {
         return float64_zero;
     }
Index: qemu-git-trunk/target-mips/msa_helper.c
===================================================================
--- qemu-git-trunk.orig/target-mips/msa_helper.c	2014-12-02 00:12:48.308340454 +0000
+++ qemu-git-trunk/target-mips/msa_helper.c	2014-12-02 00:13:14.309029586 +0000
@@ -1503,11 +1503,11 @@ MSA_UNOP_DF(pcnt)
 #define FLOAT_ONE32 make_float32(0x3f8 << 20)
 #define FLOAT_ONE64 make_float64(0x3ffULL << 52)
 
-#define FLOAT_SNAN16 (float16_default_nan ^ 0x0220)
+#define FLOAT_SNAN16 (float16_default_nan() ^ 0x0220)
         /* 0x7c20 */
-#define FLOAT_SNAN32 (float32_default_nan ^ 0x00400020)
+#define FLOAT_SNAN32 (float32_default_nan() ^ 0x00400020)
         /* 0x7f800020 */
-#define FLOAT_SNAN64 (float64_default_nan ^ 0x0008000000000020ULL)
+#define FLOAT_SNAN64 (float64_default_nan() ^ 0x0008000000000020ULL)
         /* 0x7ff0000000000020 */
 
 static inline void clear_msacsr_cause(CPUMIPSState *env)

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [Qemu-devel] [PATCH 4/7] softfloat: Add SoftFloat status parameter to `*_nan' functions
  2014-12-09  1:54 [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support Maciej W. Rozycki
                   ` (2 preceding siblings ...)
  2014-12-09  1:55 ` [Qemu-devel] [PATCH 3/7] softfloat: Convert `*_default_nan' variables into inline functions Maciej W. Rozycki
@ 2014-12-09  1:55 ` Maciej W. Rozycki
  2014-12-09  1:55 ` [Qemu-devel] [PATCH 5/7] softfloat: Rework `*_is_*_nan' functions Maciej W. Rozycki
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-12-09  1:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: Blue Swirl, Leon Alrae, Thomas Schwinge, Aurelien Jarno

Mechanically update `*_nan' functions with a SoftFloat status parameter 
where qNaNs and sNaNs need to be told apart.  Update all callers 
accordingly.

Signed-off-by: Thomas Schwinge <thomas@codesourcery.com>
Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
 BTW, this is another patch checkpatch.pl hangs on.

 Please apply.

qemu-softfloat-nan-status.diff
Index: qemu-git-trunk/fpu/softfloat-specialize.h
===================================================================
--- qemu-git-trunk.orig/fpu/softfloat-specialize.h	2014-12-08 22:36:20.000000000 +0000
+++ qemu-git-trunk/fpu/softfloat-specialize.h	2014-12-08 22:37:36.758946934 +0000
@@ -51,7 +51,7 @@ these four paragraphs for those parts of
 /*----------------------------------------------------------------------------
 | The pattern for a default generated half-precision NaN.
 *----------------------------------------------------------------------------*/
-inline float16 float16_default_nan(void)
+inline float16 float16_default_nan(STATUS_PARAM_ONLY)
 {
 #if defined(TARGET_ARM)
     return const_float16(0x7E00);
@@ -65,7 +65,7 @@ inline float16 float16_default_nan(void)
 /*----------------------------------------------------------------------------
 | The pattern for a default generated single-precision NaN.
 *----------------------------------------------------------------------------*/
-inline float32 float32_default_nan(void)
+inline float32 float32_default_nan(STATUS_PARAM_ONLY)
 {
 #if defined(TARGET_SPARC)
     return const_float32(0x7FFFFFFF);
@@ -82,7 +82,7 @@ inline float32 float32_default_nan(void)
 /*----------------------------------------------------------------------------
 | The pattern for a default generated double-precision NaN.
 *----------------------------------------------------------------------------*/
-inline float64 float64_default_nan(void)
+inline float64 float64_default_nan(STATUS_PARAM_ONLY)
 {
 #if defined(TARGET_SPARC)
     return const_float64(LIT64(0x7FFFFFFFFFFFFFFF));
@@ -98,7 +98,7 @@ inline float64 float64_default_nan(void)
 /*----------------------------------------------------------------------------
 | The pattern for a default generated extended double-precision NaN.
 *----------------------------------------------------------------------------*/
-inline floatx80 floatx80_default_nan(void)
+inline floatx80 floatx80_default_nan(STATUS_PARAM_ONLY)
 {
 #if SNAN_BIT_IS_ONE
     return make_floatx80(0x7FFF, LIT64(0xBFFFFFFFFFFFFFFF));
@@ -111,7 +111,7 @@ inline floatx80 floatx80_default_nan(voi
 | The pattern for a default generated quadruple-precision NaN.  The `high' and
 | `low' values hold the most- and least-significant bits, respectively.
 *----------------------------------------------------------------------------*/
-inline float128 float128_default_nan(void)
+inline float128 float128_default_nan(STATUS_PARAM_ONLY)
 {
 #if SNAN_BIT_IS_ONE
     return make_float128(LIT64(0x7FFF7FFFFFFFFFFF), LIT64(0xFFFFFFFFFFFFFFFF));
@@ -141,12 +141,12 @@ typedef struct {
 } commonNaNT;
 
 #ifdef NO_SIGNALING_NANS
-int float16_is_quiet_nan(float16 a_)
+int float16_is_quiet_nan(float16 a_ STATUS_PARAM)
 {
     return float16_is_any_nan(a_);
 }
 
-int float16_is_signaling_nan(float16 a_)
+int float16_is_signaling_nan(float16 a_ STATUS_PARAM)
 {
     return 0;
 }
@@ -156,7 +156,7 @@ int float16_is_signaling_nan(float16 a_)
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-int float16_is_quiet_nan(float16 a_)
+int float16_is_quiet_nan(float16 a_ STATUS_PARAM)
 {
     uint16_t a = float16_val(a_);
 #if SNAN_BIT_IS_ONE
@@ -171,7 +171,7 @@ int float16_is_quiet_nan(float16 a_)
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-int float16_is_signaling_nan(float16 a_)
+int float16_is_signaling_nan(float16 a_ STATUS_PARAM)
 {
     uint16_t a = float16_val(a_);
 #if SNAN_BIT_IS_ONE
@@ -186,12 +186,12 @@ int float16_is_signaling_nan(float16 a_)
 | Returns a quiet NaN if the half-precision floating point value `a' is a
 | signaling NaN; otherwise returns `a'.
 *----------------------------------------------------------------------------*/
-float16 float16_maybe_silence_nan(float16 a_)
+float16 float16_maybe_silence_nan(float16 a_ STATUS_PARAM)
 {
-    if (float16_is_signaling_nan(a_)) {
+    if (float16_is_signaling_nan(a_ STATUS_VAR)) {
 #if SNAN_BIT_IS_ONE
 #  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-        return float16_default_nan();
+        return float16_default_nan(status);
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
 #  endif
@@ -210,14 +210,16 @@ float16 float16_maybe_silence_nan(float1
 | exception is raised.
 *----------------------------------------------------------------------------*/
 
-static commonNaNT float16ToCommonNaN( float16 a STATUS_PARAM )
+static commonNaNT float16ToCommonNaN(float16 a STATUS_PARAM)
 {
     commonNaNT z;
 
-    if ( float16_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
+    if (float16_is_signaling_nan(a STATUS_VAR)) {
+        float_raise(float_flag_invalid STATUS_VAR);
+    }
     z.sign = float16_val(a) >> 15;
     z.low = 0;
-    z.high = ((uint64_t) float16_val(a))<<54;
+    z.high = ((uint64_t) float16_val(a)) << 54;
     return z;
 }
 
@@ -231,24 +233,24 @@ static float16 commonNaNToFloat16(common
     uint16_t mantissa = a.high>>54;
 
     if (STATUS(default_nan_mode)) {
-        return float16_default_nan();
+        return float16_default_nan(status);
     }
 
     if (mantissa) {
         return make_float16(((((uint16_t) a.sign) << 15)
                              | (0x1F << 10) | mantissa));
     } else {
-        return float16_default_nan();
+        return float16_default_nan(status);
     }
 }
 
 #ifdef NO_SIGNALING_NANS
-int float32_is_quiet_nan(float32 a_)
+int float32_is_quiet_nan(float32 a_ STATUS_PARAM)
 {
     return float32_is_any_nan(a_);
 }
 
-int float32_is_signaling_nan(float32 a_)
+int float32_is_signaling_nan(float32 a_ STATUS_PARAM)
 {
     return 0;
 }
@@ -258,7 +260,7 @@ int float32_is_signaling_nan(float32 a_)
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-int float32_is_quiet_nan( float32 a_ )
+int float32_is_quiet_nan(float32 a_ STATUS_PARAM)
 {
     uint32_t a = float32_val(a_);
 #if SNAN_BIT_IS_ONE
@@ -273,7 +275,7 @@ int float32_is_quiet_nan( float32 a_ )
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-int float32_is_signaling_nan( float32 a_ )
+int float32_is_signaling_nan(float32 a_ STATUS_PARAM)
 {
     uint32_t a = float32_val(a_);
 #if SNAN_BIT_IS_ONE
@@ -289,12 +291,12 @@ int float32_is_signaling_nan( float32 a_
 | signaling NaN; otherwise returns `a'.
 *----------------------------------------------------------------------------*/
 
-float32 float32_maybe_silence_nan( float32 a_ )
+float32 float32_maybe_silence_nan(float32 a_ STATUS_PARAM)
 {
-    if (float32_is_signaling_nan(a_)) {
+    if (float32_is_signaling_nan(a_ STATUS_VAR)) {
 #if SNAN_BIT_IS_ONE
 #  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-        return float32_default_nan();
+        return float32_default_nan(status);
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
 #  endif
@@ -313,14 +315,16 @@ float32 float32_maybe_silence_nan( float
 | exception is raised.
 *----------------------------------------------------------------------------*/
 
-static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
+static commonNaNT float32ToCommonNaN(float32 a STATUS_PARAM)
 {
     commonNaNT z;
 
-    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
-    z.sign = float32_val(a)>>31;
+    if (float32_is_signaling_nan(a STATUS_VAR)) {
+        float_raise(float_flag_invalid STATUS_VAR);
+    }
+    z.sign = float32_val(a) >> 31;
     z.low = 0;
-    z.high = ( (uint64_t) float32_val(a) )<<41;
+    z.high = ((uint64_t) float32_val(a)) << 41;
     return z;
 }
 
@@ -334,14 +338,14 @@ static float32 commonNaNToFloat32( commo
     uint32_t mantissa = a.high>>41;
 
     if ( STATUS(default_nan_mode) ) {
-        return float32_default_nan();
+        return float32_default_nan(status);
     }
 
     if ( mantissa )
         return make_float32(
             ( ( (uint32_t) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
     else
-        return float32_default_nan();
+        return float32_default_nan(status);
 }
 
 /*----------------------------------------------------------------------------
@@ -571,17 +575,17 @@ static float32 propagateFloat32NaN( floa
     flag aIsLargerSignificand;
     uint32_t av, bv;
 
-    aIsQuietNaN = float32_is_quiet_nan( a );
-    aIsSignalingNaN = float32_is_signaling_nan( a );
-    bIsQuietNaN = float32_is_quiet_nan( b );
-    bIsSignalingNaN = float32_is_signaling_nan( b );
+    aIsQuietNaN = float32_is_quiet_nan(a STATUS_VAR);
+    aIsSignalingNaN = float32_is_signaling_nan(a STATUS_VAR);
+    bIsQuietNaN = float32_is_quiet_nan(b STATUS_VAR);
+    bIsSignalingNaN = float32_is_signaling_nan(b STATUS_VAR);
     av = float32_val(a);
     bv = float32_val(b);
 
     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
 
     if ( STATUS(default_nan_mode) )
-        return float32_default_nan();
+        return float32_default_nan(status);
 
     if ((uint32_t)(av<<1) < (uint32_t)(bv<<1)) {
         aIsLargerSignificand = 0;
@@ -593,9 +597,9 @@ static float32 propagateFloat32NaN( floa
 
     if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
                 aIsLargerSignificand)) {
-        return float32_maybe_silence_nan(b);
+        return float32_maybe_silence_nan(b STATUS_VAR);
     } else {
-        return float32_maybe_silence_nan(a);
+        return float32_maybe_silence_nan(a STATUS_VAR);
     }
 }
 
@@ -615,12 +619,12 @@ static float32 propagateFloat32MulAddNaN
         cIsQuietNaN, cIsSignalingNaN;
     int which;
 
-    aIsQuietNaN = float32_is_quiet_nan(a);
-    aIsSignalingNaN = float32_is_signaling_nan(a);
-    bIsQuietNaN = float32_is_quiet_nan(b);
-    bIsSignalingNaN = float32_is_signaling_nan(b);
-    cIsQuietNaN = float32_is_quiet_nan(c);
-    cIsSignalingNaN = float32_is_signaling_nan(c);
+    aIsQuietNaN = float32_is_quiet_nan(a STATUS_VAR);
+    aIsSignalingNaN = float32_is_signaling_nan(a STATUS_VAR);
+    bIsQuietNaN = float32_is_quiet_nan(b STATUS_VAR);
+    bIsSignalingNaN = float32_is_signaling_nan(b STATUS_VAR);
+    cIsQuietNaN = float32_is_quiet_nan(c STATUS_VAR);
+    cIsSignalingNaN = float32_is_signaling_nan(c STATUS_VAR);
 
     if (aIsSignalingNaN | bIsSignalingNaN | cIsSignalingNaN) {
         float_raise(float_flag_invalid STATUS_VAR);
@@ -634,29 +638,29 @@ static float32 propagateFloat32MulAddNaN
         /* Note that this check is after pickNaNMulAdd so that function
          * has an opportunity to set the Invalid flag.
          */
-        return float32_default_nan();
+        return float32_default_nan(status);
     }
 
     switch (which) {
     case 0:
-        return float32_maybe_silence_nan(a);
+        return float32_maybe_silence_nan(a STATUS_VAR);
     case 1:
-        return float32_maybe_silence_nan(b);
+        return float32_maybe_silence_nan(b STATUS_VAR);
     case 2:
-        return float32_maybe_silence_nan(c);
+        return float32_maybe_silence_nan(c STATUS_VAR);
     case 3:
     default:
-        return float32_default_nan();
+        return float32_default_nan(status);
     }
 }
 
 #ifdef NO_SIGNALING_NANS
-int float64_is_quiet_nan(float64 a_)
+int float64_is_quiet_nan(float64 a_ STATUS_PARAM)
 {
     return float64_is_any_nan(a_);
 }
 
-int float64_is_signaling_nan(float64 a_)
+int float64_is_signaling_nan(float64 a_ STATUS_PARAM)
 {
     return 0;
 }
@@ -666,7 +670,7 @@ int float64_is_signaling_nan(float64 a_)
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-int float64_is_quiet_nan( float64 a_ )
+int float64_is_quiet_nan(float64 a_ STATUS_PARAM)
 {
     uint64_t a = float64_val(a_);
 #if SNAN_BIT_IS_ONE
@@ -683,7 +687,7 @@ int float64_is_quiet_nan( float64 a_ )
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-int float64_is_signaling_nan( float64 a_ )
+int float64_is_signaling_nan(float64 a_ STATUS_PARAM)
 {
     uint64_t a = float64_val(a_);
 #if SNAN_BIT_IS_ONE
@@ -701,12 +705,12 @@ int float64_is_signaling_nan( float64 a_
 | signaling NaN; otherwise returns `a'.
 *----------------------------------------------------------------------------*/
 
-float64 float64_maybe_silence_nan( float64 a_ )
+float64 float64_maybe_silence_nan(float64 a_ STATUS_PARAM)
 {
-    if (float64_is_signaling_nan(a_)) {
+    if (float64_is_signaling_nan(a_ STATUS_VAR)) {
 #if SNAN_BIT_IS_ONE
 #  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-        return float64_default_nan();
+        return float64_default_nan(status);
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
 #  endif
@@ -725,14 +729,16 @@ float64 float64_maybe_silence_nan( float
 | exception is raised.
 *----------------------------------------------------------------------------*/
 
-static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
+static commonNaNT float64ToCommonNaN(float64 a STATUS_PARAM)
 {
     commonNaNT z;
 
-    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
-    z.sign = float64_val(a)>>63;
+    if (float64_is_signaling_nan(a STATUS_VAR)) {
+        float_raise(float_flag_invalid STATUS_VAR);
+    }
+    z.sign = float64_val(a) >> 63;
     z.low = 0;
-    z.high = float64_val(a)<<12;
+    z.high = float64_val(a) << 12;
     return z;
 }
 
@@ -746,7 +752,7 @@ static float64 commonNaNToFloat64( commo
     uint64_t mantissa = a.high>>12;
 
     if ( STATUS(default_nan_mode) ) {
-        return float64_default_nan();
+        return float64_default_nan(status);
     }
 
     if ( mantissa )
@@ -755,7 +761,7 @@ static float64 commonNaNToFloat64( commo
             | LIT64( 0x7FF0000000000000 )
             | ( a.high>>12 ));
     else
-        return float64_default_nan();
+        return float64_default_nan(status);
 }
 
 /*----------------------------------------------------------------------------
@@ -770,17 +776,17 @@ static float64 propagateFloat64NaN( floa
     flag aIsLargerSignificand;
     uint64_t av, bv;
 
-    aIsQuietNaN = float64_is_quiet_nan( a );
-    aIsSignalingNaN = float64_is_signaling_nan( a );
-    bIsQuietNaN = float64_is_quiet_nan( b );
-    bIsSignalingNaN = float64_is_signaling_nan( b );
+    aIsQuietNaN = float64_is_quiet_nan(a STATUS_VAR);
+    aIsSignalingNaN = float64_is_signaling_nan(a STATUS_VAR);
+    bIsQuietNaN = float64_is_quiet_nan(b STATUS_VAR);
+    bIsSignalingNaN = float64_is_signaling_nan(b STATUS_VAR);
     av = float64_val(a);
     bv = float64_val(b);
 
     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
 
     if ( STATUS(default_nan_mode) )
-        return float64_default_nan();
+        return float64_default_nan(status);
 
     if ((uint64_t)(av<<1) < (uint64_t)(bv<<1)) {
         aIsLargerSignificand = 0;
@@ -792,9 +798,9 @@ static float64 propagateFloat64NaN( floa
 
     if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
                 aIsLargerSignificand)) {
-        return float64_maybe_silence_nan(b);
+        return float64_maybe_silence_nan(b STATUS_VAR);
     } else {
-        return float64_maybe_silence_nan(a);
+        return float64_maybe_silence_nan(a STATUS_VAR);
     }
 }
 
@@ -814,12 +820,12 @@ static float64 propagateFloat64MulAddNaN
         cIsQuietNaN, cIsSignalingNaN;
     int which;
 
-    aIsQuietNaN = float64_is_quiet_nan(a);
-    aIsSignalingNaN = float64_is_signaling_nan(a);
-    bIsQuietNaN = float64_is_quiet_nan(b);
-    bIsSignalingNaN = float64_is_signaling_nan(b);
-    cIsQuietNaN = float64_is_quiet_nan(c);
-    cIsSignalingNaN = float64_is_signaling_nan(c);
+    aIsQuietNaN = float64_is_quiet_nan(a STATUS_VAR);
+    aIsSignalingNaN = float64_is_signaling_nan(a STATUS_VAR);
+    bIsQuietNaN = float64_is_quiet_nan(b STATUS_VAR);
+    bIsSignalingNaN = float64_is_signaling_nan(b STATUS_VAR);
+    cIsQuietNaN = float64_is_quiet_nan(c STATUS_VAR);
+    cIsSignalingNaN = float64_is_signaling_nan(c STATUS_VAR);
 
     if (aIsSignalingNaN | bIsSignalingNaN | cIsSignalingNaN) {
         float_raise(float_flag_invalid STATUS_VAR);
@@ -833,29 +839,29 @@ static float64 propagateFloat64MulAddNaN
         /* Note that this check is after pickNaNMulAdd so that function
          * has an opportunity to set the Invalid flag.
          */
-        return float64_default_nan();
+        return float64_default_nan(status);
     }
 
     switch (which) {
     case 0:
-        return float64_maybe_silence_nan(a);
+        return float64_maybe_silence_nan(a STATUS_VAR);
     case 1:
-        return float64_maybe_silence_nan(b);
+        return float64_maybe_silence_nan(b STATUS_VAR);
     case 2:
-        return float64_maybe_silence_nan(c);
+        return float64_maybe_silence_nan(c STATUS_VAR);
     case 3:
     default:
-        return float64_default_nan();
+        return float64_default_nan(status);
     }
 }
 
 #ifdef NO_SIGNALING_NANS
-int floatx80_is_quiet_nan(floatx80 a_)
+int floatx80_is_quiet_nan(floatx80 a_ STATUS_PARAM)
 {
     return floatx80_is_any_nan(a_);
 }
 
-int floatx80_is_signaling_nan(floatx80 a_)
+int floatx80_is_signaling_nan(floatx80 a_ STATUS_PARAM)
 {
     return 0;
 }
@@ -866,7 +872,7 @@ int floatx80_is_signaling_nan(floatx80 a
 | function for other types as floatx80 has an explicit bit.
 *----------------------------------------------------------------------------*/
 
-int floatx80_is_quiet_nan( floatx80 a )
+int floatx80_is_quiet_nan(floatx80 a STATUS_PARAM)
 {
 #if SNAN_BIT_IS_ONE
     uint64_t aLow;
@@ -888,7 +894,7 @@ int floatx80_is_quiet_nan( floatx80 a )
 | function for other types as floatx80 has an explicit bit.
 *----------------------------------------------------------------------------*/
 
-int floatx80_is_signaling_nan( floatx80 a )
+int floatx80_is_signaling_nan(floatx80 a STATUS_PARAM)
 {
 #if SNAN_BIT_IS_ONE
     return ( ( a.high & 0x7FFF ) == 0x7FFF )
@@ -910,12 +916,12 @@ int floatx80_is_signaling_nan( floatx80 
 | `a' is a signaling NaN; otherwise returns `a'.
 *----------------------------------------------------------------------------*/
 
-floatx80 floatx80_maybe_silence_nan( floatx80 a )
+floatx80 floatx80_maybe_silence_nan(floatx80 a STATUS_PARAM)
 {
-    if (floatx80_is_signaling_nan(a)) {
+    if (floatx80_is_signaling_nan(a STATUS_VAR)) {
 #if SNAN_BIT_IS_ONE
 #  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-        a = floatx80_default_nan();
+        a = floatx80_default_nan(status);
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
 #  endif
@@ -933,14 +939,16 @@ floatx80 floatx80_maybe_silence_nan( flo
 | invalid exception is raised.
 *----------------------------------------------------------------------------*/
 
-static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
+static commonNaNT floatx80ToCommonNaN(floatx80 a STATUS_PARAM)
 {
     commonNaNT z;
 
-    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
+    if (floatx80_is_signaling_nan(a STATUS_VAR)) {
+        float_raise(float_flag_invalid STATUS_VAR);
+    }
     /* Replace a Pseudo NaN with a default NaN.  */
     if (!(a.low >> 63)) {
-        a = floatx80_default_nan();
+        a = floatx80_default_nan(status);
     }
     z.sign = a.high >> 15;
     z.low = 0;
@@ -958,14 +966,14 @@ static floatx80 commonNaNToFloatx80( com
     floatx80 z;
 
     if ( STATUS(default_nan_mode) ) {
-        return floatx80_default_nan();
+        return floatx80_default_nan(status);
     }
 
     if (a.high >> 1) {
         z.low = LIT64( 0x8000000000000000 ) | a.high >> 1;
         z.high = ( ( (uint16_t) a.sign )<<15 ) | 0x7FFF;
     } else {
-        z = floatx80_default_nan();
+        z = floatx80_default_nan(status);
     }
 
     return z;
@@ -982,15 +990,15 @@ static floatx80 propagateFloatx80NaN( fl
     flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
     flag aIsLargerSignificand;
 
-    aIsQuietNaN = floatx80_is_quiet_nan( a );
-    aIsSignalingNaN = floatx80_is_signaling_nan( a );
-    bIsQuietNaN = floatx80_is_quiet_nan( b );
-    bIsSignalingNaN = floatx80_is_signaling_nan( b );
+    aIsQuietNaN = floatx80_is_quiet_nan(a STATUS_VAR);
+    aIsSignalingNaN = floatx80_is_signaling_nan(a STATUS_VAR);
+    bIsQuietNaN = floatx80_is_quiet_nan(b STATUS_VAR);
+    bIsSignalingNaN = floatx80_is_signaling_nan(b STATUS_VAR);
 
     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
 
     if ( STATUS(default_nan_mode) ) {
-        return floatx80_default_nan();
+        return floatx80_default_nan(status);
     }
 
     if (a.low < b.low) {
@@ -1003,19 +1011,19 @@ static floatx80 propagateFloatx80NaN( fl
 
     if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
                 aIsLargerSignificand)) {
-        return floatx80_maybe_silence_nan(b);
+        return floatx80_maybe_silence_nan(b STATUS_VAR);
     } else {
-        return floatx80_maybe_silence_nan(a);
+        return floatx80_maybe_silence_nan(a STATUS_VAR);
     }
 }
 
 #ifdef NO_SIGNALING_NANS
-int float128_is_quiet_nan(float128 a_)
+int float128_is_quiet_nan(float128 a_ STATUS_PARAM)
 {
     return float128_is_any_nan(a_);
 }
 
-int float128_is_signaling_nan(float128 a_)
+int float128_is_signaling_nan(float128 a_ STATUS_PARAM)
 {
     return 0;
 }
@@ -1025,7 +1033,7 @@ int float128_is_signaling_nan(float128 a
 | NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-int float128_is_quiet_nan( float128 a )
+int float128_is_quiet_nan(float128 a STATUS_PARAM)
 {
 #if SNAN_BIT_IS_ONE
     return
@@ -1043,7 +1051,7 @@ int float128_is_quiet_nan( float128 a )
 | signaling NaN; otherwise returns 0.
 *----------------------------------------------------------------------------*/
 
-int float128_is_signaling_nan( float128 a )
+int float128_is_signaling_nan(float128 a STATUS_PARAM)
 {
 #if SNAN_BIT_IS_ONE
     return
@@ -1062,12 +1070,12 @@ int float128_is_signaling_nan( float128 
 | a signaling NaN; otherwise returns `a'.
 *----------------------------------------------------------------------------*/
 
-float128 float128_maybe_silence_nan( float128 a )
+float128 float128_maybe_silence_nan(float128 a STATUS_PARAM)
 {
-    if (float128_is_signaling_nan(a)) {
+    if (float128_is_signaling_nan(a STATUS_VAR)) {
 #if SNAN_BIT_IS_ONE
 #  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-        a = float128_default_nan();
+        a = float128_default_nan(status);
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
 #  endif
@@ -1085,13 +1093,15 @@ float128 float128_maybe_silence_nan( flo
 | exception is raised.
 *----------------------------------------------------------------------------*/
 
-static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
+static commonNaNT float128ToCommonNaN(float128 a STATUS_PARAM)
 {
     commonNaNT z;
 
-    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
-    z.sign = a.high>>63;
-    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
+    if (float128_is_signaling_nan(a STATUS_VAR)) {
+        float_raise(float_flag_invalid STATUS_VAR);
+    }
+    z.sign = a.high >> 63;
+    shortShift128Left(a.high, a.low, 16, &z.high, &z.low);
     return z;
 }
 
@@ -1105,7 +1115,7 @@ static float128 commonNaNToFloat128( com
     float128 z;
 
     if ( STATUS(default_nan_mode) ) {
-        return float128_default_nan();
+        return float128_default_nan(status);
     }
 
     shift128Right( a.high, a.low, 16, &z.high, &z.low );
@@ -1124,15 +1134,15 @@ static float128 propagateFloat128NaN( fl
     flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
     flag aIsLargerSignificand;
 
-    aIsQuietNaN = float128_is_quiet_nan( a );
-    aIsSignalingNaN = float128_is_signaling_nan( a );
-    bIsQuietNaN = float128_is_quiet_nan( b );
-    bIsSignalingNaN = float128_is_signaling_nan( b );
+    aIsQuietNaN = float128_is_quiet_nan(a STATUS_VAR);
+    aIsSignalingNaN = float128_is_signaling_nan(a STATUS_VAR);
+    bIsQuietNaN = float128_is_quiet_nan(b STATUS_VAR);
+    bIsSignalingNaN = float128_is_signaling_nan(b STATUS_VAR);
 
     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
 
     if ( STATUS(default_nan_mode) ) {
-        return float128_default_nan();
+        return float128_default_nan(status);
     }
 
     if (lt128(a.high<<1, a.low, b.high<<1, b.low)) {
@@ -1145,9 +1155,9 @@ static float128 propagateFloat128NaN( fl
 
     if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
                 aIsLargerSignificand)) {
-        return float128_maybe_silence_nan(b);
+        return float128_maybe_silence_nan(b STATUS_VAR);
     } else {
-        return float128_maybe_silence_nan(a);
+        return float128_maybe_silence_nan(a STATUS_VAR);
     }
 }
 
Index: qemu-git-trunk/fpu/softfloat.c
===================================================================
--- qemu-git-trunk.orig/fpu/softfloat.c	2014-12-08 22:36:20.000000000 +0000
+++ qemu-git-trunk/fpu/softfloat.c	2014-12-08 22:37:36.758946934 +0000
@@ -1714,7 +1714,8 @@ float64 float32_to_float64( float32 a ST
         if (aSig) {
             return float64_maybe_silence_nan(
                 commonNaNToFloat64(float32ToCommonNaN(a STATUS_VAR)
-                                   STATUS_VAR));
+                                   STATUS_VAR)
+                STATUS_VAR);
         }
         return packFloat64( aSign, 0x7FF, 0 );
     }
@@ -1748,7 +1749,8 @@ floatx80 float32_to_floatx80( float32 a 
         if (aSig) {
             return floatx80_maybe_silence_nan(
                 commonNaNToFloatx80(float32ToCommonNaN(a STATUS_VAR)
-                                    STATUS_VAR));
+                                    STATUS_VAR)
+                STATUS_VAR);
         }
         return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
     }
@@ -1782,7 +1784,8 @@ float128 float32_to_float128( float32 a 
         if (aSig) {
             return float128_maybe_silence_nan(
                 commonNaNToFloat128(float32ToCommonNaN(a STATUS_VAR)
-                                    STATUS_VAR));
+                                    STATUS_VAR)
+                STATUS_VAR);
         }
         return packFloat128( aSign, 0x7FFF, 0, 0 );
     }
@@ -1979,7 +1982,7 @@ static float32 subFloat32Sigs( float32 a
     if ( aExp == 0xFF ) {
         if ( aSig | bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
         float_raise( float_flag_invalid STATUS_VAR);
-        return float32_default_nan();
+        return float32_default_nan(status);
     }
     if ( aExp == 0 ) {
         aExp = 1;
@@ -2104,7 +2107,7 @@ float32 float32_mul( float32 a, float32 
         }
         if ( ( bExp | bSig ) == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float32_default_nan();
+            return float32_default_nan(status);
         }
         return packFloat32( zSign, 0xFF, 0 );
     }
@@ -2112,7 +2115,7 @@ float32 float32_mul( float32 a, float32 
         if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
         if ( ( aExp | aSig ) == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float32_default_nan();
+            return float32_default_nan(status);
         }
         return packFloat32( zSign, 0xFF, 0 );
     }
@@ -2163,7 +2166,7 @@ float32 float32_div( float32 a, float32 
         if ( bExp == 0xFF ) {
             if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
             float_raise( float_flag_invalid STATUS_VAR);
-            return float32_default_nan();
+            return float32_default_nan(status);
         }
         return packFloat32( zSign, 0xFF, 0 );
     }
@@ -2175,7 +2178,7 @@ float32 float32_div( float32 a, float32 
         if ( bSig == 0 ) {
             if ( ( aExp | aSig ) == 0 ) {
                 float_raise( float_flag_invalid STATUS_VAR);
-                return float32_default_nan();
+                return float32_default_nan(status);
             }
             float_raise( float_flag_divbyzero STATUS_VAR);
             return packFloat32( zSign, 0xFF, 0 );
@@ -2229,7 +2232,7 @@ float32 float32_rem( float32 a, float32 
             return propagateFloat32NaN( a, b STATUS_VAR );
         }
         float_raise( float_flag_invalid STATUS_VAR);
-        return float32_default_nan();
+        return float32_default_nan(status);
     }
     if ( bExp == 0xFF ) {
         if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
@@ -2238,7 +2241,7 @@ float32 float32_rem( float32 a, float32 
     if ( bExp == 0 ) {
         if ( bSig == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float32_default_nan();
+            return float32_default_nan(status);
         }
         normalizeFloat32Subnormal( bSig, &bExp, &bSig );
     }
@@ -2353,7 +2356,7 @@ float32 float32_muladd(float32 a, float3
 
     if (infzero) {
         float_raise(float_flag_invalid STATUS_VAR);
-        return float32_default_nan();
+        return float32_default_nan(status);
     }
 
     if (flags & float_muladd_negate_c) {
@@ -2374,7 +2377,7 @@ float32 float32_muladd(float32 a, float3
         if (pInf && (pSign ^ cSign)) {
             /* addition of opposite-signed infinities => InvalidOperation */
             float_raise(float_flag_invalid STATUS_VAR);
-            return float32_default_nan();
+            return float32_default_nan(status);
         }
         /* Otherwise generate an infinity of the same sign */
         return packFloat32(cSign ^ signflip, 0xff, 0);
@@ -2548,12 +2551,12 @@ float32 float32_sqrt( float32 a STATUS_P
         if ( aSig ) return propagateFloat32NaN( a, float32_zero STATUS_VAR );
         if ( ! aSign ) return a;
         float_raise( float_flag_invalid STATUS_VAR);
-        return float32_default_nan();
+        return float32_default_nan(status);
     }
     if ( aSign ) {
         if ( ( aExp | aSig ) == 0 ) return a;
         float_raise( float_flag_invalid STATUS_VAR);
-        return float32_default_nan();
+        return float32_default_nan(status);
     }
     if ( aExp == 0 ) {
         if ( aSig == 0 ) return float32_zero;
@@ -2684,7 +2687,7 @@ float32 float32_log2( float32 a STATUS_P
     }
     if ( aSign ) {
         float_raise( float_flag_invalid STATUS_VAR);
-        return float32_default_nan();
+        return float32_default_nan(status);
     }
     if ( aExp == 0xFF ) {
         if ( aSig ) return propagateFloat32NaN( a, float32_zero STATUS_VAR );
@@ -2828,8 +2831,9 @@ int float32_eq_quiet( float32 a, float32
     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
        ) {
-        if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+        if (float32_is_signaling_nan(a STATUS_VAR) ||
+            float32_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return 0;
     }
@@ -2854,8 +2858,9 @@ int float32_le_quiet( float32 a, float32
     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
        ) {
-        if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+        if (float32_is_signaling_nan(a STATUS_VAR) ||
+            float32_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return 0;
     }
@@ -2885,8 +2890,9 @@ int float32_lt_quiet( float32 a, float32
     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
        ) {
-        if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+        if (float32_is_signaling_nan(a STATUS_VAR) ||
+            float32_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return 0;
     }
@@ -2914,8 +2920,9 @@ int float32_unordered_quiet( float32 a, 
     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
        ) {
-        if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+        if (float32_is_signaling_nan(a STATUS_VAR) ||
+            float32_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return 1;
     }
@@ -3166,7 +3173,8 @@ float32 float64_to_float32( float64 a ST
         if (aSig) {
             return float32_maybe_silence_nan(
                 commonNaNToFloat32(float64ToCommonNaN(a STATUS_VAR)
-                                   STATUS_VAR));
+                                   STATUS_VAR)
+                STATUS_VAR);
         }
         return packFloat32( aSign, 0xFF, 0 );
     }
@@ -3336,7 +3344,8 @@ float32 float16_to_float32(float16 a, fl
         if (aSig) {
             return float32_maybe_silence_nan(
                 commonNaNToFloat32(float16ToCommonNaN(a STATUS_VAR)
-                                   STATUS_VAR));
+                                   STATUS_VAR)
+                STATUS_VAR);
         }
         return packFloat32(aSign, 0xff, 0);
     }
@@ -3371,7 +3380,8 @@ float16 float32_to_float16(float32 a, fl
             }
             return float16_maybe_silence_nan(
                 commonNaNToFloat16(float32ToCommonNaN(a STATUS_VAR)
-                                   STATUS_VAR));
+                                   STATUS_VAR)
+                STATUS_VAR);
         }
         /* Infinity */
         if (!ieee) {
@@ -3410,7 +3420,8 @@ float64 float16_to_float64(float16 a, fl
         if (aSig) {
             return float64_maybe_silence_nan(
                 commonNaNToFloat64(float16ToCommonNaN(a STATUS_VAR)
-                                   STATUS_VAR));
+                                   STATUS_VAR)
+                STATUS_VAR);
         }
         return packFloat64(aSign, 0x7ff, 0);
     }
@@ -3446,7 +3457,8 @@ float16 float64_to_float16(float64 a, fl
             }
             return float16_maybe_silence_nan(
                 commonNaNToFloat16(float64ToCommonNaN(a STATUS_VAR)
-                                   STATUS_VAR));
+                                   STATUS_VAR)
+                STATUS_VAR);
         }
         /* Infinity */
         if (!ieee) {
@@ -3494,7 +3506,8 @@ floatx80 float64_to_floatx80( float64 a 
         if (aSig) {
             return floatx80_maybe_silence_nan(
                 commonNaNToFloatx80(float64ToCommonNaN(a STATUS_VAR)
-                                    STATUS_VAR));
+                                    STATUS_VAR)
+                STATUS_VAR);
         }
         return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
     }
@@ -3529,7 +3542,8 @@ float128 float64_to_float128( float64 a 
         if (aSig) {
             return float128_maybe_silence_nan(
                 commonNaNToFloat128(float64ToCommonNaN(a STATUS_VAR)
-                                    STATUS_VAR));
+                                    STATUS_VAR)
+                STATUS_VAR);
         }
         return packFloat128( aSign, 0x7FFF, 0, 0 );
     }
@@ -3740,7 +3754,7 @@ static float64 subFloat64Sigs( float64 a
     if ( aExp == 0x7FF ) {
         if ( aSig | bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
         float_raise( float_flag_invalid STATUS_VAR);
-        return float64_default_nan();
+        return float64_default_nan(status);
     }
     if ( aExp == 0 ) {
         aExp = 1;
@@ -3863,7 +3877,7 @@ float64 float64_mul( float64 a, float64 
         }
         if ( ( bExp | bSig ) == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float64_default_nan();
+            return float64_default_nan(status);
         }
         return packFloat64( zSign, 0x7FF, 0 );
     }
@@ -3871,7 +3885,7 @@ float64 float64_mul( float64 a, float64 
         if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
         if ( ( aExp | aSig ) == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float64_default_nan();
+            return float64_default_nan(status);
         }
         return packFloat64( zSign, 0x7FF, 0 );
     }
@@ -3924,7 +3938,7 @@ float64 float64_div( float64 a, float64 
         if ( bExp == 0x7FF ) {
             if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
             float_raise( float_flag_invalid STATUS_VAR);
-            return float64_default_nan();
+            return float64_default_nan(status);
         }
         return packFloat64( zSign, 0x7FF, 0 );
     }
@@ -3936,7 +3950,7 @@ float64 float64_div( float64 a, float64 
         if ( bSig == 0 ) {
             if ( ( aExp | aSig ) == 0 ) {
                 float_raise( float_flag_invalid STATUS_VAR);
-                return float64_default_nan();
+                return float64_default_nan(status);
             }
             float_raise( float_flag_divbyzero STATUS_VAR);
             return packFloat64( zSign, 0x7FF, 0 );
@@ -3994,7 +4008,7 @@ float64 float64_rem( float64 a, float64 
             return propagateFloat64NaN( a, b STATUS_VAR );
         }
         float_raise( float_flag_invalid STATUS_VAR);
-        return float64_default_nan();
+        return float64_default_nan(status);
     }
     if ( bExp == 0x7FF ) {
         if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
@@ -4003,7 +4017,7 @@ float64 float64_rem( float64 a, float64 
     if ( bExp == 0 ) {
         if ( bSig == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float64_default_nan();
+            return float64_default_nan(status);
         }
         normalizeFloat64Subnormal( bSig, &bExp, &bSig );
     }
@@ -4104,7 +4118,7 @@ float64 float64_muladd(float64 a, float6
 
     if (infzero) {
         float_raise(float_flag_invalid STATUS_VAR);
-        return float64_default_nan();
+        return float64_default_nan(status);
     }
 
     if (flags & float_muladd_negate_c) {
@@ -4125,7 +4139,7 @@ float64 float64_muladd(float64 a, float6
         if (pInf && (pSign ^ cSign)) {
             /* addition of opposite-signed infinities => InvalidOperation */
             float_raise(float_flag_invalid STATUS_VAR);
-            return float64_default_nan();
+            return float64_default_nan(status);
         }
         /* Otherwise generate an infinity of the same sign */
         return packFloat64(cSign ^ signflip, 0x7ff, 0);
@@ -4321,12 +4335,12 @@ float64 float64_sqrt( float64 a STATUS_P
         if ( aSig ) return propagateFloat64NaN( a, a STATUS_VAR );
         if ( ! aSign ) return a;
         float_raise( float_flag_invalid STATUS_VAR);
-        return float64_default_nan();
+        return float64_default_nan(status);
     }
     if ( aSign ) {
         if ( ( aExp | aSig ) == 0 ) return a;
         float_raise( float_flag_invalid STATUS_VAR);
-        return float64_default_nan();
+        return float64_default_nan(status);
     }
     if ( aExp == 0 ) {
         if ( aSig == 0 ) return float64_zero;
@@ -4374,7 +4388,7 @@ float64 float64_log2( float64 a STATUS_P
     }
     if ( aSign ) {
         float_raise( float_flag_invalid STATUS_VAR);
-        return float64_default_nan();
+        return float64_default_nan(status);
     }
     if ( aExp == 0x7FF ) {
         if ( aSig ) return propagateFloat64NaN( a, float64_zero STATUS_VAR );
@@ -4519,8 +4533,9 @@ int float64_eq_quiet( float64 a, float64
     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
        ) {
-        if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+        if (float64_is_signaling_nan(a STATUS_VAR) ||
+            float64_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return 0;
     }
@@ -4547,8 +4562,9 @@ int float64_le_quiet( float64 a, float64
     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
        ) {
-        if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+        if (float64_is_signaling_nan(a STATUS_VAR) ||
+            float64_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return 0;
     }
@@ -4578,8 +4594,9 @@ int float64_lt_quiet( float64 a, float64
     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
        ) {
-        if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+        if (float64_is_signaling_nan(a STATUS_VAR) ||
+            float64_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return 0;
     }
@@ -4607,8 +4624,9 @@ int float64_unordered_quiet( float64 a, 
     if (    ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
          || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
        ) {
-        if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+        if (float64_is_signaling_nan(a STATUS_VAR) ||
+            float64_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return 1;
     }
@@ -4791,7 +4809,8 @@ float32 floatx80_to_float32( floatx80 a 
         if ((uint64_t)(aSig << 1)) {
             return float32_maybe_silence_nan(
                 commonNaNToFloat32(floatx80ToCommonNaN(a STATUS_VAR)
-                                   STATUS_VAR));
+                                   STATUS_VAR)
+                STATUS_VAR);
         }
         return packFloat32( aSign, 0xFF, 0 );
     }
@@ -4821,7 +4840,8 @@ float64 floatx80_to_float64( floatx80 a 
         if ((uint64_t)(aSig << 1)) {
             return float64_maybe_silence_nan(
                 commonNaNToFloat64(floatx80ToCommonNaN(a STATUS_VAR)
-                                   STATUS_VAR));
+                                   STATUS_VAR)
+                STATUS_VAR);
         }
         return packFloat64( aSign, 0x7FF, 0 );
     }
@@ -4849,7 +4869,8 @@ float128 floatx80_to_float128( floatx80 
     aSign = extractFloatx80Sign( a );
     if (aExp == 0x7FFF && (uint64_t)(aSig << 1)) {
         return float128_maybe_silence_nan(
-            commonNaNToFloat128(floatx80ToCommonNaN(a STATUS_VAR) STATUS_VAR));
+            commonNaNToFloat128(floatx80ToCommonNaN(a STATUS_VAR) STATUS_VAR)
+            STATUS_VAR);
     }
     shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 );
     return packFloat128( aSign, aExp, zSig0, zSig1 );
@@ -5040,7 +5061,7 @@ static floatx80 subFloatx80Sigs( floatx8
             return propagateFloatx80NaN( a, b STATUS_VAR );
         }
         float_raise( float_flag_invalid STATUS_VAR);
-        return floatx80_default_nan();
+        return floatx80_default_nan(status);
     }
     if ( aExp == 0 ) {
         aExp = 1;
@@ -5153,7 +5174,7 @@ floatx80 floatx80_mul( floatx80 a, float
         if ( ( aExp | aSig ) == 0 ) {
  invalid:
             float_raise( float_flag_invalid STATUS_VAR);
-            return floatx80_default_nan();
+            return floatx80_default_nan(status);
         }
         return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
     }
@@ -5214,7 +5235,7 @@ floatx80 floatx80_div( floatx80 a, float
             if ( ( aExp | aSig ) == 0 ) {
  invalid:
                 float_raise( float_flag_invalid STATUS_VAR);
-                return floatx80_default_nan();
+                return floatx80_default_nan(status);
             }
             float_raise( float_flag_divbyzero STATUS_VAR);
             return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
@@ -5287,7 +5308,7 @@ floatx80 floatx80_rem( floatx80 a, float
         if ( bSig == 0 ) {
  invalid:
             float_raise( float_flag_invalid STATUS_VAR);
-            return floatx80_default_nan();
+            return floatx80_default_nan(status);
         }
         normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
     }
@@ -5372,7 +5393,7 @@ floatx80 floatx80_sqrt( floatx80 a STATU
         if ( ( aExp | aSig0 ) == 0 ) return a;
  invalid:
         float_raise( float_flag_invalid STATUS_VAR);
-        return floatx80_default_nan();
+        return floatx80_default_nan(status);
     }
     if ( aExp == 0 ) {
         if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 );
@@ -5542,9 +5563,9 @@ int floatx80_eq_quiet( floatx80 a, float
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
               && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
        ) {
-        if (    floatx80_is_signaling_nan( a )
-             || floatx80_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+        if (floatx80_is_signaling_nan(a STATUS_VAR) ||
+            floatx80_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return 0;
     }
@@ -5573,9 +5594,9 @@ int floatx80_le_quiet( floatx80 a, float
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
               && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
        ) {
-        if (    floatx80_is_signaling_nan( a )
-             || floatx80_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+        if (floatx80_is_signaling_nan(a STATUS_VAR) ||
+            floatx80_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return 0;
     }
@@ -5609,9 +5630,9 @@ int floatx80_lt_quiet( floatx80 a, float
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
               && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
        ) {
-        if (    floatx80_is_signaling_nan( a )
-             || floatx80_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+        if (floatx80_is_signaling_nan(a STATUS_VAR) ||
+            floatx80_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return 0;
     }
@@ -5642,9 +5663,9 @@ int floatx80_unordered_quiet( floatx80 a
          || (    ( extractFloatx80Exp( b ) == 0x7FFF )
               && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
        ) {
-        if (    floatx80_is_signaling_nan( a )
-             || floatx80_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+        if (floatx80_is_signaling_nan(a STATUS_VAR) ||
+            floatx80_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return 1;
     }
@@ -5854,7 +5875,8 @@ float32 float128_to_float32( float128 a 
         if (aSig0 | aSig1) {
             return float32_maybe_silence_nan(
                 commonNaNToFloat32(float128ToCommonNaN(a STATUS_VAR)
-                                   STATUS_VAR));
+                                   STATUS_VAR)
+                STATUS_VAR);
         }
         return packFloat32( aSign, 0xFF, 0 );
     }
@@ -5890,7 +5912,8 @@ float64 float128_to_float64( float128 a 
         if (aSig0 | aSig1) {
             return float64_maybe_silence_nan(
                 commonNaNToFloat64(float128ToCommonNaN(a STATUS_VAR)
-                                   STATUS_VAR));
+                                   STATUS_VAR)
+                STATUS_VAR);
         }
         return packFloat64( aSign, 0x7FF, 0 );
     }
@@ -5925,7 +5948,8 @@ floatx80 float128_to_floatx80( float128 
         if (aSig0 | aSig1) {
             return floatx80_maybe_silence_nan(
                 commonNaNToFloatx80(float128ToCommonNaN(a STATUS_VAR)
-                                    STATUS_VAR));
+                                    STATUS_VAR)
+                STATUS_VAR);
         }
         return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
     }
@@ -6195,7 +6219,7 @@ static float128 subFloat128Sigs( float12
             return propagateFloat128NaN( a, b STATUS_VAR );
         }
         float_raise( float_flag_invalid STATUS_VAR);
-        return float128_default_nan();
+        return float128_default_nan(status);
     }
     if ( aExp == 0 ) {
         aExp = 1;
@@ -6322,7 +6346,7 @@ float128 float128_mul( float128 a, float
         if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
  invalid:
             float_raise( float_flag_invalid STATUS_VAR);
-            return float128_default_nan();
+            return float128_default_nan(status);
         }
         return packFloat128( zSign, 0x7FFF, 0, 0 );
     }
@@ -6388,7 +6412,7 @@ float128 float128_div( float128 a, float
             if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
  invalid:
                 float_raise( float_flag_invalid STATUS_VAR);
-                return float128_default_nan();
+                return float128_default_nan(status);
             }
             float_raise( float_flag_divbyzero STATUS_VAR);
             return packFloat128( zSign, 0x7FFF, 0, 0 );
@@ -6466,7 +6490,7 @@ float128 float128_rem( float128 a, float
         if ( ( bSig0 | bSig1 ) == 0 ) {
  invalid:
             float_raise( float_flag_invalid STATUS_VAR);
-            return float128_default_nan();
+            return float128_default_nan(status);
         }
         normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
     }
@@ -6562,7 +6586,7 @@ float128 float128_sqrt( float128 a STATU
         if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a;
  invalid:
         float_raise( float_flag_invalid STATUS_VAR);
-        return float128_default_nan();
+        return float128_default_nan(status);
     }
     if ( aExp == 0 ) {
         if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 );
@@ -6730,9 +6754,9 @@ int float128_eq_quiet( float128 a, float
          || (    ( extractFloat128Exp( b ) == 0x7FFF )
               && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
        ) {
-        if (    float128_is_signaling_nan( a )
-             || float128_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+        if (float128_is_signaling_nan(a STATUS_VAR) ||
+            float128_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return 0;
     }
@@ -6761,9 +6785,9 @@ int float128_le_quiet( float128 a, float
          || (    ( extractFloat128Exp( b ) == 0x7FFF )
               && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
        ) {
-        if (    float128_is_signaling_nan( a )
-             || float128_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+        if (float128_is_signaling_nan(a STATUS_VAR) ||
+            float128_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return 0;
     }
@@ -6797,9 +6821,9 @@ int float128_lt_quiet( float128 a, float
          || (    ( extractFloat128Exp( b ) == 0x7FFF )
               && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
        ) {
-        if (    float128_is_signaling_nan( a )
-             || float128_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+        if (float128_is_signaling_nan(a STATUS_VAR) ||
+            float128_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return 0;
     }
@@ -6831,9 +6855,9 @@ int float128_unordered_quiet( float128 a
          || (    ( extractFloat128Exp( b ) == 0x7FFF )
               && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
        ) {
-        if (    float128_is_signaling_nan( a )
-             || float128_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+        if (float128_is_signaling_nan(a STATUS_VAR) ||
+            float128_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return 1;
     }
@@ -7111,9 +7135,9 @@ static inline int float ## s ## _compare
         ( ( extractFloat ## s ## Exp( b ) == nan_exp ) &&                    \
           extractFloat ## s ## Frac( b ) )) {                                \
         if (!is_quiet ||                                                     \
-            float ## s ## _is_signaling_nan( a ) ||                          \
-            float ## s ## _is_signaling_nan( b ) ) {                         \
-            float_raise( float_flag_invalid STATUS_VAR);                     \
+            float ## s ## _is_signaling_nan(a STATUS_VAR) ||                 \
+            float ## s ## _is_signaling_nan(b STATUS_VAR)) {                 \
+            float_raise(float_flag_invalid STATUS_VAR);                      \
         }                                                                    \
         return float_relation_unordered;                                     \
     }                                                                        \
@@ -7160,9 +7184,9 @@ static inline int floatx80_compare_inter
         ( ( extractFloatx80Exp( b ) == 0x7fff ) &&
           ( extractFloatx80Frac( b )<<1 ) )) {
         if (!is_quiet ||
-            floatx80_is_signaling_nan( a ) ||
-            floatx80_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+            floatx80_is_signaling_nan(a STATUS_VAR) ||
+            floatx80_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return float_relation_unordered;
     }
@@ -7206,9 +7230,9 @@ static inline int float128_compare_inter
         ( ( extractFloat128Exp( b ) == 0x7fff ) &&
           ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )) {
         if (!is_quiet ||
-            float128_is_signaling_nan( a ) ||
-            float128_is_signaling_nan( b ) ) {
-            float_raise( float_flag_invalid STATUS_VAR);
+            float128_is_signaling_nan(a STATUS_VAR) ||
+            float128_is_signaling_nan(b STATUS_VAR)) {
+            float_raise(float_flag_invalid STATUS_VAR);
         }
         return float_relation_unordered;
     }
@@ -7266,10 +7290,10 @@ static inline float ## s float ## s ## _
     if (float ## s ## _is_any_nan(a) ||                                 \
         float ## s ## _is_any_nan(b)) {                                 \
         if (isieee) {                                                   \
-            if (float ## s ## _is_quiet_nan(a) &&                       \
+            if (float ## s ## _is_quiet_nan(a STATUS_VAR) &&            \
                 !float ## s ##_is_any_nan(b)) {                         \
                 return b;                                               \
-            } else if (float ## s ## _is_quiet_nan(b) &&                \
+            } else if (float ## s ## _is_quiet_nan(b STATUS_VAR) &&     \
                        !float ## s ## _is_any_nan(a)) {                 \
                 return a;                                               \
             }                                                           \
Index: qemu-git-trunk/include/fpu/softfloat.h
===================================================================
--- qemu-git-trunk.orig/include/fpu/softfloat.h	2014-12-08 22:36:20.000000000 +0000
+++ qemu-git-trunk/include/fpu/softfloat.h	2014-12-08 22:40:14.768923514 +0000
@@ -64,7 +64,8 @@ typedef int64_t int64;
 
 #define LIT64( a ) a##LL
 
-#define STATUS_PARAM , float_status *status
+#define STATUS_PARAM_ONLY float_status *status
+#define STATUS_PARAM , STATUS_PARAM_ONLY
 #define STATUS(field) status->field
 #define STATUS_VAR , status
 
@@ -314,9 +315,9 @@ float64 float16_to_float64(float16 a, fl
 /*----------------------------------------------------------------------------
 | Software half-precision operations.
 *----------------------------------------------------------------------------*/
-int float16_is_quiet_nan( float16 );
-int float16_is_signaling_nan( float16 );
-float16 float16_maybe_silence_nan( float16 );
+int float16_is_quiet_nan(float16 STATUS_PARAM);
+int float16_is_signaling_nan(float16 STATUS_PARAM);
+float16 float16_maybe_silence_nan(float16 STATUS_PARAM);
 
 static inline int float16_is_any_nan(float16 a)
 {
@@ -326,7 +327,7 @@ static inline int float16_is_any_nan(flo
 /*----------------------------------------------------------------------------
 | The pattern for a default generated half-precision NaN.
 *----------------------------------------------------------------------------*/
-__inline__ float16 float16_default_nan(void);
+__inline__ float16 float16_default_nan(STATUS_PARAM_ONLY);
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE single-precision conversion routines.
@@ -376,9 +377,9 @@ float32 float32_minnum(float32, float32 
 float32 float32_maxnum(float32, float32 STATUS_PARAM);
 float32 float32_minnummag(float32, float32 STATUS_PARAM);
 float32 float32_maxnummag(float32, float32 STATUS_PARAM);
-int float32_is_quiet_nan( float32 );
-int float32_is_signaling_nan( float32 );
-float32 float32_maybe_silence_nan( float32 );
+int float32_is_quiet_nan(float32 STATUS_PARAM);
+int float32_is_signaling_nan(float32 STATUS_PARAM);
+float32 float32_maybe_silence_nan(float32 STATUS_PARAM);
 float32 float32_scalbn( float32, int STATUS_PARAM );
 
 static inline float32 float32_abs(float32 a)
@@ -438,7 +439,7 @@ static inline float32 float32_set_sign(f
 /*----------------------------------------------------------------------------
 | The pattern for a default generated single-precision NaN.
 *----------------------------------------------------------------------------*/
-__inline__ float32 float32_default_nan(void);
+__inline__ float32 float32_default_nan(STATUS_PARAM_ONLY);
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE double-precision conversion routines.
@@ -488,9 +489,9 @@ float64 float64_minnum(float64, float64 
 float64 float64_maxnum(float64, float64 STATUS_PARAM);
 float64 float64_minnummag(float64, float64 STATUS_PARAM);
 float64 float64_maxnummag(float64, float64 STATUS_PARAM);
-int float64_is_quiet_nan( float64 a );
-int float64_is_signaling_nan( float64 );
-float64 float64_maybe_silence_nan( float64 );
+int float64_is_quiet_nan(float64 a STATUS_PARAM);
+int float64_is_signaling_nan(float64 STATUS_PARAM);
+float64 float64_maybe_silence_nan(float64 STATUS_PARAM);
 float64 float64_scalbn( float64, int STATUS_PARAM );
 
 static inline float64 float64_abs(float64 a)
@@ -550,7 +551,7 @@ static inline float64 float64_set_sign(f
 /*----------------------------------------------------------------------------
 | The pattern for a default generated double-precision NaN.
 *----------------------------------------------------------------------------*/
-__inline__ float64 float64_default_nan(void);
+__inline__ float64 float64_default_nan(STATUS_PARAM_ONLY);
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE extended double-precision conversion routines.
@@ -583,9 +584,9 @@ int floatx80_lt_quiet( floatx80, floatx8
 int floatx80_unordered_quiet( floatx80, floatx80 STATUS_PARAM );
 int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
 int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
-int floatx80_is_quiet_nan( floatx80 );
-int floatx80_is_signaling_nan( floatx80 );
-floatx80 floatx80_maybe_silence_nan( floatx80 );
+int floatx80_is_quiet_nan(floatx80 STATUS_PARAM);
+int floatx80_is_signaling_nan(floatx80 STATUS_PARAM);
+floatx80 floatx80_maybe_silence_nan(floatx80 STATUS_PARAM);
 floatx80 floatx80_scalbn( floatx80, int STATUS_PARAM );
 
 static inline floatx80 floatx80_abs(floatx80 a)
@@ -635,7 +636,7 @@ static inline int floatx80_is_any_nan(fl
 /*----------------------------------------------------------------------------
 | The pattern for a default generated extended double-precision NaN.
 *----------------------------------------------------------------------------*/
-__inline__ floatx80 floatx80_default_nan(void);
+__inline__ floatx80 floatx80_default_nan(STATUS_PARAM_ONLY);
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE quadruple-precision conversion routines.
@@ -668,9 +669,9 @@ int float128_lt_quiet( float128, float12
 int float128_unordered_quiet( float128, float128 STATUS_PARAM );
 int float128_compare( float128, float128 STATUS_PARAM );
 int float128_compare_quiet( float128, float128 STATUS_PARAM );
-int float128_is_quiet_nan( float128 );
-int float128_is_signaling_nan( float128 );
-float128 float128_maybe_silence_nan( float128 );
+int float128_is_quiet_nan(float128 STATUS_PARAM);
+int float128_is_signaling_nan(float128 STATUS_PARAM);
+float128 float128_maybe_silence_nan(float128 STATUS_PARAM);
 float128 float128_scalbn( float128, int STATUS_PARAM );
 
 static inline float128 float128_abs(float128 a)
@@ -716,6 +717,6 @@ static inline int float128_is_any_nan(fl
 /*----------------------------------------------------------------------------
 | The pattern for a default generated quadruple-precision NaN.
 *----------------------------------------------------------------------------*/
-__inline__ float128 float128_default_nan(void);
+__inline__ float128 float128_default_nan(STATUS_PARAM_ONLY);
 
 #endif /* !SOFTFLOAT_H */
Index: qemu-git-trunk/target-arm/helper-a64.c
===================================================================
--- qemu-git-trunk.orig/target-arm/helper-a64.c	2014-12-08 22:36:20.000000000 +0000
+++ qemu-git-trunk/target-arm/helper-a64.c	2014-12-08 22:37:36.758946934 +0000
@@ -337,12 +337,12 @@ float32 HELPER(frecpx_f32)(float32 a, vo
 
     if (float32_is_any_nan(a)) {
         float32 nan = a;
-        if (float32_is_signaling_nan(a)) {
+        if (float32_is_signaling_nan(a, fpst)) {
             float_raise(float_flag_invalid, fpst);
-            nan = float32_maybe_silence_nan(a);
+            nan = float32_maybe_silence_nan(a, fpst);
         }
         if (fpst->default_nan_mode) {
-            nan = float32_default_nan();
+            nan = float32_default_nan(fpst);
         }
         return nan;
     }
@@ -366,12 +366,12 @@ float64 HELPER(frecpx_f64)(float64 a, vo
 
     if (float64_is_any_nan(a)) {
         float64 nan = a;
-        if (float64_is_signaling_nan(a)) {
+        if (float64_is_signaling_nan(a, fpst)) {
             float_raise(float_flag_invalid, fpst);
-            nan = float64_maybe_silence_nan(a);
+            nan = float64_maybe_silence_nan(a, fpst);
         }
         if (fpst->default_nan_mode) {
-            nan = float64_default_nan();
+            nan = float64_default_nan(fpst);
         }
         return nan;
     }
@@ -400,7 +400,7 @@ float32 HELPER(fcvtx_f64_to_f32)(float64
     set_float_rounding_mode(float_round_to_zero, &tstat);
     set_float_exception_flags(0, &tstat);
     r = float64_to_float32(a, &tstat);
-    r = float32_maybe_silence_nan(r);
+    r = float32_maybe_silence_nan(r, &tstat);
     exflags = get_float_exception_flags(&tstat);
     if (exflags & float_flag_inexact) {
         r = make_float32(float32_val(r) | 1);
Index: qemu-git-trunk/target-arm/helper.c
===================================================================
--- qemu-git-trunk.orig/target-arm/helper.c	2014-12-08 22:36:20.000000000 +0000
+++ qemu-git-trunk/target-arm/helper.c	2014-12-08 22:37:36.758946934 +0000
@@ -5523,7 +5523,7 @@ float64 VFP_HELPER(fcvtd, s)(float32 x, 
     /* ARM requires that S<->D conversion of any kind of NaN generates
      * a quiet NaN by forcing the most significant frac bit to 1.
      */
-    return float64_maybe_silence_nan(r);
+    return float64_maybe_silence_nan(r, &env->vfp.fp_status);
 }
 
 float32 VFP_HELPER(fcvts, d)(float64 x, CPUARMState *env)
@@ -5532,7 +5532,7 @@ float32 VFP_HELPER(fcvts, d)(float64 x, 
     /* ARM requires that S<->D conversion of any kind of NaN generates
      * a quiet NaN by forcing the most significant frac bit to 1.
      */
-    return float32_maybe_silence_nan(r);
+    return float32_maybe_silence_nan(r, &env->vfp.fp_status);
 }
 
 /* VFP3 fixed point conversion.  */
@@ -5631,7 +5631,7 @@ static float32 do_fcvt_f16_to_f32(uint32
     int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
     float32 r = float16_to_float32(make_float16(a), ieee, s);
     if (ieee) {
-        return float32_maybe_silence_nan(r);
+        return float32_maybe_silence_nan(r, s);
     }
     return r;
 }
@@ -5641,7 +5641,7 @@ static uint32_t do_fcvt_f32_to_f16(float
     int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
     float16 r = float32_to_float16(a, ieee, s);
     if (ieee) {
-        r = float16_maybe_silence_nan(r);
+        r = float16_maybe_silence_nan(r, s);
     }
     return float16_val(r);
 }
@@ -5671,7 +5671,7 @@ float64 HELPER(vfp_fcvt_f16_to_f64)(uint
     int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
     float64 r = float16_to_float64(make_float16(a), ieee, &env->vfp.fp_status);
     if (ieee) {
-        return float64_maybe_silence_nan(r);
+        return float64_maybe_silence_nan(r, &env->vfp.fp_status);
     }
     return r;
 }
@@ -5681,7 +5681,7 @@ uint32_t HELPER(vfp_fcvt_f64_to_f16)(flo
     int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
     float16 r = float64_to_float16(a, ieee, &env->vfp.fp_status);
     if (ieee) {
-        r = float16_maybe_silence_nan(r);
+        r = float16_maybe_silence_nan(r, &env->vfp.fp_status);
     }
     return float16_val(r);
 }
@@ -5831,12 +5831,12 @@ float32 HELPER(recpe_f32)(float32 input,
 
     if (float32_is_any_nan(f32)) {
         float32 nan = f32;
-        if (float32_is_signaling_nan(f32)) {
+        if (float32_is_signaling_nan(f32, fpst)) {
             float_raise(float_flag_invalid, fpst);
-            nan = float32_maybe_silence_nan(f32);
+            nan = float32_maybe_silence_nan(f32, fpst);
         }
         if (fpst->default_nan_mode) {
-            nan = float32_default_nan();
+            nan = float32_default_nan(fpst);
         }
         return nan;
     } else if (float32_is_infinity(f32)) {
@@ -5885,12 +5885,12 @@ float64 HELPER(recpe_f64)(float64 input,
     /* Deal with any special cases */
     if (float64_is_any_nan(f64)) {
         float64 nan = f64;
-        if (float64_is_signaling_nan(f64)) {
+        if (float64_is_signaling_nan(f64, fpst)) {
             float_raise(float_flag_invalid, fpst);
-            nan = float64_maybe_silence_nan(f64);
+            nan = float64_maybe_silence_nan(f64, fpst);
         }
         if (fpst->default_nan_mode) {
-            nan = float64_default_nan();
+            nan = float64_default_nan(fpst);
         }
         return nan;
     } else if (float64_is_infinity(f64)) {
@@ -5992,12 +5992,12 @@ float32 HELPER(rsqrte_f32)(float32 input
 
     if (float32_is_any_nan(f32)) {
         float32 nan = f32;
-        if (float32_is_signaling_nan(f32)) {
+        if (float32_is_signaling_nan(f32, s)) {
             float_raise(float_flag_invalid, s);
-            nan = float32_maybe_silence_nan(f32);
+            nan = float32_maybe_silence_nan(f32, s);
         }
         if (s->default_nan_mode) {
-            nan = float32_default_nan();
+            nan = float32_default_nan(s);
         }
         return nan;
     } else if (float32_is_zero(f32)) {
@@ -6005,7 +6005,7 @@ float32 HELPER(rsqrte_f32)(float32 input
         return float32_set_sign(float32_infinity, float32_is_neg(f32));
     } else if (float32_is_neg(f32)) {
         float_raise(float_flag_invalid, s);
-        return float32_default_nan();
+        return float32_default_nan(s);
     } else if (float32_is_infinity(f32)) {
         return float32_zero;
     }
@@ -6056,12 +6056,12 @@ float64 HELPER(rsqrte_f64)(float64 input
 
     if (float64_is_any_nan(f64)) {
         float64 nan = f64;
-        if (float64_is_signaling_nan(f64)) {
+        if (float64_is_signaling_nan(f64, s)) {
             float_raise(float_flag_invalid, s);
-            nan = float64_maybe_silence_nan(f64);
+            nan = float64_maybe_silence_nan(f64, s);
         }
         if (s->default_nan_mode) {
-            nan = float64_default_nan();
+            nan = float64_default_nan(s);
         }
         return nan;
     } else if (float64_is_zero(f64)) {
@@ -6069,7 +6069,7 @@ float64 HELPER(rsqrte_f64)(float64 input
         return float64_set_sign(float64_infinity, float64_is_neg(f64));
     } else if (float64_is_neg(f64)) {
         float_raise(float_flag_invalid, s);
-        return float64_default_nan();
+        return float64_default_nan(s);
     } else if (float64_is_infinity(f64)) {
         return float64_zero;
     }
Index: qemu-git-trunk/target-m68k/helper.c
===================================================================
--- qemu-git-trunk.orig/target-m68k/helper.c	2014-12-08 22:36:20.000000000 +0000
+++ qemu-git-trunk/target-m68k/helper.c	2014-12-08 22:37:36.758946934 +0000
@@ -556,10 +556,10 @@ float64 HELPER(sub_cmp_f64)(CPUM68KState
     /* ??? Should flush denormals to zero.  */
     float64 res;
     res = float64_sub(a, b, &env->fp_status);
-    if (float64_is_quiet_nan(res)) {
+    if (float64_is_quiet_nan(res, &env->fp_status)) {
         /* +/-inf compares equal against itself, but sub returns nan.  */
-        if (!float64_is_quiet_nan(a)
-            && !float64_is_quiet_nan(b)) {
+        if (!float64_is_quiet_nan(a, &env->fp_status)
+            && !float64_is_quiet_nan(b, &env->fp_status)) {
             res = float64_zero;
             if (float64_lt_quiet(a, res, &env->fp_status))
                 res = float64_chs(res);
Index: qemu-git-trunk/target-microblaze/op_helper.c
===================================================================
--- qemu-git-trunk.orig/target-microblaze/op_helper.c	2014-12-08 22:36:20.000000000 +0000
+++ qemu-git-trunk/target-microblaze/op_helper.c	2014-12-08 22:37:36.758946934 +0000
@@ -289,12 +289,14 @@ uint32_t helper_fcmp_un(CPUMBState *env,
     fa.l = a;
     fb.l = b;
 
-    if (float32_is_signaling_nan(fa.f) || float32_is_signaling_nan(fb.f)) {
+    if (float32_is_signaling_nan(fa.f, &env->fp_status)
+        || float32_is_signaling_nan(fb.f, &env->fp_status)) {
         update_fpu_flags(env, float_flag_invalid);
         r = 1;
     }
 
-    if (float32_is_quiet_nan(fa.f) || float32_is_quiet_nan(fb.f)) {
+    if (float32_is_quiet_nan(fa.f, &env->fp_status) ||
+        float32_is_quiet_nan(fb.f, &env->fp_status)) {
         r = 1;
     }
 
Index: qemu-git-trunk/target-mips/helper.h
===================================================================
--- qemu-git-trunk.orig/target-mips/helper.h	2014-12-08 22:36:20.000000000 +0000
+++ qemu-git-trunk/target-mips/helper.h	2014-12-08 22:37:36.758946934 +0000
@@ -209,8 +209,8 @@ DEF_HELPER_2(float_cvtw_d, i32, env, i64
 DEF_HELPER_3(float_addr_ps, i64, env, i64, i64)
 DEF_HELPER_3(float_mulr_ps, i64, env, i64, i64)
 
-DEF_HELPER_FLAGS_1(float_class_s, TCG_CALL_NO_RWG_SE, i32, i32)
-DEF_HELPER_FLAGS_1(float_class_d, TCG_CALL_NO_RWG_SE, i64, i64)
+DEF_HELPER_FLAGS_3(float_class_s, TCG_CALL_NO_RWG_SE, i32, env, i32, i32)
+DEF_HELPER_FLAGS_3(float_class_d, TCG_CALL_NO_RWG_SE, i64, env, i64, i32)
 
 #define FOP_PROTO(op)                                     \
 DEF_HELPER_4(float_ ## op ## _s, i32, env, i32, i32, i32) \
Index: qemu-git-trunk/target-mips/msa_helper.c
===================================================================
--- qemu-git-trunk.orig/target-mips/msa_helper.c	2014-12-08 22:36:20.000000000 +0000
+++ qemu-git-trunk/target-mips/msa_helper.c	2014-12-08 22:37:36.758946934 +0000
@@ -1503,11 +1503,11 @@ MSA_UNOP_DF(pcnt)
 #define FLOAT_ONE32 make_float32(0x3f8 << 20)
 #define FLOAT_ONE64 make_float64(0x3ffULL << 52)
 
-#define FLOAT_SNAN16 (float16_default_nan() ^ 0x0220)
+#define FLOAT_SNAN16(s) (float16_default_nan(s) ^ 0x0220)
         /* 0x7c20 */
-#define FLOAT_SNAN32 (float32_default_nan() ^ 0x00400020)
+#define FLOAT_SNAN32(s) (float32_default_nan(s) ^ 0x00400020)
         /* 0x7f800020 */
-#define FLOAT_SNAN64 (float64_default_nan() ^ 0x0008000000000020ULL)
+#define FLOAT_SNAN64(s) (float64_default_nan(s) ^ 0x0008000000000020ULL)
         /* 0x7ff0000000000020 */
 
 static inline void clear_msacsr_cause(CPUMIPSState *env)
@@ -1619,7 +1619,7 @@ static inline float16 float16_from_float
       float16 f_val;
 
       f_val = float32_to_float16((float32)a, ieee  STATUS_VAR);
-      f_val = float16_maybe_silence_nan(f_val);
+      f_val = float16_maybe_silence_nan(f_val STATUS_VAR);
 
       return a < 0 ? (f_val | (1 << 15)) : f_val;
 }
@@ -1629,7 +1629,7 @@ static inline float32 float32_from_float
       float32 f_val;
 
       f_val = float64_to_float32((float64)a STATUS_VAR);
-      f_val = float32_maybe_silence_nan(f_val);
+      f_val = float32_maybe_silence_nan(f_val STATUS_VAR);
 
       return a < 0 ? (f_val | (1 << 31)) : f_val;
 }
@@ -1639,7 +1639,7 @@ static inline float32 float32_from_float
       float32 f_val;
 
       f_val = float16_to_float32((float16)a, ieee STATUS_VAR);
-      f_val = float32_maybe_silence_nan(f_val);
+      f_val = float32_maybe_silence_nan(f_val STATUS_VAR);
 
       return a < 0 ? (f_val | (1 << 31)) : f_val;
 }
@@ -1649,7 +1649,7 @@ static inline float64 float64_from_float
       float64 f_val;
 
       f_val = float32_to_float64((float64)a STATUS_VAR);
-      f_val = float64_maybe_silence_nan(f_val);
+      f_val = float64_maybe_silence_nan(f_val STATUS_VAR);
 
       return a < 0 ? (f_val | (1ULL << 63)) : f_val;
 }
@@ -1795,7 +1795,7 @@ static inline int32 float64_to_q32(float
         c = update_msacsr(env, CLEAR_IS_INEXACT, 0);                        \
                                                                             \
         if (get_enabled_exceptions(env, c)) {                               \
-            DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c;                    \
+            DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c;            \
         }                                                                   \
     } while (0)
 
@@ -2382,7 +2382,7 @@ void helper_msa_fsne_df(CPUMIPSState *en
         c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS));                 \
                                                                             \
         if (get_enabled_exceptions(env, c)) {                               \
-            DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c;                    \
+            DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c;            \
         }                                                                   \
     } while (0)
 
@@ -2518,7 +2518,7 @@ void helper_msa_fdiv_df(CPUMIPSState *en
         c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS));                 \
                                                                             \
         if (get_enabled_exceptions(env, c)) {                               \
-            DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c;                    \
+            DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c;            \
         }                                                                   \
     } while (0)
 
@@ -2637,7 +2637,7 @@ void helper_msa_fexp2_df(CPUMIPSState *e
         c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS));                 \
                                                                             \
         if (get_enabled_exceptions(env, c)) {                               \
-            DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c;                    \
+            DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c;            \
         }                                                                   \
     } while (0)
 
@@ -2686,7 +2686,7 @@ void helper_msa_fexdo_df(CPUMIPSState *e
         c = update_msacsr(env, CLEAR_FS_UNDERFLOW, 0);                      \
                                                                             \
         if (get_enabled_exceptions(env, c)) {                               \
-            DEST = ((FLOAT_SNAN ## XBITS >> 6) << 6) | c;                   \
+            DEST = ((FLOAT_SNAN ## XBITS(status) >> 6) << 6) | c;           \
         }                                                                   \
     } while (0)
 
@@ -2723,9 +2723,9 @@ void helper_msa_ftq_df(CPUMIPSState *env
     msa_move_v(pwd, pwx);
 }
 
-#define NUMBER_QNAN_PAIR(ARG1, ARG2, BITS)      \
-    !float ## BITS ## _is_any_nan(ARG1)         \
-    && float ## BITS ## _is_quiet_nan(ARG2)
+#define NUMBER_QNAN_PAIR(ARG1, ARG2, BITS, STATUS)                  \
+    !float ## BITS ## _is_any_nan(ARG1)                             \
+    && float ## BITS ## _is_quiet_nan(ARG2, STATUS)
 
 #define MSA_FLOAT_MAXOP(DEST, OP, ARG1, ARG2, BITS)                         \
     do {                                                                    \
@@ -2737,18 +2737,18 @@ void helper_msa_ftq_df(CPUMIPSState *env
         c = update_msacsr(env, 0, 0);                                       \
                                                                             \
         if (get_enabled_exceptions(env, c)) {                               \
-            DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c;                    \
+            DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c;            \
         }                                                                   \
     } while (0)
 
-#define FMAXMIN_A(F, G, X, _S, _T, BITS)                            \
+#define FMAXMIN_A(F, G, X, _S, _T, BITS, STATUS)                    \
     do {                                                            \
         uint## BITS ##_t S = _S, T = _T;                            \
         uint## BITS ##_t as, at, xs, xt, xd;                        \
-        if (NUMBER_QNAN_PAIR(S, T, BITS)) {                         \
+        if (NUMBER_QNAN_PAIR(S, T, BITS, STATUS)) {                 \
             T = S;                                                  \
         }                                                           \
-        else if (NUMBER_QNAN_PAIR(T, S, BITS)) {                    \
+        else if (NUMBER_QNAN_PAIR(T, S, BITS, STATUS)) {            \
             S = T;                                                  \
         }                                                           \
         as = float## BITS ##_abs(S);                                \
@@ -2762,6 +2762,7 @@ void helper_msa_ftq_df(CPUMIPSState *env
 void helper_msa_fmin_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
         uint32_t ws, uint32_t wt)
 {
+    float_status *status = &env->active_tc.msa_fp_status;
     wr_t wx, *pwx = &wx;
     wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
     wr_t *pws = &(env->active_fpu.fpr[ws].wr);
@@ -2773,9 +2774,9 @@ void helper_msa_fmin_df(CPUMIPSState *en
     switch (df) {
     case DF_WORD:
         for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
-            if (NUMBER_QNAN_PAIR(pws->w[i], pwt->w[i], 32)) {
+            if (NUMBER_QNAN_PAIR(pws->w[i], pwt->w[i], 32, status)) {
                 MSA_FLOAT_MAXOP(pwx->w[i], min, pws->w[i], pws->w[i], 32);
-            } else if (NUMBER_QNAN_PAIR(pwt->w[i], pws->w[i], 32)) {
+            } else if (NUMBER_QNAN_PAIR(pwt->w[i], pws->w[i], 32, status)) {
                 MSA_FLOAT_MAXOP(pwx->w[i], min, pwt->w[i], pwt->w[i], 32);
             } else {
                 MSA_FLOAT_MAXOP(pwx->w[i], min, pws->w[i], pwt->w[i], 32);
@@ -2784,9 +2785,9 @@ void helper_msa_fmin_df(CPUMIPSState *en
         break;
     case DF_DOUBLE:
         for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
-            if (NUMBER_QNAN_PAIR(pws->d[i], pwt->d[i], 64)) {
+            if (NUMBER_QNAN_PAIR(pws->d[i], pwt->d[i], 64, status)) {
                 MSA_FLOAT_MAXOP(pwx->d[i], min, pws->d[i], pws->d[i], 64);
-            } else if (NUMBER_QNAN_PAIR(pwt->d[i], pws->d[i], 64)) {
+            } else if (NUMBER_QNAN_PAIR(pwt->d[i], pws->d[i], 64, status)) {
                 MSA_FLOAT_MAXOP(pwx->d[i], min, pwt->d[i], pwt->d[i], 64);
             } else {
                 MSA_FLOAT_MAXOP(pwx->d[i], min, pws->d[i], pwt->d[i], 64);
@@ -2805,6 +2806,7 @@ void helper_msa_fmin_df(CPUMIPSState *en
 void helper_msa_fmin_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
         uint32_t ws, uint32_t wt)
 {
+    float_status *status = &env->active_tc.msa_fp_status;
     wr_t wx, *pwx = &wx;
     wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
     wr_t *pws = &(env->active_fpu.fpr[ws].wr);
@@ -2816,12 +2818,12 @@ void helper_msa_fmin_a_df(CPUMIPSState *
     switch (df) {
     case DF_WORD:
         for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
-            FMAXMIN_A(min, max, pwx->w[i], pws->w[i], pwt->w[i], 32);
+            FMAXMIN_A(min, max, pwx->w[i], pws->w[i], pwt->w[i], 32, status);
         }
         break;
     case DF_DOUBLE:
         for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
-            FMAXMIN_A(min, max, pwx->d[i], pws->d[i], pwt->d[i], 64);
+            FMAXMIN_A(min, max, pwx->d[i], pws->d[i], pwt->d[i], 64, status);
         }
         break;
     default:
@@ -2836,6 +2838,7 @@ void helper_msa_fmin_a_df(CPUMIPSState *
 void helper_msa_fmax_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
         uint32_t ws, uint32_t wt)
 {
+    float_status *status = &env->active_tc.msa_fp_status;
     wr_t wx, *pwx = &wx;
     wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
     wr_t *pws = &(env->active_fpu.fpr[ws].wr);
@@ -2847,9 +2850,9 @@ void helper_msa_fmax_df(CPUMIPSState *en
     switch (df) {
     case DF_WORD:
         for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
-            if (NUMBER_QNAN_PAIR(pws->w[i], pwt->w[i], 32)) {
+            if (NUMBER_QNAN_PAIR(pws->w[i], pwt->w[i], 32, status)) {
                 MSA_FLOAT_MAXOP(pwx->w[i], max, pws->w[i], pws->w[i], 32);
-            } else if (NUMBER_QNAN_PAIR(pwt->w[i], pws->w[i], 32)) {
+            } else if (NUMBER_QNAN_PAIR(pwt->w[i], pws->w[i], 32, status)) {
                 MSA_FLOAT_MAXOP(pwx->w[i], max, pwt->w[i], pwt->w[i], 32);
             } else {
                 MSA_FLOAT_MAXOP(pwx->w[i], max, pws->w[i], pwt->w[i], 32);
@@ -2858,9 +2861,9 @@ void helper_msa_fmax_df(CPUMIPSState *en
         break;
     case DF_DOUBLE:
         for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
-            if (NUMBER_QNAN_PAIR(pws->d[i], pwt->d[i], 64)) {
+            if (NUMBER_QNAN_PAIR(pws->d[i], pwt->d[i], 64, status)) {
                 MSA_FLOAT_MAXOP(pwx->d[i], max, pws->d[i], pws->d[i], 64);
-            } else if (NUMBER_QNAN_PAIR(pwt->d[i], pws->d[i], 64)) {
+            } else if (NUMBER_QNAN_PAIR(pwt->d[i], pws->d[i], 64, status)) {
                 MSA_FLOAT_MAXOP(pwx->d[i], max, pwt->d[i], pwt->d[i], 64);
             } else {
                 MSA_FLOAT_MAXOP(pwx->d[i], max, pws->d[i], pwt->d[i], 64);
@@ -2879,6 +2882,7 @@ void helper_msa_fmax_df(CPUMIPSState *en
 void helper_msa_fmax_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
         uint32_t ws, uint32_t wt)
 {
+    float_status *status = &env->active_tc.msa_fp_status;
     wr_t wx, *pwx = &wx;
     wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
     wr_t *pws = &(env->active_fpu.fpr[ws].wr);
@@ -2890,12 +2894,12 @@ void helper_msa_fmax_a_df(CPUMIPSState *
     switch (df) {
     case DF_WORD:
         for (i = 0; i < DF_ELEMENTS(DF_WORD); i++) {
-            FMAXMIN_A(max, min, pwx->w[i], pws->w[i], pwt->w[i], 32);
+            FMAXMIN_A(max, min, pwx->w[i], pws->w[i], pwt->w[i], 32, status);
         }
         break;
     case DF_DOUBLE:
         for (i = 0; i < DF_ELEMENTS(DF_DOUBLE); i++) {
-            FMAXMIN_A(max, min, pwx->d[i], pws->d[i], pwt->d[i], 64);
+            FMAXMIN_A(max, min, pwx->d[i], pws->d[i], pwt->d[i], 64, status);
         }
         break;
     default:
@@ -2913,13 +2917,13 @@ void helper_msa_fclass_df(CPUMIPSState *
     wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
     wr_t *pws = &(env->active_fpu.fpr[ws].wr);
     if (df == DF_WORD) {
-        pwd->w[0] = helper_float_class_s(pws->w[0]);
-        pwd->w[1] = helper_float_class_s(pws->w[1]);
-        pwd->w[2] = helper_float_class_s(pws->w[2]);
-        pwd->w[3] = helper_float_class_s(pws->w[3]);
+        pwd->w[0] = helper_float_class_s(env, pws->w[0], 1);
+        pwd->w[1] = helper_float_class_s(env, pws->w[1], 1);
+        pwd->w[2] = helper_float_class_s(env, pws->w[2], 1);
+        pwd->w[3] = helper_float_class_s(env, pws->w[3], 1);
     } else {
-        pwd->d[0] = helper_float_class_d(pws->d[0]);
-        pwd->d[1] = helper_float_class_d(pws->d[1]);
+        pwd->d[0] = helper_float_class_d(env, pws->d[0], 1);
+        pwd->d[1] = helper_float_class_d(env, pws->d[1], 1);
     }
 }
 
@@ -2933,7 +2937,7 @@ void helper_msa_fclass_df(CPUMIPSState *
         c = update_msacsr(env, CLEAR_FS_UNDERFLOW, 0);                      \
                                                                             \
         if (get_enabled_exceptions(env, c)) {                               \
-            DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c;                    \
+            DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c;            \
         } else if (float ## BITS ## _is_any_nan(ARG)) {                     \
             DEST = 0;                                                       \
         }                                                                   \
@@ -3037,12 +3041,12 @@ void helper_msa_fsqrt_df(CPUMIPSState *e
         set_float_exception_flags(0, status);                               \
         DEST = float ## BITS ## _ ## div(FLOAT_ONE ## BITS, ARG, status);   \
         c = update_msacsr(env, float ## BITS ## _is_infinity(ARG) ||        \
-                          float ## BITS ## _is_quiet_nan(DEST) ?            \
+                          float ## BITS ## _is_quiet_nan(DEST, status) ?    \
                           0 : RECIPROCAL_INEXACT,                           \
                           IS_DENORMAL(DEST, BITS));                         \
                                                                             \
         if (get_enabled_exceptions(env, c)) {                               \
-            DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c;                    \
+            DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c;            \
         }                                                                   \
     } while (0)
 
@@ -3158,7 +3162,7 @@ void helper_msa_frint_df(CPUMIPSState *e
         c = update_msacsr(env, 0, IS_DENORMAL(DEST, BITS));                 \
                                                                             \
         if (get_enabled_exceptions(env, c)) {                               \
-            DEST = ((FLOAT_SNAN ## BITS >> 6) << 6) | c;                    \
+            DEST = ((FLOAT_SNAN ## BITS(status) >> 6) << 6) | c;            \
         }                                                                   \
     } while (0)
 
Index: qemu-git-trunk/target-mips/op_helper.c
===================================================================
--- qemu-git-trunk.orig/target-mips/op_helper.c	2014-12-08 22:36:20.000000000 +0000
+++ qemu-git-trunk/target-mips/op_helper.c	2014-12-08 22:37:36.758946934 +0000
@@ -2990,11 +2990,17 @@ FLOAT_RINT(rint_d, 64)
 #define FLOAT_CLASS_POSITIVE_ZERO      0x200
 
 #define FLOAT_CLASS(name, bits)                                      \
-uint ## bits ## _t helper_float_ ## name (uint ## bits ## _t arg)    \
+uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env,         \
+                                          uint ## bits ## _t arg,    \
+                                          uint32_t msa)              \
 {                                                                    \
-    if (float ## bits ## _is_signaling_nan(arg)) {                   \
+    float_status *status = msa ?                                     \
+                           &env->active_tc.msa_fp_status :           \
+                           &env->active_fpu.fp_status;               \
+                                                                     \
+    if (float ## bits ## _is_signaling_nan(arg, status)) {           \
         return FLOAT_CLASS_SIGNALING_NAN;                            \
-    } else if (float ## bits ## _is_quiet_nan(arg)) {                \
+    } else if (float ## bits ## _is_quiet_nan(arg, status)) {        \
         return FLOAT_CLASS_QUIET_NAN;                                \
     } else if (float ## bits ## _is_neg(arg)) {                      \
         if (float ## bits ## _is_infinity(arg)) {                    \
Index: qemu-git-trunk/target-mips/translate.c
===================================================================
--- qemu-git-trunk.orig/target-mips/translate.c	2014-12-08 22:36:20.000000000 +0000
+++ qemu-git-trunk/target-mips/translate.c	2014-12-08 22:37:36.758946934 +0000
@@ -8972,9 +8972,11 @@ static void gen_farith (DisasContext *ct
         check_insn(ctx, ISA_MIPS32R6);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
+            TCGv_i32 msa = tcg_const_i32(0);
             gen_load_fpr32(fp0, fs);
-            gen_helper_float_class_s(fp0, fp0);
+            gen_helper_float_class_s(fp0, cpu_env, fp0, msa);
             gen_store_fpr32(fp0, fd);
+            tcg_temp_free_i32(msa);
             tcg_temp_free_i32(fp0);
             opn = "class.s";
         }
@@ -9517,9 +9519,11 @@ static void gen_farith (DisasContext *ct
         check_insn(ctx, ISA_MIPS32R6);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
+            TCGv_i32 msa = tcg_const_i32(0);
             gen_load_fpr64(ctx, fp0, fs);
-            gen_helper_float_class_d(fp0, fp0);
+            gen_helper_float_class_d(fp0, cpu_env, fp0, msa);
             gen_store_fpr64(ctx, fp0, fd);
+            tcg_temp_free_i32(msa);
             tcg_temp_free_i64(fp0);
             opn = "class.d";
         }
Index: qemu-git-trunk/target-ppc/fpu_helper.c
===================================================================
--- qemu-git-trunk.orig/target-ppc/fpu_helper.c	2014-12-08 22:36:20.000000000 +0000
+++ qemu-git-trunk/target-ppc/fpu_helper.c	2014-12-08 22:37:36.758946934 +0000
@@ -69,7 +69,7 @@ uint32_t helper_compute_fprf(CPUPPCState
     farg.ll = arg;
     isneg = float64_is_neg(farg.d);
     if (unlikely(float64_is_any_nan(farg.d))) {
-        if (float64_is_signaling_nan(farg.d)) {
+        if (float64_is_signaling_nan(farg.d, &env->fp_status)) {
             /* Signaling NaN: flags are undefined */
             ret = 0x00;
         } else {
@@ -534,8 +534,8 @@ uint64_t helper_fadd(CPUPPCState *env, u
         /* Magnitude subtraction of infinities */
         farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
     } else {
-        if (unlikely(float64_is_signaling_nan(farg1.d) ||
-                     float64_is_signaling_nan(farg2.d))) {
+        if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
+                     float64_is_signaling_nan(farg2.d, &env->fp_status))) {
             /* sNaN addition */
             fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
         }
@@ -558,8 +558,8 @@ uint64_t helper_fsub(CPUPPCState *env, u
         /* Magnitude subtraction of infinities */
         farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
     } else {
-        if (unlikely(float64_is_signaling_nan(farg1.d) ||
-                     float64_is_signaling_nan(farg2.d))) {
+        if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
+                     float64_is_signaling_nan(farg2.d, &env->fp_status))) {
             /* sNaN subtraction */
             fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
         }
@@ -582,8 +582,8 @@ uint64_t helper_fmul(CPUPPCState *env, u
         /* Multiplication of zero by infinity */
         farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
     } else {
-        if (unlikely(float64_is_signaling_nan(farg1.d) ||
-                     float64_is_signaling_nan(farg2.d))) {
+        if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
+                     float64_is_signaling_nan(farg2.d, &env->fp_status))) {
             /* sNaN multiplication */
             fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
         }
@@ -609,8 +609,8 @@ uint64_t helper_fdiv(CPUPPCState *env, u
         /* Division of zero by zero */
         farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, 1);
     } else {
-        if (unlikely(float64_is_signaling_nan(farg1.d) ||
-                     float64_is_signaling_nan(farg2.d))) {
+        if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
+                     float64_is_signaling_nan(farg2.d, &env->fp_status))) {
             /* sNaN division */
             fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
         }
@@ -632,7 +632,7 @@ uint64_t helper_##op(CPUPPCState *env, u
     if (unlikely(env->fp_status.float_exception_flags)) {              \
         if (float64_is_any_nan(arg)) {                                 \
             fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 1);      \
-            if (float64_is_signaling_nan(arg)) {                       \
+            if (float64_is_signaling_nan(arg, &env->fp_status)) {      \
                 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); \
             }                                                          \
             farg.ll = nanval;                                          \
@@ -681,7 +681,7 @@ static inline uint64_t do_fri(CPUPPCStat
 
     farg.ll = arg;
 
-    if (unlikely(float64_is_signaling_nan(farg.d))) {
+    if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
         /* sNaN round */
         fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
         farg.ll = arg | 0x0008000000000000ULL;
@@ -737,9 +737,9 @@ uint64_t helper_fmadd(CPUPPCState *env, 
         /* Multiplication of zero by infinity */
         farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
     } else {
-        if (unlikely(float64_is_signaling_nan(farg1.d) ||
-                     float64_is_signaling_nan(farg2.d) ||
-                     float64_is_signaling_nan(farg3.d))) {
+        if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
+                     float64_is_signaling_nan(farg2.d, &env->fp_status) ||
+                     float64_is_signaling_nan(farg3.d, &env->fp_status))) {
             /* sNaN operation */
             fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
         }
@@ -780,9 +780,9 @@ uint64_t helper_fmsub(CPUPPCState *env, 
         /* Multiplication of zero by infinity */
         farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
     } else {
-        if (unlikely(float64_is_signaling_nan(farg1.d) ||
-                     float64_is_signaling_nan(farg2.d) ||
-                     float64_is_signaling_nan(farg3.d))) {
+        if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
+                     float64_is_signaling_nan(farg2.d, &env->fp_status) ||
+                     float64_is_signaling_nan(farg3.d, &env->fp_status))) {
             /* sNaN operation */
             fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
         }
@@ -821,9 +821,9 @@ uint64_t helper_fnmadd(CPUPPCState *env,
         /* Multiplication of zero by infinity */
         farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
     } else {
-        if (unlikely(float64_is_signaling_nan(farg1.d) ||
-                     float64_is_signaling_nan(farg2.d) ||
-                     float64_is_signaling_nan(farg3.d))) {
+        if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
+                     float64_is_signaling_nan(farg2.d, &env->fp_status) ||
+                     float64_is_signaling_nan(farg3.d, &env->fp_status))) {
             /* sNaN operation */
             fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
         }
@@ -866,9 +866,9 @@ uint64_t helper_fnmsub(CPUPPCState *env,
         /* Multiplication of zero by infinity */
         farg1.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1);
     } else {
-        if (unlikely(float64_is_signaling_nan(farg1.d) ||
-                     float64_is_signaling_nan(farg2.d) ||
-                     float64_is_signaling_nan(farg3.d))) {
+        if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) ||
+                     float64_is_signaling_nan(farg2.d, &env->fp_status) ||
+                     float64_is_signaling_nan(farg3.d, &env->fp_status))) {
             /* sNaN operation */
             fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
         }
@@ -903,7 +903,7 @@ uint64_t helper_frsp(CPUPPCState *env, u
 
     farg.ll = arg;
 
-    if (unlikely(float64_is_signaling_nan(farg.d))) {
+    if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
         /* sNaN square root */
         fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
     }
@@ -924,7 +924,7 @@ uint64_t helper_fsqrt(CPUPPCState *env, 
         /* Square root of a negative nonzero number */
         farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
     } else {
-        if (unlikely(float64_is_signaling_nan(farg.d))) {
+        if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
             /* sNaN square root */
             fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
         }
@@ -940,7 +940,7 @@ uint64_t helper_fre(CPUPPCState *env, ui
 
     farg.ll = arg;
 
-    if (unlikely(float64_is_signaling_nan(farg.d))) {
+    if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
         /* sNaN reciprocal */
         fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
     }
@@ -956,7 +956,7 @@ uint64_t helper_fres(CPUPPCState *env, u
 
     farg.ll = arg;
 
-    if (unlikely(float64_is_signaling_nan(farg.d))) {
+    if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
         /* sNaN reciprocal */
         fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
     }
@@ -978,7 +978,7 @@ uint64_t helper_frsqrte(CPUPPCState *env
         /* Reciprocal square root of a negative nonzero number */
         farg.ll = fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
     } else {
-        if (unlikely(float64_is_signaling_nan(farg.d))) {
+        if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
             /* sNaN reciprocal square root */
             fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
         }
@@ -1095,8 +1095,8 @@ void helper_fcmpu(CPUPPCState *env, uint
     env->fpscr |= ret << FPSCR_FPRF;
     env->crf[crfD] = ret;
     if (unlikely(ret == 0x01UL
-                 && (float64_is_signaling_nan(farg1.d) ||
-                     float64_is_signaling_nan(farg2.d)))) {
+                 && (float64_is_signaling_nan(farg1.d, &env->fp_status) ||
+                     float64_is_signaling_nan(farg2.d, &env->fp_status)))) {
         /* sNaN comparison */
         fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
     }
@@ -1126,8 +1126,8 @@ void helper_fcmpo(CPUPPCState *env, uint
     env->fpscr |= ret << FPSCR_FPRF;
     env->crf[crfD] = ret;
     if (unlikely(ret == 0x01UL)) {
-        if (float64_is_signaling_nan(farg1.d) ||
-            float64_is_signaling_nan(farg2.d)) {
+        if (float64_is_signaling_nan(farg1.d, &env->fp_status) ||
+            float64_is_signaling_nan(farg2.d, &env->fp_status)) {
             /* sNaN comparison */
             fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN |
                                   POWERPC_EXCP_FP_VXVC, 1);
@@ -1163,7 +1163,7 @@ static inline int32_t efsctsi(CPUPPCStat
 
     u.l = val;
     /* NaN are not treated the same way IEEE 754 does */
-    if (unlikely(float32_is_quiet_nan(u.f))) {
+    if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) {
         return 0;
     }
 
@@ -1176,7 +1176,7 @@ static inline uint32_t efsctui(CPUPPCSta
 
     u.l = val;
     /* NaN are not treated the same way IEEE 754 does */
-    if (unlikely(float32_is_quiet_nan(u.f))) {
+    if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) {
         return 0;
     }
 
@@ -1189,7 +1189,7 @@ static inline uint32_t efsctsiz(CPUPPCSt
 
     u.l = val;
     /* NaN are not treated the same way IEEE 754 does */
-    if (unlikely(float32_is_quiet_nan(u.f))) {
+    if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) {
         return 0;
     }
 
@@ -1202,7 +1202,7 @@ static inline uint32_t efsctuiz(CPUPPCSt
 
     u.l = val;
     /* NaN are not treated the same way IEEE 754 does */
-    if (unlikely(float32_is_quiet_nan(u.f))) {
+    if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) {
         return 0;
     }
 
@@ -1240,7 +1240,7 @@ static inline uint32_t efsctsf(CPUPPCSta
 
     u.l = val;
     /* NaN are not treated the same way IEEE 754 does */
-    if (unlikely(float32_is_quiet_nan(u.f))) {
+    if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) {
         return 0;
     }
     tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
@@ -1256,7 +1256,7 @@ static inline uint32_t efsctuf(CPUPPCSta
 
     u.l = val;
     /* NaN are not treated the same way IEEE 754 does */
-    if (unlikely(float32_is_quiet_nan(u.f))) {
+    if (unlikely(float32_is_quiet_nan(u.f, &env->vec_status))) {
         return 0;
     }
     tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
@@ -1834,8 +1834,8 @@ void helper_##name(CPUPPCState *env, uin
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
             if (tp##_is_infinity(xa.fld) && tp##_is_infinity(xb.fld)) {      \
                 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, sfprf);    \
-            } else if (tp##_is_signaling_nan(xa.fld) ||                      \
-                       tp##_is_signaling_nan(xb.fld)) {                      \
+            } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||              \
+                       tp##_is_signaling_nan(xb.fld, &tstat)) {              \
                 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   \
             }                                                                \
         }                                                                    \
@@ -1889,8 +1889,8 @@ void helper_##op(CPUPPCState *env, uint3
             if ((tp##_is_infinity(xa.fld) && tp##_is_zero(xb.fld)) ||        \
                 (tp##_is_infinity(xb.fld) && tp##_is_zero(xa.fld))) {        \
                 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, sfprf);    \
-            } else if (tp##_is_signaling_nan(xa.fld) ||                      \
-                       tp##_is_signaling_nan(xb.fld)) {                      \
+            } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||              \
+                       tp##_is_signaling_nan(xb.fld, &tstat)) {              \
                 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   \
             }                                                                \
         }                                                                    \
@@ -1943,8 +1943,8 @@ void helper_##op(CPUPPCState *env, uint3
             } else if (tp##_is_zero(xa.fld) &&                                \
                 tp##_is_zero(xb.fld)) {                                       \
                 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, sfprf);     \
-            } else if (tp##_is_signaling_nan(xa.fld) ||                       \
-                tp##_is_signaling_nan(xb.fld)) {                              \
+            } else if (tp##_is_signaling_nan(xa.fld, &tstat) ||               \
+                tp##_is_signaling_nan(xb.fld, &tstat)) {                      \
                 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);    \
             }                                                                 \
         }                                                                     \
@@ -1985,7 +1985,7 @@ void helper_##op(CPUPPCState *env, uint3
     helper_reset_fpstatus(env);                                               \
                                                                               \
     for (i = 0; i < nels; i++) {                                              \
-        if (unlikely(tp##_is_signaling_nan(xb.fld))) {                        \
+        if (unlikely(tp##_is_signaling_nan(xb.fld, &env->fp_status))) {       \
                 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);    \
         }                                                                     \
         xt.fld = tp##_div(tp##_one, xb.fld, &env->fp_status);                 \
@@ -2034,7 +2034,7 @@ void helper_##op(CPUPPCState *env, uint3
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
             if (tp##_is_neg(xb.fld) && !tp##_is_zero(xb.fld)) {              \
                 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf);   \
-            } else if (tp##_is_signaling_nan(xb.fld)) {                      \
+            } else if (tp##_is_signaling_nan(xb.fld, &tstat)) {              \
                 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   \
             }                                                                \
         }                                                                    \
@@ -2084,7 +2084,7 @@ void helper_##op(CPUPPCState *env, uint3
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {    \
             if (tp##_is_neg(xb.fld) && !tp##_is_zero(xb.fld)) {              \
                 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, sfprf);   \
-            } else if (tp##_is_signaling_nan(xb.fld)) {                      \
+            } else if (tp##_is_signaling_nan(xb.fld, &tstat)) {              \
                 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);   \
             }                                                                \
         }                                                                    \
@@ -2269,9 +2269,9 @@ void helper_##op(CPUPPCState *env, uint3
         env->fp_status.float_exception_flags |= tstat.float_exception_flags;  \
                                                                               \
         if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {     \
-            if (tp##_is_signaling_nan(xa.fld) ||                              \
-                tp##_is_signaling_nan(b->fld) ||                              \
-                tp##_is_signaling_nan(c->fld)) {                              \
+            if (tp##_is_signaling_nan(xa.fld, &tstat) ||                      \
+                tp##_is_signaling_nan(b->fld, &tstat) ||                      \
+                tp##_is_signaling_nan(c->fld, &tstat)) {                      \
                 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf);    \
                 tstat.float_exception_flags &= ~float_flag_invalid;           \
             }                                                                 \
@@ -2353,8 +2353,8 @@ void helper_##op(CPUPPCState *env, uint3
                                                                          \
     if (unlikely(float64_is_any_nan(xa.VsrD(0)) ||                       \
                  float64_is_any_nan(xb.VsrD(0)))) {                      \
-        if (float64_is_signaling_nan(xa.VsrD(0)) ||                      \
-            float64_is_signaling_nan(xb.VsrD(0))) {                      \
+        if (float64_is_signaling_nan(xa.VsrD(0), &env->fp_status) ||     \
+            float64_is_signaling_nan(xb.VsrD(0), &env->fp_status)) {     \
             fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);       \
         }                                                                \
         if (ordered) {                                                   \
@@ -2404,8 +2404,8 @@ void helper_##name(CPUPPCState *env, uin
                                                                               \
     for (i = 0; i < nels; i++) {                                              \
         xt.fld = tp##_##op(xa.fld, xb.fld, &env->fp_status);                  \
-        if (unlikely(tp##_is_signaling_nan(xa.fld) ||                         \
-                     tp##_is_signaling_nan(xb.fld))) {                        \
+        if (unlikely(tp##_is_signaling_nan(xa.fld, &env->fp_status) ||        \
+                     tp##_is_signaling_nan(xb.fld, &env->fp_status))) {       \
             fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);            \
         }                                                                     \
     }                                                                         \
@@ -2444,8 +2444,8 @@ void helper_##op(CPUPPCState *env, uint3
     for (i = 0; i < nels; i++) {                                          \
         if (unlikely(tp##_is_any_nan(xa.fld) ||                           \
                      tp##_is_any_nan(xb.fld))) {                          \
-            if (tp##_is_signaling_nan(xa.fld) ||                          \
-                tp##_is_signaling_nan(xb.fld)) {                          \
+            if (tp##_is_signaling_nan(xa.fld, &env->fp_status) ||         \
+                tp##_is_signaling_nan(xb.fld, &env->fp_status)) {         \
                 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);    \
             }                                                             \
             if (svxvc) {                                                  \
@@ -2498,7 +2498,8 @@ void helper_##op(CPUPPCState *env, uint3
                                                                    \
     for (i = 0; i < nels; i++) {                                   \
         xt.tfld = stp##_to_##ttp(xb.sfld, &env->fp_status);        \
-        if (unlikely(stp##_is_signaling_nan(xb.sfld))) {           \
+        if (unlikely(stp##_is_signaling_nan(xb.sfld,               \
+                                            &env->fp_status))) {   \
             fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \
             xt.tfld = ttp##_snan_to_qnan(xt.tfld);                 \
         }                                                          \
@@ -2553,7 +2554,7 @@ void helper_##op(CPUPPCState *env, uint3
                                                                              \
     for (i = 0; i < nels; i++) {                                             \
         if (unlikely(stp##_is_any_nan(xb.sfld))) {                           \
-            if (stp##_is_signaling_nan(xb.sfld)) {                           \
+            if (stp##_is_signaling_nan(xb.sfld, &env->fp_status)) {          \
                 fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);       \
             }                                                                \
             fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXCVI, 0);            \
@@ -2662,7 +2663,8 @@ void helper_##op(CPUPPCState *env, uint3
     }                                                                  \
                                                                        \
     for (i = 0; i < nels; i++) {                                       \
-        if (unlikely(tp##_is_signaling_nan(xb.fld))) {                 \
+        if (unlikely(tp##_is_signaling_nan(xb.fld,                     \
+                                           &env->fp_status))) {        \
             fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0);     \
             xt.fld = tp##_snan_to_qnan(xb.fld);                        \
         } else {                                                       \
Index: qemu-git-trunk/target-s390x/fpu_helper.c
===================================================================
--- qemu-git-trunk.orig/target-s390x/fpu_helper.c	2014-12-08 22:36:20.000000000 +0000
+++ qemu-git-trunk/target-s390x/fpu_helper.c	2014-12-08 22:37:36.758946934 +0000
@@ -591,7 +591,7 @@ uint64_t HELPER(msdb)(CPUS390XState *env
 }
 
 /* test data class 32-bit */
-uint32_t HELPER(tceb)(uint64_t f1, uint64_t m2)
+uint32_t HELPER(tceb)(CPUS390XState *env, uint64_t f1, uint64_t m2)
 {
     float32 v1 = f1;
     int neg = float32_is_neg(v1);
@@ -600,7 +600,8 @@ uint32_t HELPER(tceb)(uint64_t f1, uint6
     if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
         (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
         (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
-        (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
+        (float32_is_signaling_nan(v1, &env->fpu_status) &&
+         (m2 & (1 << (1-neg))))) {
         cc = 1;
     } else if (m2 & (1 << (9-neg))) {
         /* assume normalized number */
@@ -611,7 +612,7 @@ uint32_t HELPER(tceb)(uint64_t f1, uint6
 }
 
 /* test data class 64-bit */
-uint32_t HELPER(tcdb)(uint64_t v1, uint64_t m2)
+uint32_t HELPER(tcdb)(CPUS390XState *env, uint64_t v1, uint64_t m2)
 {
     int neg = float64_is_neg(v1);
     uint32_t cc = 0;
@@ -619,7 +620,8 @@ uint32_t HELPER(tcdb)(uint64_t v1, uint6
     if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
         (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
         (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
-        (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
+        (float64_is_signaling_nan(v1, &env->fpu_status) &&
+         (m2 & (1 << (1-neg))))) {
         cc = 1;
     } else if (m2 & (1 << (9-neg))) {
         /* assume normalized number */
@@ -630,7 +632,8 @@ uint32_t HELPER(tcdb)(uint64_t v1, uint6
 }
 
 /* test data class 128-bit */
-uint32_t HELPER(tcxb)(uint64_t ah, uint64_t al, uint64_t m2)
+uint32_t HELPER(tcxb)(CPUS390XState *env, uint64_t ah,
+                      uint64_t al, uint64_t m2)
 {
     float128 v1 = make_float128(ah, al);
     int neg = float128_is_neg(v1);
@@ -639,7 +642,8 @@ uint32_t HELPER(tcxb)(uint64_t ah, uint6
     if ((float128_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
         (float128_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
         (float128_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
-        (float128_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
+        (float128_is_signaling_nan(v1, &env->fpu_status) &&
+         (m2 & (1 << (1-neg))))) {
         cc = 1;
     } else if (m2 & (1 << (9-neg))) {
         /* assume normalized number */
Index: qemu-git-trunk/target-s390x/helper.h
===================================================================
--- qemu-git-trunk.orig/target-s390x/helper.h	2014-12-08 22:36:20.000000000 +0000
+++ qemu-git-trunk/target-s390x/helper.h	2014-12-08 22:37:36.758946934 +0000
@@ -68,9 +68,9 @@ DEF_HELPER_FLAGS_4(maeb, TCG_CALL_NO_WG,
 DEF_HELPER_FLAGS_4(madb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_4(mseb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_4(msdb, TCG_CALL_NO_WG, i64, env, i64, i64, i64)
-DEF_HELPER_FLAGS_2(tceb, TCG_CALL_NO_RWG_SE, i32, i64, i64)
-DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_NO_RWG_SE, i32, i64, i64)
-DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_NO_RWG_SE, i32, i64, i64, i64)
+DEF_HELPER_FLAGS_3(tceb, TCG_CALL_NO_RWG_SE, i32, env, i64, i64)
+DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_NO_RWG_SE, i32, env, i64, i64)
+DEF_HELPER_FLAGS_4(tcxb, TCG_CALL_NO_RWG_SE, i32, env, i64, i64, i64)
 DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, i64, i64)
 DEF_HELPER_FLAGS_2(sqeb, TCG_CALL_NO_WG, i64, env, i64)
 DEF_HELPER_FLAGS_2(sqdb, TCG_CALL_NO_WG, i64, env, i64)
Index: qemu-git-trunk/target-s390x/translate.c
===================================================================
--- qemu-git-trunk.orig/target-s390x/translate.c	2014-12-08 22:36:20.000000000 +0000
+++ qemu-git-trunk/target-s390x/translate.c	2014-12-08 22:37:36.758946934 +0000
@@ -3513,21 +3513,21 @@ static ExitStatus op_svc(DisasContext *s
 
 static ExitStatus op_tceb(DisasContext *s, DisasOps *o)
 {
-    gen_helper_tceb(cc_op, o->in1, o->in2);
+    gen_helper_tceb(cc_op, cpu_env, o->in1, o->in2);
     set_cc_static(s);
     return NO_EXIT;
 }
 
 static ExitStatus op_tcdb(DisasContext *s, DisasOps *o)
 {
-    gen_helper_tcdb(cc_op, o->in1, o->in2);
+    gen_helper_tcdb(cc_op, cpu_env, o->in1, o->in2);
     set_cc_static(s);
     return NO_EXIT;
 }
 
 static ExitStatus op_tcxb(DisasContext *s, DisasOps *o)
 {
-    gen_helper_tcxb(cc_op, o->out, o->out2, o->in2);
+    gen_helper_tcxb(cc_op, cpu_env, o->out, o->out2, o->in2);
     set_cc_static(s);
     return NO_EXIT;
 }

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [Qemu-devel] [PATCH 5/7] softfloat: Rework `*_is_*_nan' functions
  2014-12-09  1:54 [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support Maciej W. Rozycki
                   ` (3 preceding siblings ...)
  2014-12-09  1:55 ` [Qemu-devel] [PATCH 4/7] softfloat: Add SoftFloat status parameter to `*_nan' functions Maciej W. Rozycki
@ 2014-12-09  1:55 ` Maciej W. Rozycki
  2014-12-12 19:35   ` [Qemu-devel] [PATCH v2 " Maciej W. Rozycki
  2014-12-09  1:55 ` [Qemu-devel] [PATCH 6/7] softfloat: Add SoftFloat status `nan2008_mode' flag Maciej W. Rozycki
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-12-09  1:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: Leon Alrae, Thomas Schwinge, Aurelien Jarno

Precompute the possible results, and then pick the suitable one.  The 
calculation of the unused result will be optimized away by the compiler 
at any reasonable optimization level, so no run-time performance loss.

Signed-off-by: Thomas Schwinge <thomas@codesourcery.com>
Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
qemu-softfloat-nan-precompute.diff
Index: qemu-git-trunk/fpu/softfloat-specialize.h
===================================================================
--- qemu-git-trunk.orig/fpu/softfloat-specialize.h	2014-12-01 21:58:05.937673826 +0000
+++ qemu-git-trunk/fpu/softfloat-specialize.h	2014-12-01 22:58:50.328200913 +0000
@@ -159,10 +159,13 @@ int float16_is_signaling_nan(float16 a_ 
 int float16_is_quiet_nan(float16 a_ STATUS_PARAM)
 {
     uint16_t a = float16_val(a_);
+    int __attribute__ ((unused)) x, y;
+    x = (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
+    y = (a & ~0x8000) >= 0x7c80;
 #if SNAN_BIT_IS_ONE
-    return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
+    return x;
 #else
-    return ((a & ~0x8000) >= 0x7c80);
+    return y;
 #endif
 }
 
@@ -174,10 +177,13 @@ int float16_is_quiet_nan(float16 a_ STAT
 int float16_is_signaling_nan(float16 a_ STATUS_PARAM)
 {
     uint16_t a = float16_val(a_);
+    int __attribute__ ((unused)) x, y;
+    x = (a & ~0x8000) >= 0x7c80;
+    y = (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
 #if SNAN_BIT_IS_ONE
-    return ((a & ~0x8000) >= 0x7c80);
+    return x;
 #else
-    return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
+    return y;
 #endif
 }
 #endif
@@ -263,10 +269,13 @@ int float32_is_signaling_nan(float32 a_ 
 int float32_is_quiet_nan(float32 a_ STATUS_PARAM)
 {
     uint32_t a = float32_val(a_);
+    int __attribute__ ((unused)) x, y;
+    x = (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
+    y = 0xFF800000 <= (uint32_t) (a << 1);
 #if SNAN_BIT_IS_ONE
-    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
+    return x;
 #else
-    return ( 0xFF800000 <= (uint32_t) ( a<<1 ) );
+    return y;
 #endif
 }
 
@@ -278,10 +287,13 @@ int float32_is_quiet_nan(float32 a_ STAT
 int float32_is_signaling_nan(float32 a_ STATUS_PARAM)
 {
     uint32_t a = float32_val(a_);
+    int __attribute__ ((unused)) x, y;
+    x = 0xFF800000 <= (uint32_t) (a << 1);
+    y = (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
 #if SNAN_BIT_IS_ONE
-    return ( 0xFF800000 <= (uint32_t) ( a<<1 ) );
+    return x;
 #else
-    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
+    return y;
 #endif
 }
 #endif
@@ -673,12 +685,13 @@ int float64_is_signaling_nan(float64 a_ 
 int float64_is_quiet_nan(float64 a_ STATUS_PARAM)
 {
     uint64_t a = float64_val(a_);
+    int __attribute__ ((unused)) x, y;
+    x = (((a >> 51) & 0xFFF) == 0xFFE) && (a & LIT64(0x0007FFFFFFFFFFFF));
+    y = LIT64(0xFFF0000000000000) <= (uint64_t) (a << 1);
 #if SNAN_BIT_IS_ONE
-    return
-           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
-        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
+    return x;
 #else
-    return ( LIT64( 0xFFF0000000000000 ) <= (uint64_t) ( a<<1 ) );
+    return y;
 #endif
 }
 
@@ -690,12 +703,13 @@ int float64_is_quiet_nan(float64 a_ STAT
 int float64_is_signaling_nan(float64 a_ STATUS_PARAM)
 {
     uint64_t a = float64_val(a_);
+    int __attribute__ ((unused)) x, y;
+    x = LIT64(0xFFF0000000000000) <= (uint64_t) (a << 1);
+    y = (((a >> 51) & 0xFFF) == 0xFFE) && (a & LIT64(0x0007FFFFFFFFFFFF));
 #if SNAN_BIT_IS_ONE
-    return ( LIT64( 0xFFF0000000000000 ) <= (uint64_t) ( a<<1 ) );
+    return x;
 #else
-    return
-           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
-        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
+    return y;
 #endif
 }
 #endif
@@ -874,17 +888,18 @@ int floatx80_is_signaling_nan(floatx80 a
 
 int floatx80_is_quiet_nan(floatx80 a STATUS_PARAM)
 {
-#if SNAN_BIT_IS_ONE
     uint64_t aLow;
-
-    aLow = a.low & ~ LIT64( 0x4000000000000000 );
-    return
-           ( ( a.high & 0x7FFF ) == 0x7FFF )
-        && (uint64_t) ( aLow<<1 )
-        && ( a.low == aLow );
+    int __attribute__ ((unused)) x, y;
+    aLow = a.low & ~LIT64(0x4000000000000000);
+    x = (((a.high & 0x7FFF) == 0x7FFF)
+         && (uint64_t) (aLow << 1)
+         && (a.low == aLow));
+    y = (((a.high & 0x7FFF) == 0x7FFF)
+         && (LIT64(0x8000000000000000) <= ((uint64_t) (a.low << 1))));
+#if SNAN_BIT_IS_ONE
+    return x;
 #else
-    return ( ( a.high & 0x7FFF ) == 0x7FFF )
-        && (LIT64( 0x8000000000000000 ) <= ((uint64_t) ( a.low<<1 )));
+    return y;
 #endif
 }
 
@@ -896,17 +911,18 @@ int floatx80_is_quiet_nan(floatx80 a STA
 
 int floatx80_is_signaling_nan(floatx80 a STATUS_PARAM)
 {
+    uint64_t aLow;
+    int __attribute__ ((unused)) x, y;
+    aLow = a.low & ~LIT64(0x4000000000000000);
+    x = (((a.high & 0x7FFF) == 0x7FFF)
+         && (LIT64(0x8000000000000000) <= ((uint64_t) (a.low << 1))));
+    y = (((a.high & 0x7FFF) == 0x7FFF)
+         && (uint64_t) (aLow << 1)
+         && (a.low == aLow));
 #if SNAN_BIT_IS_ONE
-    return ( ( a.high & 0x7FFF ) == 0x7FFF )
-        && (LIT64( 0x8000000000000000 ) <= ((uint64_t) ( a.low<<1 )));
+    return x;
 #else
-    uint64_t aLow;
-
-    aLow = a.low & ~ LIT64( 0x4000000000000000 );
-    return
-           ( ( a.high & 0x7FFF ) == 0x7FFF )
-        && (uint64_t) ( aLow<<1 )
-        && ( a.low == aLow );
+    return y;
 #endif
 }
 #endif
@@ -1035,14 +1051,15 @@ int float128_is_signaling_nan(float128 a
 
 int float128_is_quiet_nan(float128 a STATUS_PARAM)
 {
+    int __attribute__ ((unused)) x, y;
+    x = ((((a.high >> 47) & 0xFFFF) == 0xFFFE)
+         && (a.low || (a.high & LIT64(0x00007FFFFFFFFFFF))));
+    y = ((LIT64(0xFFFE000000000000) <= (uint64_t) (a.high << 1))
+         && (a.low || (a.high & LIT64(0x0000FFFFFFFFFFFF))));
 #if SNAN_BIT_IS_ONE
-    return
-           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
-        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
+    return x;
 #else
-    return
-           ( LIT64( 0xFFFE000000000000 ) <= (uint64_t) ( a.high<<1 ) )
-        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
+    return y;
 #endif
 }
 
@@ -1053,14 +1070,15 @@ int float128_is_quiet_nan(float128 a STA
 
 int float128_is_signaling_nan(float128 a STATUS_PARAM)
 {
+    int __attribute__ ((unused)) x, y;
+    x = ((LIT64(0xFFFE000000000000) <= (uint64_t) (a.high << 1))
+         && (a.low || (a.high & LIT64(0x0000FFFFFFFFFFFF))));
+    y = ((((a.high >> 47) & 0xFFFF) == 0xFFFE)
+         && (a.low || (a.high & LIT64(0x00007FFFFFFFFFFF))));
 #if SNAN_BIT_IS_ONE
-    return
-           ( LIT64( 0xFFFE000000000000 ) <= (uint64_t) ( a.high<<1 ) )
-        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
+    return x;
 #else
-    return
-           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
-        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
+    return y;
 #endif
 }
 #endif

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [Qemu-devel] [PATCH 6/7] softfloat: Add SoftFloat status `nan2008_mode' flag
  2014-12-09  1:54 [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support Maciej W. Rozycki
                   ` (4 preceding siblings ...)
  2014-12-09  1:55 ` [Qemu-devel] [PATCH 5/7] softfloat: Rework `*_is_*_nan' functions Maciej W. Rozycki
@ 2014-12-09  1:55 ` Maciej W. Rozycki
  2014-12-12 19:35   ` [Qemu-devel] [PATCH v2 " Maciej W. Rozycki
  2014-12-09  1:56 ` [Qemu-devel] [PATCH 7/7] target-mips: Add IEEE 754-2008 features support Maciej W. Rozycki
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-12-09  1:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: Leon Alrae, Thomas Schwinge, Aurelien Jarno

Add support for switching between legacy NaN and IEEE 754-2008 NaN modes 
where required, currently for the MIPS target only.  Also handle the 
saving and restoration of the `nan2008_mode' status flag.

Use qNaN bit patterns for the 2008 NaN mode as from revision 5.00 [1][2] 
of the MIPS Architecture, updated from revision 3.50 that used a 
different choice.

References:

[1] "MIPS Architecture For Programmers, Volume I-A: Introduction to the
    MIPS32 Architecture", MIPS Technologies, Inc., Document Number:
    MD00082, Revision 5.02, April 30, 2013, Table 5.3 "Value Supplied 
    When a New Quiet NaN Is Created", p. 73

[2] "MIPS Architecture For Programmers, Volume I-A: Introduction to the
    MIPS64 Architecture", MIPS Technologies, Inc., Document Number:
    MD00083, Revision 5.01, December 15, 2012, Table 5.3 "Value Supplied 
    When a New Quiet NaN Is Created", p. 73

Signed-off-by: Thomas Schwinge <thomas@codesourcery.com>
Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
 I missed revision 5.00 of the architecture documents before they were 
taken offline; however there have been no changes to Table 5.3 between 
revision 5.00 and, respectively, revisions 5.02 and 5.01 of these 
documents according to the revision history included there.

 Please apply.

qemu-softfloat-nan2008.diff
Index: qemu-git-trunk/fpu/softfloat-specialize.h
===================================================================
--- qemu-git-trunk.orig/fpu/softfloat-specialize.h	2014-12-08 22:57:38.000000000 +0000
+++ qemu-git-trunk/fpu/softfloat-specialize.h	2014-12-08 23:24:19.558923071 +0000
@@ -35,10 +35,16 @@ these four paragraphs for those parts of
 
 =============================================================================*/
 
-#if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-#define SNAN_BIT_IS_ONE		1
+#if defined(TARGET_MIPS)
+/* Has to be decided dynamically.  */
+#define SNAN_BIT_IS_VARIABLE   1
+#define SNAN_BIT_IS_ONE        0
+#elif defined(TARGET_SH4) || defined(TARGET_UNICORE32)
+#define SNAN_BIT_IS_VARIABLE   0
+#define SNAN_BIT_IS_ONE        1
 #else
-#define SNAN_BIT_IS_ONE		0
+#define SNAN_BIT_IS_VARIABLE   0
+#define SNAN_BIT_IS_ONE        0
 #endif
 
 #if defined(TARGET_XTENSA)
@@ -55,6 +61,10 @@ inline float16 float16_default_nan(STATU
 {
 #if defined(TARGET_ARM)
     return const_float16(0x7E00);
+#elif SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode)
+           ? const_float16(0x7E00)
+           : const_float16(0x7DFF);
 #elif SNAN_BIT_IS_ONE
     return const_float16(0x7DFF);
 #else
@@ -72,6 +82,10 @@ inline float32 float32_default_nan(STATU
 #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
       defined(TARGET_XTENSA)
     return const_float32(0x7FC00000);
+#elif SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode)
+           ? const_float32(0x7FC00000)
+           : const_float32(0x7FBFFFFF);
 #elif SNAN_BIT_IS_ONE
     return const_float32(0x7FBFFFFF);
 #else
@@ -88,6 +102,10 @@ inline float64 float64_default_nan(STATU
     return const_float64(LIT64(0x7FFFFFFFFFFFFFFF));
 #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
     return const_float64(LIT64(0x7FF8000000000000));
+#elif SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode)
+           ? const_float64(LIT64(0x7FF8000000000000))
+           : const_float64(LIT64(0x7FF7FFFFFFFFFFFF));
 #elif SNAN_BIT_IS_ONE
     return const_float64(LIT64(0x7FF7FFFFFFFFFFFF));
 #else
@@ -100,7 +118,11 @@ inline float64 float64_default_nan(STATU
 *----------------------------------------------------------------------------*/
 inline floatx80 floatx80_default_nan(STATUS_PARAM_ONLY)
 {
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode)
+           ? make_floatx80(0xFFFF, LIT64(0xC000000000000000))
+           : make_floatx80(0x7FFF, LIT64(0xBFFFFFFFFFFFFFFF));
+#elif SNAN_BIT_IS_ONE
     return make_floatx80(0x7FFF, LIT64(0xBFFFFFFFFFFFFFFF));
 #else
     return make_floatx80(0xFFFF, LIT64(0xC000000000000000));
@@ -113,7 +135,13 @@ inline floatx80 floatx80_default_nan(STA
 *----------------------------------------------------------------------------*/
 inline float128 float128_default_nan(STATUS_PARAM_ONLY)
 {
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode)
+           ? make_float128(LIT64(0x7FFF800000000000),
+                           LIT64(0x0000000000000000))
+           : make_float128(LIT64(0x7FFF7FFFFFFFFFFF),
+                           LIT64(0xFFFFFFFFFFFFFFFF));
+#elif SNAN_BIT_IS_ONE
     return make_float128(LIT64(0x7FFF7FFFFFFFFFFF), LIT64(0xFFFFFFFFFFFFFFFF));
 #else
     return make_float128(LIT64(0xFFFF800000000000), LIT64(0x0000000000000000));
@@ -162,7 +190,9 @@ int float16_is_quiet_nan(float16 a_ STAT
     int __attribute__ ((unused)) x, y;
     x = (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
     y = (a & ~0x8000) >= 0x7c80;
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -180,7 +210,9 @@ int float16_is_signaling_nan(float16 a_ 
     int __attribute__ ((unused)) x, y;
     x = (a & ~0x8000) >= 0x7c80;
     y = (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -195,8 +227,10 @@ int float16_is_signaling_nan(float16 a_ 
 float16 float16_maybe_silence_nan(float16 a_ STATUS_PARAM)
 {
     if (float16_is_signaling_nan(a_ STATUS_VAR)) {
-#if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
+#if SNAN_BIT_IS_VARIABLE
+        return float16_default_nan(status);
+#elif SNAN_BIT_IS_ONE
+#  if defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         return float16_default_nan(status);
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
@@ -272,7 +306,9 @@ int float32_is_quiet_nan(float32 a_ STAT
     int __attribute__ ((unused)) x, y;
     x = (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
     y = 0xFF800000 <= (uint32_t) (a << 1);
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -290,7 +326,9 @@ int float32_is_signaling_nan(float32 a_ 
     int __attribute__ ((unused)) x, y;
     x = 0xFF800000 <= (uint32_t) (a << 1);
     y = (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -306,8 +344,10 @@ int float32_is_signaling_nan(float32 a_ 
 float32 float32_maybe_silence_nan(float32 a_ STATUS_PARAM)
 {
     if (float32_is_signaling_nan(a_ STATUS_VAR)) {
-#if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
+#if SNAN_BIT_IS_VARIABLE
+        return float32_default_nan(status);
+#elif SNAN_BIT_IS_ONE
+#  if defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         return float32_default_nan(status);
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
@@ -688,7 +728,9 @@ int float64_is_quiet_nan(float64 a_ STAT
     int __attribute__ ((unused)) x, y;
     x = (((a >> 51) & 0xFFF) == 0xFFE) && (a & LIT64(0x0007FFFFFFFFFFFF));
     y = LIT64(0xFFF0000000000000) <= (uint64_t) (a << 1);
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -706,7 +748,9 @@ int float64_is_signaling_nan(float64 a_ 
     int __attribute__ ((unused)) x, y;
     x = LIT64(0xFFF0000000000000) <= (uint64_t) (a << 1);
     y = (((a >> 51) & 0xFFF) == 0xFFE) && (a & LIT64(0x0007FFFFFFFFFFFF));
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -722,8 +766,10 @@ int float64_is_signaling_nan(float64 a_ 
 float64 float64_maybe_silence_nan(float64 a_ STATUS_PARAM)
 {
     if (float64_is_signaling_nan(a_ STATUS_VAR)) {
-#if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
+#if SNAN_BIT_IS_VARIABLE
+        return float64_default_nan(status);
+#elif SNAN_BIT_IS_ONE
+#  if defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         return float64_default_nan(status);
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
@@ -896,7 +942,9 @@ int floatx80_is_quiet_nan(floatx80 a STA
          && (a.low == aLow));
     y = (((a.high & 0x7FFF) == 0x7FFF)
          && (LIT64(0x8000000000000000) <= ((uint64_t) (a.low << 1))));
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -919,7 +967,9 @@ int floatx80_is_signaling_nan(floatx80 a
     y = (((a.high & 0x7FFF) == 0x7FFF)
          && (uint64_t) (aLow << 1)
          && (a.low == aLow));
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -935,8 +985,10 @@ int floatx80_is_signaling_nan(floatx80 a
 floatx80 floatx80_maybe_silence_nan(floatx80 a STATUS_PARAM)
 {
     if (floatx80_is_signaling_nan(a STATUS_VAR)) {
-#if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
+#if SNAN_BIT_IS_VARIABLE
+        a = floatx80_default_nan(status);
+#elif SNAN_BIT_IS_ONE
+#  if defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         a = floatx80_default_nan(status);
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
@@ -1056,7 +1108,9 @@ int float128_is_quiet_nan(float128 a STA
          && (a.low || (a.high & LIT64(0x00007FFFFFFFFFFF))));
     y = ((LIT64(0xFFFE000000000000) <= (uint64_t) (a.high << 1))
          && (a.low || (a.high & LIT64(0x0000FFFFFFFFFFFF))));
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -1075,7 +1129,9 @@ int float128_is_signaling_nan(float128 a
          && (a.low || (a.high & LIT64(0x0000FFFFFFFFFFFF))));
     y = ((((a.high >> 47) & 0xFFFF) == 0xFFFE)
          && (a.low || (a.high & LIT64(0x00007FFFFFFFFFFF))));
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -1091,8 +1147,10 @@ int float128_is_signaling_nan(float128 a
 float128 float128_maybe_silence_nan(float128 a STATUS_PARAM)
 {
     if (float128_is_signaling_nan(a STATUS_VAR)) {
-#if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
+#if SNAN_BIT_IS_VARIABLE
+        a = float128_default_nan(status);
+#elif SNAN_BIT_IS_ONE
+#  if defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         a = float128_default_nan(status);
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
Index: qemu-git-trunk/include/fpu/softfloat.h
===================================================================
--- qemu-git-trunk.orig/include/fpu/softfloat.h	2014-12-08 22:57:37.000000000 +0000
+++ qemu-git-trunk/include/fpu/softfloat.h	2014-12-08 22:59:22.897902279 +0000
@@ -179,6 +179,7 @@ typedef struct float_status {
     /* should denormalised inputs go to zero and set the input_denormal flag? */
     flag flush_inputs_to_zero;
     flag default_nan_mode;
+    flag nan2008_mode;
 } float_status;
 
 static inline void set_float_detect_tininess(int val STATUS_PARAM)
@@ -209,6 +210,10 @@ static inline void set_default_nan_mode(
 {
     STATUS(default_nan_mode) = val;
 }
+static inline void set_nan2008_mode(flag val STATUS_PARAM)
+{
+    STATUS(nan2008_mode) = val;
+}
 static inline int get_float_detect_tininess(float_status *status)
 {
     return STATUS(float_detect_tininess);
Index: qemu-git-trunk/target-mips/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-mips/cpu.h	2014-12-08 22:57:37.000000000 +0000
+++ qemu-git-trunk/target-mips/cpu.h	2014-12-08 23:22:12.537811707 +0000
@@ -615,7 +615,11 @@ void mips_cpu_list (FILE *f, fprintf_fun
 extern void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env);
 extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env);
 
-#define CPU_SAVE_VERSION 7
+#define CPU_SAVE_VERSION 8
+/* We preserve compatibility with rev. 7 images.  */
+#define CPU_SAVE_VERSION_OLDEST_SUPPORTED 7
+/* Rev. 8 added 2008 NaN support.  */
+#define CPU_SAVE_VERSION_2008_NAN 8
 
 /* MMU modes definitions. We carefully match the indices with our
    hflags layout. */
Index: qemu-git-trunk/target-mips/machine.c
===================================================================
--- qemu-git-trunk.orig/target-mips/machine.c	2014-12-08 22:57:37.000000000 +0000
+++ qemu-git-trunk/target-mips/machine.c	2014-12-08 22:59:22.897902279 +0000
@@ -39,6 +39,7 @@ static void save_fpu(QEMUFile *f, CPUMIP
     for(i = 0; i < 32; i++)
         qemu_put_be64s(f, &fpu->fpr[i].d);
     qemu_put_8s(f, &fpu->fp_status.flush_to_zero);
+    qemu_put_8s(f, &fpu->fp_status.nan2008_mode);
     qemu_put_s8s(f, &fpu->fp_status.float_rounding_mode);
     qemu_put_s8s(f, &fpu->fp_status.float_exception_flags);
     qemu_put_be32s(f, &fpu->fcr0);
@@ -195,13 +196,18 @@ static void load_tc(QEMUFile *f, TCState
     qemu_get_8s(f, &tc->msa_fp_status.flush_inputs_to_zero);
 }
 
-static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
+static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu, int version_id)
 {
     int i;
 
     for(i = 0; i < 32; i++)
         qemu_get_be64s(f, &fpu->fpr[i].d);
     qemu_get_8s(f, &fpu->fp_status.flush_to_zero);
+    if (version_id >= CPU_SAVE_VERSION_2008_NAN) {
+        qemu_get_8s(f, &fpu->fp_status.nan2008_mode);
+    } else {
+        fpu->fp_status.nan2008_mode = 0;
+    }
     qemu_get_s8s(f, &fpu->fp_status.float_rounding_mode);
     qemu_get_s8s(f, &fpu->fp_status.float_exception_flags);
     qemu_get_be32s(f, &fpu->fcr0);
@@ -214,7 +220,7 @@ int cpu_load(QEMUFile *f, void *opaque, 
     MIPSCPU *cpu = mips_env_get_cpu(env);
     int i;
 
-    if (version_id != CPU_SAVE_VERSION) {
+    if (version_id < CPU_SAVE_VERSION_OLDEST_SUPPORTED) {
         return -EINVAL;
     }
 
@@ -222,7 +228,7 @@ int cpu_load(QEMUFile *f, void *opaque, 
     load_tc(f, &env->active_tc);
 
     /* Load active FPU */
-    load_fpu(f, &env->active_fpu);
+    load_fpu(f, &env->active_fpu, version_id);
 
     /* Load MVP */
     qemu_get_sbe32s(f, &env->mvp->CP0_MVPControl);
@@ -336,8 +342,9 @@ int cpu_load(QEMUFile *f, void *opaque, 
     for (i = 0; i < MIPS_SHADOW_SET_MAX; i++) {
         load_tc(f, &env->tcs[i]);
     }
-    for (i = 0; i < MIPS_FPU_MAX; i++)
-        load_fpu(f, &env->fpus[i]);
+    for (i = 0; i < MIPS_FPU_MAX; i++) {
+        load_fpu(f, &env->fpus[i], version_id);
+    }
 
     /* XXX: ensure compatibility for halted bit ? */
     tlb_flush(CPU(cpu), 1);

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [Qemu-devel] [PATCH 7/7] target-mips: Add IEEE 754-2008 features support
  2014-12-09  1:54 [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support Maciej W. Rozycki
                   ` (5 preceding siblings ...)
  2014-12-09  1:55 ` [Qemu-devel] [PATCH 6/7] softfloat: Add SoftFloat status `nan2008_mode' flag Maciej W. Rozycki
@ 2014-12-09  1:56 ` Maciej W. Rozycki
  2015-02-09 17:10   ` Leon Alrae
  2015-02-17 13:55   ` Maciej W. Rozycki
  2014-12-09  9:20 ` [Qemu-devel] [PATCH 0/7] MIPS: " Peter Maydell
  2015-01-30 11:59 ` Peter Maydell
  8 siblings, 2 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-12-09  1:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: Leon Alrae, Thomas Schwinge, Aurelien Jarno

Add support for the IEEE 754-2008 features introduced to revision 3.50 
[1][2] of the MIPS Architecture as follows.

1. IEEE 754-2008 NaN encoding.

   Implement the CP1.FCSR.NAN2008 bit with the expected intepretation.  
   Update code to handle CP1.FCSR.NAN2008 correctly in CTC1 and the GDB 
   stub, and to respect the bit in SoftFloat and integer conversion 
   operations.  Strap MSA operations to the 2008-NaN mode as per the MSA 
   architecture specification [3]; the MSACSR register has no 
   corresponding NAN2008 bit.

   Configure CP1.FCSR.NAN2008 at startup in the Linux user emulation 
   mode according to the value of the EF_MIPS_NAN2008 ELF file header 
   flag of the executable invoked, or reject it if the requested NaN 
   mode is not supported by the processor selected for emulation.

2. IEEE 754-2008 non-arithmetic ABS and NEG instructions.

   Reimplement legacy ABS.fmt and NEG.fmt instructions as arithmetic, as 
   defined by the MIPS Architecture.  Implement the CP1.FCSR.ABS2008 
   bits with the expected intepretation.  Update code to respect the bit 
   in the implementation of the ABS.fmt and NEG.fmt instructions.

Implement the CP1.FIR.HAS2008 bit with the expected meaning.  Implement 
a CP1.FCSR reset value and r/w bit mask so that NAN2008 and ABS2008 bits 
can be r/o or r/w and preset as required; as a side effect correctly 
handle the remaining CP1.FCSR bits that can be r/o or r/w depending on 
the architecture level, specifically FCC[7:1]; FS could benefit sometime 
too.

References:

[1] "MIPS Architecture For Programmers, Volume I-A: Introduction to the
    MIPS32 Architecture", MIPS Technologies, Inc., Document Number:
    MD00082, Revision 3.50, September 20, 2012, Section 2.1.2.3 "MIPSr3
    Architecture", p. 21

[2] "MIPS Architecture For Programmers, Volume I-A: Introduction to the
    MIPS64 Architecture", MIPS Technologies, Inc., Document Number:
    MD00083, Revision 3.50, September 20, 2012, Section 2.1.2.3 "MIPSr3
    Architecture", p. 21

[3] "MIPS Architecture for Programmers, Volume IV-j: The MIPS32 SIMD
    Architecture Module", MIPS Technologies, Inc., Document Number:
    MD00866, Revision 1.07, October 2, 2013, Section 3.3.2 
    "Floating-Point Registers Mapping", p. 38

Signed-off-by: Thomas Schwinge <thomas@codesourcery.com>
Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
 Shall I post the artificial *-nan2008 processors we've been using for 
testing or will you be adding real CPU templates with CP1.FCSR NAN2008 
and ABS2008 bits writable?

  Maciej

qemu-mips-nan2008.diff
Index: qemu-git-trunk/include/elf.h
===================================================================
--- qemu-git-trunk.orig/include/elf.h	2014-12-08 23:22:12.000000000 +0000
+++ qemu-git-trunk/include/elf.h	2014-12-08 23:25:02.558929097 +0000
@@ -53,6 +53,7 @@ typedef int64_t  Elf64_Sxword;
 #define EF_MIPS_ABI2		0x00000020
 #define EF_MIPS_OPTIONS_FIRST	0x00000080
 #define EF_MIPS_32BITMODE	0x00000100
+#define EF_MIPS_NAN2008         0x00000400
 #define EF_MIPS_ABI		0x0000f000
 #define EF_MIPS_ARCH      0xf0000000
 
Index: qemu-git-trunk/linux-user/main.c
===================================================================
--- qemu-git-trunk.orig/linux-user/main.c	2014-12-08 23:22:12.000000000 +0000
+++ qemu-git-trunk/linux-user/main.c	2014-12-09 00:48:02.598941233 +0000
@@ -4342,6 +4342,18 @@ int main(int argc, char **argv, char **e
         if (regs->cp0_epc & 1) {
             env->hflags |= MIPS_HFLAG_M16;
         }
+        if (info->elf_flags & EF_MIPS_NAN2008)
+            env->active_fpu.fcr31 |=
+                (1 << FCR31_NAN2008) & env->active_fpu.fcr31_rw_bitmask;
+        else
+            env->active_fpu.fcr31 &=
+                ~((1 << FCR31_NAN2008) & env->active_fpu.fcr31_rw_bitmask);
+        if (((info->elf_flags & EF_MIPS_NAN2008) != 0) !=
+            ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) {
+            fprintf(stderr, "ELF binary's NaN mode not supported by CPU\n");
+            exit(1);
+        }
+        restore_nan_mode(env);
     }
 #elif defined(TARGET_OPENRISC)
     {
Index: qemu-git-trunk/target-mips/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-mips/cpu.h	2014-12-08 23:22:12.000000000 +0000
+++ qemu-git-trunk/target-mips/cpu.h	2014-12-08 23:25:02.558929097 +0000
@@ -102,6 +102,7 @@ struct CPUMIPSFPUContext {
     /* fpu implementation/revision register (fir) */
     uint32_t fcr0;
 #define FCR0_UFRP 28
+#define FCR0_HAS2008 23
 #define FCR0_F64 22
 #define FCR0_L 21
 #define FCR0_W 20
@@ -112,7 +113,10 @@ struct CPUMIPSFPUContext {
 #define FCR0_PRID 8
 #define FCR0_REV 0
     /* fcsr */
+    uint32_t fcr31_rw_bitmask;
     uint32_t fcr31;
+#define FCR31_ABS2008 19
+#define FCR31_NAN2008 18
 #define SET_FP_COND(num,env)     do { ((env).fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
 #define CLEAR_FP_COND(num,env)   do { ((env).fcr31) &= ~((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
 #define GET_FP_COND(env)         ((((env).fcr31 >> 24) & 0xfe) | (((env).fcr31 >> 23) & 0x1))
@@ -793,6 +797,12 @@ static inline void restore_flush_mode(CP
                       &env->active_fpu.fp_status);
 }
 
+static inline void restore_nan_mode(CPUMIPSState *env)
+{
+    set_nan2008_mode((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0,
+                          &env->active_fpu.fp_status);
+}
+
 extern target_ulong mdi_semihost_breakpoint;
 void do_mips_semihosting(CPUMIPSState *env);
 void install_semihosting_breakpoint(CPUState *cs, target_ulong bkpt_address);
Index: qemu-git-trunk/target-mips/gdbstub.c
===================================================================
--- qemu-git-trunk.orig/target-mips/gdbstub.c	2014-12-08 23:22:12.000000000 +0000
+++ qemu-git-trunk/target-mips/gdbstub.c	2014-12-08 23:25:02.558929097 +0000
@@ -91,11 +91,14 @@ int mips_cpu_gdb_write_register(CPUState
     if (env->CP0_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 72) {
         switch (n) {
         case 70:
-            env->active_fpu.fcr31 = tmp & 0xFF83FFFF;
+            env->active_fpu.fcr31 &= ~env->active_fpu.fcr31_rw_bitmask;
+            env->active_fpu.fcr31 |= tmp & env->active_fpu.fcr31_rw_bitmask;
             /* set rounding mode */
             restore_rounding_mode(env);
             /* set flush-to-zero mode */
             restore_flush_mode(env);
+            /* set NaN mode */
+            restore_nan_mode(env);
             break;
         case 71:
             /* FIR is read-only.  Ignore writes.  */
Index: qemu-git-trunk/target-mips/helper.h
===================================================================
--- qemu-git-trunk.orig/target-mips/helper.h	2014-12-08 23:22:12.000000000 +0000
+++ qemu-git-trunk/target-mips/helper.h	2014-12-08 23:25:02.558929097 +0000
@@ -248,12 +248,20 @@ FOP_PROTO(recip)
 FOP_PROTO(rint)
 #undef FOP_PROTO
 
+#define FOP_PROTO(op)                            \
+DEF_HELPER_2(float_ ## op ## _s, i32, env, i32)  \
+DEF_HELPER_2(float_ ## op ## _d, i64, env, i64)  \
+DEF_HELPER_2(float_ ## op ## _ps, i64, env, i64)
+FOP_PROTO(abs)
+FOP_PROTO(chs)
+#undef FOP_PROTO
+
 #define FOP_PROTO(op)                       \
 DEF_HELPER_1(float_ ## op ## _s, i32, i32)  \
 DEF_HELPER_1(float_ ## op ## _d, i64, i64)  \
 DEF_HELPER_1(float_ ## op ## _ps, i64, i64)
-FOP_PROTO(abs)
-FOP_PROTO(chs)
+FOP_PROTO(abs2008)
+FOP_PROTO(chs2008)
 #undef FOP_PROTO
 
 #define FOP_PROTO(op)                            \
Index: qemu-git-trunk/target-mips/op_helper.c
===================================================================
--- qemu-git-trunk.orig/target-mips/op_helper.c	2014-12-08 23:22:12.000000000 +0000
+++ qemu-git-trunk/target-mips/op_helper.c	2014-12-08 23:25:02.558929097 +0000
@@ -2274,8 +2274,12 @@ void mips_cpu_unassigned_access(CPUState
 
 #define FLOAT_TWO32 make_float32(1 << 30)
 #define FLOAT_TWO64 make_float64(1ULL << 62)
-#define FP_TO_INT32_OVERFLOW 0x7fffffff
-#define FP_TO_INT64_OVERFLOW 0x7fffffffffffffffULL
+#define FLOAT_INAN32(env)                                               \
+    (((env)->active_fpu.fcr31 & (1 << FCR31_NAN2008))                   \
+     ? 0x00000000 : 0x7fffffff)
+#define FLOAT_INAN64(env)                                               \
+    (((env)->active_fpu.fcr31 & (1 << FCR31_NAN2008))                   \
+     ? 0x0000000000000000ULL : 0x7fffffffffffffffULL)
 
 /* convert MIPS rounding mode in FCR31 to IEEE library */
 unsigned int ieee_rm[] = {
@@ -2367,13 +2371,8 @@ void helper_ctc1(CPUMIPSState *env, targ
                      ((arg1 & 0x4) << 22);
         break;
     case 31:
-        if (env->insn_flags & ISA_MIPS32R6) {
-            uint32_t mask = 0xfefc0000;
-            env->active_fpu.fcr31 = (arg1 & ~mask) |
-                (env->active_fpu.fcr31 & mask);
-        } else if (!(arg1 & 0x007c0000)) {
-            env->active_fpu.fcr31 = arg1;
-        }
+        env->active_fpu.fcr31 &= ~env->active_fpu.fcr31_rw_bitmask;
+        env->active_fpu.fcr31 |= arg1 & env->active_fpu.fcr31_rw_bitmask;
         break;
     default:
         return;
@@ -2382,6 +2381,8 @@ void helper_ctc1(CPUMIPSState *env, targ
     restore_rounding_mode(env);
     /* set flush-to-zero mode */
     restore_flush_mode(env);
+    /* set NaN mode */
+    restore_nan_mode(env);
     set_float_exception_flags(0, &env->active_fpu.fp_status);
     if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & GET_FP_CAUSE(env->active_fpu.fcr31))
         do_raise_exception(env, EXCP_FPE, GETPC());
@@ -2481,7 +2482,7 @@ uint64_t helper_float_cvtl_d(CPUMIPSStat
     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        dt2 = FP_TO_INT64_OVERFLOW;
+        dt2 = FLOAT_INAN64(env);
     }
     update_fcr31(env, GETPC());
     return dt2;
@@ -2494,7 +2495,7 @@ uint64_t helper_float_cvtl_s(CPUMIPSStat
     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        dt2 = FP_TO_INT64_OVERFLOW;
+        dt2 = FLOAT_INAN64(env);
     }
     update_fcr31(env, GETPC());
     return dt2;
@@ -2520,14 +2521,14 @@ uint64_t helper_float_cvtpw_ps(CPUMIPSSt
     wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
     excp = get_float_exception_flags(&env->active_fpu.fp_status);
     if (excp & (float_flag_overflow | float_flag_invalid)) {
-        wt2 = FP_TO_INT32_OVERFLOW;
+        wt2 = FLOAT_INAN32(env);
     }
 
     set_float_exception_flags(0, &env->active_fpu.fp_status);
     wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status);
     excph = get_float_exception_flags(&env->active_fpu.fp_status);
     if (excph & (float_flag_overflow | float_flag_invalid)) {
-        wth2 = FP_TO_INT32_OVERFLOW;
+        wth2 = FLOAT_INAN32(env);
     }
 
     set_float_exception_flags(excp | excph, &env->active_fpu.fp_status);
@@ -2588,7 +2589,7 @@ uint32_t helper_float_cvtw_s(CPUMIPSStat
     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        wt2 = FP_TO_INT32_OVERFLOW;
+        wt2 = FLOAT_INAN32(env);
     }
     update_fcr31(env, GETPC());
     return wt2;
@@ -2601,7 +2602,7 @@ uint32_t helper_float_cvtw_d(CPUMIPSStat
     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        wt2 = FP_TO_INT32_OVERFLOW;
+        wt2 = FLOAT_INAN32(env);
     }
     update_fcr31(env, GETPC());
     return wt2;
@@ -2616,7 +2617,7 @@ uint64_t helper_float_roundl_d(CPUMIPSSt
     restore_rounding_mode(env);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        dt2 = FP_TO_INT64_OVERFLOW;
+        dt2 = FLOAT_INAN64(env);
     }
     update_fcr31(env, GETPC());
     return dt2;
@@ -2631,7 +2632,7 @@ uint64_t helper_float_roundl_s(CPUMIPSSt
     restore_rounding_mode(env);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        dt2 = FP_TO_INT64_OVERFLOW;
+        dt2 = FLOAT_INAN64(env);
     }
     update_fcr31(env, GETPC());
     return dt2;
@@ -2646,7 +2647,7 @@ uint32_t helper_float_roundw_d(CPUMIPSSt
     restore_rounding_mode(env);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        wt2 = FP_TO_INT32_OVERFLOW;
+        wt2 = FLOAT_INAN32(env);
     }
     update_fcr31(env, GETPC());
     return wt2;
@@ -2661,7 +2662,7 @@ uint32_t helper_float_roundw_s(CPUMIPSSt
     restore_rounding_mode(env);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        wt2 = FP_TO_INT32_OVERFLOW;
+        wt2 = FLOAT_INAN32(env);
     }
     update_fcr31(env, GETPC());
     return wt2;
@@ -2674,7 +2675,7 @@ uint64_t helper_float_truncl_d(CPUMIPSSt
     dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        dt2 = FP_TO_INT64_OVERFLOW;
+        dt2 = FLOAT_INAN64(env);
     }
     update_fcr31(env, GETPC());
     return dt2;
@@ -2687,7 +2688,7 @@ uint64_t helper_float_truncl_s(CPUMIPSSt
     dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        dt2 = FP_TO_INT64_OVERFLOW;
+        dt2 = FLOAT_INAN64(env);
     }
     update_fcr31(env, GETPC());
     return dt2;
@@ -2700,7 +2701,7 @@ uint32_t helper_float_truncw_d(CPUMIPSSt
     wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        wt2 = FP_TO_INT32_OVERFLOW;
+        wt2 = FLOAT_INAN32(env);
     }
     update_fcr31(env, GETPC());
     return wt2;
@@ -2713,7 +2714,7 @@ uint32_t helper_float_truncw_s(CPUMIPSSt
     wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        wt2 = FP_TO_INT32_OVERFLOW;
+        wt2 = FLOAT_INAN32(env);
     }
     update_fcr31(env, GETPC());
     return wt2;
@@ -2728,7 +2729,7 @@ uint64_t helper_float_ceill_d(CPUMIPSSta
     restore_rounding_mode(env);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        dt2 = FP_TO_INT64_OVERFLOW;
+        dt2 = FLOAT_INAN64(env);
     }
     update_fcr31(env, GETPC());
     return dt2;
@@ -2743,7 +2744,7 @@ uint64_t helper_float_ceill_s(CPUMIPSSta
     restore_rounding_mode(env);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        dt2 = FP_TO_INT64_OVERFLOW;
+        dt2 = FLOAT_INAN64(env);
     }
     update_fcr31(env, GETPC());
     return dt2;
@@ -2758,7 +2759,7 @@ uint32_t helper_float_ceilw_d(CPUMIPSSta
     restore_rounding_mode(env);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        wt2 = FP_TO_INT32_OVERFLOW;
+        wt2 = FLOAT_INAN32(env);
     }
     update_fcr31(env, GETPC());
     return wt2;
@@ -2773,7 +2774,7 @@ uint32_t helper_float_ceilw_s(CPUMIPSSta
     restore_rounding_mode(env);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        wt2 = FP_TO_INT32_OVERFLOW;
+        wt2 = FLOAT_INAN32(env);
     }
     update_fcr31(env, GETPC());
     return wt2;
@@ -2788,7 +2789,7 @@ uint64_t helper_float_floorl_d(CPUMIPSSt
     restore_rounding_mode(env);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        dt2 = FP_TO_INT64_OVERFLOW;
+        dt2 = FLOAT_INAN64(env);
     }
     update_fcr31(env, GETPC());
     return dt2;
@@ -2803,7 +2804,7 @@ uint64_t helper_float_floorl_s(CPUMIPSSt
     restore_rounding_mode(env);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        dt2 = FP_TO_INT64_OVERFLOW;
+        dt2 = FLOAT_INAN64(env);
     }
     update_fcr31(env, GETPC());
     return dt2;
@@ -2818,7 +2819,7 @@ uint32_t helper_float_floorw_d(CPUMIPSSt
     restore_rounding_mode(env);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        wt2 = FP_TO_INT32_OVERFLOW;
+        wt2 = FLOAT_INAN32(env);
     }
     update_fcr31(env, GETPC());
     return wt2;
@@ -2833,23 +2834,23 @@ uint32_t helper_float_floorw_s(CPUMIPSSt
     restore_rounding_mode(env);
     if (get_float_exception_flags(&env->active_fpu.fp_status)
         & (float_flag_invalid | float_flag_overflow)) {
-        wt2 = FP_TO_INT32_OVERFLOW;
+        wt2 = FLOAT_INAN32(env);
     }
     update_fcr31(env, GETPC());
     return wt2;
 }
 
-/* unary operations, not modifying fp status  */
+/* IEEE 754-2008 unary operations, not modifying fp status.  */
 #define FLOAT_UNOP(name)                                       \
-uint64_t helper_float_ ## name ## _d(uint64_t fdt0)                \
+uint64_t helper_float_ ## name ## 2008_d(uint64_t fdt0)        \
 {                                                              \
     return float64_ ## name(fdt0);                             \
 }                                                              \
-uint32_t helper_float_ ## name ## _s(uint32_t fst0)                \
+uint32_t helper_float_ ## name ## 2008_s(uint32_t fst0)        \
 {                                                              \
     return float32_ ## name(fst0);                             \
 }                                                              \
-uint64_t helper_float_ ## name ## _ps(uint64_t fdt0)               \
+uint64_t helper_float_ ## name ## 2008_ps(uint64_t fdt0)       \
 {                                                              \
     uint32_t wt0;                                              \
     uint32_t wth0;                                             \
@@ -2862,6 +2863,85 @@ FLOAT_UNOP(abs)
 FLOAT_UNOP(chs)
 #undef FLOAT_UNOP
 
+/* Legacy unary operations, arithmetic.  */
+uint64_t helper_float_abs_d(CPUMIPSState *env, uint64_t fdt0)
+{
+    uint64_t fdt1;
+
+    if (float64_is_neg(fdt0)) {
+        fdt1 = float64_sub(0, fdt0, &env->active_fpu.fp_status);
+    } else {
+        fdt1 = float64_add(0, fdt0, &env->active_fpu.fp_status);
+    }
+    update_fcr31(env, GETPC());
+    return fdt1;
+}
+
+uint32_t helper_float_abs_s(CPUMIPSState *env, uint32_t fst0)
+{
+    uint32_t fst1;
+
+    if (float32_is_neg(fst0)) {
+        fst1 = float32_sub(0, fst0, &env->active_fpu.fp_status);
+    } else {
+        fst1 = float32_add(0, fst0, &env->active_fpu.fp_status);
+    }
+    update_fcr31(env, GETPC());
+    return fst1;
+}
+
+uint64_t helper_float_abs_ps(CPUMIPSState *env, uint64_t fpst0)
+{
+    uint32_t fst0 = fpst0 & 0XFFFFFFFF;
+    uint32_t fsth0 = fpst0 >> 32;
+    uint32_t fst1;
+    uint32_t fsth1;
+
+    if (float32_is_neg(fst0)) {
+        fst1 = float32_sub(0, fst0, &env->active_fpu.fp_status);
+    } else {
+        fst1 = float32_add(0, fst0, &env->active_fpu.fp_status);
+    }
+    if (float32_is_neg(fsth0)) {
+        fsth1 = float32_sub(0, fsth0, &env->active_fpu.fp_status);
+    } else {
+        fsth1 = float32_add(0, fsth0, &env->active_fpu.fp_status);
+    }
+    update_fcr31(env, GETPC());
+    return ((uint64_t)fsth1 << 32) | fst1;
+}
+
+uint64_t helper_float_chs_d(CPUMIPSState *env, uint64_t fdt0)
+{
+    uint64_t fdt1;
+
+    fdt1 = float64_sub(0, fdt0, &env->active_fpu.fp_status);
+    update_fcr31(env, GETPC());
+    return fdt1;
+}
+
+uint32_t helper_float_chs_s(CPUMIPSState *env, uint32_t fst0)
+{
+    uint32_t fst1;
+
+    fst1 = float32_sub(0, fst0, &env->active_fpu.fp_status);
+    update_fcr31(env, GETPC());
+    return fst1;
+}
+
+uint64_t helper_float_chs_ps(CPUMIPSState *env, uint64_t fpst0)
+{
+    uint32_t fst0 = fpst0 & 0XFFFFFFFF;
+    uint32_t fsth0 = fpst0 >> 32;
+    uint32_t fst1;
+    uint32_t fsth1;
+
+    fst1 = float32_sub(0, fst0, &env->active_fpu.fp_status);
+    fsth1 = float32_sub(0, fsth0, &env->active_fpu.fp_status);
+    update_fcr31(env, GETPC());
+    return ((uint64_t)fsth1 << 32) | fst1;
+}
+
 /* MIPS specific unary operations */
 uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0)
 {
Index: qemu-git-trunk/target-mips/translate.c
===================================================================
--- qemu-git-trunk.orig/target-mips/translate.c	2014-12-08 23:22:12.000000000 +0000
+++ qemu-git-trunk/target-mips/translate.c	2014-12-08 23:25:02.558929097 +0000
@@ -1424,6 +1424,7 @@ typedef struct DisasContext {
     int ie;
     bool bi;
     bool bp;
+    bool abs2008;
 } DisasContext;
 
 enum {
@@ -8718,7 +8719,10 @@ static void gen_farith (DisasContext *ct
             TCGv_i32 fp0 = tcg_temp_new_i32();
 
             gen_load_fpr32(fp0, fs);
-            gen_helper_float_abs_s(fp0, fp0);
+            if (ctx->abs2008)
+                gen_helper_float_abs2008_s(fp0, fp0);
+            else
+                gen_helper_float_abs_s(fp0, cpu_env, fp0);
             gen_store_fpr32(fp0, fd);
             tcg_temp_free_i32(fp0);
         }
@@ -8739,7 +8743,10 @@ static void gen_farith (DisasContext *ct
             TCGv_i32 fp0 = tcg_temp_new_i32();
 
             gen_load_fpr32(fp0, fs);
-            gen_helper_float_chs_s(fp0, fp0);
+            if (ctx->abs2008)
+                gen_helper_float_chs2008_s(fp0, fp0);
+            else
+                gen_helper_float_chs_s(fp0, cpu_env, fp0);
             gen_store_fpr32(fp0, fd);
             tcg_temp_free_i32(fp0);
         }
@@ -9259,7 +9266,10 @@ static void gen_farith (DisasContext *ct
             TCGv_i64 fp0 = tcg_temp_new_i64();
 
             gen_load_fpr64(ctx, fp0, fs);
-            gen_helper_float_abs_d(fp0, fp0);
+            if (ctx->abs2008)
+                gen_helper_float_abs2008_d(fp0, fp0);
+            else
+                gen_helper_float_abs_d(fp0, cpu_env, fp0);
             gen_store_fpr64(ctx, fp0, fd);
             tcg_temp_free_i64(fp0);
         }
@@ -9282,7 +9292,10 @@ static void gen_farith (DisasContext *ct
             TCGv_i64 fp0 = tcg_temp_new_i64();
 
             gen_load_fpr64(ctx, fp0, fs);
-            gen_helper_float_chs_d(fp0, fp0);
+            if (ctx->abs2008)
+                gen_helper_float_chs2008_d(fp0, fp0);
+            else
+                gen_helper_float_chs_d(fp0, cpu_env, fp0);
             gen_store_fpr64(ctx, fp0, fd);
             tcg_temp_free_i64(fp0);
         }
@@ -9818,7 +9831,10 @@ static void gen_farith (DisasContext *ct
             TCGv_i64 fp0 = tcg_temp_new_i64();
 
             gen_load_fpr64(ctx, fp0, fs);
-            gen_helper_float_abs_ps(fp0, fp0);
+            if (ctx->abs2008)
+                gen_helper_float_abs2008_ps(fp0, fp0);
+            else
+                gen_helper_float_abs_ps(fp0, cpu_env, fp0);
             gen_store_fpr64(ctx, fp0, fd);
             tcg_temp_free_i64(fp0);
         }
@@ -9841,7 +9857,10 @@ static void gen_farith (DisasContext *ct
             TCGv_i64 fp0 = tcg_temp_new_i64();
 
             gen_load_fpr64(ctx, fp0, fs);
-            gen_helper_float_chs_ps(fp0, fp0);
+            if (ctx->abs2008)
+                gen_helper_float_chs2008_ps(fp0, fp0);
+            else
+                gen_helper_float_chs_ps(fp0, cpu_env, fp0);
             gen_store_fpr64(ctx, fp0, fd);
             tcg_temp_free_i64(fp0);
         }
@@ -19121,6 +19140,7 @@ gen_intermediate_code_internal(MIPSCPU *
     /* Restore delay slot state from the tb context.  */
     ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
     ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
+    ctx.abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
     restore_cpu_state(env, &ctx);
 #ifdef CONFIG_USER_ONLY
         ctx.mem_idx = MIPS_HFLAG_UM;
@@ -19527,6 +19547,8 @@ void cpu_state_reset(CPUMIPSState *env)
     env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
     env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
     env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
+    env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
+    env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
     env->msair = env->cpu_model->MSAIR;
     env->insn_flags = env->cpu_model->insn_flags;
 
@@ -19634,6 +19656,7 @@ void cpu_state_reset(CPUMIPSState *env)
     compute_hflags(env);
     restore_rounding_mode(env);
     restore_flush_mode(env);
+    restore_nan_mode(env);
     cs->exception_index = EXCP_NONE;
 }
 
Index: qemu-git-trunk/target-mips/translate_init.c
===================================================================
--- qemu-git-trunk.orig/target-mips/translate_init.c	2014-12-08 23:22:12.000000000 +0000
+++ qemu-git-trunk/target-mips/translate_init.c	2014-12-09 00:51:53.118937156 +0000
@@ -84,6 +84,8 @@ struct mips_def_t {
     int32_t CP0_TCStatus_rw_bitmask;
     int32_t CP0_SRSCtl;
     int32_t CP1_fcr0;
+    int32_t CP1_fcr31;
+    int32_t CP1_fcr31_rw_bitmask;
     int32_t MSAIR;
     int32_t SEGBITS;
     int32_t PABITS;
@@ -315,6 +317,8 @@ static const mips_def_t mips_defs[] =
         .CP0_Status_rw_bitmask = 0x3678FF1F,
         .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
                     (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
+        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
+        .CP1_fcr31 = 0,
         .SEGBITS = 32,
         .PABITS = 32,
         .insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
@@ -368,6 +372,8 @@ static const mips_def_t mips_defs[] =
                     (0xff << CP0TCSt_TASID),
         .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
                     (1 << FCR0_D) | (1 << FCR0_S) | (0x95 << FCR0_PRID),
+        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
+        .CP1_fcr31 = 0,
         .CP0_SRSCtl = (0xf << CP0SRSCtl_HSS),
         .CP0_SRSConf0_rw_bitmask = 0x3fffffff,
         .CP0_SRSConf0 = (1U << CP0SRSC0_M) | (0x3fe << CP0SRSC0_SRS3) |
@@ -408,6 +414,8 @@ static const mips_def_t mips_defs[] =
         .CP0_Status_rw_bitmask = 0x3778FF1F,
         .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
                     (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
+        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
+        .CP1_fcr31 = 0,
         .SEGBITS = 32,
         .PABITS = 32,
         .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2,
@@ -479,9 +487,11 @@ static const mips_def_t mips_defs[] =
         .SYNCI_Step = 32,
         .CCRes = 2,
         .CP0_Status_rw_bitmask = 0x3778FF1F,
-        .CP1_fcr0 = (1 << FCR0_UFRP) | (1 << FCR0_F64) | (1 << FCR0_L) |
-                    (1 << FCR0_W) | (1 << FCR0_D) | (1 << FCR0_S) |
-                    (0x93 << FCR0_PRID),
+        .CP1_fcr0 = (1 << FCR0_UFRP) | (1 << FCR0_HAS2008) |
+                    (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
+                    (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
+        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
+        .CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008),
         .SEGBITS = 32,
         .PABITS = 32,
         .insn_flags = CPU_MIPS32R5 | ASE_MIPS16 | ASE_MSA,
@@ -503,6 +513,8 @@ static const mips_def_t mips_defs[] =
         .CP0_Status_rw_bitmask = 0x3678FFFF,
         /* The R4000 has a full 64bit FPU but doesn't use the fcr0 bits. */
         .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV),
+        .CP1_fcr31_rw_bitmask = 0x0183FFFF,
+        .CP1_fcr31 = 0,
         .SEGBITS = 40,
         .PABITS = 36,
         .insn_flags = CPU_MIPS3,
@@ -521,6 +533,8 @@ static const mips_def_t mips_defs[] =
         .CP0_Status_rw_bitmask = 0x3678FFFF,
         /* The VR5432 has a full 64bit FPU but doesn't use the fcr0 bits. */
         .CP1_fcr0 = (0x54 << FCR0_PRID) | (0x0 << FCR0_REV),
+        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
+        .CP1_fcr31 = 0,
         .SEGBITS = 40,
         .PABITS = 32,
         .insn_flags = CPU_VR54XX,
@@ -566,6 +580,8 @@ static const mips_def_t mips_defs[] =
         /* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */
         .CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) |
                     (0x81 << FCR0_PRID) | (0x0 << FCR0_REV),
+        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
+        .CP1_fcr31 = 0,
         .SEGBITS = 42,
         .PABITS = 36,
         .insn_flags = CPU_MIPS64,
@@ -593,6 +609,8 @@ static const mips_def_t mips_defs[] =
         .CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) |
                     (1 << FCR0_D) | (1 << FCR0_S) |
                     (0x82 << FCR0_PRID) | (0x0 << FCR0_REV),
+        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
+        .CP1_fcr31 = 0,
         .SEGBITS = 40,
         .PABITS = 36,
         .insn_flags = CPU_MIPS64 | ASE_MIPS3D,
@@ -619,6 +637,8 @@ static const mips_def_t mips_defs[] =
         .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) |
                     (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
                     (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
+        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
+        .CP1_fcr31 = 0,
         .SEGBITS = 42,
         /* The architectural limit is 59, but we have hardcoded 36 bit
            in some places...
@@ -667,6 +687,8 @@ static const mips_def_t mips_defs[] =
         .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
                     (1 << FCR0_D) | (1 << FCR0_S) |
                     (0x89 << FCR0_PRID) | (0x0 << FCR0_REV),
+        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
+        .CP1_fcr31 = 0,
         .SEGBITS = 42,
         .PABITS = 36,
         .insn_flags = CPU_MIPS64R2,
@@ -750,6 +772,8 @@ static const mips_def_t mips_defs[] =
         .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
                     (1 << FCR0_D) | (1 << FCR0_S) | (0x00 << FCR0_PRID) |
                     (0x0 << FCR0_REV),
+        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
+        .CP1_fcr31 = 0,
         .SEGBITS = 42,
         /* The architectural limit is 59, but we have hardcoded 36 bit
            in some places...
@@ -771,6 +795,8 @@ static const mips_def_t mips_defs[] =
         .CCRes = 2,
         .CP0_Status_rw_bitmask = 0x35D0FFFF,
         .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV),
+        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
+        .CP1_fcr31 = 0,
         .SEGBITS = 40,
         .PABITS = 40,
         .insn_flags = CPU_LOONGSON2E,
@@ -789,6 +815,8 @@ static const mips_def_t mips_defs[] =
         .CCRes = 2,
         .CP0_Status_rw_bitmask = 0xF5D0FF1F,   /* Bits 7:5 not writable.  */
         .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV),
+        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
+        .CP1_fcr31 = 0,
         .SEGBITS = 40,
         .PABITS = 40,
         .insn_flags = CPU_LOONGSON2F,
@@ -816,6 +844,8 @@ static const mips_def_t mips_defs[] =
         .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) |
                     (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
                     (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
+        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
+        .CP1_fcr31 = 0,
         .SEGBITS = 42,
         /* The architectural limit is 59, but we have hardcoded 36 bit
            in some places...
@@ -966,6 +996,7 @@ static void msa_reset(CPUMIPSState *env)
     set_flush_to_zero(0, &env->active_tc.msa_fp_status);
     set_flush_inputs_to_zero(0, &env->active_tc.msa_fp_status);
 
-    /* clear float_status nan mode */
+    /* set float_status nan modes */
     set_default_nan_mode(0, &env->active_tc.msa_fp_status);
+    set_nan2008_mode(1, &env->active_tc.msa_fp_status);
 }

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support
  2014-12-09  1:54 [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support Maciej W. Rozycki
                   ` (6 preceding siblings ...)
  2014-12-09  1:56 ` [Qemu-devel] [PATCH 7/7] target-mips: Add IEEE 754-2008 features support Maciej W. Rozycki
@ 2014-12-09  9:20 ` Peter Maydell
  2014-12-09 12:28   ` Maciej W. Rozycki
  2015-01-30 11:59 ` Peter Maydell
  8 siblings, 1 reply; 43+ messages in thread
From: Peter Maydell @ 2014-12-09  9:20 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Leon Alrae, QEMU Developers, Aurelien Jarno, Thomas Schwinge

On 9 December 2014 at 01:54, Maciej W. Rozycki <macro@codesourcery.com> wrote:
> Hi,
>
>  This patch series comprises changes to QEMU, both the MIPS backend and
> generic SoftFloat support code, to support IEEE 754-2008 features
> introduced to revision 3.50 of the MIPS Architecture as follows

I really really want to hold this patchset off until the softfloat
relicensing has gone through, because repeating that work would
be really painful...

thanks
-- PMM

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support
  2014-12-09  9:20 ` [Qemu-devel] [PATCH 0/7] MIPS: " Peter Maydell
@ 2014-12-09 12:28   ` Maciej W. Rozycki
  2014-12-09 12:41     ` Peter Maydell
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-12-09 12:28 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Leon Alrae, QEMU Developers, Aurelien Jarno, Thomas Schwinge

On Tue, 9 Dec 2014, Peter Maydell wrote:

> >  This patch series comprises changes to QEMU, both the MIPS backend and
> > generic SoftFloat support code, to support IEEE 754-2008 features
> > introduced to revision 3.50 of the MIPS Architecture as follows
> 
> I really really want to hold this patchset off until the softfloat
> relicensing has gone through, because repeating that work would
> be really painful...

 Understood.  Do you have an ETA for this to happen?

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support
  2014-12-09 12:28   ` Maciej W. Rozycki
@ 2014-12-09 12:41     ` Peter Maydell
  2014-12-09 18:16       ` Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Peter Maydell @ 2014-12-09 12:41 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Leon Alrae, QEMU Developers, Aurelien Jarno, Thomas Schwinge

On 9 December 2014 at 12:28, Maciej W. Rozycki <macro@codesourcery.com> wrote:
> On Tue, 9 Dec 2014, Peter Maydell wrote:
>> I really really want to hold this patchset off until the softfloat
>> relicensing has gone through, because repeating that work would
>> be really painful...
>
>  Understood.  Do you have an ETA for this to happen?

It's waiting for people to review the relicensing patchset
(which includes a couple of reimplementations of functions,
so you might want to review and test if you have any handy
test setups.)

thanks
-- PMM

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support
  2014-12-09 12:41     ` Peter Maydell
@ 2014-12-09 18:16       ` Maciej W. Rozycki
  0 siblings, 0 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-12-09 18:16 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Leon Alrae, QEMU Developers, Aurelien Jarno, Thomas Schwinge

On Tue, 9 Dec 2014, Peter Maydell wrote:

> >> I really really want to hold this patchset off until the softfloat
> >> relicensing has gone through, because repeating that work would
> >> be really painful...
> >
> >  Understood.  Do you have an ETA for this to happen?
> 
> It's waiting for people to review the relicensing patchset
> (which includes a couple of reimplementations of functions,
> so you might want to review and test if you have any handy
> test setups.)

 I have grabbed your patch set now and will see if I can integrate it into 
my tree, rebase my MIPS patchset against it and retest.  Little time has 
left for me to complete this effort though so I will give precedence to 
the outstanding ~6 MIPS patches I haven't posted yet.  Full testing I did 
takes ~72 hours so I'll see if I can schedule it over the next weekend.

 BTW, Paul Brook left CodeSourcery/Mentor long ago, but if you have any 
queries regarding his contributions to SoftFloat, then either me or one of 
my colleagues may be able to look up our internal code repositories and 
discussion archives to provide further information required; unless that 
is something that he contributed directly upstream, that is.

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [Qemu-devel] [PATCH v2 3/7] softfloat: Convert `*_default_nan' variables into inline functions
  2014-12-09  1:55 ` [Qemu-devel] [PATCH 3/7] softfloat: Convert `*_default_nan' variables into inline functions Maciej W. Rozycki
@ 2014-12-12 19:34   ` Maciej W. Rozycki
  2015-01-30 14:09     ` Leon Alrae
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-12-12 19:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: Leon Alrae, Thomas Schwinge, Aurelien Jarno

Mechanically replace `*_default_nan' variables with inline functions and 
convert references accordingly.  Use `__inline__' rather than `inline' 
so that the latter does not cause the definitions to become static as a 
result of macro expansion, the functions are best inlined when referred 
to from softfloat.c, but external copies must be also produced for 
external callers.

Signed-off-by: Thomas Schwinge <thomas@codesourcery.com>
Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
Changes from v1:

- regenerate on top of the SoftFloat relicensing patch set.

qemu-softfloat-default-nan-func.diff
Index: qemu-git-trunk/fpu/softfloat-specialize.h
===================================================================
--- qemu-git-trunk.orig/fpu/softfloat-specialize.h	2014-12-11 18:17:59.418972577 +0000
+++ qemu-git-trunk/fpu/softfloat-specialize.h	2014-12-11 18:18:00.918095644 +0000
@@ -99,69 +99,74 @@ this code that are retained.
 /*----------------------------------------------------------------------------
 | The pattern for a default generated half-precision NaN.
 *----------------------------------------------------------------------------*/
+inline float16 float16_default_nan(void)
+{
 #if defined(TARGET_ARM)
-const float16 float16_default_nan = const_float16(0x7E00);
+    return const_float16(0x7E00);
 #elif SNAN_BIT_IS_ONE
-const float16 float16_default_nan = const_float16(0x7DFF);
+    return const_float16(0x7DFF);
 #else
-const float16 float16_default_nan = const_float16(0xFE00);
+    return const_float16(0xFE00);
 #endif
+}
 
 /*----------------------------------------------------------------------------
 | The pattern for a default generated single-precision NaN.
 *----------------------------------------------------------------------------*/
+inline float32 float32_default_nan(void)
+{
 #if defined(TARGET_SPARC)
-const float32 float32_default_nan = const_float32(0x7FFFFFFF);
+    return const_float32(0x7FFFFFFF);
 #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
       defined(TARGET_XTENSA)
-const float32 float32_default_nan = const_float32(0x7FC00000);
+    return const_float32(0x7FC00000);
 #elif SNAN_BIT_IS_ONE
-const float32 float32_default_nan = const_float32(0x7FBFFFFF);
+    return const_float32(0x7FBFFFFF);
 #else
-const float32 float32_default_nan = const_float32(0xFFC00000);
+    return const_float32(0xFFC00000);
 #endif
+}
 
 /*----------------------------------------------------------------------------
 | The pattern for a default generated double-precision NaN.
 *----------------------------------------------------------------------------*/
+inline float64 float64_default_nan(void)
+{
 #if defined(TARGET_SPARC)
-const float64 float64_default_nan = const_float64(LIT64( 0x7FFFFFFFFFFFFFFF ));
+    return const_float64(LIT64(0x7FFFFFFFFFFFFFFF));
 #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
-const float64 float64_default_nan = const_float64(LIT64( 0x7FF8000000000000 ));
+    return const_float64(LIT64(0x7FF8000000000000));
 #elif SNAN_BIT_IS_ONE
-const float64 float64_default_nan = const_float64(LIT64(0x7FF7FFFFFFFFFFFF));
+    return const_float64(LIT64(0x7FF7FFFFFFFFFFFF));
 #else
-const float64 float64_default_nan = const_float64(LIT64( 0xFFF8000000000000 ));
+    return const_float64(LIT64(0xFFF8000000000000));
 #endif
+}
 
 /*----------------------------------------------------------------------------
 | The pattern for a default generated extended double-precision NaN.
 *----------------------------------------------------------------------------*/
+inline floatx80 floatx80_default_nan(void)
+{
 #if SNAN_BIT_IS_ONE
-#define floatx80_default_nan_high 0x7FFF
-#define floatx80_default_nan_low  LIT64(0xBFFFFFFFFFFFFFFF)
+    return make_floatx80(0x7FFF, LIT64(0xBFFFFFFFFFFFFFFF));
 #else
-#define floatx80_default_nan_high 0xFFFF
-#define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
+    return make_floatx80(0xFFFF, LIT64(0xC000000000000000));
 #endif
-
-const floatx80 floatx80_default_nan
-    = make_floatx80_init(floatx80_default_nan_high, floatx80_default_nan_low);
+}
 
 /*----------------------------------------------------------------------------
 | The pattern for a default generated quadruple-precision NaN.  The `high' and
 | `low' values hold the most- and least-significant bits, respectively.
 *----------------------------------------------------------------------------*/
+inline float128 float128_default_nan(void)
+{
 #if SNAN_BIT_IS_ONE
-#define float128_default_nan_high LIT64(0x7FFF7FFFFFFFFFFF)
-#define float128_default_nan_low  LIT64(0xFFFFFFFFFFFFFFFF)
+    return make_float128(LIT64(0x7FFF7FFFFFFFFFFF), LIT64(0xFFFFFFFFFFFFFFFF));
 #else
-#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
-#define float128_default_nan_low  LIT64( 0x0000000000000000 )
+    return make_float128(LIT64(0xFFFF800000000000), LIT64(0x0000000000000000));
 #endif
-
-const float128 float128_default_nan
-    = make_float128_init(float128_default_nan_high, float128_default_nan_low);
+}
 
 /*----------------------------------------------------------------------------
 | Raises the exceptions specified by `flags'.  Floating-point traps can be
@@ -234,7 +239,7 @@ float16 float16_maybe_silence_nan(float1
     if (float16_is_signaling_nan(a_)) {
 #if SNAN_BIT_IS_ONE
 #  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-        return float16_default_nan;
+        return float16_default_nan();
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
 #  endif
@@ -274,14 +279,14 @@ static float16 commonNaNToFloat16(common
     uint16_t mantissa = a.high>>54;
 
     if (STATUS(default_nan_mode)) {
-        return float16_default_nan;
+        return float16_default_nan();
     }
 
     if (mantissa) {
         return make_float16(((((uint16_t) a.sign) << 15)
                              | (0x1F << 10) | mantissa));
     } else {
-        return float16_default_nan;
+        return float16_default_nan();
     }
 }
 
@@ -337,7 +342,7 @@ float32 float32_maybe_silence_nan( float
     if (float32_is_signaling_nan(a_)) {
 #if SNAN_BIT_IS_ONE
 #  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-        return float32_default_nan;
+        return float32_default_nan();
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
 #  endif
@@ -377,14 +382,14 @@ static float32 commonNaNToFloat32( commo
     uint32_t mantissa = a.high>>41;
 
     if ( STATUS(default_nan_mode) ) {
-        return float32_default_nan;
+        return float32_default_nan();
     }
 
     if ( mantissa )
         return make_float32(
             ( ( (uint32_t) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
     else
-        return float32_default_nan;
+        return float32_default_nan();
 }
 
 /*----------------------------------------------------------------------------
@@ -624,7 +629,7 @@ static float32 propagateFloat32NaN( floa
     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
 
     if ( STATUS(default_nan_mode) )
-        return float32_default_nan;
+        return float32_default_nan();
 
     if ((uint32_t)(av<<1) < (uint32_t)(bv<<1)) {
         aIsLargerSignificand = 0;
@@ -677,7 +682,7 @@ static float32 propagateFloat32MulAddNaN
         /* Note that this check is after pickNaNMulAdd so that function
          * has an opportunity to set the Invalid flag.
          */
-        return float32_default_nan;
+        return float32_default_nan();
     }
 
     switch (which) {
@@ -689,7 +694,7 @@ static float32 propagateFloat32MulAddNaN
         return float32_maybe_silence_nan(c);
     case 3:
     default:
-        return float32_default_nan;
+        return float32_default_nan();
     }
 }
 
@@ -748,7 +753,7 @@ float64 float64_maybe_silence_nan( float
     if (float64_is_signaling_nan(a_)) {
 #if SNAN_BIT_IS_ONE
 #  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-        return float64_default_nan;
+        return float64_default_nan();
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
 #  endif
@@ -788,7 +793,7 @@ static float64 commonNaNToFloat64( commo
     uint64_t mantissa = a.high>>12;
 
     if ( STATUS(default_nan_mode) ) {
-        return float64_default_nan;
+        return float64_default_nan();
     }
 
     if ( mantissa )
@@ -797,7 +802,7 @@ static float64 commonNaNToFloat64( commo
             | LIT64( 0x7FF0000000000000 )
             | ( a.high>>12 ));
     else
-        return float64_default_nan;
+        return float64_default_nan();
 }
 
 /*----------------------------------------------------------------------------
@@ -822,7 +827,7 @@ static float64 propagateFloat64NaN( floa
     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
 
     if ( STATUS(default_nan_mode) )
-        return float64_default_nan;
+        return float64_default_nan();
 
     if ((uint64_t)(av<<1) < (uint64_t)(bv<<1)) {
         aIsLargerSignificand = 0;
@@ -875,7 +880,7 @@ static float64 propagateFloat64MulAddNaN
         /* Note that this check is after pickNaNMulAdd so that function
          * has an opportunity to set the Invalid flag.
          */
-        return float64_default_nan;
+        return float64_default_nan();
     }
 
     switch (which) {
@@ -887,7 +892,7 @@ static float64 propagateFloat64MulAddNaN
         return float64_maybe_silence_nan(c);
     case 3:
     default:
-        return float64_default_nan;
+        return float64_default_nan();
     }
 }
 
@@ -956,8 +961,7 @@ floatx80 floatx80_maybe_silence_nan( flo
     if (floatx80_is_signaling_nan(a)) {
 #if SNAN_BIT_IS_ONE
 #  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-        a.low = floatx80_default_nan_low;
-        a.high = floatx80_default_nan_high;
+        a = floatx80_default_nan();
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
 #  endif
@@ -982,8 +986,7 @@ static commonNaNT floatx80ToCommonNaN( f
     if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
     /* Replace a Pseudo NaN with a default NaN.  */
     if (!(a.low >> 63)) {
-        a.low = floatx80_default_nan_low;
-        a.high = floatx80_default_nan_high;
+        a = floatx80_default_nan();
     }
     z.sign = a.high >> 15;
     z.low = 0;
@@ -1001,17 +1004,14 @@ static floatx80 commonNaNToFloatx80( com
     floatx80 z;
 
     if ( STATUS(default_nan_mode) ) {
-        z.low = floatx80_default_nan_low;
-        z.high = floatx80_default_nan_high;
-        return z;
+        return floatx80_default_nan();
     }
 
     if (a.high >> 1) {
         z.low = LIT64( 0x8000000000000000 ) | a.high >> 1;
         z.high = ( ( (uint16_t) a.sign )<<15 ) | 0x7FFF;
     } else {
-        z.low = floatx80_default_nan_low;
-        z.high = floatx80_default_nan_high;
+        z = floatx80_default_nan();
     }
 
     return z;
@@ -1036,9 +1036,7 @@ static floatx80 propagateFloatx80NaN( fl
     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
 
     if ( STATUS(default_nan_mode) ) {
-        a.low = floatx80_default_nan_low;
-        a.high = floatx80_default_nan_high;
-        return a;
+        return floatx80_default_nan();
     }
 
     if (a.low < b.low) {
@@ -1114,8 +1112,7 @@ float128 float128_maybe_silence_nan( flo
     if (float128_is_signaling_nan(a)) {
 #if SNAN_BIT_IS_ONE
 #  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-        a.low = float128_default_nan_low;
-        a.high = float128_default_nan_high;
+        a = float128_default_nan();
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
 #  endif
@@ -1153,9 +1150,7 @@ static float128 commonNaNToFloat128( com
     float128 z;
 
     if ( STATUS(default_nan_mode) ) {
-        z.low = float128_default_nan_low;
-        z.high = float128_default_nan_high;
-        return z;
+        return float128_default_nan();
     }
 
     shift128Right( a.high, a.low, 16, &z.high, &z.low );
@@ -1182,9 +1177,7 @@ static float128 propagateFloat128NaN( fl
     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
 
     if ( STATUS(default_nan_mode) ) {
-        a.low = float128_default_nan_low;
-        a.high = float128_default_nan_high;
-        return a;
+        return float128_default_nan();
     }
 
     if (lt128(a.high<<1, a.low, b.high<<1, b.low)) {
Index: qemu-git-trunk/fpu/softfloat.c
===================================================================
--- qemu-git-trunk.orig/fpu/softfloat.c	2014-12-11 18:17:58.418989075 +0000
+++ qemu-git-trunk/fpu/softfloat.c	2014-12-11 18:18:00.918095644 +0000
@@ -2035,7 +2035,7 @@ static float32 subFloat32Sigs( float32 a
     if ( aExp == 0xFF ) {
         if ( aSig | bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
         float_raise( float_flag_invalid STATUS_VAR);
-        return float32_default_nan;
+        return float32_default_nan();
     }
     if ( aExp == 0 ) {
         aExp = 1;
@@ -2160,7 +2160,7 @@ float32 float32_mul( float32 a, float32 
         }
         if ( ( bExp | bSig ) == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float32_default_nan;
+            return float32_default_nan();
         }
         return packFloat32( zSign, 0xFF, 0 );
     }
@@ -2168,7 +2168,7 @@ float32 float32_mul( float32 a, float32 
         if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
         if ( ( aExp | aSig ) == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float32_default_nan;
+            return float32_default_nan();
         }
         return packFloat32( zSign, 0xFF, 0 );
     }
@@ -2219,7 +2219,7 @@ float32 float32_div( float32 a, float32 
         if ( bExp == 0xFF ) {
             if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
             float_raise( float_flag_invalid STATUS_VAR);
-            return float32_default_nan;
+            return float32_default_nan();
         }
         return packFloat32( zSign, 0xFF, 0 );
     }
@@ -2231,7 +2231,7 @@ float32 float32_div( float32 a, float32 
         if ( bSig == 0 ) {
             if ( ( aExp | aSig ) == 0 ) {
                 float_raise( float_flag_invalid STATUS_VAR);
-                return float32_default_nan;
+                return float32_default_nan();
             }
             float_raise( float_flag_divbyzero STATUS_VAR);
             return packFloat32( zSign, 0xFF, 0 );
@@ -2285,7 +2285,7 @@ float32 float32_rem( float32 a, float32 
             return propagateFloat32NaN( a, b STATUS_VAR );
         }
         float_raise( float_flag_invalid STATUS_VAR);
-        return float32_default_nan;
+        return float32_default_nan();
     }
     if ( bExp == 0xFF ) {
         if ( bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
@@ -2294,7 +2294,7 @@ float32 float32_rem( float32 a, float32 
     if ( bExp == 0 ) {
         if ( bSig == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float32_default_nan;
+            return float32_default_nan();
         }
         normalizeFloat32Subnormal( bSig, &bExp, &bSig );
     }
@@ -2409,7 +2409,7 @@ float32 float32_muladd(float32 a, float3
 
     if (infzero) {
         float_raise(float_flag_invalid STATUS_VAR);
-        return float32_default_nan;
+        return float32_default_nan();
     }
 
     if (flags & float_muladd_negate_c) {
@@ -2430,7 +2430,7 @@ float32 float32_muladd(float32 a, float3
         if (pInf && (pSign ^ cSign)) {
             /* addition of opposite-signed infinities => InvalidOperation */
             float_raise(float_flag_invalid STATUS_VAR);
-            return float32_default_nan;
+            return float32_default_nan();
         }
         /* Otherwise generate an infinity of the same sign */
         return packFloat32(cSign ^ signflip, 0xff, 0);
@@ -2604,12 +2604,12 @@ float32 float32_sqrt( float32 a STATUS_P
         if ( aSig ) return propagateFloat32NaN( a, float32_zero STATUS_VAR );
         if ( ! aSign ) return a;
         float_raise( float_flag_invalid STATUS_VAR);
-        return float32_default_nan;
+        return float32_default_nan();
     }
     if ( aSign ) {
         if ( ( aExp | aSig ) == 0 ) return a;
         float_raise( float_flag_invalid STATUS_VAR);
-        return float32_default_nan;
+        return float32_default_nan();
     }
     if ( aExp == 0 ) {
         if ( aSig == 0 ) return float32_zero;
@@ -2740,7 +2740,7 @@ float32 float32_log2( float32 a STATUS_P
     }
     if ( aSign ) {
         float_raise( float_flag_invalid STATUS_VAR);
-        return float32_default_nan;
+        return float32_default_nan();
     }
     if ( aExp == 0xFF ) {
         if ( aSig ) return propagateFloat32NaN( a, float32_zero STATUS_VAR );
@@ -3796,7 +3796,7 @@ static float64 subFloat64Sigs( float64 a
     if ( aExp == 0x7FF ) {
         if ( aSig | bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
         float_raise( float_flag_invalid STATUS_VAR);
-        return float64_default_nan;
+        return float64_default_nan();
     }
     if ( aExp == 0 ) {
         aExp = 1;
@@ -3919,7 +3919,7 @@ float64 float64_mul( float64 a, float64 
         }
         if ( ( bExp | bSig ) == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float64_default_nan;
+            return float64_default_nan();
         }
         return packFloat64( zSign, 0x7FF, 0 );
     }
@@ -3927,7 +3927,7 @@ float64 float64_mul( float64 a, float64 
         if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
         if ( ( aExp | aSig ) == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float64_default_nan;
+            return float64_default_nan();
         }
         return packFloat64( zSign, 0x7FF, 0 );
     }
@@ -3980,7 +3980,7 @@ float64 float64_div( float64 a, float64 
         if ( bExp == 0x7FF ) {
             if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
             float_raise( float_flag_invalid STATUS_VAR);
-            return float64_default_nan;
+            return float64_default_nan();
         }
         return packFloat64( zSign, 0x7FF, 0 );
     }
@@ -3992,7 +3992,7 @@ float64 float64_div( float64 a, float64 
         if ( bSig == 0 ) {
             if ( ( aExp | aSig ) == 0 ) {
                 float_raise( float_flag_invalid STATUS_VAR);
-                return float64_default_nan;
+                return float64_default_nan();
             }
             float_raise( float_flag_divbyzero STATUS_VAR);
             return packFloat64( zSign, 0x7FF, 0 );
@@ -4050,7 +4050,7 @@ float64 float64_rem( float64 a, float64 
             return propagateFloat64NaN( a, b STATUS_VAR );
         }
         float_raise( float_flag_invalid STATUS_VAR);
-        return float64_default_nan;
+        return float64_default_nan();
     }
     if ( bExp == 0x7FF ) {
         if ( bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
@@ -4059,7 +4059,7 @@ float64 float64_rem( float64 a, float64 
     if ( bExp == 0 ) {
         if ( bSig == 0 ) {
             float_raise( float_flag_invalid STATUS_VAR);
-            return float64_default_nan;
+            return float64_default_nan();
         }
         normalizeFloat64Subnormal( bSig, &bExp, &bSig );
     }
@@ -4160,7 +4160,7 @@ float64 float64_muladd(float64 a, float6
 
     if (infzero) {
         float_raise(float_flag_invalid STATUS_VAR);
-        return float64_default_nan;
+        return float64_default_nan();
     }
 
     if (flags & float_muladd_negate_c) {
@@ -4181,7 +4181,7 @@ float64 float64_muladd(float64 a, float6
         if (pInf && (pSign ^ cSign)) {
             /* addition of opposite-signed infinities => InvalidOperation */
             float_raise(float_flag_invalid STATUS_VAR);
-            return float64_default_nan;
+            return float64_default_nan();
         }
         /* Otherwise generate an infinity of the same sign */
         return packFloat64(cSign ^ signflip, 0x7ff, 0);
@@ -4377,12 +4377,12 @@ float64 float64_sqrt( float64 a STATUS_P
         if ( aSig ) return propagateFloat64NaN( a, a STATUS_VAR );
         if ( ! aSign ) return a;
         float_raise( float_flag_invalid STATUS_VAR);
-        return float64_default_nan;
+        return float64_default_nan();
     }
     if ( aSign ) {
         if ( ( aExp | aSig ) == 0 ) return a;
         float_raise( float_flag_invalid STATUS_VAR);
-        return float64_default_nan;
+        return float64_default_nan();
     }
     if ( aExp == 0 ) {
         if ( aSig == 0 ) return float64_zero;
@@ -4430,7 +4430,7 @@ float64 float64_log2( float64 a STATUS_P
     }
     if ( aSign ) {
         float_raise( float_flag_invalid STATUS_VAR);
-        return float64_default_nan;
+        return float64_default_nan();
     }
     if ( aExp == 0x7FF ) {
         if ( aSig ) return propagateFloat64NaN( a, float64_zero STATUS_VAR );
@@ -5083,7 +5083,6 @@ static floatx80 subFloatx80Sigs( floatx8
     int32 aExp, bExp, zExp;
     uint64_t aSig, bSig, zSig0, zSig1;
     int32 expDiff;
-    floatx80 z;
 
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
@@ -5097,9 +5096,7 @@ static floatx80 subFloatx80Sigs( floatx8
             return propagateFloatx80NaN( a, b STATUS_VAR );
         }
         float_raise( float_flag_invalid STATUS_VAR);
-        z.low = floatx80_default_nan_low;
-        z.high = floatx80_default_nan_high;
-        return z;
+        return floatx80_default_nan();
     }
     if ( aExp == 0 ) {
         aExp = 1;
@@ -5191,7 +5188,6 @@ floatx80 floatx80_mul( floatx80 a, float
     flag aSign, bSign, zSign;
     int32 aExp, bExp, zExp;
     uint64_t aSig, bSig, zSig0, zSig1;
-    floatx80 z;
 
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
@@ -5213,9 +5209,7 @@ floatx80 floatx80_mul( floatx80 a, float
         if ( ( aExp | aSig ) == 0 ) {
  invalid:
             float_raise( float_flag_invalid STATUS_VAR);
-            z.low = floatx80_default_nan_low;
-            z.high = floatx80_default_nan_high;
-            return z;
+            return floatx80_default_nan();
         }
         return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
     }
@@ -5251,7 +5245,6 @@ floatx80 floatx80_div( floatx80 a, float
     int32 aExp, bExp, zExp;
     uint64_t aSig, bSig, zSig0, zSig1;
     uint64_t rem0, rem1, rem2, term0, term1, term2;
-    floatx80 z;
 
     aSig = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
@@ -5277,9 +5270,7 @@ floatx80 floatx80_div( floatx80 a, float
             if ( ( aExp | aSig ) == 0 ) {
  invalid:
                 float_raise( float_flag_invalid STATUS_VAR);
-                z.low = floatx80_default_nan_low;
-                z.high = floatx80_default_nan_high;
-                return z;
+                return floatx80_default_nan();
             }
             float_raise( float_flag_divbyzero STATUS_VAR);
             return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
@@ -5331,7 +5322,6 @@ floatx80 floatx80_rem( floatx80 a, float
     int32 aExp, bExp, expDiff;
     uint64_t aSig0, aSig1, bSig;
     uint64_t q, term0, term1, alternateASig0, alternateASig1;
-    floatx80 z;
 
     aSig0 = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
@@ -5353,9 +5343,7 @@ floatx80 floatx80_rem( floatx80 a, float
         if ( bSig == 0 ) {
  invalid:
             float_raise( float_flag_invalid STATUS_VAR);
-            z.low = floatx80_default_nan_low;
-            z.high = floatx80_default_nan_high;
-            return z;
+            return floatx80_default_nan();
         }
         normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
     }
@@ -5427,7 +5415,6 @@ floatx80 floatx80_sqrt( floatx80 a STATU
     int32 aExp, zExp;
     uint64_t aSig0, aSig1, zSig0, zSig1, doubleZSig0;
     uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
-    floatx80 z;
 
     aSig0 = extractFloatx80Frac( a );
     aExp = extractFloatx80Exp( a );
@@ -5441,9 +5428,7 @@ floatx80 floatx80_sqrt( floatx80 a STATU
         if ( ( aExp | aSig0 ) == 0 ) return a;
  invalid:
         float_raise( float_flag_invalid STATUS_VAR);
-        z.low = floatx80_default_nan_low;
-        z.high = floatx80_default_nan_high;
-        return z;
+        return floatx80_default_nan();
     }
     if ( aExp == 0 ) {
         if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 );
@@ -6249,7 +6234,6 @@ static float128 subFloat128Sigs( float12
     int32 aExp, bExp, zExp;
     uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1;
     int32 expDiff;
-    float128 z;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
@@ -6267,9 +6251,7 @@ static float128 subFloat128Sigs( float12
             return propagateFloat128NaN( a, b STATUS_VAR );
         }
         float_raise( float_flag_invalid STATUS_VAR);
-        z.low = float128_default_nan_low;
-        z.high = float128_default_nan_high;
-        return z;
+        return float128_default_nan();
     }
     if ( aExp == 0 ) {
         aExp = 1;
@@ -6373,7 +6355,6 @@ float128 float128_mul( float128 a, float
     flag aSign, bSign, zSign;
     int32 aExp, bExp, zExp;
     uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3;
-    float128 z;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
@@ -6397,9 +6378,7 @@ float128 float128_mul( float128 a, float
         if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
  invalid:
             float_raise( float_flag_invalid STATUS_VAR);
-            z.low = float128_default_nan_low;
-            z.high = float128_default_nan_high;
-            return z;
+            return float128_default_nan();
         }
         return packFloat128( zSign, 0x7FFF, 0, 0 );
     }
@@ -6438,7 +6417,6 @@ float128 float128_div( float128 a, float
     int32 aExp, bExp, zExp;
     uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
     uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
-    float128 z;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
@@ -6466,9 +6444,7 @@ float128 float128_div( float128 a, float
             if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
  invalid:
                 float_raise( float_flag_invalid STATUS_VAR);
-                z.low = float128_default_nan_low;
-                z.high = float128_default_nan_high;
-                return z;
+                return float128_default_nan();
             }
             float_raise( float_flag_divbyzero STATUS_VAR);
             return packFloat128( zSign, 0x7FFF, 0, 0 );
@@ -6523,7 +6499,6 @@ float128 float128_rem( float128 a, float
     uint64_t aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2;
     uint64_t allZero, alternateASig0, alternateASig1, sigMean1;
     int64_t sigMean0;
-    float128 z;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
@@ -6547,9 +6522,7 @@ float128 float128_rem( float128 a, float
         if ( ( bSig0 | bSig1 ) == 0 ) {
  invalid:
             float_raise( float_flag_invalid STATUS_VAR);
-            z.low = float128_default_nan_low;
-            z.high = float128_default_nan_high;
-            return z;
+            return float128_default_nan();
         }
         normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
     }
@@ -6631,7 +6604,6 @@ float128 float128_sqrt( float128 a STATU
     int32 aExp, zExp;
     uint64_t aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0;
     uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
-    float128 z;
 
     aSig1 = extractFloat128Frac1( a );
     aSig0 = extractFloat128Frac0( a );
@@ -6646,9 +6618,7 @@ float128 float128_sqrt( float128 a STATU
         if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a;
  invalid:
         float_raise( float_flag_invalid STATUS_VAR);
-        z.low = float128_default_nan_low;
-        z.high = float128_default_nan_high;
-        return z;
+        return float128_default_nan();
     }
     if ( aExp == 0 ) {
         if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 );
Index: qemu-git-trunk/include/fpu/softfloat.h
===================================================================
--- qemu-git-trunk.orig/include/fpu/softfloat.h	2014-12-11 18:15:02.000000000 +0000
+++ qemu-git-trunk/include/fpu/softfloat.h	2014-12-11 18:18:00.918095644 +0000
@@ -370,7 +370,7 @@ static inline int float16_is_any_nan(flo
 /*----------------------------------------------------------------------------
 | The pattern for a default generated half-precision NaN.
 *----------------------------------------------------------------------------*/
-extern const float16 float16_default_nan;
+__inline__ float16 float16_default_nan(void);
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE single-precision conversion routines.
@@ -482,7 +482,7 @@ static inline float32 float32_set_sign(f
 /*----------------------------------------------------------------------------
 | The pattern for a default generated single-precision NaN.
 *----------------------------------------------------------------------------*/
-extern const float32 float32_default_nan;
+__inline__ float32 float32_default_nan(void);
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE double-precision conversion routines.
@@ -594,7 +594,7 @@ static inline float64 float64_set_sign(f
 /*----------------------------------------------------------------------------
 | The pattern for a default generated double-precision NaN.
 *----------------------------------------------------------------------------*/
-extern const float64 float64_default_nan;
+__inline__ float64 float64_default_nan(void);
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE extended double-precision conversion routines.
@@ -679,7 +679,7 @@ static inline int floatx80_is_any_nan(fl
 /*----------------------------------------------------------------------------
 | The pattern for a default generated extended double-precision NaN.
 *----------------------------------------------------------------------------*/
-extern const floatx80 floatx80_default_nan;
+__inline__ floatx80 floatx80_default_nan(void);
 
 /*----------------------------------------------------------------------------
 | Software IEC/IEEE quadruple-precision conversion routines.
@@ -760,6 +760,6 @@ static inline int float128_is_any_nan(fl
 /*----------------------------------------------------------------------------
 | The pattern for a default generated quadruple-precision NaN.
 *----------------------------------------------------------------------------*/
-extern const float128 float128_default_nan;
+__inline__ float128 float128_default_nan(void);
 
 #endif /* !SOFTFLOAT_H */
Index: qemu-git-trunk/target-arm/helper-a64.c
===================================================================
--- qemu-git-trunk.orig/target-arm/helper-a64.c	2014-12-10 20:51:35.000000000 +0000
+++ qemu-git-trunk/target-arm/helper-a64.c	2014-12-11 18:18:00.918095644 +0000
@@ -342,7 +342,7 @@ float32 HELPER(frecpx_f32)(float32 a, vo
             nan = float32_maybe_silence_nan(a);
         }
         if (fpst->default_nan_mode) {
-            nan = float32_default_nan;
+            nan = float32_default_nan();
         }
         return nan;
     }
@@ -371,7 +371,7 @@ float64 HELPER(frecpx_f64)(float64 a, vo
             nan = float64_maybe_silence_nan(a);
         }
         if (fpst->default_nan_mode) {
-            nan = float64_default_nan;
+            nan = float64_default_nan();
         }
         return nan;
     }
Index: qemu-git-trunk/target-arm/helper.c
===================================================================
--- qemu-git-trunk.orig/target-arm/helper.c	2014-12-10 20:51:35.000000000 +0000
+++ qemu-git-trunk/target-arm/helper.c	2014-12-11 18:18:00.918095644 +0000
@@ -5836,7 +5836,7 @@ float32 HELPER(recpe_f32)(float32 input,
             nan = float32_maybe_silence_nan(f32);
         }
         if (fpst->default_nan_mode) {
-            nan =  float32_default_nan;
+            nan = float32_default_nan();
         }
         return nan;
     } else if (float32_is_infinity(f32)) {
@@ -5890,7 +5890,7 @@ float64 HELPER(recpe_f64)(float64 input,
             nan = float64_maybe_silence_nan(f64);
         }
         if (fpst->default_nan_mode) {
-            nan =  float64_default_nan;
+            nan = float64_default_nan();
         }
         return nan;
     } else if (float64_is_infinity(f64)) {
@@ -5997,7 +5997,7 @@ float32 HELPER(rsqrte_f32)(float32 input
             nan = float32_maybe_silence_nan(f32);
         }
         if (s->default_nan_mode) {
-            nan =  float32_default_nan;
+            nan = float32_default_nan();
         }
         return nan;
     } else if (float32_is_zero(f32)) {
@@ -6005,7 +6005,7 @@ float32 HELPER(rsqrte_f32)(float32 input
         return float32_set_sign(float32_infinity, float32_is_neg(f32));
     } else if (float32_is_neg(f32)) {
         float_raise(float_flag_invalid, s);
-        return float32_default_nan;
+        return float32_default_nan();
     } else if (float32_is_infinity(f32)) {
         return float32_zero;
     }
@@ -6061,7 +6061,7 @@ float64 HELPER(rsqrte_f64)(float64 input
             nan = float64_maybe_silence_nan(f64);
         }
         if (s->default_nan_mode) {
-            nan =  float64_default_nan;
+            nan = float64_default_nan();
         }
         return nan;
     } else if (float64_is_zero(f64)) {
@@ -6069,7 +6069,7 @@ float64 HELPER(rsqrte_f64)(float64 input
         return float64_set_sign(float64_infinity, float64_is_neg(f64));
     } else if (float64_is_neg(f64)) {
         float_raise(float_flag_invalid, s);
-        return float64_default_nan;
+        return float64_default_nan();
     } else if (float64_is_infinity(f64)) {
         return float64_zero;
     }
Index: qemu-git-trunk/target-mips/msa_helper.c
===================================================================
--- qemu-git-trunk.orig/target-mips/msa_helper.c	2014-12-11 16:30:29.000000000 +0000
+++ qemu-git-trunk/target-mips/msa_helper.c	2014-12-11 18:18:00.918095644 +0000
@@ -1503,11 +1503,11 @@ MSA_UNOP_DF(pcnt)
 #define FLOAT_ONE32 make_float32(0x3f8 << 20)
 #define FLOAT_ONE64 make_float64(0x3ffULL << 52)
 
-#define FLOAT_SNAN16 (float16_default_nan ^ 0x0220)
+#define FLOAT_SNAN16 (float16_default_nan() ^ 0x0220)
         /* 0x7c20 */
-#define FLOAT_SNAN32 (float32_default_nan ^ 0x00400020)
+#define FLOAT_SNAN32 (float32_default_nan() ^ 0x00400020)
         /* 0x7f800020 */
-#define FLOAT_SNAN64 (float64_default_nan ^ 0x0008000000000020ULL)
+#define FLOAT_SNAN64 (float64_default_nan() ^ 0x0008000000000020ULL)
         /* 0x7ff0000000000020 */
 
 static inline void clear_msacsr_cause(CPUMIPSState *env)

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [Qemu-devel] [PATCH v2 5/7] softfloat: Rework `*_is_*_nan' functions
  2014-12-09  1:55 ` [Qemu-devel] [PATCH 5/7] softfloat: Rework `*_is_*_nan' functions Maciej W. Rozycki
@ 2014-12-12 19:35   ` Maciej W. Rozycki
  2015-02-05 16:42     ` Peter Maydell
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-12-12 19:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: Leon Alrae, Thomas Schwinge, Aurelien Jarno

Precompute the possible results, and then pick the suitable one.  The 
calculation of the unused result will be optimized away by the compiler 
at any reasonable optimization level, so no run-time performance loss.

Signed-off-by: Thomas Schwinge <thomas@codesourcery.com>
Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
Changes from v1:

- regenerate on top of the SoftFloat relicensing patch set.

qemu-softfloat-nan-precompute.diff
Index: qemu-git-trunk/fpu/softfloat-specialize.h
===================================================================
--- qemu-git-trunk.orig/fpu/softfloat-specialize.h	2014-12-11 22:41:47.118930659 +0000
+++ qemu-git-trunk/fpu/softfloat-specialize.h	2014-12-11 22:42:29.128941855 +0000
@@ -207,10 +207,13 @@ int float16_is_signaling_nan(float16 a_ 
 int float16_is_quiet_nan(float16 a_ STATUS_PARAM)
 {
     uint16_t a = float16_val(a_);
+    int __attribute__ ((unused)) x, y;
+    x = (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
+    y = (a & ~0x8000) >= 0x7c80;
 #if SNAN_BIT_IS_ONE
-    return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
+    return x;
 #else
-    return ((a & ~0x8000) >= 0x7c80);
+    return y;
 #endif
 }
 
@@ -222,10 +225,13 @@ int float16_is_quiet_nan(float16 a_ STAT
 int float16_is_signaling_nan(float16 a_ STATUS_PARAM)
 {
     uint16_t a = float16_val(a_);
+    int __attribute__ ((unused)) x, y;
+    x = (a & ~0x8000) >= 0x7c80;
+    y = (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
 #if SNAN_BIT_IS_ONE
-    return ((a & ~0x8000) >= 0x7c80);
+    return x;
 #else
-    return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
+    return y;
 #endif
 }
 #endif
@@ -311,10 +317,13 @@ int float32_is_signaling_nan(float32 a_ 
 int float32_is_quiet_nan(float32 a_ STATUS_PARAM)
 {
     uint32_t a = float32_val(a_);
+    int __attribute__ ((unused)) x, y;
+    x = (((a >> 22) & 0x1ff) == 0x1fe) && (a & 0x003fffff);
+    y = (uint32_t)(a << 1) >= 0xff800000;
 #if SNAN_BIT_IS_ONE
-    return (((a >> 22) & 0x1ff) == 0x1fe) && (a & 0x003fffff);
+    return x;
 #else
-    return ((uint32_t)(a << 1) >= 0xff800000);
+    return y;
 #endif
 }
 
@@ -326,10 +335,13 @@ int float32_is_quiet_nan(float32 a_ STAT
 int float32_is_signaling_nan(float32 a_ STATUS_PARAM)
 {
     uint32_t a = float32_val(a_);
+    int __attribute__ ((unused)) x, y;
+    x = (uint32_t)(a << 1) >= 0xff800000;
+    y = (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
 #if SNAN_BIT_IS_ONE
-    return ((uint32_t)(a << 1) >= 0xff800000);
+    return x;
 #else
-    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
+    return y;
 #endif
 }
 #endif
@@ -721,11 +733,13 @@ int float64_is_signaling_nan(float64 a_ 
 int float64_is_quiet_nan(float64 a_ STATUS_PARAM)
 {
     uint64_t a = float64_val(a_);
+    int __attribute__ ((unused)) x, y;
+    x = (((a >> 51) & 0xfff) == 0xffe) && (a & 0x0007ffffffffffffULL);
+    y = (a << 1) >= 0xfff0000000000000ULL;
 #if SNAN_BIT_IS_ONE
-    return (((a >> 51) & 0xfff) == 0xffe)
-           && (a & 0x0007ffffffffffffULL);
+    return x;
 #else
-    return ((a << 1) >= 0xfff0000000000000ULL);
+    return y;
 #endif
 }
 
@@ -737,12 +751,13 @@ int float64_is_quiet_nan(float64 a_ STAT
 int float64_is_signaling_nan(float64 a_ STATUS_PARAM)
 {
     uint64_t a = float64_val(a_);
+    int __attribute__ ((unused)) x, y;
+    x = ((a << 1) >= 0xfff0000000000000ULL);
+    y = (((a >> 51) & 0xFFF) == 0xFFE) && (a & LIT64(0x0007FFFFFFFFFFFF));
 #if SNAN_BIT_IS_ONE
-    return ((a << 1) >= 0xfff0000000000000ULL);
+    return x;
 #else
-    return
-           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
-        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
+    return y;
 #endif
 }
 #endif
@@ -921,16 +936,18 @@ int floatx80_is_signaling_nan(floatx80 a
 
 int floatx80_is_quiet_nan(floatx80 a STATUS_PARAM)
 {
-#if SNAN_BIT_IS_ONE
     uint64_t aLow;
-
+    int __attribute__ ((unused)) x, y;
     aLow = a.low & ~0x4000000000000000ULL;
-    return ((a.high & 0x7fff) == 0x7fff)
+    x = ((a.high & 0x7fff) == 0x7fff)
         && (aLow << 1)
         && (a.low == aLow);
+    y = ((a.high & 0x7FFF) == 0x7FFF)
+        && (LIT64(0x8000000000000000) <= ((uint64_t) (a.low << 1)));
+#if SNAN_BIT_IS_ONE
+    return x;
 #else
-    return ( ( a.high & 0x7FFF ) == 0x7FFF )
-        && (LIT64( 0x8000000000000000 ) <= ((uint64_t) ( a.low<<1 )));
+    return y;
 #endif
 }
 
@@ -942,17 +959,18 @@ int floatx80_is_quiet_nan(floatx80 a STA
 
 int floatx80_is_signaling_nan(floatx80 a STATUS_PARAM)
 {
-#if SNAN_BIT_IS_ONE
-    return ((a.high & 0x7fff) == 0x7fff)
+    uint64_t aLow;
+    int __attribute__ ((unused)) x, y;
+    aLow = a.low & ~LIT64(0x4000000000000000);
+    x = ((a.high & 0x7fff) == 0x7fff)
         && ((a.low << 1) >= 0x8000000000000000ULL);
+    y = ((a.high & 0x7FFF) == 0x7FFF)
+        && (uint64_t) (aLow << 1)
+        && (a.low == aLow);
+#if SNAN_BIT_IS_ONE
+    return x;
 #else
-    uint64_t aLow;
-
-    aLow = a.low & ~ LIT64( 0x4000000000000000 );
-    return
-           ( ( a.high & 0x7FFF ) == 0x7FFF )
-        && (uint64_t) ( aLow<<1 )
-        && ( a.low == aLow );
+    return y;
 #endif
 }
 #endif
@@ -1081,13 +1099,15 @@ int float128_is_signaling_nan(float128 a
 
 int float128_is_quiet_nan(float128 a STATUS_PARAM)
 {
-#if SNAN_BIT_IS_ONE
-    return (((a.high >> 47) & 0xffff) == 0xfffe)
+    int __attribute__ ((unused)) x, y;
+    x = (((a.high >> 47) & 0xffff) == 0xfffe)
         && (a.low || (a.high & 0x00007fffffffffffULL));
-#else
-    return
-        ((a.high << 1) >= 0xffff000000000000)
+    y = ((a.high << 1) >= 0xffff000000000000)
         && (a.low || (a.high & 0x0000ffffffffffffULL));
+#if SNAN_BIT_IS_ONE
+    return x;
+#else
+    return y;
 #endif
 }
 
@@ -1098,14 +1118,15 @@ int float128_is_quiet_nan(float128 a STA
 
 int float128_is_signaling_nan(float128 a STATUS_PARAM)
 {
-#if SNAN_BIT_IS_ONE
-    return
-        ((a.high << 1) >= 0xffff000000000000)
+    int __attribute__ ((unused)) x, y;
+    x = ((a.high << 1) >= 0xffff000000000000)
         && (a.low || (a.high & 0x0000ffffffffffffULL));
+    y = (((a.high >> 47) & 0xFFFF) == 0xFFFE)
+        && (a.low || (a.high & LIT64(0x00007FFFFFFFFFFF)));
+#if SNAN_BIT_IS_ONE
+    return x;
 #else
-    return
-           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
-        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
+    return y;
 #endif
 }
 #endif

^ permalink raw reply	[flat|nested] 43+ messages in thread

* [Qemu-devel] [PATCH v2 6/7] softfloat: Add SoftFloat status `nan2008_mode' flag
  2014-12-09  1:55 ` [Qemu-devel] [PATCH 6/7] softfloat: Add SoftFloat status `nan2008_mode' flag Maciej W. Rozycki
@ 2014-12-12 19:35   ` Maciej W. Rozycki
  2015-02-05 17:00     ` Peter Maydell
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2014-12-12 19:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: Leon Alrae, Thomas Schwinge, Aurelien Jarno

Add support for switching between legacy NaN and IEEE 754-2008 NaN modes 
where required, currently for the MIPS target only.  Also handle the 
saving and restoration of the `nan2008_mode' status flag.

Use qNaN bit patterns for the 2008 NaN mode as from revision 5.00 [1][2] 
of the MIPS Architecture, updated from revision 3.50 that used a 
different choice.

References:

[1] "MIPS Architecture For Programmers, Volume I-A: Introduction to the
    MIPS32 Architecture", MIPS Technologies, Inc., Document Number:
    MD00082, Revision 5.02, April 30, 2013, Table 5.3 "Value Supplied 
    When a New Quiet NaN Is Created", p. 73

[2] "MIPS Architecture For Programmers, Volume I-A: Introduction to the
    MIPS64 Architecture", MIPS Technologies, Inc., Document Number:
    MD00083, Revision 5.01, December 15, 2012, Table 5.3 "Value Supplied 
    When a New Quiet NaN Is Created", p. 73

Signed-off-by: Thomas Schwinge <thomas@codesourcery.com>
Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
---
Changes from v1:

- regenerate on top of the SoftFloat relicensing patch set.

qemu-softfloat-nan2008.diff
Index: qemu-git-trunk/fpu/softfloat-specialize.h
===================================================================
--- qemu-git-trunk.orig/fpu/softfloat-specialize.h	2014-12-11 22:42:41.128934304 +0000
+++ qemu-git-trunk/fpu/softfloat-specialize.h	2014-12-11 22:43:02.128938514 +0000
@@ -83,10 +83,16 @@ this code that are retained.
  * by setting the most significant bit of the mantissa for a signaling NaN?
  * (The more common choice is to have it be zero for SNaN and one for QNaN.)
  */
-#if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
-#define SNAN_BIT_IS_ONE 1
+#if defined(TARGET_MIPS)
+/* Has to be decided dynamically.  */
+#define SNAN_BIT_IS_VARIABLE   1
+#define SNAN_BIT_IS_ONE        0
+#elif defined(TARGET_SH4) || defined(TARGET_UNICORE32)
+#define SNAN_BIT_IS_VARIABLE   0
+#define SNAN_BIT_IS_ONE        1
 #else
-#define SNAN_BIT_IS_ONE 0
+#define SNAN_BIT_IS_VARIABLE   0
+#define SNAN_BIT_IS_ONE        0
 #endif
 
 #if defined(TARGET_XTENSA)
@@ -103,6 +109,10 @@ inline float16 float16_default_nan(STATU
 {
 #if defined(TARGET_ARM)
     return const_float16(0x7E00);
+#elif SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode)
+           ? const_float16(0x7E00)
+           : const_float16(0x7DFF);
 #elif SNAN_BIT_IS_ONE
     return const_float16(0x7DFF);
 #else
@@ -120,6 +130,10 @@ inline float32 float32_default_nan(STATU
 #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
       defined(TARGET_XTENSA)
     return const_float32(0x7FC00000);
+#elif SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode)
+           ? const_float32(0x7FC00000)
+           : const_float32(0x7FBFFFFF);
 #elif SNAN_BIT_IS_ONE
     return const_float32(0x7FBFFFFF);
 #else
@@ -136,6 +150,10 @@ inline float64 float64_default_nan(STATU
     return const_float64(LIT64(0x7FFFFFFFFFFFFFFF));
 #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
     return const_float64(LIT64(0x7FF8000000000000));
+#elif SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode)
+           ? const_float64(LIT64(0x7FF8000000000000))
+           : const_float64(LIT64(0x7FF7FFFFFFFFFFFF));
 #elif SNAN_BIT_IS_ONE
     return const_float64(LIT64(0x7FF7FFFFFFFFFFFF));
 #else
@@ -148,7 +166,11 @@ inline float64 float64_default_nan(STATU
 *----------------------------------------------------------------------------*/
 inline floatx80 floatx80_default_nan(STATUS_PARAM_ONLY)
 {
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode)
+           ? make_floatx80(0xFFFF, LIT64(0xC000000000000000))
+           : make_floatx80(0x7FFF, LIT64(0xBFFFFFFFFFFFFFFF));
+#elif SNAN_BIT_IS_ONE
     return make_floatx80(0x7FFF, LIT64(0xBFFFFFFFFFFFFFFF));
 #else
     return make_floatx80(0xFFFF, LIT64(0xC000000000000000));
@@ -161,7 +183,13 @@ inline floatx80 floatx80_default_nan(STA
 *----------------------------------------------------------------------------*/
 inline float128 float128_default_nan(STATUS_PARAM_ONLY)
 {
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode)
+           ? make_float128(LIT64(0x7FFF800000000000),
+                           LIT64(0x0000000000000000))
+           : make_float128(LIT64(0x7FFF7FFFFFFFFFFF),
+                           LIT64(0xFFFFFFFFFFFFFFFF));
+#elif SNAN_BIT_IS_ONE
     return make_float128(LIT64(0x7FFF7FFFFFFFFFFF), LIT64(0xFFFFFFFFFFFFFFFF));
 #else
     return make_float128(LIT64(0xFFFF800000000000), LIT64(0x0000000000000000));
@@ -210,7 +238,9 @@ int float16_is_quiet_nan(float16 a_ STAT
     int __attribute__ ((unused)) x, y;
     x = (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
     y = (a & ~0x8000) >= 0x7c80;
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -228,7 +258,9 @@ int float16_is_signaling_nan(float16 a_ 
     int __attribute__ ((unused)) x, y;
     x = (a & ~0x8000) >= 0x7c80;
     y = (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -243,8 +275,10 @@ int float16_is_signaling_nan(float16 a_ 
 float16 float16_maybe_silence_nan(float16 a_ STATUS_PARAM)
 {
     if (float16_is_signaling_nan(a_ STATUS_VAR)) {
-#if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
+#if SNAN_BIT_IS_VARIABLE
+        return float16_default_nan(status);
+#elif SNAN_BIT_IS_ONE
+#  if defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         return float16_default_nan(status);
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
@@ -320,7 +354,9 @@ int float32_is_quiet_nan(float32 a_ STAT
     int __attribute__ ((unused)) x, y;
     x = (((a >> 22) & 0x1ff) == 0x1fe) && (a & 0x003fffff);
     y = (uint32_t)(a << 1) >= 0xff800000;
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -338,7 +374,9 @@ int float32_is_signaling_nan(float32 a_ 
     int __attribute__ ((unused)) x, y;
     x = (uint32_t)(a << 1) >= 0xff800000;
     y = (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -354,8 +392,10 @@ int float32_is_signaling_nan(float32 a_ 
 float32 float32_maybe_silence_nan(float32 a_ STATUS_PARAM)
 {
     if (float32_is_signaling_nan(a_ STATUS_VAR)) {
-#if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
+#if SNAN_BIT_IS_VARIABLE
+        return float32_default_nan(status);
+#elif SNAN_BIT_IS_ONE
+#  if defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         return float32_default_nan(status);
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
@@ -736,7 +776,9 @@ int float64_is_quiet_nan(float64 a_ STAT
     int __attribute__ ((unused)) x, y;
     x = (((a >> 51) & 0xfff) == 0xffe) && (a & 0x0007ffffffffffffULL);
     y = (a << 1) >= 0xfff0000000000000ULL;
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -754,7 +796,9 @@ int float64_is_signaling_nan(float64 a_ 
     int __attribute__ ((unused)) x, y;
     x = ((a << 1) >= 0xfff0000000000000ULL);
     y = (((a >> 51) & 0xFFF) == 0xFFE) && (a & LIT64(0x0007FFFFFFFFFFFF));
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -770,8 +814,10 @@ int float64_is_signaling_nan(float64 a_ 
 float64 float64_maybe_silence_nan(float64 a_ STATUS_PARAM)
 {
     if (float64_is_signaling_nan(a_ STATUS_VAR)) {
-#if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
+#if SNAN_BIT_IS_VARIABLE
+        return float64_default_nan(status);
+#elif SNAN_BIT_IS_ONE
+#  if defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         return float64_default_nan(status);
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
@@ -944,7 +990,9 @@ int floatx80_is_quiet_nan(floatx80 a STA
         && (a.low == aLow);
     y = ((a.high & 0x7FFF) == 0x7FFF)
         && (LIT64(0x8000000000000000) <= ((uint64_t) (a.low << 1)));
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -967,7 +1015,9 @@ int floatx80_is_signaling_nan(floatx80 a
     y = ((a.high & 0x7FFF) == 0x7FFF)
         && (uint64_t) (aLow << 1)
         && (a.low == aLow);
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -983,8 +1033,10 @@ int floatx80_is_signaling_nan(floatx80 a
 floatx80 floatx80_maybe_silence_nan(floatx80 a STATUS_PARAM)
 {
     if (floatx80_is_signaling_nan(a STATUS_VAR)) {
-#if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
+#if SNAN_BIT_IS_VARIABLE
+        a = floatx80_default_nan(status);
+#elif SNAN_BIT_IS_ONE
+#  if defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         a = floatx80_default_nan(status);
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
@@ -1104,7 +1156,9 @@ int float128_is_quiet_nan(float128 a STA
         && (a.low || (a.high & 0x00007fffffffffffULL));
     y = ((a.high << 1) >= 0xffff000000000000)
         && (a.low || (a.high & 0x0000ffffffffffffULL));
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -1123,7 +1177,9 @@ int float128_is_signaling_nan(float128 a
         && (a.low || (a.high & 0x0000ffffffffffffULL));
     y = (((a.high >> 47) & 0xFFFF) == 0xFFFE)
         && (a.low || (a.high & LIT64(0x00007FFFFFFFFFFF)));
-#if SNAN_BIT_IS_ONE
+#if SNAN_BIT_IS_VARIABLE
+    return STATUS(nan2008_mode) ? y : x;
+#elif SNAN_BIT_IS_ONE
     return x;
 #else
     return y;
@@ -1139,8 +1195,10 @@ int float128_is_signaling_nan(float128 a
 float128 float128_maybe_silence_nan(float128 a STATUS_PARAM)
 {
     if (float128_is_signaling_nan(a STATUS_VAR)) {
-#if SNAN_BIT_IS_ONE
-#  if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
+#if SNAN_BIT_IS_VARIABLE
+        a = float128_default_nan(status);
+#elif SNAN_BIT_IS_ONE
+#  if defined(TARGET_SH4) || defined(TARGET_UNICORE32)
         a = float128_default_nan(status);
 #  else
 #    error Rules for silencing a signaling NaN are target-specific
Index: qemu-git-trunk/include/fpu/softfloat.h
===================================================================
--- qemu-git-trunk.orig/include/fpu/softfloat.h	2014-12-11 22:42:41.128934304 +0000
+++ qemu-git-trunk/include/fpu/softfloat.h	2014-12-11 22:43:02.128938514 +0000
@@ -223,6 +223,7 @@ typedef struct float_status {
     /* should denormalised inputs go to zero and set the input_denormal flag? */
     flag flush_inputs_to_zero;
     flag default_nan_mode;
+    flag nan2008_mode;
 } float_status;
 
 static inline void set_float_detect_tininess(int val STATUS_PARAM)
@@ -253,6 +254,10 @@ static inline void set_default_nan_mode(
 {
     STATUS(default_nan_mode) = val;
 }
+static inline void set_nan2008_mode(flag val STATUS_PARAM)
+{
+    STATUS(nan2008_mode) = val;
+}
 static inline int get_float_detect_tininess(float_status *status)
 {
     return STATUS(float_detect_tininess);
Index: qemu-git-trunk/target-mips/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-mips/cpu.h	2014-12-11 22:42:41.128934304 +0000
+++ qemu-git-trunk/target-mips/cpu.h	2014-12-11 22:43:02.128938514 +0000
@@ -615,7 +615,11 @@ void mips_cpu_list (FILE *f, fprintf_fun
 extern void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env);
 extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env);
 
-#define CPU_SAVE_VERSION 7
+#define CPU_SAVE_VERSION 8
+/* We preserve compatibility with rev. 7 images.  */
+#define CPU_SAVE_VERSION_OLDEST_SUPPORTED 7
+/* Rev. 8 added 2008 NaN support.  */
+#define CPU_SAVE_VERSION_2008_NAN 8
 
 /* MMU modes definitions. We carefully match the indices with our
    hflags layout. */
Index: qemu-git-trunk/target-mips/machine.c
===================================================================
--- qemu-git-trunk.orig/target-mips/machine.c	2014-12-11 22:42:41.128934304 +0000
+++ qemu-git-trunk/target-mips/machine.c	2014-12-11 22:43:02.128938514 +0000
@@ -39,6 +39,7 @@ static void save_fpu(QEMUFile *f, CPUMIP
     for(i = 0; i < 32; i++)
         qemu_put_be64s(f, &fpu->fpr[i].d);
     qemu_put_8s(f, &fpu->fp_status.flush_to_zero);
+    qemu_put_8s(f, &fpu->fp_status.nan2008_mode);
     qemu_put_s8s(f, &fpu->fp_status.float_rounding_mode);
     qemu_put_s8s(f, &fpu->fp_status.float_exception_flags);
     qemu_put_be32s(f, &fpu->fcr0);
@@ -195,13 +196,18 @@ static void load_tc(QEMUFile *f, TCState
     qemu_get_8s(f, &tc->msa_fp_status.flush_inputs_to_zero);
 }
 
-static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu)
+static void load_fpu(QEMUFile *f, CPUMIPSFPUContext *fpu, int version_id)
 {
     int i;
 
     for(i = 0; i < 32; i++)
         qemu_get_be64s(f, &fpu->fpr[i].d);
     qemu_get_8s(f, &fpu->fp_status.flush_to_zero);
+    if (version_id >= CPU_SAVE_VERSION_2008_NAN) {
+        qemu_get_8s(f, &fpu->fp_status.nan2008_mode);
+    } else {
+        fpu->fp_status.nan2008_mode = 0;
+    }
     qemu_get_s8s(f, &fpu->fp_status.float_rounding_mode);
     qemu_get_s8s(f, &fpu->fp_status.float_exception_flags);
     qemu_get_be32s(f, &fpu->fcr0);
@@ -214,7 +220,7 @@ int cpu_load(QEMUFile *f, void *opaque, 
     MIPSCPU *cpu = mips_env_get_cpu(env);
     int i;
 
-    if (version_id != CPU_SAVE_VERSION) {
+    if (version_id < CPU_SAVE_VERSION_OLDEST_SUPPORTED) {
         return -EINVAL;
     }
 
@@ -222,7 +228,7 @@ int cpu_load(QEMUFile *f, void *opaque, 
     load_tc(f, &env->active_tc);
 
     /* Load active FPU */
-    load_fpu(f, &env->active_fpu);
+    load_fpu(f, &env->active_fpu, version_id);
 
     /* Load MVP */
     qemu_get_sbe32s(f, &env->mvp->CP0_MVPControl);
@@ -336,8 +342,9 @@ int cpu_load(QEMUFile *f, void *opaque, 
     for (i = 0; i < MIPS_SHADOW_SET_MAX; i++) {
         load_tc(f, &env->tcs[i]);
     }
-    for (i = 0; i < MIPS_FPU_MAX; i++)
-        load_fpu(f, &env->fpus[i]);
+    for (i = 0; i < MIPS_FPU_MAX; i++) {
+        load_fpu(f, &env->fpus[i], version_id);
+    }
 
     /* XXX: ensure compatibility for halted bit ? */
     tlb_flush(CPU(cpu), 1);

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 2/7] softfloat: Simplify `floatx80ToCommonNaN' function
  2014-12-09  1:54 ` [Qemu-devel] [PATCH 2/7] softfloat: Simplify `floatx80ToCommonNaN' function Maciej W. Rozycki
@ 2015-01-28 16:15   ` Leon Alrae
  0 siblings, 0 replies; 43+ messages in thread
From: Leon Alrae @ 2015-01-28 16:15 UTC (permalink / raw)
  To: Maciej W. Rozycki, qemu-devel; +Cc: Thomas Schwinge, Aurelien Jarno

On 09/12/2014 01:54, Maciej W. Rozycki wrote:
> Make the bit shuffling in one place only and replace input if required 
> instead.
> 
> Signed-off-by: Thomas Schwinge <thomas@codesourcery.com>
> Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
> ---
> qemu-softfloat-floatx80-nan.diff
> Index: qemu-git-trunk/fpu/softfloat-specialize.h

Reviewed-by: Leon Alrae <leon.alrae@imgtec.com>

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion operations
  2014-12-09  1:54 ` [Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion operations Maciej W. Rozycki
@ 2015-01-29 14:51   ` Leon Alrae
  2015-02-05 16:37   ` Peter Maydell
  1 sibling, 0 replies; 43+ messages in thread
From: Leon Alrae @ 2015-01-29 14:51 UTC (permalink / raw)
  To: Maciej W. Rozycki, qemu-devel; +Cc: Thomas Schwinge, Aurelien Jarno

On 09/12/2014 01:54, Maciej W. Rozycki wrote:
> 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 <macro@codesourcery.com>
> ---
>  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

Reviewed-by: Leon Alrae <leon.alrae@imgtec.com>

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support
  2014-12-09  1:54 [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support Maciej W. Rozycki
                   ` (7 preceding siblings ...)
  2014-12-09  9:20 ` [Qemu-devel] [PATCH 0/7] MIPS: " Peter Maydell
@ 2015-01-30 11:59 ` Peter Maydell
  2015-01-30 13:47   ` Maciej W. Rozycki
  8 siblings, 1 reply; 43+ messages in thread
From: Peter Maydell @ 2015-01-30 11:59 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Leon Alrae, QEMU Developers, Aurelien Jarno, Thomas Schwinge

On 9 December 2014 at 01:54, Maciej W. Rozycki <macro@codesourcery.com> wrote:
>  This patch series comprises changes to QEMU, both the MIPS backend and
> generic SoftFloat support code, to support IEEE 754-2008 features
> introduced to revision 3.50 of the MIPS Architecture as follows.

Just to let you know that:
(1) the softfloat relicensing has hit master, so this patchset isn't
    blocked by anything now
(2) I would like to see a definite "we are happy to license this
patchset under the SoftFloat-2a license" for these changes, because
they were submitted before we applied the relicensing, and therefore
the "changes after $DATE will be -2a license unless otherwise stated"
note in the sourcecode can't be assumed to apply to them.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support
  2015-01-30 11:59 ` Peter Maydell
@ 2015-01-30 13:47   ` Maciej W. Rozycki
       [not found]     ` <54CE9614.2060805@codesourcery.com>
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2015-01-30 13:47 UTC (permalink / raw)
  To: Peter Maydell, Thomas Schwinge
  Cc: Leon Alrae, QEMU Developers, Aurelien Jarno

On Fri, 30 Jan 2015, Peter Maydell wrote:

> >  This patch series comprises changes to QEMU, both the MIPS backend and
> > generic SoftFloat support code, to support IEEE 754-2008 features
> > introduced to revision 3.50 of the MIPS Architecture as follows.
> 
> Just to let you know that:
> (1) the softfloat relicensing has hit master, so this patchset isn't
>     blocked by anything now
> (2) I would like to see a definite "we are happy to license this
> patchset under the SoftFloat-2a license" for these changes, because
> they were submitted before we applied the relicensing, and therefore
> the "changes after $DATE will be -2a license unless otherwise stated"
> note in the sourcecode can't be assumed to apply to them.

 Thanks for the heads-up!  At this stage however someone at Mentor will 
have to make such a statement on behalf of the company as I am no longer 
there and as far as this patch set is concerned I am merely a member of 
the public who can just make technical comments as anyone can, including 
you.

 I think Thomas, being the writer of the majority of code comprising these 
patches, is now in the best position to make such a statement happen.  
Thomas -- will you be able to take it from here?  Thanks!

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH v2 3/7] softfloat: Convert `*_default_nan' variables into inline functions
  2014-12-12 19:34   ` [Qemu-devel] [PATCH v2 " Maciej W. Rozycki
@ 2015-01-30 14:09     ` Leon Alrae
  2015-01-30 16:02       ` Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Leon Alrae @ 2015-01-30 14:09 UTC (permalink / raw)
  To: Maciej W. Rozycki, qemu-devel; +Cc: Thomas Schwinge, Aurelien Jarno

On 12/12/2014 19:34, Maciej W. Rozycki wrote:
> Mechanically replace `*_default_nan' variables with inline functions and 
> convert references accordingly.  Use `__inline__' rather than `inline' 
> so that the latter does not cause the definitions to become static as a 
> result of macro expansion, the functions are best inlined when referred 
> to from softfloat.c, but external copies must be also produced for 
> external callers.
> 
> Signed-off-by: Thomas Schwinge <thomas@codesourcery.com>
> Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
<snip>
> Index: qemu-git-trunk/include/fpu/softfloat.h
> ===================================================================
> --- qemu-git-trunk.orig/include/fpu/softfloat.h	2014-12-11 18:15:02.000000000 +0000
> +++ qemu-git-trunk/include/fpu/softfloat.h	2014-12-11 18:18:00.918095644 +0000
> @@ -370,7 +370,7 @@ static inline int float16_is_any_nan(flo
>  /*----------------------------------------------------------------------------
>  | The pattern for a default generated half-precision NaN.
>  *----------------------------------------------------------------------------*/
> -extern const float16 float16_default_nan;
> +__inline__ float16 float16_default_nan(void);
>  
>  /*----------------------------------------------------------------------------
>  | Software IEC/IEEE single-precision conversion routines.
> @@ -482,7 +482,7 @@ static inline float32 float32_set_sign(f
>  /*----------------------------------------------------------------------------
>  | The pattern for a default generated single-precision NaN.
>  *----------------------------------------------------------------------------*/
> -extern const float32 float32_default_nan;
> +__inline__ float32 float32_default_nan(void);
>  
>  /*----------------------------------------------------------------------------
>  | Software IEC/IEEE double-precision conversion routines.
> @@ -594,7 +594,7 @@ static inline float64 float64_set_sign(f
>  /*----------------------------------------------------------------------------
>  | The pattern for a default generated double-precision NaN.
>  *----------------------------------------------------------------------------*/
> -extern const float64 float64_default_nan;
> +__inline__ float64 float64_default_nan(void);
>  
>  /*----------------------------------------------------------------------------
>  | Software IEC/IEEE extended double-precision conversion routines.
> @@ -679,7 +679,7 @@ static inline int floatx80_is_any_nan(fl
>  /*----------------------------------------------------------------------------
>  | The pattern for a default generated extended double-precision NaN.
>  *----------------------------------------------------------------------------*/
> -extern const floatx80 floatx80_default_nan;
> +__inline__ floatx80 floatx80_default_nan(void);
>  
>  /*----------------------------------------------------------------------------
>  | Software IEC/IEEE quadruple-precision conversion routines.
> @@ -760,6 +760,6 @@ static inline int float128_is_any_nan(fl
>  /*----------------------------------------------------------------------------
>  | The pattern for a default generated quadruple-precision NaN.
>  *----------------------------------------------------------------------------*/
> -extern const float128 float128_default_nan;
> +__inline__ float128 float128_default_nan(void);
>  

Unfortunately clang complains about it and eventually it won't link:

  CC    aarch64-softmmu/target-arm/helper-a64.o
In file included from /qemu/target-arm/helper-a64.c:20:
In file included from /qemu/target-arm/cpu.h:37:
In file included from /qemu/include/qemu-common.h:120:
In file included from /qemu/include/qemu/bswap.h:8:
/qemu/include/fpu/softfloat.h:485:20: warning: inline function
'float32_default_nan' is not defined [-Wundefined-inline]
__inline__ float32 float32_default_nan(void);
                   ^
/qemu/target-arm/helper-a64.c:345:19: note: used here
            nan = float32_default_nan();
                  ^
In file included from /qemu/target-arm/helper-a64.c:20:
In file included from /qemu/target-arm/cpu.h:37:
In file included from /qemu/include/qemu-common.h:120:
In file included from /qemu/include/qemu/bswap.h:8:
/qemu/include/fpu/softfloat.h:597:20: warning: inline function
'float64_default_nan' is not defined [-Wundefined-inline]
__inline__ float64 float64_default_nan(void);
                   ^
/qemu/target-arm/helper-a64.c:374:19: note: used here
            nan = float64_default_nan();
                  ^
2 warnings generated.
  CC    aarch64-softmmu/target-arm/gdbstub64.o
  CC    aarch64-softmmu/target-arm/crypto_helper.o
  GEN   trace/generated-helpers.c
  CC    aarch64-softmmu/trace/generated-helpers.o
  LINK  aarch64-softmmu/qemu-system-aarch64
fpu/softfloat.o: In function `commonNaNToFloat64':
/qemu/fpu/softfloat-specialize.h:796: undefined reference to
`float64_default_nan'
/qemu/fpu/softfloat-specialize.h:805: undefined reference to
`float64_default_nan'
fpu/softfloat.o: In function `commonNaNToFloatx80':
/qemu/fpu/softfloat-specialize.h:1007: undefined reference to
`floatx80_default_nan'
/qemu/fpu/softfloat-specialize.h:1014: undefined reference to
`floatx80_default_nan'

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH v2 3/7] softfloat: Convert `*_default_nan' variables into inline functions
  2015-01-30 14:09     ` Leon Alrae
@ 2015-01-30 16:02       ` Maciej W. Rozycki
  2015-01-30 16:55         ` Peter Maydell
  2015-02-03 15:43         ` Richard Henderson
  0 siblings, 2 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2015-01-30 16:02 UTC (permalink / raw)
  To: Leon Alrae; +Cc: qemu-devel, Aurelien Jarno, Thomas Schwinge

On Fri, 30 Jan 2015, Leon Alrae wrote:

> > @@ -760,6 +760,6 @@ static inline int float128_is_any_nan(fl
> >  /*----------------------------------------------------------------------------
> >  | The pattern for a default generated quadruple-precision NaN.
> >  *----------------------------------------------------------------------------*/
> > -extern const float128 float128_default_nan;
> > +__inline__ float128 float128_default_nan(void);
> >  
> 
> Unfortunately clang complains about it and eventually it won't link:
> 
>   CC    aarch64-softmmu/target-arm/helper-a64.o
> In file included from /qemu/target-arm/helper-a64.c:20:
> In file included from /qemu/target-arm/cpu.h:37:
> In file included from /qemu/include/qemu-common.h:120:
> In file included from /qemu/include/qemu/bswap.h:8:
> /qemu/include/fpu/softfloat.h:485:20: warning: inline function
> 'float32_default_nan' is not defined [-Wundefined-inline]
> __inline__ float32 float32_default_nan(void);
>                    ^
> /qemu/target-arm/helper-a64.c:345:19: note: used here
>             nan = float32_default_nan();
>                   ^
> In file included from /qemu/target-arm/helper-a64.c:20:
> In file included from /qemu/target-arm/cpu.h:37:
> In file included from /qemu/include/qemu-common.h:120:
> In file included from /qemu/include/qemu/bswap.h:8:
> /qemu/include/fpu/softfloat.h:597:20: warning: inline function
> 'float64_default_nan' is not defined [-Wundefined-inline]
> __inline__ float64 float64_default_nan(void);
>                    ^
> /qemu/target-arm/helper-a64.c:374:19: note: used here
>             nan = float64_default_nan();
>                   ^
> 2 warnings generated.
>   CC    aarch64-softmmu/target-arm/gdbstub64.o
>   CC    aarch64-softmmu/target-arm/crypto_helper.o
>   GEN   trace/generated-helpers.c
>   CC    aarch64-softmmu/trace/generated-helpers.o
>   LINK  aarch64-softmmu/qemu-system-aarch64
> fpu/softfloat.o: In function `commonNaNToFloat64':
> /qemu/fpu/softfloat-specialize.h:796: undefined reference to
> `float64_default_nan'
> /qemu/fpu/softfloat-specialize.h:805: undefined reference to
> `float64_default_nan'
> fpu/softfloat.o: In function `commonNaNToFloatx80':
> /qemu/fpu/softfloat-specialize.h:1007: undefined reference to
> `floatx80_default_nan'
> /qemu/fpu/softfloat-specialize.h:1014: undefined reference to
> `floatx80_default_nan'

 Hmm, so perhaps my idea for a later improvement:

>  Eventually we might want to move the new inline functions into a
> separate header to be included from softfloat.h instead of softfloat.c,
> but let's make changes one step at a time.

will actually have to be made right away.  I suspect GCC is more liberal 
here due to its convoluted extern/static/inline semantics history.  
Sigh...

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH v2 3/7] softfloat: Convert `*_default_nan' variables into inline functions
  2015-01-30 16:02       ` Maciej W. Rozycki
@ 2015-01-30 16:55         ` Peter Maydell
  2015-01-31 11:56           ` Maciej W. Rozycki
  2015-02-03 15:43         ` Richard Henderson
  1 sibling, 1 reply; 43+ messages in thread
From: Peter Maydell @ 2015-01-30 16:55 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Leon Alrae, QEMU Developers, Aurelien Jarno, Thomas Schwinge

On 30 January 2015 at 16:02, Maciej W. Rozycki <macro@linux-mips.org> wrote:
>  Hmm, so perhaps my idea for a later improvement:
>
>>  Eventually we might want to move the new inline functions into a
>> separate header to be included from softfloat.h instead of softfloat.c,
>> but let's make changes one step at a time.
>
> will actually have to be made right away.  I suspect GCC is more liberal
> here due to its convoluted extern/static/inline semantics history.
> Sigh...

I would suggest just using "static inline", as we do elsewhere
for little utility functions.

-- PMM

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH v2 3/7] softfloat: Convert `*_default_nan' variables into inline functions
  2015-01-30 16:55         ` Peter Maydell
@ 2015-01-31 11:56           ` Maciej W. Rozycki
  2015-01-31 12:52             ` Peter Maydell
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2015-01-31 11:56 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Leon Alrae, QEMU Developers, Aurelien Jarno, Thomas Schwinge

On Fri, 30 Jan 2015, Peter Maydell wrote:

> >  Hmm, so perhaps my idea for a later improvement:
> >
> >>  Eventually we might want to move the new inline functions into a
> >> separate header to be included from softfloat.h instead of softfloat.c,
> >> but let's make changes one step at a time.
> >
> > will actually have to be made right away.  I suspect GCC is more liberal
> > here due to its convoluted extern/static/inline semantics history.
> > Sigh...
> 
> I would suggest just using "static inline", as we do elsewhere
> for little utility functions.

 Yes, that's exactly what they'd have to be moved into a separate header 
for.

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH v2 3/7] softfloat: Convert `*_default_nan' variables into inline functions
  2015-01-31 11:56           ` Maciej W. Rozycki
@ 2015-01-31 12:52             ` Peter Maydell
  2015-01-31 14:58               ` Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Peter Maydell @ 2015-01-31 12:52 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Leon Alrae, QEMU Developers, Aurelien Jarno, Thomas Schwinge

On 31 January 2015 at 11:56, Maciej W. Rozycki <macro@linux-mips.org> wrote:
> On Fri, 30 Jan 2015, Peter Maydell wrote:
>
>> >  Hmm, so perhaps my idea for a later improvement:
>> >
>> >>  Eventually we might want to move the new inline functions into a
>> >> separate header to be included from softfloat.h instead of softfloat.c,
>> >> but let's make changes one step at a time.
>> >
>> > will actually have to be made right away.  I suspect GCC is more liberal
>> > here due to its convoluted extern/static/inline semantics history.
>> > Sigh...
>>
>> I would suggest just using "static inline", as we do elsewhere
>> for little utility functions.
>
>  Yes, that's exactly what they'd have to be moved into a separate header
> for.

Why do they need to be moved into a different header to do this?
I must be missing something...

-- PMM

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH v2 3/7] softfloat: Convert `*_default_nan' variables into inline functions
  2015-01-31 12:52             ` Peter Maydell
@ 2015-01-31 14:58               ` Maciej W. Rozycki
  0 siblings, 0 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2015-01-31 14:58 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Leon Alrae, QEMU Developers, Aurelien Jarno, Thomas Schwinge

On Sat, 31 Jan 2015, Peter Maydell wrote:

> >> >  Hmm, so perhaps my idea for a later improvement:
> >> >
> >> >>  Eventually we might want to move the new inline functions into a
> >> >> separate header to be included from softfloat.h instead of softfloat.c,
> >> >> but let's make changes one step at a time.
> >> >
> >> > will actually have to be made right away.  I suspect GCC is more liberal
> >> > here due to its convoluted extern/static/inline semantics history.
> >> > Sigh...
> >>
> >> I would suggest just using "static inline", as we do elsewhere
> >> for little utility functions.
> >
> >  Yes, that's exactly what they'd have to be moved into a separate header
> > for.
> 
> Why do they need to be moved into a different header to do this?
> I must be missing something...

 This is because fpu/softfloat-specialize.h is an implementation header 
private to SoftFloat and therefore such inline definitions won't be seen 
by users outside SoftFloat, such as target-mips/msa_helper.c.  And IMO 
they shouldn't be moved into include/fpu/softfloat.h itself as this header 
contains generic stuff and is supposed to have no TARGET_foo stuff, as 
observed by current usage and inferred from comments in fpu/softfloat.c.

 So ultimately I think the newly converted `*_default_nan' inline 
functions will need to go into include/fpu/softfloat-public-specialize.h 
or suchlike, which will be pulled from include/fpu/softfloat.h for general 
availability.

 Overall I think the whole arrangement in fpu/softfloat-specialize.h has a 
potential to being cleaned up by removing all the chains of #ifdef's and 
splitting the conditional bits into separate headers matching the current 
variants.  E.g. the presence of this construct:

#if defined(TARGET_SPARC)
const float64 float64_default_nan = const_float64(LIT64( 0x7FFFFFFFFFFFFFFF ));
#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
const float64 float64_default_nan = const_float64(LIT64( 0x7FF8000000000000 ));
#elif SNAN_BIT_IS_ONE
const float64 float64_default_nan = const_float64(LIT64( 0x7FF7FFFFFFFFFFFF ));
#else
const float64 float64_default_nan = const_float64(LIT64( 0xFFF8000000000000 ));
#endif

asks for 4 independent headers defining the 4 bit pattern styles used by 
targets for symbolic FP data, one each -- perhaps even pulled indirectly 
via target headers rather than copying the chain of #ifdef's above around 
#include's from wherever they'll be pulled.

 Please correct me if I am wrong, but it appears to me possible right away 
by removing fpu/softfloat-specialize.h and instead creating individual 
target-*/softfloat-specialize.h headers that'll pull the right variant 
each target requires from a pool of templates made available in fpu/.  
Then include/fpu/softfloat.h could do the same for the public stuff (i.e. 
these NaN bits concerned here) placed similarly in include/fpu/.

 FWIW,

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH v2 3/7] softfloat: Convert `*_default_nan' variables into inline functions
  2015-01-30 16:02       ` Maciej W. Rozycki
  2015-01-30 16:55         ` Peter Maydell
@ 2015-02-03 15:43         ` Richard Henderson
  1 sibling, 0 replies; 43+ messages in thread
From: Richard Henderson @ 2015-02-03 15:43 UTC (permalink / raw)
  To: Maciej W. Rozycki, Leon Alrae; +Cc: qemu-devel, Aurelien Jarno, Thomas Schwinge

On 01/30/2015 08:02 AM, Maciej W. Rozycki wrote:
>  Hmm, so perhaps my idea for a later improvement:
> 
>> >  Eventually we might want to move the new inline functions into a
>> > separate header to be included from softfloat.h instead of softfloat.c,
>> > but let's make changes one step at a time.
> will actually have to be made right away.  I suspect GCC is more liberal 
> here due to its convoluted extern/static/inline semantics history.  
> Sigh...

GCC 5 is moving to -std=gnu11 as default, and so will have the same problem.


r~

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support
       [not found]     ` <54CE9614.2060805@codesourcery.com>
@ 2015-02-03 16:28       ` Thomas Schwinge
  2015-02-03 22:30         ` Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Thomas Schwinge @ 2015-02-03 16:28 UTC (permalink / raw)
  To: Maciej W. Rozycki, Peter Maydell
  Cc: Sandra Loosemore, Leon Alrae, QEMU Developers, Aurelien Jarno

[-- Attachment #1: Type: text/plain, Size: 1579 bytes --]

Hi!

On Fri, 30 Jan 2015 13:47:17 +0000, "Maciej W. Rozycki" <macro@linux-mips.org> wrote:
> On Fri, 30 Jan 2015, Peter Maydell wrote:
> 
> > >  This patch series comprises changes to QEMU, both the MIPS backend and
> > > generic SoftFloat support code, to support IEEE 754-2008 features
> > > introduced to revision 3.50 of the MIPS Architecture as follows.
> > 
> > Just to let you know that:
> > (1) the softfloat relicensing has hit master, so this patchset isn't
> >     blocked by anything now

\o/

> > (2) I would like to see a definite "we are happy to license this
> > patchset under the SoftFloat-2a license" for these changes, because
> > they were submitted before we applied the relicensing, and therefore
> > the "changes after $DATE will be -2a license unless otherwise stated"
> > note in the sourcecode can't be assumed to apply to them.
> 
>  Thanks for the heads-up!  At this stage however someone at Mentor will 
> have to make such a statement on behalf of the company as I am no longer 
> there and as far as this patch set is concerned I am merely a member of 
> the public who can just make technical comments as anyone can, including 
> you.
> 
>  I think Thomas, being the writer of the majority of code comprising these 
> patches

Too bad that Git doesn't allow for listing several authors.  ;-)

> is now in the best position to make such a statement happen.  
> Thomas -- will you be able to take it from here?  Thanks!

It is fine to license these changes under the SoftFloat-2a license.


Grüße,
 Thomas

[-- Attachment #2: Type: application/pgp-signature, Size: 472 bytes --]

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support
  2015-02-03 16:28       ` Thomas Schwinge
@ 2015-02-03 22:30         ` Maciej W. Rozycki
  0 siblings, 0 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2015-02-03 22:30 UTC (permalink / raw)
  To: Thomas Schwinge
  Cc: Peter Maydell, Sandra Loosemore, Leon Alrae, QEMU Developers,
	Aurelien Jarno

On Tue, 3 Feb 2015, Thomas Schwinge wrote:

> >  I think Thomas, being the writer of the majority of code comprising these 
> > patches
> 
> Too bad that Git doesn't allow for listing several authors.  ;-)

 I believe `Signed-off-by' serves this purpose:

"The Signed-off-by: tag indicates that the signer was involved in the
development of the patch, or that he/she was in the patch's delivery path."

-- as originally specified by linux/Documentation/SubmittingPatches that 
we refer to from <http://wiki.qemu.org/Contribute/SubmitAPatch>.  See also 
Section 1, Point 12 "Sign your work" in the same document referred.

 The way the tag has been defined may make it a little bit ambiguous who 
the actual authors are, but I think it is safe to interpret it as meaning 
that all people named by `Signed-off-by' tags of a given patch being the 
authors of the change.

> > is now in the best position to make such a statement happen.  
> > Thomas -- will you be able to take it from here?  Thanks!
> 
> It is fine to license these changes under the SoftFloat-2a license.

 Great!  Thanks for confirming.

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion operations
  2014-12-09  1:54 ` [Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion operations Maciej W. Rozycki
  2015-01-29 14:51   ` Leon Alrae
@ 2015-02-05 16:37   ` Peter Maydell
  2015-02-05 16:38     ` Peter Maydell
  2015-02-06 14:37     ` Maciej W. Rozycki
  1 sibling, 2 replies; 43+ messages in thread
From: Peter Maydell @ 2015-02-05 16:37 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Leon Alrae, QEMU Developers, Aurelien Jarno, Thomas Schwinge

On 9 December 2014 at 01:54, Maciej W. Rozycki <macro@codesourcery.com> wrote:
> 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 <macro@codesourcery.com>
> ---
>  This is in particular how MIPS hardware operates, other processors
> supposedly do the same if they claim compliance to IEEE 754.

ARM currently handles this issue by calling the _maybe_silence_nan()
function in all target-specific helper functions that call
float-to-float conversion functions (but that has its own
issues, see below).

Have you looked at the other architectures that use these
functions to convert float values to see what their NaN
handling semantics are? I agree about what the spec says,
but we may well have targets which are not fully IEEE
compliant and rely on the current semantics (x86 springs to
mind).

Also in this area, ARM has a problem where we don't give the
correct answers for fp-to-fp conversions from a higher precision
to a lower precision where the input is a signaling NaN whose
non-zero mantissa bits are all at the low end such that the
truncation of the mantissa into the lower precision format
would drop them all. The result is the wrong value of quiet NaN
(we return the default NaN, which has the sign bit clear, but the
FPConvertNaN pseudocode specifies that we should effectively get
the default NaN but with the same sign bit as the input SNaN).

I think this means that:
 (1) we want to put handling of silencing the signaling NaNs
 into the NaN conversion functions themselves (since it's
 too late to do it correctly once the commonNaNtoFloat16
 function has thrown away data)
 (2) that handling needs to be target specific, as most details
 of quiet vs signaling NaNs are

I note in passing that the float*ToCommonNaN and commonNaNToFloat*
functions are used only in the back-to-back call sequence of
   return commonNaNToFloatX(floatYToCommonNaN(...))
for handling the NaN inputs on FP-to-FP conversion.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion operations
  2015-02-05 16:37   ` Peter Maydell
@ 2015-02-05 16:38     ` Peter Maydell
  2015-02-06 14:37     ` Maciej W. Rozycki
  1 sibling, 0 replies; 43+ messages in thread
From: Peter Maydell @ 2015-02-05 16:38 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Leon Alrae, QEMU Developers, Aurelien Jarno, Thomas Schwinge

Oops, forgot to fix up Maciej's email address...

On 5 February 2015 at 16:37, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 9 December 2014 at 01:54, Maciej W. Rozycki <macro@codesourcery.com> wrote:
>> Fix sNaN handling in floating-point format conversion operations, that
>> are classified by the IEEE 754-2008 standard as general-computational
>> operations [1]:

>>  This is in particular how MIPS hardware operates, other processors
>> supposedly do the same if they claim compliance to IEEE 754.
>
> ARM currently handles this issue by calling the _maybe_silence_nan()
> function in all target-specific helper functions that call
> float-to-float conversion functions (but that has its own
> issues, see below).
>
> Have you looked at the other architectures that use these
> functions to convert float values to see what their NaN
> handling semantics are? I agree about what the spec says,
> but we may well have targets which are not fully IEEE
> compliant and rely on the current semantics (x86 springs to
> mind).
>
> Also in this area, ARM has a problem where we don't give the
> correct answers for fp-to-fp conversions from a higher precision
> to a lower precision where the input is a signaling NaN whose
> non-zero mantissa bits are all at the low end such that the
> truncation of the mantissa into the lower precision format
> would drop them all. The result is the wrong value of quiet NaN
> (we return the default NaN, which has the sign bit clear, but the
> FPConvertNaN pseudocode specifies that we should effectively get
> the default NaN but with the same sign bit as the input SNaN).
>
> I think this means that:
>  (1) we want to put handling of silencing the signaling NaNs
>  into the NaN conversion functions themselves (since it's
>  too late to do it correctly once the commonNaNtoFloat16
>  function has thrown away data)
>  (2) that handling needs to be target specific, as most details
>  of quiet vs signaling NaNs are
>
> I note in passing that the float*ToCommonNaN and commonNaNToFloat*
> functions are used only in the back-to-back call sequence of
>    return commonNaNToFloatX(floatYToCommonNaN(...))
> for handling the NaN inputs on FP-to-FP conversion.
>
> thanks
> -- PMM

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH v2 5/7] softfloat: Rework `*_is_*_nan' functions
  2014-12-12 19:35   ` [Qemu-devel] [PATCH v2 " Maciej W. Rozycki
@ 2015-02-05 16:42     ` Peter Maydell
  0 siblings, 0 replies; 43+ messages in thread
From: Peter Maydell @ 2015-02-05 16:42 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Leon Alrae, QEMU Developers, Aurelien Jarno, Thomas Schwinge

On 12 December 2014 at 19:35, Maciej W. Rozycki <macro@codesourcery.com> wrote:
> Precompute the possible results, and then pick the suitable one.  The
> calculation of the unused result will be optimized away by the compiler
> at any reasonable optimization level, so no run-time performance loss.
>
> Signed-off-by: Thomas Schwinge <thomas@codesourcery.com>
> Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>

> --- qemu-git-trunk.orig/fpu/softfloat-specialize.h      2014-12-11 22:41:47.118930659 +0000
> +++ qemu-git-trunk/fpu/softfloat-specialize.h   2014-12-11 22:42:29.128941855 +0000
> @@ -207,10 +207,13 @@ int float16_is_signaling_nan(float16 a_
>  int float16_is_quiet_nan(float16 a_ STATUS_PARAM)
>  {
>      uint16_t a = float16_val(a_);
> +    int __attribute__ ((unused)) x, y;
> +    x = (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
> +    y = (a & ~0x8000) >= 0x7c80;
>  #if SNAN_BIT_IS_ONE
> -    return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
> +    return x;
>  #else
> -    return ((a & ~0x8000) >= 0x7c80);
> +    return y;
>  #endif
>  }

I don't really see the point in this patch -- the existing
version of the code seems better to me (doesn't need the
extra __attribute__ ((unused)) variables, for instance).
What's the benefit?

thanks
-- PMM

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH v2 6/7] softfloat: Add SoftFloat status `nan2008_mode' flag
  2014-12-12 19:35   ` [Qemu-devel] [PATCH v2 " Maciej W. Rozycki
@ 2015-02-05 17:00     ` Peter Maydell
  2015-02-05 19:07       ` Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Peter Maydell @ 2015-02-05 17:00 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Leon Alrae, QEMU Developers, Aurelien Jarno, Thomas Schwinge

On 12 December 2014 at 19:35, Maciej W. Rozycki <macro@codesourcery.com> wrote:
> Add support for switching between legacy NaN and IEEE 754-2008 NaN modes
> where required, currently for the MIPS target only.  Also handle the
> saving and restoration of the `nan2008_mode' status flag.
>
> Use qNaN bit patterns for the 2008 NaN mode as from revision 5.00 [1][2]
> of the MIPS Architecture, updated from revision 3.50 that used a
> different choice.
>
> References:
>
> [1] "MIPS Architecture For Programmers, Volume I-A: Introduction to the
>     MIPS32 Architecture", MIPS Technologies, Inc., Document Number:
>     MD00082, Revision 5.02, April 30, 2013, Table 5.3 "Value Supplied
>     When a New Quiet NaN Is Created", p. 73
>
> [2] "MIPS Architecture For Programmers, Volume I-A: Introduction to the
>     MIPS64 Architecture", MIPS Technologies, Inc., Document Number:
>     MD00083, Revision 5.01, December 15, 2012, Table 5.3 "Value Supplied
>     When a New Quiet NaN Is Created", p. 73
>
> Signed-off-by: Thomas Schwinge <thomas@codesourcery.com>
> Signed-off-by: Maciej W. Rozycki <macro@codesourcery.com>
> ---
> Changes from v1:
>
> - regenerate on top of the SoftFloat relicensing patch set.
>
> qemu-softfloat-nan2008.diff
> Index: qemu-git-trunk/fpu/softfloat-specialize.h
> ===================================================================
> --- qemu-git-trunk.orig/fpu/softfloat-specialize.h      2014-12-11 22:42:41.128934304 +0000
> +++ qemu-git-trunk/fpu/softfloat-specialize.h   2014-12-11 22:43:02.128938514 +0000
> @@ -83,10 +83,16 @@ this code that are retained.
>   * by setting the most significant bit of the mantissa for a signaling NaN?
>   * (The more common choice is to have it be zero for SNaN and one for QNaN.)
>   */
> -#if defined(TARGET_MIPS) || defined(TARGET_SH4) || defined(TARGET_UNICORE32)
> -#define SNAN_BIT_IS_ONE 1
> +#if defined(TARGET_MIPS)
> +/* Has to be decided dynamically.  */
> +#define SNAN_BIT_IS_VARIABLE   1
> +#define SNAN_BIT_IS_ONE        0
> +#elif defined(TARGET_SH4) || defined(TARGET_UNICORE32)
> +#define SNAN_BIT_IS_VARIABLE   0
> +#define SNAN_BIT_IS_ONE        1
>  #else
> -#define SNAN_BIT_IS_ONE 0
> +#define SNAN_BIT_IS_VARIABLE   0
> +#define SNAN_BIT_IS_ONE        0
>  #endif
>
>  #if defined(TARGET_XTENSA)
> @@ -103,6 +109,10 @@ inline float16 float16_default_nan(STATU
>  {
>  #if defined(TARGET_ARM)
>      return const_float16(0x7E00);
> +#elif SNAN_BIT_IS_VARIABLE
> +    return STATUS(nan2008_mode)
> +           ? const_float16(0x7E00)
> +           : const_float16(0x7DFF);
>  #elif SNAN_BIT_IS_ONE
>      return const_float16(0x7DFF);
>  #else

Ah, I see now what the previous patch was in aid of.

(I hadn't realised that the 2008 rev of IEEE754 nailed down
the SNaN/QNaN bit sense. That was always a dumb thing to have
left impdef, so good news I guess.)

Can we get the ifdefs out of these functions entirely, by
something like

#if defined(TARGET_SH4) || etc
#define SNAN_BIT_IS_ONE(status) 1
#elif defined(TARGET_MIPS)
#define SNAN_BIT_IS_ONE(status) (status->nan2008_mode)
#else
#define SNAN_BIT_IS_ONE(status) 0

and then just have all the conversion functions do
   return SNAN_BIT_IS_ONE(status) ? x : y;

(that should also eliminate the need to mark x and y
as unused I think).

NB: you probably want to do that on top of my series
for getting rid of the STATUS macros.

> Index: qemu-git-trunk/include/fpu/softfloat.h
> ===================================================================
> --- qemu-git-trunk.orig/include/fpu/softfloat.h 2014-12-11 22:42:41.128934304 +0000
> +++ qemu-git-trunk/include/fpu/softfloat.h      2014-12-11 22:43:02.128938514 +0000
> @@ -223,6 +223,7 @@ typedef struct float_status {
>      /* should denormalised inputs go to zero and set the input_denormal flag? */
>      flag flush_inputs_to_zero;
>      flag default_nan_mode;

This could use a comment about what the semantics of the new flag are...

> +    flag nan2008_mode;
>  } float_status;
>
> Index: qemu-git-trunk/target-mips/cpu.h
> ===================================================================
> --- qemu-git-trunk.orig/target-mips/cpu.h       2014-12-11 22:42:41.128934304 +0000
> +++ qemu-git-trunk/target-mips/cpu.h    2014-12-11 22:43:02.128938514 +0000
> @@ -615,7 +615,11 @@ void mips_cpu_list (FILE *f, fprintf_fun
>  extern void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env);
>  extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env);
>
> -#define CPU_SAVE_VERSION 7
> +#define CPU_SAVE_VERSION 8
> +/* We preserve compatibility with rev. 7 images.  */
> +#define CPU_SAVE_VERSION_OLDEST_SUPPORTED 7
> +/* Rev. 8 added 2008 NaN support.  */
> +#define CPU_SAVE_VERSION_2008_NAN 8

It would be nicer to split this into two patches: one adding
the new features to softfloat, and one using them in the MIPS
target.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH v2 6/7] softfloat: Add SoftFloat status `nan2008_mode' flag
  2015-02-05 17:00     ` Peter Maydell
@ 2015-02-05 19:07       ` Maciej W. Rozycki
  0 siblings, 0 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2015-02-05 19:07 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Leon Alrae, QEMU Developers, Aurelien Jarno, Thomas Schwinge

On Thu, 5 Feb 2015, Peter Maydell wrote:

> > Index: qemu-git-trunk/fpu/softfloat-specialize.h
> > ===================================================================
> > --- qemu-git-trunk.orig/fpu/softfloat-specialize.h      2014-12-11 22:42:41.128934304 +0000
> > +++ qemu-git-trunk/fpu/softfloat-specialize.h   2014-12-11 22:43:02.128938514 +0000
> > @@ -103,6 +109,10 @@ inline float16 float16_default_nan(STATU
> >  {
> >  #if defined(TARGET_ARM)
> >      return const_float16(0x7E00);
> > +#elif SNAN_BIT_IS_VARIABLE
> > +    return STATUS(nan2008_mode)
> > +           ? const_float16(0x7E00)
> > +           : const_float16(0x7DFF);
> >  #elif SNAN_BIT_IS_ONE
> >      return const_float16(0x7DFF);
> >  #else
> 
> Ah, I see now what the previous patch was in aid of.
> 
> (I hadn't realised that the 2008 rev of IEEE754 nailed down
> the SNaN/QNaN bit sense. That was always a dumb thing to have
> left impdef, so good news I guess.)

 For MIPS the good side (or more likely intended) effect of the quiet bit 
being set for sNaNs was you could preinitialise hardware registers in any 
new FP context created to all-ones to have them trap uninitialised read 
accesses for both single and double (and for that matter paired-single) 
arithmetic.  With the quiet bit being clear for sNaNs, there is no such a 
single encoding available, you have to choose if you want to trap for 
single (and paired-single) arithmetic only, double arithmetic only, or not 
at all.

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion operations
  2015-02-05 16:37   ` Peter Maydell
  2015-02-05 16:38     ` Peter Maydell
@ 2015-02-06 14:37     ` Maciej W. Rozycki
  2015-02-06 14:45       ` Peter Maydell
  1 sibling, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2015-02-06 14:37 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Leon Alrae, Maciej W. Rozycki, QEMU Developers, Aurelien Jarno,
	Thomas Schwinge

On Thu, 5 Feb 2015, Peter Maydell wrote:

> > 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 <macro@codesourcery.com>
> > ---
> >  This is in particular how MIPS hardware operates, other processors
> > supposedly do the same if they claim compliance to IEEE 754.
> 
> ARM currently handles this issue by calling the _maybe_silence_nan()
> function in all target-specific helper functions that call
> float-to-float conversion functions (but that has its own
> issues, see below).
> 
> Have you looked at the other architectures that use these
> functions to convert float values to see what their NaN
> handling semantics are? I agree about what the spec says,
> but we may well have targets which are not fully IEEE
> compliant and rely on the current semantics (x86 springs to
> mind).

 I think the IEEE 754 standard-compliant behaviour shouldn't be left to 
target helpers, it would bound to cause discrepancies and chaos.  I 
wouldn't expect every target maintainer to be fluent in IEEE 754 arcana, 
or even have access to the standard's normative document.

 What I think would make sense here is instead of say `float32_to_float64' 
making a call to `float64_maybe_silence_nan' directly, we'd have a static 
inline function or a macro called say `float64_convert_silence_nan' 
invoked where the former is in my patch proposed.  That function in turn 
would call the former function by default and which could be overridden by 
something else for individual targets that require it.

 And I think we shouldn't be making our decisions based on x86 despite its 
ubiquity -- it is, especially as the x87 implementation is concerned, the 
earliest attempt to implement IEEE 754 with all the oddities resulting.  
Or more specifically not even that but more of an FP implementation that 
(as of the 8087 FPU) Intel wanted to become the basis of the upcoming IEEE 
754 standard, and mostly succeeded in principle, but not in some details, 
some of which were later corrected with the 80287 and 80387 
implementations, and some of which had to stay, for compatibility reasons.

 For one the x87 doesn't really implement proper single or double 
arithmetic.  While there are two precision control bits in its control 
register, not all arithmetic operations respect them, making their 
calculation unconditionally in the extended precision instead.  And even 
these that do only respect them for the significand and not the 
exponent[1]:

"
* The precision control (PC) bits (bits 9-8) can be used to set the MCP 
  internal operating precision of the significand at less than the default 
  of 64 bits (extended precision).  This can be useful in providing 
  compatibility with early generation arithmetic processors of smaller 
  precision.  PC affects only the instructions ADD, SUB, DIV, MUL, and 
  SQRT. For all other instructions, either the precision is determined by 
  the opcode or extended precision is used.
"

 So I think that any x87 intricacies are best handled either by hooks 
similar to `float64_convert_silence_nan' I propose or by individual 
implementation of whole operations where the actions required diverge from 
the standard so much as to make the use of such hooks infeasible.

 Besides are you sure?  I see x87 documentation say this[2]:

"
          |                                        |     Default Action
Exception |                Cause                   | (if exception is masked)
----------+----------------------------------------+-------------------------
Invalid   | Operation on a signaling NaN,          | Result is a quiet NaN,
Operation | unsupported format, indeterminate form | integer indeterminate,
          | (0*Inf, 0/0, (+Inf)+(-Inf), etc.), or  | or BCD indefinite
          | stack overflow/underflow (SF is also   |
          | set).                                  |
"

and this[3]:

"
11. FLD single/double precision when the operand is denormal converts the 
    number to extended precision and signals the denormalized operand 
    exception.  When loading a signaling NaN, FLD single/double precision 
    signals an invalid-operand exception.
"

so it looks to me conversions do actually quieten an sNaN.  Or are you 
referring to earlier x87 implementations that did not implement sNaNs[3]:

"
12. The Intel387 DX MCP only generates quiet NaNs (as on the 80287); 
    however, the Intel387 DX MCP distinguishes between quiet NaNs and 
    signaling NaNs.  Signaling NaNs trigger exceptions when they are used 
    as operands; quiet NaNs do not (except for FCOM, FIST, and FBSTP which 
    also raise IE for quiet NaNs).
"

But does QEMU support 16-bit x86 machines?  Or at least a configuration 
where an 80386 CPU is paired with an 80287 FPU -- which is a bit unusual, 
but architecturally supported (see the CR0.ET bit, in later 80386 versions 
as well as all newer architecture revisions removed and the bit location 
hardwired to 1 instead as for an 80386 CPU paired with an 80387 FPU)?

 If so, then even more variance will have to be taken into account here as 
far as x87 is considered, and I believe it all can be handled by using 
such `float*_convert_silence_nan' hooks proposed.

> Also in this area, ARM has a problem where we don't give the
> correct answers for fp-to-fp conversions from a higher precision
> to a lower precision where the input is a signaling NaN whose
> non-zero mantissa bits are all at the low end such that the
> truncation of the mantissa into the lower precision format
> would drop them all. The result is the wrong value of quiet NaN
> (we return the default NaN, which has the sign bit clear, but the
> FPConvertNaN pseudocode specifies that we should effectively get
> the default NaN but with the same sign bit as the input SNaN).
> 
> I think this means that:
>  (1) we want to put handling of silencing the signaling NaNs
>  into the NaN conversion functions themselves (since it's
>  too late to do it correctly once the commonNaNtoFloat16
>  function has thrown away data)
>  (2) that handling needs to be target specific, as most details
>  of quiet vs signaling NaNs are
> 
> I note in passing that the float*ToCommonNaN and commonNaNToFloat*
> functions are used only in the back-to-back call sequence of
>    return commonNaNToFloatX(floatYToCommonNaN(...))
> for handling the NaN inputs on FP-to-FP conversion.

 I believe my proposal addresses your concerns in a burden-free way for 
target maintainers who look after processors that implement the IEEE 754 
standard as it stands.  Of course someone will have to implement it and 
it's not entirely clear to me at the moment who that person would be.

 References:

[1] "Intel387 DX Math CoProcessor", Intel Corporation, Order Number:
    240448-005, March 1992, Section 2.3 "Register Set", Subsection 2.3.5 
    "Control Word", p. 14

[2] same, Table 2.7 "Exceptions", p. 16

[3] same, Section 2.7 "8087 and 80287 Compatibility", Subsection 2.7.2 
    "Exceptions", p. 17

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion operations
  2015-02-06 14:37     ` Maciej W. Rozycki
@ 2015-02-06 14:45       ` Peter Maydell
  2015-02-06 19:35         ` Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Peter Maydell @ 2015-02-06 14:45 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Leon Alrae, Maciej W. Rozycki, QEMU Developers, Aurelien Jarno,
	Thomas Schwinge

On 6 February 2015 at 14:37, Maciej W. Rozycki <macro@linux-mips.org> wrote:
> On Thu, 5 Feb 2015, Peter Maydell wrote:
>> Have you looked at the other architectures that use these
>> functions to convert float values to see what their NaN
>> handling semantics are? I agree about what the spec says,
>> but we may well have targets which are not fully IEEE
>> compliant and rely on the current semantics (x86 springs to
>> mind).
>
>  I think the IEEE 754 standard-compliant behaviour shouldn't be left to
> target helpers, it would bound to cause discrepancies and chaos.  I
> wouldn't expect every target maintainer to be fluent in IEEE 754 arcana,
> or even have access to the standard's normative document.
>
>  What I think would make sense here is instead of say `float32_to_float64'
> making a call to `float64_maybe_silence_nan' directly, we'd have a static
> inline function or a macro called say `float64_convert_silence_nan'
> invoked where the former is in my patch proposed.  That function in turn
> would call the former function by default and which could be overridden by
> something else for individual targets that require it.

This still doesn't work for ARM, because you can't do the
silencing after conversion. You have to have a way for
targets to put in target-specific behaviour directly in the
64-to-32 conversion process, before data is lost in the narrowing.

>  And I think we shouldn't be making our decisions based on x86 despite its
> ubiquity -- it is, especially as the x87 implementation is concerned, the
> earliest attempt to implement IEEE 754 with all the oddities resulting.
> Or more specifically not even that but more of an FP implementation that
> (as of the 8087 FPU) Intel wanted to become the basis of the upcoming IEEE
> 754 standard, and mostly succeeded in principle, but not in some details,
> some of which were later corrected with the 80287 and 80387
> implementations, and some of which had to stay, for compatibility reasons.

My point is that you mustn't regress other targets. So either you
need to retain the same behaviour for targets which don't specifically
add new code/flags/whatever, or you need to go through and look up
all the other architecture specifications to check that you haven't
broken them (ie that any changes you make are actually improving their
accuracy). This patch isn't doing the first of those, so you need
to do the second...

>  Besides are you sure?

I was asking if you'd checked all the targets whose behaviour you're
changing, not making a definite "you have broken x86" statement.
x86 is just the most likely because as you say it is the weirdest
and least compliant.

>> Also in this area, ARM has a problem where we don't give the
>> correct answers for fp-to-fp conversions from a higher precision
>> to a lower precision where the input is a signaling NaN whose
>> non-zero mantissa bits are all at the low end such that the
>> truncation of the mantissa into the lower precision format
>> would drop them all. The result is the wrong value of quiet NaN
>> (we return the default NaN, which has the sign bit clear, but the
>> FPConvertNaN pseudocode specifies that we should effectively get
>> the default NaN but with the same sign bit as the input SNaN).
>>
>> I think this means that:
>>  (1) we want to put handling of silencing the signaling NaNs
>>  into the NaN conversion functions themselves (since it's
>>  too late to do it correctly once the commonNaNtoFloat16
>>  function has thrown away data)
>>  (2) that handling needs to be target specific, as most details
>>  of quiet vs signaling NaNs are
>>
>> I note in passing that the float*ToCommonNaN and commonNaNToFloat*
>> functions are used only in the back-to-back call sequence of
>>    return commonNaNToFloatX(floatYToCommonNaN(...))
>> for handling the NaN inputs on FP-to-FP conversion.
>
>  I believe my proposal addresses your concerns in a burden-free way for
> target maintainers who look after processors that implement the IEEE 754
> standard as it stands.

I don't, which is why I made the comment above. If you're going to
fix up NaN handling in the float-to-float conversion routines we
should do it in a way that lets us handle the behaviour of
target CPUs we care about.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion operations
  2015-02-06 14:45       ` Peter Maydell
@ 2015-02-06 19:35         ` Maciej W. Rozycki
  2015-02-08 12:12           ` Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2015-02-06 19:35 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Leon Alrae, QEMU Developers, Aurelien Jarno, Thomas Schwinge

On Fri, 6 Feb 2015, Peter Maydell wrote:

> >  What I think would make sense here is instead of say `float32_to_float64'
> > making a call to `float64_maybe_silence_nan' directly, we'd have a static
> > inline function or a macro called say `float64_convert_silence_nan'
> > invoked where the former is in my patch proposed.  That function in turn
> > would call the former function by default and which could be overridden by
> > something else for individual targets that require it.
> 
> This still doesn't work for ARM, because you can't do the
> silencing after conversion. You have to have a way for
> targets to put in target-specific behaviour directly in the
> 64-to-32 conversion process, before data is lost in the narrowing.

 Somehow I missed from your description that ARM actually requires actions 
at an earlier stage, sorry.  What I understood is that it is only the sign 
bit that is lost, and that could be easily handled with a bespoke version 
of `float64_convert_silence_nan', etc.  Is that the sign bit is supposed 
to be preserved in quietening an sNaN iff truncation of a non-zero wider 
trailing significand field produced all-zeros in the narrower result, and 
otherwise set to zero then?

> >  And I think we shouldn't be making our decisions based on x86 despite its
> > ubiquity -- it is, especially as the x87 implementation is concerned, the
> > earliest attempt to implement IEEE 754 with all the oddities resulting.
> > Or more specifically not even that but more of an FP implementation that
> > (as of the 8087 FPU) Intel wanted to become the basis of the upcoming IEEE
> > 754 standard, and mostly succeeded in principle, but not in some details,
> > some of which were later corrected with the 80287 and 80387
> > implementations, and some of which had to stay, for compatibility reasons.
> 
> My point is that you mustn't regress other targets. So either you
> need to retain the same behaviour for targets which don't specifically
> add new code/flags/whatever, or you need to go through and look up
> all the other architecture specifications to check that you haven't
> broken them (ie that any changes you make are actually improving their
> accuracy). This patch isn't doing the first of those, so you need
> to do the second...

 I agree making sure no target has regressed is a valuable goal, but TBH 
I'd welcome some cooperation from target maintainers here, especially as 
the current situation looks like core code is non-compliant and I find it
hard to believe all the processors out there (except MIPS) got their IEEE 
754 implementation wrong.  So what this change does I'd expect actually to 
*progress* most of the targets, except from maybe a couple of oddballs.

 And I would very much appreciate feedback from target maintainers of 
these oddball architectures, after all they know the internals of the 
processors they care of the best!

> >  Besides are you sure?
> 
> I was asking if you'd checked all the targets whose behaviour you're
> changing, not making a definite "you have broken x86" statement.
> x86 is just the most likely because as you say it is the weirdest
> and least compliant.

 We can surely sort out the level of support x87 requires in further 
updates to the proposed change.  I'd expect x86's more modern SSE 
implementation of IEEE 754, that I'm less familiar with (which I guess 
just shows my age), got the details just as the standard expects them, 
which in turn implies more complication on our side.  But if we set the 
minimum at 80387, then as it stands it does not appear to me that this 
change will regress anything.

 But as I say, I think it would be most productive if target maintainers 
of at least ARM and x86, and maybe other architectures as well if they 
have quirks in this area, chimed in and identified issues.  I think it is 
impractical to require submitters of a generic change like this to chase 
architecture manuals of all the processors affected and study and 
understand their instruction sets to infer whether the change is going to 
have a negative effect.  Especially given that from the current code and 
the standard it is supposed to implement it is clear to me that the code 
is buggy.

 I also think that papering the issue over by fixing the thing up somehow 
in the MIPS TCG and letting other people worry about their architecture of 
interest is not the way to go, although it clearly looks like the path of 
least resistance to me.

> >> I think this means that:
> >>  (1) we want to put handling of silencing the signaling NaNs
> >>  into the NaN conversion functions themselves (since it's
> >>  too late to do it correctly once the commonNaNtoFloat16
> >>  function has thrown away data)
> >>  (2) that handling needs to be target specific, as most details
> >>  of quiet vs signaling NaNs are
> >>
> >> I note in passing that the float*ToCommonNaN and commonNaNToFloat*
> >> functions are used only in the back-to-back call sequence of
> >>    return commonNaNToFloatX(floatYToCommonNaN(...))
> >> for handling the NaN inputs on FP-to-FP conversion.
> >
> >  I believe my proposal addresses your concerns in a burden-free way for
> > target maintainers who look after processors that implement the IEEE 754
> > standard as it stands.
> 
> I don't, which is why I made the comment above. If you're going to
> fix up NaN handling in the float-to-float conversion routines we
> should do it in a way that lets us handle the behaviour of
> target CPUs we care about.

 No argument about maintaining correct emulation where it already is such, 
sure.  Please note that `float64_maybe_silence_nan' and friends are 
already target-specific, which should generally let us deal with things, 
and I am sort of surprised ARM sets certain rules for sNaN silencing for 
conversions and different ones for other arithmetic operations.  Or is it 
really that an input sNaN's sign bit is propagated in the single weird 
corner case only?

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion operations
  2015-02-06 19:35         ` Maciej W. Rozycki
@ 2015-02-08 12:12           ` Maciej W. Rozycki
  0 siblings, 0 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2015-02-08 12:12 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Leon Alrae, QEMU Developers, Aurelien Jarno, Thomas Schwinge

On Fri, 6 Feb 2015, Maciej W. Rozycki wrote:

> > >> I think this means that:
> > >>  (1) we want to put handling of silencing the signaling NaNs
> > >>  into the NaN conversion functions themselves (since it's
> > >>  too late to do it correctly once the commonNaNtoFloat16
> > >>  function has thrown away data)
> > >>  (2) that handling needs to be target specific, as most details
> > >>  of quiet vs signaling NaNs are
> > >>
> > >> I note in passing that the float*ToCommonNaN and commonNaNToFloat*
> > >> functions are used only in the back-to-back call sequence of
> > >>    return commonNaNToFloatX(floatYToCommonNaN(...))
> > >> for handling the NaN inputs on FP-to-FP conversion.
> > >
> > >  I believe my proposal addresses your concerns in a burden-free way for
> > > target maintainers who look after processors that implement the IEEE 754
> > > standard as it stands.
> > 
> > I don't, which is why I made the comment above. If you're going to
> > fix up NaN handling in the float-to-float conversion routines we
> > should do it in a way that lets us handle the behaviour of
> > target CPUs we care about.
> 
>  No argument about maintaining correct emulation where it already is such, 
> sure.  Please note that `float64_maybe_silence_nan' and friends are 
> already target-specific, which should generally let us deal with things, 
> and I am sort of surprised ARM sets certain rules for sNaN silencing for 
> conversions and different ones for other arithmetic operations.  Or is it 
> really that an input sNaN's sign bit is propagated in the single weird 
> corner case only?

 OK, I see where the issue is -- this is specifically about the case where 
dropping trailing significand bits of an sNaN in the process of format 
conversion would result in an infinity being produced.  This is handled by 
`commonNaNToFloat*' functions, but not in a way the ARM architecture 
requires.  As a preexisting problem this has nothing to do with my 
proposal and neither my proposal makes things worse, though I indeed 
missed the opportunity to correct it.

 I've thought of two general solutions:

1. Given that `*_default_nan' are now functions make them accept the sign 
   bit as input and propagate it to output if required by a given 
   implementation.  Conversions would pass the input sign bit while
   arithmetic operations would hardcode it to 0.

2. Quieten an sNaN being converted in the wider format operated on.  For a 
   widening conversion it would be the output format just as in the 
   original patch proposed.  For a narrowing conversion it would be the 
   input format.

I'm leaning towards the second option as being more elegant and robust.

 So to give a specific example, `float32_to_float64' would have:

        if (aSig) {
            float64 nan;
            nan = commonNaNToFloat64(float32ToCommonNaN(a, status), status);
            return float64_maybe_silence_nan(nan);
        }

but `float64_to_float32' would have:

        if (aSig) {
            float64 nan;
            nan = float64_maybe_silence_nan(a);
            return commonNaNToFloat32(float64ToCommonNaN(nan, status), status);
        }

instead.  This does the right thing as far as NaN quietening is concerned 
and avoids the `!mantissa' case triggering in `commonNaNToFloat32'.

 Based on the lone contents of fpu/softfloat-specialize.h this solution 
looks correct to me, in particular for the SNAN_BIT_IS_ONE case -- are you 
aware of any processor architectures for which this approach would not 
produce the result required?

 I've had a look at target-arm/helper.c and target-arm/helper-a64.c and 
AFAICT the hacks they do for NaN quietening do not follow the architecture 
specification in narrowing conversions (they merely reproduce what I 
proposed with the original patch and therefore do not preserve the sign 
bit in the case concerned), so the approach I outlined above will actually 
progress these targets as well, and these hacks can then be removed.  
This solution also meets the IEEE 754-2008 requirement for the way NaN 
quietening is done where the preferred NaN encoding is implemented.

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 7/7] target-mips: Add IEEE 754-2008 features support
  2014-12-09  1:56 ` [Qemu-devel] [PATCH 7/7] target-mips: Add IEEE 754-2008 features support Maciej W. Rozycki
@ 2015-02-09 17:10   ` Leon Alrae
  2015-02-09 20:55     ` Maciej W. Rozycki
  2015-02-17 13:55   ` Maciej W. Rozycki
  1 sibling, 1 reply; 43+ messages in thread
From: Leon Alrae @ 2015-02-09 17:10 UTC (permalink / raw)
  To: Maciej W. Rozycki, qemu-devel; +Cc: Thomas Schwinge, Aurelien Jarno

On 09/12/2014 01:56, Maciej W. Rozycki wrote:
> +        if (info->elf_flags & EF_MIPS_NAN2008)
> +            env->active_fpu.fcr31 |=
> +                (1 << FCR31_NAN2008) & env->active_fpu.fcr31_rw_bitmask;
> +        else
> +            env->active_fpu.fcr31 &=
> +                ~((1 << FCR31_NAN2008) & env->active_fpu.fcr31_rw_bitmask);

braces are needed here

> +uint64_t helper_float_chs_d(CPUMIPSState *env, uint64_t fdt0)
> +{
> +    uint64_t fdt1;
> +
> +    fdt1 = float64_sub(0, fdt0, &env->active_fpu.fp_status);
> +    update_fcr31(env, GETPC());
> +    return fdt1;
> +}
> +
> +uint32_t helper_float_chs_s(CPUMIPSState *env, uint32_t fst0)
> +{
> +    uint32_t fst1;
> +
> +    fst1 = float32_sub(0, fst0, &env->active_fpu.fp_status);
> +    update_fcr31(env, GETPC());
> +    return fst1;
> +}

I think there is one case where helper_float_chs_{d,s,ps} are not
correct -- when we have zero. In this case in subFloat32Sigs() we call:

return packFloat32(status->float_rounding_mode == float_round_down, 0, 0);

and the packFloat32() definition:

static inline float32 packFloat32(flag zSign, int_fast16_t zExp,
uint32_t zSig)
{

    return make_float32(
          ( ( (uint32_t) zSign )<<31 ) + ( ( (uint32_t) zExp )<<23 ) +
zSig);

}

Which means that the sign may not get changed, whereas I believe NEG.fmt
is supposed to reverse the sign bit of positive/negative zero regardless
of rounding mode.

>  
>  enum {
> @@ -8718,7 +8719,10 @@ static void gen_farith (DisasContext *ct
>              TCGv_i32 fp0 = tcg_temp_new_i32();
>  
>              gen_load_fpr32(fp0, fs);
> -            gen_helper_float_abs_s(fp0, fp0);
> +            if (ctx->abs2008)
> +                gen_helper_float_abs2008_s(fp0, fp0);
> +            else
> +                gen_helper_float_abs_s(fp0, cpu_env, fp0);

braces are needed here too (and also in a few other places in this patch).

Thanks,
Leon

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 7/7] target-mips: Add IEEE 754-2008 features support
  2015-02-09 17:10   ` Leon Alrae
@ 2015-02-09 20:55     ` Maciej W. Rozycki
  2015-02-10 10:44       ` Leon Alrae
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2015-02-09 20:55 UTC (permalink / raw)
  To: Leon Alrae; +Cc: qemu-devel, Aurelien Jarno, Thomas Schwinge

On Mon, 9 Feb 2015, Leon Alrae wrote:

> > +        if (info->elf_flags & EF_MIPS_NAN2008)
> > +            env->active_fpu.fcr31 |=
> > +                (1 << FCR31_NAN2008) & env->active_fpu.fcr31_rw_bitmask;
> > +        else
> > +            env->active_fpu.fcr31 &=
> > +                ~((1 << FCR31_NAN2008) & env->active_fpu.fcr31_rw_bitmask);
> 
> braces are needed here

 Umm...

> > +uint32_t helper_float_chs_s(CPUMIPSState *env, uint32_t fst0)
> > +{
> > +    uint32_t fst1;
> > +
> > +    fst1 = float32_sub(0, fst0, &env->active_fpu.fp_status);
> > +    update_fcr31(env, GETPC());
> > +    return fst1;
> > +}
> 
> I think there is one case where helper_float_chs_{d,s,ps} are not
> correct -- when we have zero. In this case in subFloat32Sigs() we call:
> 
> return packFloat32(status->float_rounding_mode == float_round_down, 0, 0);
> 
> and the packFloat32() definition:
> 
> static inline float32 packFloat32(flag zSign, int_fast16_t zExp,
> uint32_t zSig)
> {
> 
>     return make_float32(
>           ( ( (uint32_t) zSign )<<31 ) + ( ( (uint32_t) zExp )<<23 ) +
> zSig);
> 
> }
> 
> Which means that the sign may not get changed, whereas I believe NEG.fmt
> is supposed to reverse the sign bit of positive/negative zero regardless
> of rounding mode.

 Good catch, I missed this corner case, thanks!  Another corner case is 
then helper_float_abs_{d,s,ps} with -0 as input and `float_round_down' 
being the current rounding mode.

 These cases could be addressed by either replacing subtraction from 0.0 
with multiplication by -1.0, or by tweaking the rounding mode as needed 
temporarily.  Given that the computational cost of multiplication is 
uncertain and likely higher or at best the same as the cost of addition or 
subtraction, I'd be leaning towards the latter solution.

 Thoughts?

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 7/7] target-mips: Add IEEE 754-2008 features support
  2015-02-09 20:55     ` Maciej W. Rozycki
@ 2015-02-10 10:44       ` Leon Alrae
  2015-02-10 14:30         ` Maciej W. Rozycki
  0 siblings, 1 reply; 43+ messages in thread
From: Leon Alrae @ 2015-02-10 10:44 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: qemu-devel, Aurelien Jarno, Thomas Schwinge

On 09/02/2015 20:55, Maciej W. Rozycki wrote:
>>> +uint32_t helper_float_chs_s(CPUMIPSState *env, uint32_t fst0)
>>> +{
>>> +    uint32_t fst1;
>>> +
>>> +    fst1 = float32_sub(0, fst0, &env->active_fpu.fp_status);
>>> +    update_fcr31(env, GETPC());
>>> +    return fst1;
>>> +}
>>
>> I think there is one case where helper_float_chs_{d,s,ps} are not
>> correct -- when we have zero. In this case in subFloat32Sigs() we call:
>>
>> return packFloat32(status->float_rounding_mode == float_round_down, 0, 0);
>>
>> and the packFloat32() definition:
>>
>> static inline float32 packFloat32(flag zSign, int_fast16_t zExp,
>> uint32_t zSig)
>> {
>>
>>     return make_float32(
>>           ( ( (uint32_t) zSign )<<31 ) + ( ( (uint32_t) zExp )<<23 ) +
>> zSig);
>>
>> }
>>
>> Which means that the sign may not get changed, whereas I believe NEG.fmt
>> is supposed to reverse the sign bit of positive/negative zero regardless
>> of rounding mode.
> 
>  Good catch, I missed this corner case, thanks!  Another corner case is 
> then helper_float_abs_{d,s,ps} with -0 as input and `float_round_down' 
> being the current rounding mode.
> 
>  These cases could be addressed by either replacing subtraction from 0.0 
> with multiplication by -1.0, or by tweaking the rounding mode as needed 
> temporarily.  Given that the computational cost of multiplication is 
> uncertain and likely higher or at best the same as the cost of addition or 
> subtraction, I'd be leaning towards the latter solution.

My first thought was to treat zero in NEG.fmt as a special case and use
float32_chs() for it. But tweaking the rounding mode temporarily
probably is better as we will get consistent behaviour for zero as well
as input denormals which are squashed in float32_sub() when
flush_inputs_to_zero flag is set (actually I'm not sure if legacy fp
instructions should flush input denormals, but according to the spec
this is implementation dependent so I won't worry about this).

Leon

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 7/7] target-mips: Add IEEE 754-2008 features support
  2015-02-10 10:44       ` Leon Alrae
@ 2015-02-10 14:30         ` Maciej W. Rozycki
  2015-02-10 17:21           ` Leon Alrae
  0 siblings, 1 reply; 43+ messages in thread
From: Maciej W. Rozycki @ 2015-02-10 14:30 UTC (permalink / raw)
  To: Leon Alrae; +Cc: qemu-devel, Aurelien Jarno, Thomas Schwinge

On Tue, 10 Feb 2015, Leon Alrae wrote:

> >  These cases could be addressed by either replacing subtraction from 0.0 
> > with multiplication by -1.0, or by tweaking the rounding mode as needed 
> > temporarily.  Given that the computational cost of multiplication is 
> > uncertain and likely higher or at best the same as the cost of addition or 
> > subtraction, I'd be leaning towards the latter solution.
> 
> My first thought was to treat zero in NEG.fmt as a special case and use
> float32_chs() for it. But tweaking the rounding mode temporarily
> probably is better as we will get consistent behaviour for zero as well
> as input denormals which are squashed in float32_sub() when
> flush_inputs_to_zero flag is set (actually I'm not sure if legacy fp
> instructions should flush input denormals, but according to the spec
> this is implementation dependent so I won't worry about this).

 As expected setting CP1.FCSR.FS on a randomly picked R4400 processor:

CPU0 revision is: 00000440 (R4400SC)
FPU revision is: 00000500

does flush a NEG.fmt's input denormal to 0.  Given this program:

#include <stdint.h>
#include <stdio.h>

int main(void)
{
	union {
		double d;
		uint64_t i;
	} x = { .i = 0x000123456789abcdULL }, y, z;
	unsigned long tmp, fcsr;

	printf("x: %016lx\n", x.i);
	asm volatile(
		"	cfc1	%1, $31\n"
		"	or	%2, %1, %4\n"
		"	ctc1	%2, $31\n"
		"	neg.d	%0, %3\n"
		"	ctc1	%1, $31"
		: "=f" (y.d), "=&r" (fcsr), "=&r" (tmp)
		: "f" (x.d), "r" (1 << 24));
	printf("y: %016lx\n", y.i);
	asm volatile(
		"	neg.d	%0, %1"
		: "=f" (z.d) : "f" (x.d));
	printf("z: %016lx\n", z.i);
	x.i = 0;
	printf("+: %016lx\n", x.i);
	asm volatile(
		"	neg.d	%0, %1"
		: "=f" (y.d) : "f" (x.d));
	printf("-: %016lx\n", y.i);
	return 0;
}

I get this output:

x: 000123456789abcd
y: 8000000000000000
z: 800123456789abcd
+: 0000000000000000
-: 8000000000000000

under Linux.  According to R4400 documentation the value of `z' must have 
been calculated by the in-kernel emulator in the Unimplemented Operation 
handler as for this processor implementation any denormalised operands 
cause this exception except for compare instructions.  But in any case all 
the results are consistent.  So we don't actually have to do anything for 
the flush-to-zero mode, our calculation should work out as expected (as 
long as the `float_round_down' rounding mode is respected that is).

 While at it I included the result of the negation of 0 for completeness.

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 7/7] target-mips: Add IEEE 754-2008 features support
  2015-02-10 14:30         ` Maciej W. Rozycki
@ 2015-02-10 17:21           ` Leon Alrae
  0 siblings, 0 replies; 43+ messages in thread
From: Leon Alrae @ 2015-02-10 17:21 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: qemu-devel, Aurelien Jarno, Thomas Schwinge

On 10/02/2015 14:30, Maciej W. Rozycki wrote:
> On Tue, 10 Feb 2015, Leon Alrae wrote:
> 
>>>  These cases could be addressed by either replacing subtraction from 0.0 
>>> with multiplication by -1.0, or by tweaking the rounding mode as needed 
>>> temporarily.  Given that the computational cost of multiplication is 
>>> uncertain and likely higher or at best the same as the cost of addition or 
>>> subtraction, I'd be leaning towards the latter solution.
>>
>> My first thought was to treat zero in NEG.fmt as a special case and use
>> float32_chs() for it. But tweaking the rounding mode temporarily
>> probably is better as we will get consistent behaviour for zero as well
>> as input denormals which are squashed in float32_sub() when
>> flush_inputs_to_zero flag is set (actually I'm not sure if legacy fp
>> instructions should flush input denormals, but according to the spec
>> this is implementation dependent so I won't worry about this).
> 
>  As expected setting CP1.FCSR.FS on a randomly picked R4400 processor:
> 
> CPU0 revision is: 00000440 (R4400SC)
> FPU revision is: 00000500
> 
> does flush a NEG.fmt's input denormal to 0.  Given this program:

Good to know, thanks for checking that on the real CPU!

Leon

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [Qemu-devel] [PATCH 7/7] target-mips: Add IEEE 754-2008 features support
  2014-12-09  1:56 ` [Qemu-devel] [PATCH 7/7] target-mips: Add IEEE 754-2008 features support Maciej W. Rozycki
  2015-02-09 17:10   ` Leon Alrae
@ 2015-02-17 13:55   ` Maciej W. Rozycki
  1 sibling, 0 replies; 43+ messages in thread
From: Maciej W. Rozycki @ 2015-02-17 13:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: Leon Alrae, Thomas Schwinge, Aurelien Jarno

On Tue, 9 Dec 2014, Maciej W. Rozycki wrote:

> Index: qemu-git-trunk/target-mips/op_helper.c
> ===================================================================
> --- qemu-git-trunk.orig/target-mips/op_helper.c	2014-12-08 23:22:12.000000000 +0000
> +++ qemu-git-trunk/target-mips/op_helper.c	2014-12-08 23:25:02.558929097 +0000
> @@ -2274,8 +2274,12 @@ void mips_cpu_unassigned_access(CPUState
>  
>  #define FLOAT_TWO32 make_float32(1 << 30)
>  #define FLOAT_TWO64 make_float64(1ULL << 62)
> -#define FP_TO_INT32_OVERFLOW 0x7fffffff
> -#define FP_TO_INT64_OVERFLOW 0x7fffffffffffffffULL
> +#define FLOAT_INAN32(env)                                               \
> +    (((env)->active_fpu.fcr31 & (1 << FCR31_NAN2008))                   \
> +     ? 0x00000000 : 0x7fffffff)
> +#define FLOAT_INAN64(env)                                               \
> +    (((env)->active_fpu.fcr31 & (1 << FCR31_NAN2008))                   \
> +     ? 0x0000000000000000ULL : 0x7fffffffffffffffULL)
>  
>  /* convert MIPS rounding mode in FCR31 to IEEE library */
>  unsigned int ieee_rm[] = {
[...]
> @@ -2481,7 +2482,7 @@ uint64_t helper_float_cvtl_d(CPUMIPSStat
>      dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        dt2 = FP_TO_INT64_OVERFLOW;
> +        dt2 = FLOAT_INAN64(env);
>      }
>      update_fcr31(env, GETPC());
>      return dt2;
> @@ -2494,7 +2495,7 @@ uint64_t helper_float_cvtl_s(CPUMIPSStat
>      dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        dt2 = FP_TO_INT64_OVERFLOW;
> +        dt2 = FLOAT_INAN64(env);
>      }
>      update_fcr31(env, GETPC());
>      return dt2;
> @@ -2520,14 +2521,14 @@ uint64_t helper_float_cvtpw_ps(CPUMIPSSt
>      wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
>      excp = get_float_exception_flags(&env->active_fpu.fp_status);
>      if (excp & (float_flag_overflow | float_flag_invalid)) {
> -        wt2 = FP_TO_INT32_OVERFLOW;
> +        wt2 = FLOAT_INAN32(env);
>      }
>  
>      set_float_exception_flags(0, &env->active_fpu.fp_status);
>      wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status);
>      excph = get_float_exception_flags(&env->active_fpu.fp_status);
>      if (excph & (float_flag_overflow | float_flag_invalid)) {
> -        wth2 = FP_TO_INT32_OVERFLOW;
> +        wth2 = FLOAT_INAN32(env);
>      }
>  
>      set_float_exception_flags(excp | excph, &env->active_fpu.fp_status);
> @@ -2588,7 +2589,7 @@ uint32_t helper_float_cvtw_s(CPUMIPSStat
>      wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        wt2 = FP_TO_INT32_OVERFLOW;
> +        wt2 = FLOAT_INAN32(env);
>      }
>      update_fcr31(env, GETPC());
>      return wt2;
> @@ -2601,7 +2602,7 @@ uint32_t helper_float_cvtw_d(CPUMIPSStat
>      wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        wt2 = FP_TO_INT32_OVERFLOW;
> +        wt2 = FLOAT_INAN32(env);
>      }
>      update_fcr31(env, GETPC());
>      return wt2;
> @@ -2616,7 +2617,7 @@ uint64_t helper_float_roundl_d(CPUMIPSSt
>      restore_rounding_mode(env);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        dt2 = FP_TO_INT64_OVERFLOW;
> +        dt2 = FLOAT_INAN64(env);
>      }
>      update_fcr31(env, GETPC());
>      return dt2;
> @@ -2631,7 +2632,7 @@ uint64_t helper_float_roundl_s(CPUMIPSSt
>      restore_rounding_mode(env);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        dt2 = FP_TO_INT64_OVERFLOW;
> +        dt2 = FLOAT_INAN64(env);
>      }
>      update_fcr31(env, GETPC());
>      return dt2;
> @@ -2646,7 +2647,7 @@ uint32_t helper_float_roundw_d(CPUMIPSSt
>      restore_rounding_mode(env);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        wt2 = FP_TO_INT32_OVERFLOW;
> +        wt2 = FLOAT_INAN32(env);
>      }
>      update_fcr31(env, GETPC());
>      return wt2;
> @@ -2661,7 +2662,7 @@ uint32_t helper_float_roundw_s(CPUMIPSSt
>      restore_rounding_mode(env);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        wt2 = FP_TO_INT32_OVERFLOW;
> +        wt2 = FLOAT_INAN32(env);
>      }
>      update_fcr31(env, GETPC());
>      return wt2;
> @@ -2674,7 +2675,7 @@ uint64_t helper_float_truncl_d(CPUMIPSSt
>      dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        dt2 = FP_TO_INT64_OVERFLOW;
> +        dt2 = FLOAT_INAN64(env);
>      }
>      update_fcr31(env, GETPC());
>      return dt2;
> @@ -2687,7 +2688,7 @@ uint64_t helper_float_truncl_s(CPUMIPSSt
>      dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        dt2 = FP_TO_INT64_OVERFLOW;
> +        dt2 = FLOAT_INAN64(env);
>      }
>      update_fcr31(env, GETPC());
>      return dt2;
> @@ -2700,7 +2701,7 @@ uint32_t helper_float_truncw_d(CPUMIPSSt
>      wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        wt2 = FP_TO_INT32_OVERFLOW;
> +        wt2 = FLOAT_INAN32(env);
>      }
>      update_fcr31(env, GETPC());
>      return wt2;
> @@ -2713,7 +2714,7 @@ uint32_t helper_float_truncw_s(CPUMIPSSt
>      wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        wt2 = FP_TO_INT32_OVERFLOW;
> +        wt2 = FLOAT_INAN32(env);
>      }
>      update_fcr31(env, GETPC());
>      return wt2;
> @@ -2728,7 +2729,7 @@ uint64_t helper_float_ceill_d(CPUMIPSSta
>      restore_rounding_mode(env);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        dt2 = FP_TO_INT64_OVERFLOW;
> +        dt2 = FLOAT_INAN64(env);
>      }
>      update_fcr31(env, GETPC());
>      return dt2;
> @@ -2743,7 +2744,7 @@ uint64_t helper_float_ceill_s(CPUMIPSSta
>      restore_rounding_mode(env);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        dt2 = FP_TO_INT64_OVERFLOW;
> +        dt2 = FLOAT_INAN64(env);
>      }
>      update_fcr31(env, GETPC());
>      return dt2;
> @@ -2758,7 +2759,7 @@ uint32_t helper_float_ceilw_d(CPUMIPSSta
>      restore_rounding_mode(env);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        wt2 = FP_TO_INT32_OVERFLOW;
> +        wt2 = FLOAT_INAN32(env);
>      }
>      update_fcr31(env, GETPC());
>      return wt2;
> @@ -2773,7 +2774,7 @@ uint32_t helper_float_ceilw_s(CPUMIPSSta
>      restore_rounding_mode(env);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        wt2 = FP_TO_INT32_OVERFLOW;
> +        wt2 = FLOAT_INAN32(env);
>      }
>      update_fcr31(env, GETPC());
>      return wt2;
> @@ -2788,7 +2789,7 @@ uint64_t helper_float_floorl_d(CPUMIPSSt
>      restore_rounding_mode(env);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        dt2 = FP_TO_INT64_OVERFLOW;
> +        dt2 = FLOAT_INAN64(env);
>      }
>      update_fcr31(env, GETPC());
>      return dt2;
> @@ -2803,7 +2804,7 @@ uint64_t helper_float_floorl_s(CPUMIPSSt
>      restore_rounding_mode(env);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        dt2 = FP_TO_INT64_OVERFLOW;
> +        dt2 = FLOAT_INAN64(env);
>      }
>      update_fcr31(env, GETPC());
>      return dt2;
> @@ -2818,7 +2819,7 @@ uint32_t helper_float_floorw_d(CPUMIPSSt
>      restore_rounding_mode(env);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        wt2 = FP_TO_INT32_OVERFLOW;
> +        wt2 = FLOAT_INAN32(env);
>      }
>      update_fcr31(env, GETPC());
>      return wt2;
> @@ -2833,23 +2834,23 @@ uint32_t helper_float_floorw_s(CPUMIPSSt
>      restore_rounding_mode(env);
>      if (get_float_exception_flags(&env->active_fpu.fp_status)
>          & (float_flag_invalid | float_flag_overflow)) {
> -        wt2 = FP_TO_INT32_OVERFLOW;
> +        wt2 = FLOAT_INAN32(env);
>      }
>      update_fcr31(env, GETPC());
>      return wt2;

 I have realised these all need a further update to follow the 
architecture specification correctly in the 2008-NaN mode.  This is 
because in the legacy-NaN mode a single value of `maxint' is returned for 
all invalid operations, however in the 2008-NaN mode distinct values are 
returned depending of the nature of the invalidity as follows [1][2]:

* `minint' -- for negative operand overflows,

* 0 -- for NaN operands,

* `maxint' -- for positive operand overflows.

(note that the values required here were changed between revisions 3.50 
and 5.00 of the architecture specifications).  It should be 
straightforward to implement as `float64_to_int64', etc. already return 
the correct values for overflows, so it's only NaN operands that need a 
fixup similar to the above, in the 2008-NaN mode.

 Additionally the reference to the `float_flag_overflow' flag can and IMO 
should be removed here, it's never set for conversions to a fixed-point 
integer format.

 References:

[1] "MIPS Architecture For Programmers, Volume I-A: Introduction to the
    MIPS32 Architecture", MIPS Technologies, Inc., Document Number:
    MD00082, Revision 5.00, December 14, 2012, Table 5.3 "Value Supplied 
    When a New Quiet NaN Is Created", p. 72

[2] "MIPS Architecture For Programmers, Volume I-A: Introduction to the
    MIPS64 Architecture", MIPS Technologies, Inc., Document Number:
    MD00083, Revision 5.00, December 14, 2012, Table 5.3 "Value Supplied 
    When a New Quiet NaN Is Created", p. 74

  Maciej

^ permalink raw reply	[flat|nested] 43+ messages in thread

end of thread, other threads:[~2015-02-17 13:56 UTC | newest]

Thread overview: 43+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-09  1:54 [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support Maciej W. Rozycki
2014-12-09  1:54 ` [Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion operations Maciej W. Rozycki
2015-01-29 14:51   ` Leon Alrae
2015-02-05 16:37   ` Peter Maydell
2015-02-05 16:38     ` Peter Maydell
2015-02-06 14:37     ` Maciej W. Rozycki
2015-02-06 14:45       ` Peter Maydell
2015-02-06 19:35         ` Maciej W. Rozycki
2015-02-08 12:12           ` Maciej W. Rozycki
2014-12-09  1:54 ` [Qemu-devel] [PATCH 2/7] softfloat: Simplify `floatx80ToCommonNaN' function Maciej W. Rozycki
2015-01-28 16:15   ` Leon Alrae
2014-12-09  1:55 ` [Qemu-devel] [PATCH 3/7] softfloat: Convert `*_default_nan' variables into inline functions Maciej W. Rozycki
2014-12-12 19:34   ` [Qemu-devel] [PATCH v2 " Maciej W. Rozycki
2015-01-30 14:09     ` Leon Alrae
2015-01-30 16:02       ` Maciej W. Rozycki
2015-01-30 16:55         ` Peter Maydell
2015-01-31 11:56           ` Maciej W. Rozycki
2015-01-31 12:52             ` Peter Maydell
2015-01-31 14:58               ` Maciej W. Rozycki
2015-02-03 15:43         ` Richard Henderson
2014-12-09  1:55 ` [Qemu-devel] [PATCH 4/7] softfloat: Add SoftFloat status parameter to `*_nan' functions Maciej W. Rozycki
2014-12-09  1:55 ` [Qemu-devel] [PATCH 5/7] softfloat: Rework `*_is_*_nan' functions Maciej W. Rozycki
2014-12-12 19:35   ` [Qemu-devel] [PATCH v2 " Maciej W. Rozycki
2015-02-05 16:42     ` Peter Maydell
2014-12-09  1:55 ` [Qemu-devel] [PATCH 6/7] softfloat: Add SoftFloat status `nan2008_mode' flag Maciej W. Rozycki
2014-12-12 19:35   ` [Qemu-devel] [PATCH v2 " Maciej W. Rozycki
2015-02-05 17:00     ` Peter Maydell
2015-02-05 19:07       ` Maciej W. Rozycki
2014-12-09  1:56 ` [Qemu-devel] [PATCH 7/7] target-mips: Add IEEE 754-2008 features support Maciej W. Rozycki
2015-02-09 17:10   ` Leon Alrae
2015-02-09 20:55     ` Maciej W. Rozycki
2015-02-10 10:44       ` Leon Alrae
2015-02-10 14:30         ` Maciej W. Rozycki
2015-02-10 17:21           ` Leon Alrae
2015-02-17 13:55   ` Maciej W. Rozycki
2014-12-09  9:20 ` [Qemu-devel] [PATCH 0/7] MIPS: " Peter Maydell
2014-12-09 12:28   ` Maciej W. Rozycki
2014-12-09 12:41     ` Peter Maydell
2014-12-09 18:16       ` Maciej W. Rozycki
2015-01-30 11:59 ` Peter Maydell
2015-01-30 13:47   ` Maciej W. Rozycki
     [not found]     ` <54CE9614.2060805@codesourcery.com>
2015-02-03 16:28       ` Thomas Schwinge
2015-02-03 22:30         ` Maciej W. Rozycki

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.