From nobody Tue Feb 10 19:48:35 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.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 208.118.235.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 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1517718562878835.5336739877908; Sat, 3 Feb 2018 20:29:22 -0800 (PST) Received: from localhost ([::1]:58360 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBvd-0003Dt-Rk for importer@patchew.org; Sat, 03 Feb 2018 23:29:21 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47531) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eiBfB-000522-55 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eiBf6-00057j-18 for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:21 -0500 Received: from mail-pl0-x242.google.com ([2607:f8b0:400e:c01::242]:34685) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eiBf5-00057N-PA for qemu-devel@nongnu.org; Sat, 03 Feb 2018 23:12:15 -0500 Received: by mail-pl0-x242.google.com with SMTP id q17so7156453pll.1 for ; Sat, 03 Feb 2018 20:12:15 -0800 (PST) Received: from cloudburst.twiddle.net (174-21-6-47.tukw.qwest.net. [174.21.6.47]) by smtp.gmail.com with ESMTPSA id k3sm1399425pgr.12.2018.02.03.20.12.13 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 20:12:13 -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:in-reply-to:references; bh=M/rrn0hTeYecl0nmHZH6/01GanF2uSg86yLNwI3DnuM=; b=eo7CWxRYXrBxC9lPUJ/KmOb2O/dEpMUqyrEiC8SeJF/H4rhzhMVYEHvi3PvfS0rOIk uYqzp6Hf4O6XN5kS9EZxLbAvyAN6zGQGoFmSuCVVFfPwulu4jqG1yuyR9WasT2X0ZxoY vbZP+jp15rmodNNuESHFWiSuArwE6K6mDN1iw= 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:in-reply-to :references; bh=M/rrn0hTeYecl0nmHZH6/01GanF2uSg86yLNwI3DnuM=; b=DWScOsUHCSkOVtVn/KOHMthWqUAMD2i3pdvu97PDpEBYkfOuznSoczGUxALuyRW71B 5MIvHR0yjpsXd8qaMUAYzr8hmCqzX8dxj2V4GDUKBpS2C7LsPPF6RScUWk7U9hmF97iw YtaUGgzMv7G+Z8FElh4ystwvFclnzacE6E5/+EihV9hDhHhDdVMLRgYBG5Gl+6cr4dfw N81N4dt9Z7X+fvtWQICbxpV2TgzTJc2qfQYch35vLOiXovR2k2oF7ClgB+D2MBzQxgfv IJBh4A6u6TuCaPPJVqNGgv0+VDQnpFILElJ5yYMMj/SJXaZIgIc/iX1SP0j4aR3tmwsr 3s9Q== X-Gm-Message-State: AKwxytc8NTNz8UD9r9lE2l17Vfpgjx5lKlS5czjBFKn9s4Psg0u1Lzbc b7+34kiLOhrG1+aknt+w/RlUPla5RGI= X-Google-Smtp-Source: AH8x227O6ksPM/bVmBWzZWMA2AngOcPJJsNUIL+7Oq8qIGyELzQRzfHynQlkBR9QIdO5tnrI/Q/imQ== X-Received: by 2002:a17:902:8d97:: with SMTP id v23-v6mr34991063plo.248.1517717534419; Sat, 03 Feb 2018 20:12:14 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 3 Feb 2018 20:11:36 -0800 Message-Id: <20180204041136.17525-25-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180204041136.17525-1-richard.henderson@linaro.org> References: <20180204041136.17525-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::242 Subject: [Qemu-devel] [PATCH 24/24] fpu: Implement round_to_int with soft-fp.h 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: peter.maydell@linaro.org, cota@braap.org, alex.bennee@linaro.org, hsp.cat7@gmail.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add float16 support. Remove float64_trunc_to_int as unused rather than recreating it within the new framework. Signed-off-by: Richard Henderson --- include/fpu/softfloat.h | 2 +- fpu/floatxx.inc.c | 75 ++++++++++++ fpu/softfloat.c | 311 --------------------------------------------= ---- 3 files changed, 76 insertions(+), 312 deletions(-) diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 3a2d148651..95e96f8557 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -246,6 +246,7 @@ float64 float16_to_float64(float16 a, bool ieee, float_= status *status); | Software half-precision operations. *-------------------------------------------------------------------------= ---*/ =20 +float16 float16_round_to_int(float16, float_status *status); float16 float16_add(float16, float16, float_status *status); float16 float16_sub(float16, float16, float_status *status); float16 float16_mul(float16, float16, float_status *status); @@ -463,7 +464,6 @@ float128 float64_to_float128(float64, float_status *sta= tus); | Software IEC/IEEE double-precision operations. *-------------------------------------------------------------------------= ---*/ float64 float64_round_to_int(float64, float_status *status); -float64 float64_trunc_to_int(float64, float_status *status); float64 float64_add(float64, float64, float_status *status); float64 float64_sub(float64, float64, float_status *status); float64 float64_mul(float64, float64, float_status *status); diff --git a/fpu/floatxx.inc.c b/fpu/floatxx.inc.c index a4b305e1ff..a90ae95f2d 100644 --- a/fpu/floatxx.inc.c +++ b/fpu/floatxx.inc.c @@ -34,6 +34,8 @@ _FP_FRAC_SNANP(fs, X) #define FP_ADD_INTERNAL(fs, wc, R, A, B, OP) \ _FP_ADD_INTERNAL(fs, wc, R, A, B, '-') +#define FP_ROUND(wc, X) \ + _FP_ROUND(wc, X) =20 static FLOATXX addsub_internal(FLOATXX a, FLOATXX b, float_status *status, bool subtract) @@ -464,3 +466,76 @@ FLOATXX glue(FLOATXX,_minnummag)(FLOATXX a, FLOATXX b,= float_status *status) return minmax_internal(a, b, status, MINMAX_MIN | MINMAX_IEEE | MINMAX_MAG); } + +FLOATXX glue(FLOATXX,_round_to_int)(FLOATXX a, float_status *status) +{ + const int fracbits =3D glue(_FP_FRACBITS_, FS); + const int wfracbits =3D glue(_FP_WFRACBITS_, FS); + FP_DECL_EX; + glue(FP_DECL_, FS)(A); + int rshift, lshift; + + FP_INIT_ROUNDMODE; + glue(FP_UNPACK_, FS)(A, a); + + switch (A_c) { + case FP_CLS_INF: + /* No fractional part, never any exceptions, return unchanged. */ + return a; + + case FP_CLS_ZERO: + case FP_CLS_NAN: + /* No fractional part, but maybe exceptions. In the cases of + denormal-flush-to-zero and SNaN, we will have raised an + exception during unpack. For those, we need to go through + repack in order to generate zero or silence the NaN. */ + if (!FP_CUR_EXCEPTIONS) { + return a; + } + break; + + case FP_CLS_NORMAL: + /* Position the 2**0 bit at _FP_WORKBIT, + where _FP_ROUND expects to work. */ + rshift =3D fracbits - 1 - A_e; + if (rshift <=3D 0) { + /* Already integral, never any exceptions, return unchanged. = */ + return a; + } + if (rshift < wfracbits) { + glue(_FP_FRAC_SRS_, WC)(A, rshift, wfracbits); + } else { + glue(_FP_FRAC_SET_, WC)(A, glue(_FP_MINFRAC_, WC)); + } + FP_ROUND(WC, A); + + /* Drop the rounding bits. Normally this is done via right-shift + during the re-packing stage, but we need to put the rest of the + fraction back into place. */ + glue(_FP_FRAC_LOW_, WC)(A) &=3D ~(_FP_WORK_LSB - 1); + + /* Notice rounding to zero. */ + if (glue(_FP_FRAC_ZEROP_, WC)(A)) { + A_c =3D FP_CLS_ZERO; + break; + } + + /* Renormalize the fraction. This takes care of both overflow + and fixing up the fraction after the rshift. */ + glue(_FP_FRAC_CLZ_, WC)(lshift, A); + lshift -=3D glue(_FP_WFRACXBITS_, FS); + assert(lshift >=3D 0); + glue(_FP_FRAC_SLL_, WC)(A, lshift); + + A_e +=3D rshift - lshift; + break; + + default: + _FP_UNREACHABLE; + } + + glue(FP_PACK_, FS)(a, A); + FP_HANDLE_EXCEPTIONS; + + return a; +} diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 47b9dd9bd3..3d5201b268 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1310,87 +1310,6 @@ floatx80 float32_to_floatx80(float32 a, float_status= *status) =20 } =20 -/*------------------------------------------------------------------------= ---- -| Rounds the single-precision floating-point value `a' to an integer, and -| returns the result as a single-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*-------------------------------------------------------------------------= ---*/ - -float32 float32_round_to_int(float32 a, float_status *status) -{ - flag aSign; - int aExp; - uint32_t lastBitMask, roundBitsMask; - uint32_t z; - a =3D float32_squash_input_denormal(a, status); - - aExp =3D extractFloat32Exp( a ); - if ( 0x96 <=3D aExp ) { - if ( ( aExp =3D=3D 0xFF ) && extractFloat32Frac( a ) ) { - return propagateFloat32NaN(a, a, status); - } - return a; - } - if ( aExp <=3D 0x7E ) { - if ( (uint32_t) ( float32_val(a)<<1 ) =3D=3D 0 ) return a; - status->float_exception_flags |=3D float_flag_inexact; - aSign =3D extractFloat32Sign( a ); - switch (status->float_rounding_mode) { - case float_round_nearest_even: - if ( ( aExp =3D=3D 0x7E ) && extractFloat32Frac( a ) ) { - return packFloat32( aSign, 0x7F, 0 ); - } - break; - case float_round_ties_away: - if (aExp =3D=3D 0x7E) { - return packFloat32(aSign, 0x7F, 0); - } - break; - case float_round_down: - return make_float32(aSign ? 0xBF800000 : 0); - case float_round_up: - return make_float32(aSign ? 0x80000000 : 0x3F800000); - } - return packFloat32( aSign, 0, 0 ); - } - lastBitMask =3D 1; - lastBitMask <<=3D 0x96 - aExp; - roundBitsMask =3D lastBitMask - 1; - z =3D float32_val(a); - switch (status->float_rounding_mode) { - case float_round_nearest_even: - z +=3D lastBitMask>>1; - if ((z & roundBitsMask) =3D=3D 0) { - z &=3D ~lastBitMask; - } - break; - case float_round_ties_away: - z +=3D lastBitMask >> 1; - break; - case float_round_to_zero: - break; - case float_round_up: - if (!extractFloat32Sign(make_float32(z))) { - z +=3D roundBitsMask; - } - break; - case float_round_down: - if (extractFloat32Sign(make_float32(z))) { - z +=3D roundBitsMask; - } - break; - default: - abort(); - } - z &=3D ~ roundBitsMask; - if (z !=3D float32_val(a)) { - status->float_exception_flags |=3D float_flag_inexact; - } - return make_float32(z); - -} - /*------------------------------------------------------------------------= ---- | Returns the remainder of the single-precision floating-point value `a' | with respect to the corresponding value `b'. The operation is performed @@ -1672,98 +1591,6 @@ floatx80 float64_to_floatx80(float64 a, float_status= *status) aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<= 11 ); =20 } -/*------------------------------------------------------------------------= ---- -| Rounds the double-precision floating-point value `a' to an integer, and -| returns the result as a double-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*-------------------------------------------------------------------------= ---*/ - -float64 float64_round_to_int(float64 a, float_status *status) -{ - flag aSign; - int aExp; - uint64_t lastBitMask, roundBitsMask; - uint64_t z; - a =3D float64_squash_input_denormal(a, status); - - aExp =3D extractFloat64Exp( a ); - if ( 0x433 <=3D aExp ) { - if ( ( aExp =3D=3D 0x7FF ) && extractFloat64Frac( a ) ) { - return propagateFloat64NaN(a, a, status); - } - return a; - } - if ( aExp < 0x3FF ) { - if ( (uint64_t) ( float64_val(a)<<1 ) =3D=3D 0 ) return a; - status->float_exception_flags |=3D float_flag_inexact; - aSign =3D extractFloat64Sign( a ); - switch (status->float_rounding_mode) { - case float_round_nearest_even: - if ( ( aExp =3D=3D 0x3FE ) && extractFloat64Frac( a ) ) { - return packFloat64( aSign, 0x3FF, 0 ); - } - break; - case float_round_ties_away: - if (aExp =3D=3D 0x3FE) { - return packFloat64(aSign, 0x3ff, 0); - } - break; - case float_round_down: - return make_float64(aSign ? LIT64( 0xBFF0000000000000 ) : 0); - case float_round_up: - return make_float64( - aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF000000000000= 0 )); - } - return packFloat64( aSign, 0, 0 ); - } - lastBitMask =3D 1; - lastBitMask <<=3D 0x433 - aExp; - roundBitsMask =3D lastBitMask - 1; - z =3D float64_val(a); - switch (status->float_rounding_mode) { - case float_round_nearest_even: - z +=3D lastBitMask >> 1; - if ((z & roundBitsMask) =3D=3D 0) { - z &=3D ~lastBitMask; - } - break; - case float_round_ties_away: - z +=3D lastBitMask >> 1; - break; - case float_round_to_zero: - break; - case float_round_up: - if (!extractFloat64Sign(make_float64(z))) { - z +=3D roundBitsMask; - } - break; - case float_round_down: - if (extractFloat64Sign(make_float64(z))) { - z +=3D roundBitsMask; - } - break; - default: - abort(); - } - z &=3D ~ roundBitsMask; - if (z !=3D float64_val(a)) { - status->float_exception_flags |=3D float_flag_inexact; - } - return make_float64(z); - -} - -float64 float64_trunc_to_int(float64 a, float_status *status) -{ - int oldmode; - float64 res; - oldmode =3D status->float_rounding_mode; - status->float_rounding_mode =3D float_round_to_zero; - res =3D float64_round_to_int(a, status); - status->float_rounding_mode =3D oldmode; - return res; -} =20 /*------------------------------------------------------------------------= ---- | Returns the remainder of the double-precision floating-point value `a' @@ -2821,144 +2648,6 @@ floatx80 float128_to_floatx80(float128 a, float_sta= tus *status) =20 } =20 -/*------------------------------------------------------------------------= ---- -| Rounds the quadruple-precision floating-point value `a' to an integer, a= nd -| returns the result as a quadruple-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*-------------------------------------------------------------------------= ---*/ - -float128 float128_round_to_int(float128 a, float_status *status) -{ - flag aSign; - int32_t aExp; - uint64_t lastBitMask, roundBitsMask; - float128 z; - - aExp =3D extractFloat128Exp( a ); - if ( 0x402F <=3D aExp ) { - if ( 0x406F <=3D aExp ) { - if ( ( aExp =3D=3D 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a = ) ) - ) { - return propagateFloat128NaN(a, a, status); - } - return a; - } - lastBitMask =3D 1; - lastBitMask =3D ( lastBitMask<<( 0x406E - aExp ) )<<1; - roundBitsMask =3D lastBitMask - 1; - z =3D a; - switch (status->float_rounding_mode) { - case float_round_nearest_even: - if ( lastBitMask ) { - add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low = ); - if ( ( z.low & roundBitsMask ) =3D=3D 0 ) z.low &=3D ~ las= tBitMask; - } - else { - if ( (int64_t) z.low < 0 ) { - ++z.high; - if ( (uint64_t) ( z.low<<1 ) =3D=3D 0 ) z.high &=3D ~1; - } - } - break; - case 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; - } - } - break; - case float_round_to_zero: - break; - case float_round_up: - if (!extractFloat128Sign(z)) { - add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low); - } - break; - case float_round_down: - if (extractFloat128Sign(z)) { - add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low); - } - break; - default: - abort(); - } - z.low &=3D ~ roundBitsMask; - } - else { - if ( aExp < 0x3FFF ) { - if ( ( ( (uint64_t) ( a.high<<1 ) ) | a.low ) =3D=3D 0 ) retur= n a; - status->float_exception_flags |=3D float_flag_inexact; - aSign =3D extractFloat128Sign( a ); - switch (status->float_rounding_mode) { - case float_round_nearest_even: - if ( ( aExp =3D=3D 0x3FFE ) - && ( extractFloat128Frac0( a ) - | extractFloat128Frac1( a ) ) - ) { - return packFloat128( aSign, 0x3FFF, 0, 0 ); - } - break; - case float_round_ties_away: - if (aExp =3D=3D 0x3FFE) { - return packFloat128(aSign, 0x3FFF, 0, 0); - } - break; - case float_round_down: - return - aSign ? packFloat128( 1, 0x3FFF, 0, 0 ) - : packFloat128( 0, 0, 0, 0 ); - case float_round_up: - return - aSign ? packFloat128( 1, 0, 0, 0 ) - : packFloat128( 0, 0x3FFF, 0, 0 ); - } - return packFloat128( aSign, 0, 0, 0 ); - } - lastBitMask =3D 1; - lastBitMask <<=3D 0x402F - aExp; - roundBitsMask =3D lastBitMask - 1; - z.low =3D 0; - z.high =3D a.high; - switch (status->float_rounding_mode) { - case float_round_nearest_even: - z.high +=3D lastBitMask>>1; - if ( ( ( z.high & roundBitsMask ) | a.low ) =3D=3D 0 ) { - z.high &=3D ~ lastBitMask; - } - break; - case float_round_ties_away: - z.high +=3D lastBitMask>>1; - break; - case float_round_to_zero: - break; - case float_round_up: - if (!extractFloat128Sign(z)) { - z.high |=3D ( a.low !=3D 0 ); - z.high +=3D roundBitsMask; - } - break; - case float_round_down: - if (extractFloat128Sign(z)) { - z.high |=3D (a.low !=3D 0); - z.high +=3D roundBitsMask; - } - break; - default: - abort(); - } - z.high &=3D ~ roundBitsMask; - } - if ( ( z.low !=3D a.low ) || ( z.high !=3D a.high ) ) { - status->float_exception_flags |=3D float_flag_inexact; - } - return z; - -} - /*------------------------------------------------------------------------= ---- | Returns the remainder of the quadruple-precision floating-point value `a' | with respect to the corresponding value `b'. The operation is performed --=20 2.14.3