From patchwork Mon Feb 7 17:00:26 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Lyon X-Patchwork-Id: 82140 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 7663FB70E3 for ; Tue, 8 Feb 2011 07:55:19 +1100 (EST) Received: from localhost ([127.0.0.1]:58794 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PmVC9-0002Z8-QB for incoming@patchwork.ozlabs.org; Mon, 07 Feb 2011 12:48:13 -0500 Received: from [140.186.70.92] (port=45885 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PmUS8-0000du-Oa for qemu-devel@nongnu.org; Mon, 07 Feb 2011 12:00:44 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PmURx-0000a5-9g for qemu-devel@nongnu.org; Mon, 07 Feb 2011 12:00:32 -0500 Received: from eu1sys200aog117.obsmtp.com ([207.126.144.143]:53099) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PmURw-0000ZY-Qe for qemu-devel@nongnu.org; Mon, 07 Feb 2011 12:00:29 -0500 Received: from source ([164.129.1.35]) (using TLSv1) by eu1sys200aob117.postini.com ([207.126.147.11]) with SMTP ID DSNKTVAlK9LVfCsiZAYdLLjTgKImhPHc4KYn@postini.com; Mon, 07 Feb 2011 17:00:28 UTC Received: from zeta.dmz-eu.st.com (ns2.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 18DF3137 for ; Mon, 7 Feb 2011 17:00:27 +0000 (GMT) Received: from Webmail-eu.st.com (safex1hubcas5.st.com [10.75.90.71]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id EAA4844C0 for ; Mon, 7 Feb 2011 17:00:26 +0000 (GMT) Received: from [164.129.122.40] (164.129.122.40) by webmail-eu.st.com (10.75.90.13) with Microsoft SMTP Server (TLS) id 8.2.234.1; Mon, 7 Feb 2011 18:00:26 +0100 Message-ID: <4D50252A.2000100@st.com> Date: Mon, 7 Feb 2011 18:00:26 +0100 From: Christophe Lyon User-Agent: Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.9.2.13) Gecko/20101207 Lightning/1.0b2 Thunderbird/3.1.7 MIME-Version: 1.0 To: "qemu-devel@nongnu.org" X-Enigmail-Version: 1.1.1 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-Received-From: 207.126.144.143 Subject: [Qemu-devel] [PATCH v3] Softfloat: Add support to softfloat to return floatxx_default_nan when, the corresponding target status flag is set. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Some CPUs have a status flag imposing to return floatxx_default_nan whatever the input value, when converting from one FP format to another. Implement this, using the already existing default_nan_mode status flag (currently used on ARM and SH4 at the moment). Signed-off-by: Christophe Lyon --- fpu/softfloat-specialize.h | 60 +++++++++++++++++++++++++++++++++++++++++--- fpu/softfloat.c | 30 +++++++++------------ 2 files changed, 69 insertions(+), 21 deletions(-) diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h index 11521ce..3f7995c 100644 --- a/fpu/softfloat-specialize.h +++ b/fpu/softfloat-specialize.h @@ -144,9 +144,14 @@ static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM ) | precision floating-point format. *----------------------------------------------------------------------------*/ -static float32 commonNaNToFloat32( commonNaNT a ) +static float32 commonNaNToFloat32( commonNaNT a STATUS_PARAM) { bits32 mantissa = a.high>>41; + + if ( STATUS(default_nan_mode) ) { + return float32_default_nan; + } + if ( mantissa ) return make_float32( ( ( (bits32) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) ); @@ -398,10 +403,14 @@ static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM) | precision floating-point format. *----------------------------------------------------------------------------*/ -static float64 commonNaNToFloat64( commonNaNT a ) +static float64 commonNaNToFloat64( commonNaNT a STATUS_PARAM) { bits64 mantissa = a.high>>12; + if ( STATUS(default_nan_mode) ) { + return float64_default_nan; + } + if ( mantissa ) return make_float64( ( ( (bits64) a.sign )<<63 ) @@ -451,6 +460,37 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM) } } +/*---------------------------------------------------------------------------- +| The pattern for a default generated haft-precision NaN. +*----------------------------------------------------------------------------*/ +#if defined(TARGET_ARM) +#define float16_default_nan 0x7E00 +#elif SNAN_BIT_IS_ONE +#define float16_default_nan 0x7DFF +#else +#define float16_default_nan 0xFE00 +#endif + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the half- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +static bits16 commonNaNToFloat16( commonNaNT a STATUS_PARAM) +{ + bits16 mantissa = a.high>>57; + + if ( STATUS(default_nan_mode) ) { + return float16_default_nan; + } + + if ( mantissa ) { + return ( ( ( (bits16) a.sign) << 15) | (0x1F << 10) | mantissa ); + } else { + return float16_default_nan; + } +} + #ifdef FLOATX80 /*---------------------------------------------------------------------------- @@ -551,10 +591,16 @@ static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM) | double-precision floating-point format. *----------------------------------------------------------------------------*/ -static floatx80 commonNaNToFloatx80( commonNaNT a ) +static floatx80 commonNaNToFloatx80( commonNaNT a STATUS_PARAM) { floatx80 z; + if ( STATUS(default_nan_mode) ) { + z.low = floatx80_default_nan_low; + z.high = floatx80_default_nan_high; + return z; + } + if (a.high) z.low = a.high; else @@ -699,10 +745,16 @@ static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM) | precision floating-point format. *----------------------------------------------------------------------------*/ -static float128 commonNaNToFloat128( commonNaNT a ) +static float128 commonNaNToFloat128( commonNaNT a STATUS_PARAM) { float128 z; + if ( STATUS(default_nan_mode) ) { + z.low = float128_default_nan_low; + z.high = float128_default_nan_high; + return z; + } + shift128Right( a.high, a.low, 16, &z.high, &z.low ); z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF000000000000 ); return z; diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 17842f4..abf14f1 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1534,7 +1534,7 @@ float64 float32_to_float64( float32 a STATUS_PARAM ) aExp = extractFloat32Exp( a ); aSign = extractFloat32Sign( a ); if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a STATUS_VAR )); + if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); return packFloat64( aSign, 0x7FF, 0 ); } if ( aExp == 0 ) { @@ -1566,7 +1566,7 @@ floatx80 float32_to_floatx80( float32 a STATUS_PARAM ) aExp = extractFloat32Exp( a ); aSign = extractFloat32Sign( a ); if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a STATUS_VAR ) ); + if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); } if ( aExp == 0 ) { @@ -1600,7 +1600,7 @@ float128 float32_to_float128( float32 a STATUS_PARAM ) aExp = extractFloat32Exp( a ); aSign = extractFloat32Sign( a ); if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a STATUS_VAR ) ); + if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); return packFloat128( aSign, 0x7FFF, 0, 0 ); } if ( aExp == 0 ) { @@ -2689,7 +2689,7 @@ float32 float64_to_float32( float64 a STATUS_PARAM ) aExp = extractFloat64Exp( a ); aSign = extractFloat64Sign( a ); if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a STATUS_VAR ) ); + if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); return packFloat32( aSign, 0xFF, 0 ); } shift64RightJamming( aSig, 22, &aSig ); @@ -2767,11 +2767,7 @@ bits16 float32_to_float16( float32 a, flag ieee STATUS_PARAM) aExp = extractFloat32Exp( a ); aSign = extractFloat32Sign( a ); if ( aExp == 0xFF ) { - if (aSig) { - /* Make sure correct exceptions are raised. */ - float32ToCommonNaN(a STATUS_VAR); - aSig |= 0x00400000; - } + if ( aSig ) return commonNaNToFloat16( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); return packFloat16(aSign, 0x1f, aSig >> 13); } if (aExp == 0 && aSign == 0) { @@ -2861,7 +2857,7 @@ floatx80 float64_to_floatx80( float64 a STATUS_PARAM ) aExp = extractFloat64Exp( a ); aSign = extractFloat64Sign( a ); if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a STATUS_VAR ) ); + if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); } if ( aExp == 0 ) { @@ -2896,7 +2892,7 @@ float128 float64_to_float128( float64 a STATUS_PARAM ) aExp = extractFloat64Exp( a ); aSign = extractFloat64Sign( a ); if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a STATUS_VAR ) ); + if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); return packFloat128( aSign, 0x7FFF, 0, 0 ); } if ( aExp == 0 ) { @@ -3843,7 +3839,7 @@ float32 floatx80_to_float32( floatx80 a STATUS_PARAM ) aSign = extractFloatx80Sign( a ); if ( aExp == 0x7FFF ) { if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR ) ); + return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); } return packFloat32( aSign, 0xFF, 0 ); } @@ -3871,7 +3867,7 @@ float64 floatx80_to_float64( floatx80 a STATUS_PARAM ) aSign = extractFloatx80Sign( a ); if ( aExp == 0x7FFF ) { if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR ) ); + return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); } return packFloat64( aSign, 0x7FF, 0 ); } @@ -3900,7 +3896,7 @@ float128 floatx80_to_float128( floatx80 a STATUS_PARAM ) aExp = extractFloatx80Exp( a ); aSign = extractFloatx80Sign( a ); if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR ) ); + return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); } shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 ); return packFloat128( aSign, aExp, zSig0, zSig1 ); @@ -4863,7 +4859,7 @@ float32 float128_to_float32( float128 a STATUS_PARAM ) aSign = extractFloat128Sign( a ); if ( aExp == 0x7FFF ) { if ( aSig0 | aSig1 ) { - return commonNaNToFloat32( float128ToCommonNaN( a STATUS_VAR ) ); + return commonNaNToFloat32( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); } return packFloat32( aSign, 0xFF, 0 ); } @@ -4897,7 +4893,7 @@ float64 float128_to_float64( float128 a STATUS_PARAM ) aSign = extractFloat128Sign( a ); if ( aExp == 0x7FFF ) { if ( aSig0 | aSig1 ) { - return commonNaNToFloat64( float128ToCommonNaN( a STATUS_VAR ) ); + return commonNaNToFloat64( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); } return packFloat64( aSign, 0x7FF, 0 ); } @@ -4932,7 +4928,7 @@ floatx80 float128_to_floatx80( float128 a STATUS_PARAM ) aSign = extractFloat128Sign( a ); if ( aExp == 0x7FFF ) { if ( aSig0 | aSig1 ) { - return commonNaNToFloatx80( float128ToCommonNaN( a STATUS_VAR ) ); + return commonNaNToFloatx80( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); } return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); }