From nobody Sun Apr 28 08:42:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1550250330689860.0125837128643; Fri, 15 Feb 2019 09:05:30 -0800 (PST) Received: from localhost ([127.0.0.1]:43263 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gugvW-0004X7-6b for importer@patchew.org; Fri, 15 Feb 2019 12:05:26 -0500 Received: from eggs.gnu.org ([209.51.188.92]:34105) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gugss-00038O-EJ for qemu-devel@nongnu.org; Fri, 15 Feb 2019 12:02:43 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gugsn-00008B-QY for qemu-devel@nongnu.org; Fri, 15 Feb 2019 12:02:41 -0500 Received: from mail-pg1-x541.google.com ([2607:f8b0:4864:20::541]:35755) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gugsg-0008Pm-6Z for qemu-devel@nongnu.org; Fri, 15 Feb 2019 12:02:32 -0500 Received: by mail-pg1-x541.google.com with SMTP id s198so5082090pgs.2 for ; Fri, 15 Feb 2019 09:02:29 -0800 (PST) Received: from cloudburst.twiddle.net (97-113-188-82.tukw.qwest.net. [97.113.188.82]) by smtp.gmail.com with ESMTPSA id s2sm13893243pfa.167.2019.02.15.09.02.26 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 15 Feb 2019 09:02:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=K/x4eoSX+7tPqVVtKNYu8DavXEM59Bo5xgYmDfzp6A0=; b=HHeOyCJ0Q3r2gPCN5hUttgUwcbVpAgxTIXoqF6cogmamNPfpDo3cgRoH4adGvef9qf OoaylPS5q2URFoUy+n5oFbcyjCGt9qd5hdRSAPdPgf0rhEjU662xTtWX5vynmKYoalqA h/rzuh8A8EtbtmOIWtxWSVCOP/Wm4kdgZoeTtKszZyC6/nU/PtmuwRZez+O1PgtOCfKB j9OKw1Rgk1yPdvF7xiV5MMX3PKWBR0D+ZHRzhcDCId8hOHUTIxBUf9tzGzp2ZGvE/8Cf 81nwQGcx1zdT2zKvElYoalGl1DoA1Mvr0KrlmTlLHfbBK2SiVOoGbCMotD9g3Ovl/2cq 7rWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=K/x4eoSX+7tPqVVtKNYu8DavXEM59Bo5xgYmDfzp6A0=; b=G7TiWpk+7H0ONTQPlwGVashlR3floxRrbLwjKfvLC6050XY0zEN812dxUaNAoWMNFN iNVrTEucHrQdP+WqaMk+KPAXCLoR0OfhQCTqMhAzL5zvkRbYtRR08YbDelpafA7xnPIc XSD1YEsQhIgK5XyaFN189NX4mUIh1JfoMKcKF/A7nrXLhiJm3Lywu0ONYLqOWcgq4n/C tUAUSEkesyWhsrzjRZ8ApaiW1FQhQVs+0c1uudi5iwZA3o2kKuHY3igaVVrVia0gme8w 7udmdVMQLy9UCo3bZpBJpzCX47nQRYHmhYR3DR/OZ5oSWpDq5BVR6ddvL2p1M1hV4kG+ GYfw== X-Gm-Message-State: AHQUAua/Te3iWQzlUJ+bryWW5Jl0BpTwVhEQsUUZKtYve8ZBIfDRu4xA mvyTgkrNDyMwVpNMIRmsfbDomKiOVA8= X-Google-Smtp-Source: AHgI3Ib23AQUQkTmFfyv600nECWGl6BKboVi5mrat3g/Ra5LSeqyZKfkCzPoheCBw89loJN/5FRNlA== X-Received: by 2002:a62:9359:: with SMTP id b86mr10766552pfe.161.1550250147777; Fri, 15 Feb 2019 09:02:27 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Fri, 15 Feb 2019 09:02:25 -0800 Message-Id: <20190215170225.15537-1-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.2 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::541 Subject: [Qemu-devel] [PATCH v2] softfloat: Support float_round_to_odd more places X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: alex.bennee@linaro.org, david@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Previously this was only supported for roundAndPackFloat64. New support in round_canonical, round_to_int, float128_round_to_int, roundAndPackFloat32, roundAndPackInt32, roundAndPackInt64, roundAndPackUint64. This does not include any of the floatx80 routines, as we do not have users for that rounding mode there. Signed-off-by: Richard Henderson Tested-by: David Hildenbrand --- v2: Convert float128_round_to_int as well. Add fp-test support. --- fpu/softfloat.c | 64 ++++++++++++++++++++++++++++++++++++++++++---- tests/fp/fp-test.c | 43 ++++++++++++++++++++++++------- 2 files changed, 93 insertions(+), 14 deletions(-) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 9132d7a0b0..76132d4cd5 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -696,6 +696,7 @@ static FloatParts sf_canonicalize(FloatParts part, cons= t FloatFmt *parm, static FloatParts round_canonical(FloatParts p, float_status *s, const FloatFmt *parm) { + const uint64_t frac_lsb =3D parm->frac_lsb; const uint64_t frac_lsbm1 =3D parm->frac_lsbm1; const uint64_t round_mask =3D parm->round_mask; const uint64_t roundeven_mask =3D parm->roundeven_mask; @@ -731,6 +732,10 @@ static FloatParts round_canonical(FloatParts p, float_= status *s, inc =3D p.sign ? round_mask : 0; overflow_norm =3D !p.sign; break; + case float_round_to_odd: + overflow_norm =3D true; + inc =3D frac & frac_lsb ? 0 : round_mask; + break; default: g_assert_not_reached(); } @@ -778,9 +783,14 @@ static FloatParts round_canonical(FloatParts p, float_= status *s, shift64RightJamming(frac, 1 - exp, &frac); if (frac & round_mask) { /* Need to recompute round-to-even. */ - if (s->float_rounding_mode =3D=3D float_round_nearest_even= ) { + switch (s->float_rounding_mode) { + case float_round_nearest_even: inc =3D ((frac & roundeven_mask) !=3D frac_lsbm1 ? frac_lsbm1 : 0); + break; + case float_round_to_odd: + inc =3D frac & frac_lsb ? 0 : round_mask; + break; } flags |=3D float_flag_inexact; frac +=3D inc; @@ -1988,6 +1998,9 @@ static FloatParts round_to_int(FloatParts a, int rmod= e, case float_round_down: one =3D a.sign; break; + case float_round_to_odd: + one =3D true; + break; default: g_assert_not_reached(); } @@ -2021,6 +2034,9 @@ static FloatParts round_to_int(FloatParts a, int rmod= e, case float_round_down: inc =3D a.sign ? rnd_mask : 0; break; + case float_round_to_odd: + inc =3D a.frac & frac_lsb ? 0 : rnd_mask; + break; default: g_assert_not_reached(); } @@ -3314,6 +3330,9 @@ static int32_t roundAndPackInt32(flag zSign, uint64_t= absZ, float_status *status case float_round_down: roundIncrement =3D zSign ? 0x7f : 0; break; + case float_round_to_odd: + roundIncrement =3D absZ & 0x80 ? 0 : 0x7f; + break; default: abort(); } @@ -3368,6 +3387,9 @@ static int64_t roundAndPackInt64(flag zSign, uint64_t= absZ0, uint64_t absZ1, case float_round_down: increment =3D zSign && absZ1; break; + case float_round_to_odd: + increment =3D !(absZ0 & 1) && absZ1; + break; default: abort(); } @@ -3424,6 +3446,9 @@ static int64_t roundAndPackUint64(flag zSign, uint64_= t absZ0, case float_round_down: increment =3D zSign && absZ1; break; + case float_round_to_odd: + increment =3D !(absZ0 & 1) && absZ1; + break; default: abort(); } @@ -3526,6 +3551,8 @@ static float32 roundAndPackFloat32(flag zSign, int zE= xp, uint32_t zSig, case float_round_down: roundIncrement =3D zSign ? 0x7f : 0; break; + case float_round_to_odd: + roundIncrement =3D zSig & 0x80 ? 0 : 0x7f; default: abort(); break; @@ -3536,8 +3563,10 @@ static float32 roundAndPackFloat32(flag zSign, int z= Exp, uint32_t zSig, || ( ( zExp =3D=3D 0xFD ) && ( (int32_t) ( zSig + roundIncrement ) < 0 ) ) ) { + bool overflow_to_inf =3D roundingMode !=3D float_round_to_odd = && + roundIncrement !=3D 0; float_raise(float_flag_overflow | float_flag_inexact, status); - return packFloat32( zSign, 0xFF, - ( roundIncrement =3D=3D 0 )= ); + return packFloat32(zSign, 0xFF, -!overflow_to_inf); } if ( zExp < 0 ) { if (status->flush_to_zero) { @@ -3555,6 +3584,13 @@ static float32 roundAndPackFloat32(flag zSign, int z= Exp, uint32_t zSig, if (isTiny && roundBits) { float_raise(float_flag_underflow, status); } + if (roundingMode =3D=3D float_round_to_odd) { + /* + * For round-to-odd case, the roundIncrement depends on + * zSig which just changed. + */ + roundIncrement =3D zSig & 0x80 ? 0 : 0x7f; + } } } if (roundBits) { @@ -6958,6 +6994,15 @@ float128 float128_round_to_int(float128 a, float_sta= tus *status) add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low); } break; + case float_round_to_odd: + /* + * Note that if lastBitMask =3D=3D 0, the last bit is the lsb + * of high, and roundBitsMask =3D=3D -1. + */ + if ((lastBitMask ? z.low & lastBitMask : z.high & 1) =3D=3D 0)= { + add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low); + } + break; default: abort(); } @@ -6969,7 +7014,7 @@ float128 float128_round_to_int(float128 a, float_stat= us *status) status->float_exception_flags |=3D float_flag_inexact; aSign =3D extractFloat128Sign( a ); switch (status->float_rounding_mode) { - case float_round_nearest_even: + case float_round_nearest_even: if ( ( aExp =3D=3D 0x3FFE ) && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) @@ -6982,14 +7027,17 @@ float128 float128_round_to_int(float128 a, float_st= atus *status) return packFloat128(aSign, 0x3FFF, 0, 0); } break; - case float_round_down: + case float_round_down: return aSign ? packFloat128( 1, 0x3FFF, 0, 0 ) : packFloat128( 0, 0, 0, 0 ); - case float_round_up: + case float_round_up: return aSign ? packFloat128( 1, 0, 0, 0 ) : packFloat128( 0, 0x3FFF, 0, 0 ); + + case float_round_to_odd: + return packFloat128(aSign, 0x3FFF, 0, 0); } return packFloat128( aSign, 0, 0, 0 ); } @@ -7022,6 +7070,12 @@ float128 float128_round_to_int(float128 a, float_sta= tus *status) z.high +=3D roundBitsMask; } break; + case float_round_to_odd: + if ((z.high & lastBitMask) =3D=3D 0) { + z.high |=3D (a.low !=3D 0); + z.high +=3D roundBitsMask; + } + break; default: abort(); } diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c index 2a35ef601d..471adb862d 100644 --- a/tests/fp/fp-test.c +++ b/tests/fp/fp-test.c @@ -125,17 +125,42 @@ static void not_implemented(void) =20 static bool blacklisted(unsigned op, int rmode) { - /* odd has only been implemented for a few 128-bit ops */ + /* odd has not been implemented for any 80-bit ops */ if (rmode =3D=3D softfloat_round_odd) { switch (op) { - case F128_ADD: - case F128_SUB: - case F128_MUL: - case F128_DIV: - case F128_TO_F64: - case F128_SQRT: - return false; - default: + case EXTF80_TO_UI32: + case EXTF80_TO_UI64: + case EXTF80_TO_I32: + case EXTF80_TO_I64: + case EXTF80_TO_UI32_R_MINMAG: + case EXTF80_TO_UI64_R_MINMAG: + case EXTF80_TO_I32_R_MINMAG: + case EXTF80_TO_I64_R_MINMAG: + case EXTF80_TO_F16: + case EXTF80_TO_F32: + case EXTF80_TO_F64: + case EXTF80_TO_F128: + case EXTF80_ROUNDTOINT: + case EXTF80_ADD: + case EXTF80_SUB: + case EXTF80_MUL: + case EXTF80_DIV: + case EXTF80_REM: + case EXTF80_SQRT: + case EXTF80_EQ: + case EXTF80_LE: + case EXTF80_LT: + case EXTF80_EQ_SIGNALING: + case EXTF80_LE_QUIET: + case EXTF80_LT_QUIET: + case UI32_TO_EXTF80: + case UI64_TO_EXTF80: + case I32_TO_EXTF80: + case I64_TO_EXTF80: + case F16_TO_EXTF80: + case F32_TO_EXTF80: + case F64_TO_EXTF80: + case F128_TO_EXTF80: return true; } } --=20 2.17.2