From nobody Tue Feb 10 22:17:51 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 Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1512998005724175.60656383386652; Mon, 11 Dec 2017 05:13:25 -0800 (PST) Received: from localhost ([::1]:52867 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eONtb-0004j7-Q3 for importer@patchew.org; Mon, 11 Dec 2017 08:13:23 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55031) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eONn5-0005KN-Tm for qemu-devel@nongnu.org; Mon, 11 Dec 2017 08:06:42 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eONn3-0006Aa-Gb for qemu-devel@nongnu.org; Mon, 11 Dec 2017 08:06:39 -0500 Received: from mail-wr0-x243.google.com ([2a00:1450:400c:c0c::243]:34301) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eONn3-00069w-6d for qemu-devel@nongnu.org; Mon, 11 Dec 2017 08:06:37 -0500 Received: by mail-wr0-x243.google.com with SMTP id y21so17531994wrc.1 for ; Mon, 11 Dec 2017 05:06:37 -0800 (PST) Received: from zen.linaro.local ([81.128.185.34]) by smtp.gmail.com with ESMTPSA id 2sm16272649wre.17.2017.12.11.05.06.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Dec 2017 05:06:34 -0800 (PST) Received: from zen.linaroharston (localhost [127.0.0.1]) by zen.linaro.local (Postfix) with ESMTP id 936D93E0D26; Mon, 11 Dec 2017 12:57:06 +0000 (GMT) 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 :mime-version:content-transfer-encoding; bh=iLulQbh+zCpfdAk5sN6+a/SsAaDl1Wqx538JpGE1FBU=; b=HKR3gQvsuvoBTLWDmb0oirZW93NQBvq4N9+ClbUGgUpbj27WFTlMtkTLZUQ4tH7Vs5 vNtDTPtDwHIyhdmmQVPT+NA1Ta3Ll4lifeVkv0cISAghZy470bJ0CA6K1H/7F3UtHEvZ ju1WWUsfqNiCtk5s+7qBSh1jTLDe3CWrEJrfg= 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:mime-version:content-transfer-encoding; bh=iLulQbh+zCpfdAk5sN6+a/SsAaDl1Wqx538JpGE1FBU=; b=t9lcm0XEOMSRGMwHie7YZk1QgqUCF7WsTOWnYQbIanXE3S8kZg4vJ6XylKO/wiLNKB 74BdfaX0C36ufj/jYfg7ghEVjbkIZv1MA4p9UFZjTfeVyu+zkhOIVrMDXX99D+T/IRCn x6ch53z2StoCFyuP65qCK3qC+9dsDYAROGBeK5NxgXMEKaPoh+M1iJib0uT4t2LREND7 lLXQ46zDNmx5zoxuPJK6tebOBazD2K8z8FWAW7d2bek4BT9N13e5C44y5SIT3a3QbOBl nxapaEolQVPUwDaVRs95xkXLI9CetMNLZiJ5jbjmyI1n8bGLx0IDjD0PG4L4BzPqWuET fFRg== X-Gm-Message-State: AKGB3mJ7aTcEuArAWXjzJY9JISKIpewQoIaOXf4e8uAH0CFsufUOwWAw crrLYpRZ8eFj6snVLjxMLBXT+Q== X-Google-Smtp-Source: ACJfBov0t8RqpJFB9DSmKId3/5rJXlQYWYIoN5Z+C5HH/3T+mHYrNFLxa5LmOqZr4goiK1bu8fZO3Q== X-Received: by 10.223.176.113 with SMTP id g46mr333830wra.267.1512997595854; Mon, 11 Dec 2017 05:06:35 -0800 (PST) From: =?UTF-8?q?Alex=20Benn=C3=A9e?= To: richard.henderson@linaro.org, peter.maydell@linaro.org, laurent@vivier.eu, bharata@linux.vnet.ibm.com, andrew@andrewdutcher.com, aleksandar.markovic@imgtec.com Date: Mon, 11 Dec 2017 12:57:02 +0000 Message-Id: <20171211125705.16120-17-alex.bennee@linaro.org> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20171211125705.16120-1-alex.bennee@linaro.org> References: <20171211125705.16120-1-alex.bennee@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:400c:c0c::243 Subject: [Qemu-devel] [PATCH v1 16/19] fpu/softfloat: re-factor int/uint to float 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: =?UTF-8?q?Alex=20Benn=C3=A9e?= , qemu-devel@nongnu.org, Aurelien Jarno 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 These are considerably simpler as the lower order integers can just use the higher order conversion function. As the decomposed fractional part is a full 64 bit rounding and inexact handling comes from the pack functions. Signed-off-by: Alex Benn=C3=A9e Reviewed-by: Richard Henderson --- fpu/softfloat.c | 358 +++++++++++++++++++++++++-------------------= ---- include/fpu/softfloat.h | 30 ++-- 2 files changed, 195 insertions(+), 193 deletions(-) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index d7858bdae5..1a7f1cab10 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1409,17 +1409,18 @@ FLOAT_TO_INT(64, 64) =20 #undef FLOAT_TO_INT =20 -/*------------------------------------------------------------------------= ---- -| Returns the result of converting the floating-point value -| `a' to the unsigned integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| unsigned integer is returned. Otherwise, if the conversion overflows, t= he -| largest unsigned integer is returned. If the 'a' is negative, the result -| is rounded and zero is returned; values that do not round to zero will -| raise the inexact exception flag. -*-------------------------------------------------------------------------= ---*/ +/* + * Returns the result of converting the floating-point value `a' to + * the unsigned integer format. The conversion is performed according + * to the IEC/IEEE Standard for Binary Floating-Point + * Arithmetic---which means in particular that the conversion is + * rounded according to the current rounding mode. If `a' is a NaN, + * the largest unsigned integer is returned. Otherwise, if the + * conversion overflows, the largest unsigned integer is returned. If + * the 'a' is negative, the result is rounded and zero is returned; + * values that do not round to zero will raise the inexact exception + * flag. + */ =20 static uint64_t uint64_pack_decomposed(decomposed_parts p, float_status *s) { @@ -1433,6 +1434,7 @@ static uint64_t uint64_pack_decomposed(decomposed_par= ts p, float_status *s) return 0; case float_class_normal: if (p.sign) { + s->float_exception_flags |=3D float_flag_invalid; return 0; } if (p.exp < DECOMPOSED_BINARY_POINT) { @@ -1440,6 +1442,7 @@ static uint64_t uint64_pack_decomposed(decomposed_par= ts p, float_status *s) } else if (p.exp < 64) { return p.frac << (p.exp - DECOMPOSED_BINARY_POINT); } else { + s->float_exception_flags |=3D float_flag_invalid; return UINT64_MAX; } default: @@ -1450,13 +1453,21 @@ static uint64_t uint64_pack_decomposed(decomposed_p= arts p, float_status *s) static uint16_t uint16_pack_decomposed(decomposed_parts p, float_status *s) { uint64_t r =3D uint64_pack_decomposed(p, s); - return r > UINT16_MAX ? UINT16_MAX : r; + if (r > UINT16_MAX) { + s->float_exception_flags |=3D float_flag_invalid; + r =3D UINT16_MAX; + } + return r; } =20 static uint32_t uint32_pack_decomposed(decomposed_parts p, float_status *s) { uint64_t r =3D uint64_pack_decomposed(p, s); - return r > UINT32_MAX ? UINT32_MAX : r; + if (r > UINT32_MAX) { + s->float_exception_flags |=3D float_flag_invalid; + r =3D UINT32_MAX; + } + return r; } =20 #define FLOAT_TO_UINT(fsz, isz) \ @@ -1489,6 +1500,168 @@ FLOAT_TO_UINT(64, 64) =20 #undef FLOAT_TO_UINT =20 +/* + * Integer to float conversions + * + * Returns the result of converting the two's complement integer `a' + * to the floating-point format. The conversion is performed according + * to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. + */ + +static decomposed_parts int_to_float(int64_t a, float_status *status) +{ + decomposed_parts r; + if (a =3D=3D 0) { + r.cls =3D float_class_zero; + } else if (a =3D=3D (1ULL << 63)) { + r.cls =3D float_class_normal; + r.sign =3D true; + r.frac =3D DECOMPOSED_IMPLICIT_BIT; + r.exp =3D 63; + } else { + uint64_t f; + if (a < 0) { + f =3D -a; + r.sign =3D true; + } else { + f =3D a; + r.sign =3D false; + } + int shift =3D clz64(f) - 1; + r.cls =3D float_class_normal; + r.exp =3D (DECOMPOSED_BINARY_POINT - shift); + r.frac =3D f << shift; + } + + return r; +} + +float16 int64_to_float16(int64_t a, float_status *status) +{ + decomposed_parts pa =3D int_to_float(a, status); + return float16_round_pack_canonical(pa, status); +} + +float16 int32_to_float16(int32_t a, float_status *status) +{ + return int64_to_float16((int64_t) a, status); +} + +float16 int16_to_float16(int16_t a, float_status *status) +{ + return int64_to_float16((int64_t) a, status); +} + +float32 int64_to_float32(int64_t a, float_status *status) +{ + decomposed_parts pa =3D int_to_float(a, status); + return float32_round_pack_canonical(pa, status); +} + +float32 int32_to_float32(int32_t a, float_status *status) +{ + return int64_to_float32((int64_t) a, status); +} + +float32 int16_to_float32(int16_t a, float_status *status) +{ + return int64_to_float32((int64_t) a, status); +} + +float64 int64_to_float64(int64_t a, float_status *status) +{ + decomposed_parts pa =3D int_to_float(a, status); + return float64_round_pack_canonical(pa, status); +} + +float64 int32_to_float64(int32_t a, float_status *status) +{ + return int64_to_float64((int64_t) a, status); +} + +float64 int16_to_float64(int16_t a, float_status *status) +{ + return int64_to_float64((int64_t) a, status); +} + + +/* + * Unsigned Integer to float conversions + * + * Returns the result of converting the unsigned integer `a' to the + * floating-point format. The conversion is performed according to the + * IEC/IEEE Standard for Binary Floating-Point Arithmetic. + */ + +static decomposed_parts uint_to_float(uint64_t a, float_status *status) +{ + decomposed_parts r; + if (a =3D=3D 0) { + r.cls =3D float_class_zero; + } else { + int spare_bits =3D clz64(a) - 1; + r.sign =3D false; + r.cls =3D float_class_normal; + r.exp =3D DECOMPOSED_BINARY_POINT - spare_bits; + if (spare_bits < 0) { + shift64RightJamming(a, -spare_bits, &a); + r.frac =3D a; + } else { + r.frac =3D a << spare_bits; + } + } + + return r; +} + +float16 uint64_to_float16(uint64_t a, float_status *status) +{ + decomposed_parts pa =3D uint_to_float(a, status); + return float16_round_pack_canonical(pa, status); +} + +float16 uint32_to_float16(uint32_t a, float_status *status) +{ + return uint64_to_float16((uint64_t) a, status); +} + +float16 uint16_to_float16(uint16_t a, float_status *status) +{ + return uint64_to_float16((uint64_t) a, status); +} + +float32 uint64_to_float32(uint64_t a, float_status *status) +{ + decomposed_parts pa =3D uint_to_float(a, status); + return float32_round_pack_canonical(pa, status); +} + +float32 uint32_to_float32(uint32_t a, float_status *status) +{ + return uint64_to_float32((uint64_t) a, status); +} + +float32 uint16_to_float32(uint16_t a, float_status *status) +{ + return uint64_to_float32((uint64_t) a, status); +} + +float64 uint64_to_float64(uint64_t a, float_status *status) +{ + decomposed_parts pa =3D uint_to_float(a, status); + return float64_round_pack_canonical(pa, status); +} + +float64 uint32_to_float64(uint32_t a, float_status *status) +{ + return uint64_to_float64((uint64_t) a, status); +} + +float64 uint16_to_float64(uint16_t a, float_status *status) +{ + return uint64_to_float64((uint64_t) a, status); +} + /*------------------------------------------------------------------------= ---- | Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 | and 7, and returns the properly rounded 32-bit integer corresponding to = the @@ -2580,43 +2753,6 @@ static float128 normalizeRoundAndPackFloat128(flag z= Sign, int32_t zExp, =20 } =20 -/*------------------------------------------------------------------------= ---- -| Returns the result of converting the 32-bit two's complement integer `a' -| to the single-precision floating-point format. The conversion is perfor= med -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*-------------------------------------------------------------------------= ---*/ - -float32 int32_to_float32(int32_t a, float_status *status) -{ - flag zSign; - - if ( a =3D=3D 0 ) return float32_zero; - if ( a =3D=3D (int32_t) 0x80000000 ) return packFloat32( 1, 0x9E, 0 ); - zSign =3D ( a < 0 ); - return normalizeRoundAndPackFloat32(zSign, 0x9C, zSign ? -a : a, statu= s); -} - -/*------------------------------------------------------------------------= ---- -| Returns the result of converting the 32-bit two's complement integer `a' -| to the double-precision floating-point format. The conversion is perfor= med -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*-------------------------------------------------------------------------= ---*/ - -float64 int32_to_float64(int32_t a, float_status *status) -{ - flag zSign; - uint32_t absA; - int8_t shiftCount; - uint64_t zSig; - - if ( a =3D=3D 0 ) return float64_zero; - zSign =3D ( a < 0 ); - absA =3D zSign ? - a : a; - shiftCount =3D countLeadingZeros32( absA ) + 21; - zSig =3D absA; - return packFloat64( zSign, 0x432 - shiftCount, zSig<=3D 0) { - return packFloat32(0, 0x95 - shiftcount, a << shiftcount); - } - /* Otherwise we need to do a round-and-pack. roundAndPackFloat32() - * expects the binary point between bits 30 and 29, hence the + 7. - */ - shiftcount +=3D 7; - if (shiftcount < 0) { - shift64RightJamming(a, -shiftcount, &a); - } else { - a <<=3D shiftcount; - } - - return roundAndPackFloat32(0, 0x9c - shiftcount, a, status); -} - -/*------------------------------------------------------------------------= ---- -| Returns the result of converting the 64-bit unsigned integer `a' -| to the double-precision floating-point format. The conversion is perfor= med -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*-------------------------------------------------------------------------= ---*/ - -float64 uint64_to_float64(uint64_t a, float_status *status) -{ - int exp =3D 0x43C; - int shiftcount; - - if (a =3D=3D 0) { - return float64_zero; - } - - shiftcount =3D countLeadingZeros64(a) - 1; - if (shiftcount < 0) { - shift64RightJamming(a, -shiftcount, &a); - } else { - a <<=3D shiftcount; - } - return roundAndPackFloat64(0, exp - shiftcount, a, status); -} - /*------------------------------------------------------------------------= ---- | Returns the result of converting the 64-bit unsigned integer `a' | to the quadruple-precision floating-point format. The conversion is per= formed @@ -6705,19 +6732,6 @@ int float128_unordered_quiet(float128 a, float128 b,= float_status *status) return 0; } =20 -/* misc functions */ -float32 uint32_to_float32(uint32_t a, float_status *status) -{ - return int64_to_float32(a, status); -} - -float64 uint32_to_float64(uint32_t a, float_status *status) -{ - return int64_to_float64(a, status); -} - - - #define COMPARE(s, nan_exp) = \ static inline int float ## s ## _compare_internal(float ## s a, float ## s= b,\ int is_quiet, float_status *status) = \ diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 860f480af8..8ebde83251 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -299,9 +299,13 @@ enum { /*------------------------------------------------------------------------= ---- | Software IEC/IEEE integer-to-floating-point conversion routines. *-------------------------------------------------------------------------= ---*/ +float32 int16_to_float32(int16_t, float_status *status); float32 int32_to_float32(int32_t, float_status *status); +float64 int16_to_float64(int16_t, float_status *status); float64 int32_to_float64(int32_t, float_status *status); +float32 uint16_to_float32(uint16_t, float_status *status); float32 uint32_to_float32(uint32_t, float_status *status); +float64 uint16_to_float64(uint16_t, float_status *status); float64 uint32_to_float64(uint32_t, float_status *status); floatx80 int32_to_floatx80(int32_t, float_status *status); float128 int32_to_float128(int32_t, float_status *status); @@ -313,27 +317,6 @@ float32 uint64_to_float32(uint64_t, float_status *stat= us); float64 uint64_to_float64(uint64_t, float_status *status); float128 uint64_to_float128(uint64_t, float_status *status); =20 -/* We provide the int16 versions for symmetry of API with float-to-int */ -static inline float32 int16_to_float32(int16_t v, float_status *status) -{ - return int32_to_float32(v, status); -} - -static inline float32 uint16_to_float32(uint16_t v, float_status *status) -{ - return uint32_to_float32(v, status); -} - -static inline float64 int16_to_float64(int16_t v, float_status *status) -{ - return int32_to_float64(v, status); -} - -static inline float64 uint16_to_float64(uint16_t v, float_status *status) -{ - return uint32_to_float64(v, status); -} - /*------------------------------------------------------------------------= ---- | Software half-precision conversion routines. *-------------------------------------------------------------------------= ---*/ @@ -354,6 +337,11 @@ uint64_t float16_to_uint64(float16 a, float_status *st= atus); int64_t float16_to_int64_round_to_zero(float16, float_status *status); uint64_t float16_to_uint64_round_to_zero(float16 a, float_status *status); float16 int16_to_float16(int16_t a, float_status *status); +float16 int32_to_float16(int32_t a, float_status *status); +float16 int64_to_float16(int64_t a, float_status *status); +float16 uint16_to_float16(uint16_t a, float_status *status); +float16 uint32_to_float16(uint32_t a, float_status *status); +float16 uint64_to_float16(uint64_t a, float_status *status); =20 /*------------------------------------------------------------------------= ---- | Software half-precision operations. --=20 2.15.1