[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion o
From: |
Maciej W. Rozycki |
Subject: |
[Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion operations |
Date: |
Tue, 9 Dec 2014 01:54:40 +0000 |
User-agent: |
Alpine 1.10 (DEB 962 2008-03-14) |
Fix sNaN handling in floating-point format conversion operations, that
are classified by the IEEE 754-2008 standard as general-computational
operations [1]:
"5.4 formatOf general-computational operations
"5.4.2 Conversion operations for floating-point formats and decimal
character sequences
"Implementations shall provide the following formatOf conversion
operations from all supported floating-point formats to all supported
floating-point formats, as well as conversions to and from decimal
character sequences. These operations shall not propagate non-canonical
results. Some format conversion operations produce results in a
different radix than the operands."
according to the quietening requirement [2] set by the same standard:
"7.2 Invalid operation
"For operations producing results in floating-point format, the default
result of an operation that signals the invalid operation exception
shall be a quiet NaN that should provide some diagnostic information
(see 6.2).
"These operations are:
a) any general-computational or signaling-computational operation
on a signaling NaN (see 6.2), except for some conversions (see
5.12)"
and the reference above is [3]:
"5.12 Details of conversion between floating-point data and external
character sequences"
so does not apply to conversions a pair of floating-point formats.
Therefore quieten any sNaN encountered in floating-point format
conversions, in the usual manner.
References:
[1] "IEEE Standard for Floating-Point Arithmetic", IEEE Computer
Society, IEEE Std 754-2008, 29 August 2008, pp. 21-22
[2] same, p. 37
[3] same, p. 30
Signed-off-by: Maciej W. Rozycki <address@hidden>
---
This is in particular how MIPS hardware operates, other processors
supposedly do the same if they claim compliance to IEEE 754.
Please apply.
qemu-softfloat-convert-snan.diff
Index: qemu-git-trunk/fpu/softfloat.c
===================================================================
--- qemu-git-trunk.orig/fpu/softfloat.c 2014-10-24 22:03:48.000000000 +0100
+++ qemu-git-trunk/fpu/softfloat.c 2014-11-03 01:45:15.488923310 +0000
@@ -1711,7 +1711,11 @@ float64 float32_to_float64( float32 a ST
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
if ( aExp == 0xFF ) {
- if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a
STATUS_VAR ) STATUS_VAR );
+ if (aSig) {
+ return float64_maybe_silence_nan(
+ commonNaNToFloat64(float32ToCommonNaN(a STATUS_VAR)
+ STATUS_VAR));
+ }
return packFloat64( aSign, 0x7FF, 0 );
}
if ( aExp == 0 ) {
@@ -1741,7 +1745,11 @@ floatx80 float32_to_floatx80( float32 a
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
if ( aExp == 0xFF ) {
- if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a
STATUS_VAR ) STATUS_VAR );
+ if (aSig) {
+ return floatx80_maybe_silence_nan(
+ commonNaNToFloatx80(float32ToCommonNaN(a STATUS_VAR)
+ STATUS_VAR));
+ }
return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
}
if ( aExp == 0 ) {
@@ -1771,7 +1779,11 @@ float128 float32_to_float128( float32 a
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
if ( aExp == 0xFF ) {
- if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a
STATUS_VAR ) STATUS_VAR );
+ if (aSig) {
+ return float128_maybe_silence_nan(
+ commonNaNToFloat128(float32ToCommonNaN(a STATUS_VAR)
+ STATUS_VAR));
+ }
return packFloat128( aSign, 0x7FFF, 0, 0 );
}
if ( aExp == 0 ) {
@@ -3151,7 +3163,11 @@ float32 float64_to_float32( float64 a ST
aExp = extractFloat64Exp( a );
aSign = extractFloat64Sign( a );
if ( aExp == 0x7FF ) {
- if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a
STATUS_VAR ) STATUS_VAR );
+ if (aSig) {
+ return float32_maybe_silence_nan(
+ commonNaNToFloat32(float64ToCommonNaN(a STATUS_VAR)
+ STATUS_VAR));
+ }
return packFloat32( aSign, 0xFF, 0 );
}
shift64RightJamming( aSig, 22, &aSig );
@@ -3318,7 +3334,9 @@ float32 float16_to_float32(float16 a, fl
if (aExp == 0x1f && ieee) {
if (aSig) {
- return commonNaNToFloat32(float16ToCommonNaN(a STATUS_VAR)
STATUS_VAR);
+ return float32_maybe_silence_nan(
+ commonNaNToFloat32(float16ToCommonNaN(a STATUS_VAR)
+ STATUS_VAR));
}
return packFloat32(aSign, 0xff, 0);
}
@@ -3351,8 +3369,9 @@ float16 float32_to_float16(float32 a, fl
float_raise(float_flag_invalid STATUS_VAR);
return packFloat16(aSign, 0, 0);
}
- return commonNaNToFloat16(
- float32ToCommonNaN(a STATUS_VAR) STATUS_VAR);
+ return float16_maybe_silence_nan(
+ commonNaNToFloat16(float32ToCommonNaN(a STATUS_VAR)
+ STATUS_VAR));
}
/* Infinity */
if (!ieee) {
@@ -3389,8 +3408,9 @@ float64 float16_to_float64(float16 a, fl
if (aExp == 0x1f && ieee) {
if (aSig) {
- return commonNaNToFloat64(
- float16ToCommonNaN(a STATUS_VAR) STATUS_VAR);
+ return float64_maybe_silence_nan(
+ commonNaNToFloat64(float16ToCommonNaN(a STATUS_VAR)
+ STATUS_VAR));
}
return packFloat64(aSign, 0x7ff, 0);
}
@@ -3424,8 +3444,9 @@ float16 float64_to_float16(float64 a, fl
float_raise(float_flag_invalid STATUS_VAR);
return packFloat16(aSign, 0, 0);
}
- return commonNaNToFloat16(
- float64ToCommonNaN(a STATUS_VAR) STATUS_VAR);
+ return float16_maybe_silence_nan(
+ commonNaNToFloat16(float64ToCommonNaN(a STATUS_VAR)
+ STATUS_VAR));
}
/* Infinity */
if (!ieee) {
@@ -3470,7 +3491,11 @@ floatx80 float64_to_floatx80( float64 a
aExp = extractFloat64Exp( a );
aSign = extractFloat64Sign( a );
if ( aExp == 0x7FF ) {
- if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a
STATUS_VAR ) STATUS_VAR );
+ if (aSig) {
+ return floatx80_maybe_silence_nan(
+ commonNaNToFloatx80(float64ToCommonNaN(a STATUS_VAR)
+ STATUS_VAR));
+ }
return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
}
if ( aExp == 0 ) {
@@ -3501,7 +3526,11 @@ float128 float64_to_float128( float64 a
aExp = extractFloat64Exp( a );
aSign = extractFloat64Sign( a );
if ( aExp == 0x7FF ) {
- if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a
STATUS_VAR ) STATUS_VAR );
+ if (aSig) {
+ return float128_maybe_silence_nan(
+ commonNaNToFloat128(float64ToCommonNaN(a STATUS_VAR)
+ STATUS_VAR));
+ }
return packFloat128( aSign, 0x7FFF, 0, 0 );
}
if ( aExp == 0 ) {
@@ -4759,8 +4788,10 @@ float32 floatx80_to_float32( floatx80 a
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
if ( aExp == 0x7FFF ) {
- if ( (uint64_t) ( aSig<<1 ) ) {
- return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR )
STATUS_VAR );
+ if ((uint64_t)(aSig << 1)) {
+ return float32_maybe_silence_nan(
+ commonNaNToFloat32(floatx80ToCommonNaN(a STATUS_VAR)
+ STATUS_VAR));
}
return packFloat32( aSign, 0xFF, 0 );
}
@@ -4787,8 +4818,10 @@ float64 floatx80_to_float64( floatx80 a
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
if ( aExp == 0x7FFF ) {
- if ( (uint64_t) ( aSig<<1 ) ) {
- return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR )
STATUS_VAR );
+ if ((uint64_t)(aSig << 1)) {
+ return float64_maybe_silence_nan(
+ commonNaNToFloat64(floatx80ToCommonNaN(a STATUS_VAR)
+ STATUS_VAR));
}
return packFloat64( aSign, 0x7FF, 0 );
}
@@ -4814,8 +4847,9 @@ float128 floatx80_to_float128( floatx80
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
- if ( ( aExp == 0x7FFF ) && (uint64_t) ( aSig<<1 ) ) {
- return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR )
STATUS_VAR );
+ if (aExp == 0x7FFF && (uint64_t)(aSig << 1)) {
+ return float128_maybe_silence_nan(
+ commonNaNToFloat128(floatx80ToCommonNaN(a STATUS_VAR) STATUS_VAR));
}
shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 );
return packFloat128( aSign, aExp, zSig0, zSig1 );
@@ -5832,8 +5866,10 @@ float32 float128_to_float32( float128 a
aExp = extractFloat128Exp( a );
aSign = extractFloat128Sign( a );
if ( aExp == 0x7FFF ) {
- if ( aSig0 | aSig1 ) {
- return commonNaNToFloat32( float128ToCommonNaN( a STATUS_VAR )
STATUS_VAR );
+ if (aSig0 | aSig1) {
+ return float32_maybe_silence_nan(
+ commonNaNToFloat32(float128ToCommonNaN(a STATUS_VAR)
+ STATUS_VAR));
}
return packFloat32( aSign, 0xFF, 0 );
}
@@ -5866,8 +5902,10 @@ float64 float128_to_float64( float128 a
aExp = extractFloat128Exp( a );
aSign = extractFloat128Sign( a );
if ( aExp == 0x7FFF ) {
- if ( aSig0 | aSig1 ) {
- return commonNaNToFloat64( float128ToCommonNaN( a STATUS_VAR )
STATUS_VAR );
+ if (aSig0 | aSig1) {
+ return float64_maybe_silence_nan(
+ commonNaNToFloat64(float128ToCommonNaN(a STATUS_VAR)
+ STATUS_VAR));
}
return packFloat64( aSign, 0x7FF, 0 );
}
@@ -5899,8 +5937,10 @@ floatx80 float128_to_floatx80( float128
aExp = extractFloat128Exp( a );
aSign = extractFloat128Sign( a );
if ( aExp == 0x7FFF ) {
- if ( aSig0 | aSig1 ) {
- return commonNaNToFloatx80( float128ToCommonNaN( a STATUS_VAR )
STATUS_VAR );
+ if (aSig0 | aSig1) {
+ return floatx80_maybe_silence_nan(
+ commonNaNToFloatx80(float128ToCommonNaN(a STATUS_VAR)
+ STATUS_VAR));
}
return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
}
- [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support, Maciej W. Rozycki, 2014/12/08
- [Qemu-devel] [PATCH 1/7] softfloat: Fix sNaN handling in FP conversion operations,
Maciej W. Rozycki <=
- [Qemu-devel] [PATCH 2/7] softfloat: Simplify `floatx80ToCommonNaN' function, Maciej W. Rozycki, 2014/12/08
- [Qemu-devel] [PATCH 3/7] softfloat: Convert `*_default_nan' variables into inline functions, Maciej W. Rozycki, 2014/12/08
- [Qemu-devel] [PATCH 4/7] softfloat: Add SoftFloat status parameter to `*_nan' functions, Maciej W. Rozycki, 2014/12/08
- [Qemu-devel] [PATCH 5/7] softfloat: Rework `*_is_*_nan' functions, Maciej W. Rozycki, 2014/12/08
- [Qemu-devel] [PATCH 6/7] softfloat: Add SoftFloat status `nan2008_mode' flag, Maciej W. Rozycki, 2014/12/08
- [Qemu-devel] [PATCH 7/7] target-mips: Add IEEE 754-2008 features support, Maciej W. Rozycki, 2014/12/08
- Re: [Qemu-devel] [PATCH 0/7] MIPS: IEEE 754-2008 features support, Peter Maydell, 2014/12/09