From patchwork Tue Dec 31 13:35:50 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 22831 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ie0-f197.google.com (mail-ie0-f197.google.com [209.85.223.197]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 93AC8218CC for ; Tue, 31 Dec 2013 13:36:14 +0000 (UTC) Received: by mail-ie0-f197.google.com with SMTP id e14sf61328755iej.4 for ; Tue, 31 Dec 2013 05:36:13 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=ALAdqfHq7X7i1ELuo8lqnULJTa3cuVV8zQ1WUN7q1Vw=; b=Ei1XIR5Lkny3fAI70ss1OBfX30sJWeBtE4xIDbQL33yfi8qleK2XgLQeJKBx8SHo/N NP8EA9sFNEoi8HY14ONfDaszzpjMGc7mQmvcfUqP/P7QoGjj9sYSjvJ66RrSY/QdJ86d nhMPyiiSBWpXYmXOw2N+iLYW3wMhw1cpmgiLZLpuG76f07UI7HqPz5KfX/Nrfe4PXPX7 9MzczTguKwpHgOsmcUEk0WVkb4aVLN3f0LxA9N6uLDLrlCwyBGwqEL7Li/Jjz1xD9q0G dlA8+WgB9/gdMnodeBHdtS2g71JW0VPjYmnZSFMEjOx7XimQivLL5uof6nQU2aBKuwnh Adaw== X-Gm-Message-State: ALoCoQkKLEzRvrFowUn2zE0QoXxo4KcOhBcRziZYr97XnTyLmP+++/VUVq8WWnVgRS0zgcd+GpWe X-Received: by 10.50.47.18 with SMTP id z18mr29919645igm.1.1388496973867; Tue, 31 Dec 2013 05:36:13 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.25.196 with SMTP id e4ls3785784qeg.6.gmail; Tue, 31 Dec 2013 05:36:13 -0800 (PST) X-Received: by 10.220.200.65 with SMTP id ev1mr39460039vcb.13.1388496973779; Tue, 31 Dec 2013 05:36:13 -0800 (PST) Received: from mail-ve0-f171.google.com (mail-ve0-f171.google.com [209.85.128.171]) by mx.google.com with ESMTPS id mh9si19101753vec.140.2013.12.31.05.36.13 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 31 Dec 2013 05:36:13 -0800 (PST) Received-SPF: neutral (google.com: 209.85.128.171 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.171; Received: by mail-ve0-f171.google.com with SMTP id pa12so6555474veb.16 for ; Tue, 31 Dec 2013 05:36:13 -0800 (PST) X-Received: by 10.52.249.105 with SMTP id yt9mr163389vdc.67.1388496973664; Tue, 31 Dec 2013 05:36:13 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.59.13.131 with SMTP id ey3csp664812ved; Tue, 31 Dec 2013 05:36:13 -0800 (PST) X-Received: by 10.205.16.69 with SMTP id px5mr23502105bkb.9.1388496970852; Tue, 31 Dec 2013 05:36:10 -0800 (PST) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk. [2001:8b0:1d0::1]) by mx.google.com with ESMTPS id rk5si15782031bkb.18.2013.12.31.05.36.08 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Tue, 31 Dec 2013 05:36:10 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::1 as permitted sender) client-ip=2001:8b0:1d0::1; Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1VxzUE-0000wZ-UX; Tue, 31 Dec 2013 13:35:58 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, Alexander Graf , Michael Matz , Claudio Fontana , Dirk Mueller , Laurent Desnogues , kvmarm@lists.cs.columbia.edu, Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Christoffer Dall , Will Newton , Peter Crosthwaite , Tom Musta , Aurelien Jarno Subject: [PATCH 14/22] softfloat: Add support for ties-away rounding Date: Tue, 31 Dec 2013 13:35:50 +0000 Message-Id: <1388496958-3542-15-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1388496958-3542-1-git-send-email-peter.maydell@linaro.org> References: <1388496958-3542-1-git-send-email-peter.maydell@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: peter.maydell@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.171 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , IEEE754-2008 specifies a new rounding mode: "roundTiesToAway: the floating-point number nearest to the infinitely precise result shall be delivered; if the two nearest floating-point numbers bracketing an unrepresentable infinitely precise result are equally near, the one with larger magnitude shall be delivered." Implement this new mode (it is needed for ARM). The general principle is that the required code is exactly like the ties-to-even code, except that we do not need to do the "in case of exact tie clear LSB to round-to-even", because the rounding operation naturally causes the exact tie to round up in magnitude. Signed-off-by: Peter Maydell --- fpu/softfloat.c | 68 ++++++++++++++++++++++++++++++++++++------------- include/fpu/softfloat.h | 3 ++- 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 623a4b9..ce7970f 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -107,7 +107,7 @@ static int32 roundAndPackInt32( flag zSign, uint64_t absZ STATUS_PARAM) roundingMode = STATUS(float_rounding_mode); roundNearestEven = ( roundingMode == float_round_nearest_even ); roundIncrement = 0x40; - if ( ! roundNearestEven ) { + if (!roundNearestEven && roundingMode != float_round_ties_away) { if ( roundingMode == float_round_to_zero ) { roundIncrement = 0; } @@ -155,7 +155,7 @@ static int64 roundAndPackInt64( flag zSign, uint64_t absZ0, uint64_t absZ1 STATU roundingMode = STATUS(float_rounding_mode); roundNearestEven = ( roundingMode == float_round_nearest_even ); increment = ( (int64_t) absZ1 < 0 ); - if ( ! roundNearestEven ) { + if (!roundNearestEven && roundingMode != float_round_ties_away) { if ( roundingMode == float_round_to_zero ) { increment = 0; } @@ -206,7 +206,7 @@ static int64 roundAndPackUint64(flag zSign, uint64_t absZ0, roundingMode = STATUS(float_rounding_mode); roundNearestEven = (roundingMode == float_round_nearest_even); increment = ((int64_t)absZ1 < 0); - if (!roundNearestEven) { + if (!roundNearestEven && roundingMode != float_round_ties_away) { if (roundingMode == float_round_to_zero) { increment = 0; } else if (absZ1) { @@ -354,7 +354,7 @@ static float32 roundAndPackFloat32(flag zSign, int_fast16_t zExp, uint32_t zSig roundingMode = STATUS(float_rounding_mode); roundNearestEven = ( roundingMode == float_round_nearest_even ); roundIncrement = 0x40; - if ( ! roundNearestEven ) { + if (!roundNearestEven && roundingMode != float_round_ties_away) { if ( roundingMode == float_round_to_zero ) { roundIncrement = 0; } @@ -536,7 +536,7 @@ static float64 roundAndPackFloat64(flag zSign, int_fast16_t zExp, uint64_t zSig roundingMode = STATUS(float_rounding_mode); roundNearestEven = ( roundingMode == float_round_nearest_even ); roundIncrement = 0x200; - if ( ! roundNearestEven ) { + if (!roundNearestEven && roundingMode != float_round_ties_away) { if ( roundingMode == float_round_to_zero ) { roundIncrement = 0; } @@ -718,7 +718,7 @@ static floatx80 goto precision80; } zSig0 |= ( zSig1 != 0 ); - if ( ! roundNearestEven ) { + if (!roundNearestEven && roundingMode != float_round_ties_away) { if ( roundingMode == float_round_to_zero ) { roundIncrement = 0; } @@ -1029,7 +1029,7 @@ static float128 roundingMode = STATUS(float_rounding_mode); roundNearestEven = ( roundingMode == float_round_nearest_even ); increment = ( (int64_t) zSig2 < 0 ); - if ( ! roundNearestEven ) { + if (!roundNearestEven && roundingMode != float_round_ties_away) { if ( roundingMode == float_round_to_zero ) { increment = 0; } @@ -1756,6 +1756,11 @@ float32 float32_round_to_int( float32 a STATUS_PARAM) return packFloat32( aSign, 0x7F, 0 ); } break; + case float_round_ties_away: + if (aExp == 0x7E) { + return packFloat32(aSign, 0x7F, 0); + } + break; case float_round_down: return make_float32(aSign ? 0xBF800000 : 0); case float_round_up: @@ -1771,8 +1776,9 @@ float32 float32_round_to_int( float32 a STATUS_PARAM) if ( roundingMode == float_round_nearest_even ) { z += lastBitMask>>1; if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { + } else if (roundingMode == float_round_ties_away) { + z += lastBitMask >> 1; + } else if (roundingMode != float_round_to_zero) { if ( extractFloat32Sign( make_float32(z) ) ^ ( roundingMode == float_round_up ) ) { z += roundBitsMask; } @@ -3144,6 +3150,9 @@ static float32 roundAndPackFloat16(flag zSign, int_fast16_t zExp, increment = zSig & (increment << 1); } break; + case float_round_ties_away: + increment = (mask + 1) >> 1; + break; case float_round_up: increment = zSign ? 0 : mask; break; @@ -3449,6 +3458,11 @@ float64 float64_round_to_int( float64 a STATUS_PARAM ) return packFloat64( aSign, 0x3FF, 0 ); } break; + case float_round_ties_away: + if (aExp == 0x3FE) { + return packFloat64(aSign, 0x3ff, 0); + } + break; case float_round_down: return make_float64(aSign ? LIT64( 0xBFF0000000000000 ) : 0); case float_round_up: @@ -3465,8 +3479,9 @@ float64 float64_round_to_int( float64 a STATUS_PARAM ) if ( roundingMode == float_round_nearest_even ) { z += lastBitMask>>1; if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { + } else if (roundingMode == float_round_ties_away) { + z += lastBitMask >> 1; + } else if (roundingMode != float_round_to_zero) { if ( extractFloat64Sign( make_float64(z) ) ^ ( roundingMode == float_round_up ) ) { z += roundBitsMask; } @@ -4722,6 +4737,11 @@ floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM ) packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); } break; + case float_round_ties_away: + if (aExp == 0x3FFE) { + return packFloatx80(aSign, 0x3FFF, LIT64(0x8000000000000000)); + } + break; case float_round_down: return aSign ? @@ -4742,8 +4762,9 @@ floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM ) if ( roundingMode == float_round_nearest_even ) { z.low += lastBitMask>>1; if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { + } else if (roundingMode == float_round_ties_away) { + z.low += lastBitMask >> 1; + } else if (roundingMode != float_round_to_zero) { if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) { z.low += roundBitsMask; } @@ -5801,8 +5822,15 @@ float128 float128_round_to_int( float128 a STATUS_PARAM ) if ( (uint64_t) ( z.low<<1 ) == 0 ) z.high &= ~1; } } - } - else if ( roundingMode != float_round_to_zero ) { + } else if (roundingMode == float_round_ties_away) { + if (lastBitMask) { + add128(z.high, z.low, 0, lastBitMask >> 1, &z.high, &z.low); + } else { + if ((int64_t) z.low < 0) { + ++z.high; + } + } + } else if (roundingMode != float_round_to_zero) { if ( extractFloat128Sign( z ) ^ ( roundingMode == float_round_up ) ) { add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low ); @@ -5824,6 +5852,11 @@ float128 float128_round_to_int( float128 a STATUS_PARAM ) return packFloat128( aSign, 0x3FFF, 0, 0 ); } break; + case float_round_ties_away: + if (aExp == 0x3FFE) { + return packFloat128(aSign, 0x3FFF, 0, 0); + } + break; case float_round_down: return aSign ? packFloat128( 1, 0x3FFF, 0, 0 ) @@ -5846,8 +5879,9 @@ float128 float128_round_to_int( float128 a STATUS_PARAM ) if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) { z.high &= ~ lastBitMask; } - } - else if ( roundingMode != float_round_to_zero ) { + } else if (roundingMode == float_round_ties_away) { + z.high += lastBitMask>>1; + } else if (roundingMode != float_round_to_zero) { if ( extractFloat128Sign( z ) ^ ( roundingMode == float_round_up ) ) { z.high |= ( a.low != 0 ); diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 08c7559..7f50d4f 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -152,7 +152,8 @@ enum { float_round_nearest_even = 0, float_round_down = 1, float_round_up = 2, - float_round_to_zero = 3 + float_round_to_zero = 3, + float_round_ties_away = 4, }; /*----------------------------------------------------------------------------