From patchwork Mon Dec 11 12:57:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Alex_Benn=C3=A9e?= X-Patchwork-Id: 121412 Delivered-To: patch@linaro.org Received: by 10.140.22.227 with SMTP id 90csp2773059qgn; Mon, 11 Dec 2017 05:12:14 -0800 (PST) X-Google-Smtp-Source: ACJfBou6yd+fga9/SmxV3liQ+TkUnnq1BLw5W+2QEuEJuNo2XHPlC4fuAI4F/vthDdpgHqejztv/ X-Received: by 10.13.226.209 with SMTP id l200mr242083ywe.103.1512997934090; Mon, 11 Dec 2017 05:12:14 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1512997934; cv=none; d=google.com; s=arc-20160816; b=JIDV7DPGO6c9sjqF3hZpXIbPaLc46+qLPIyxrLdWNHGVCxwIePTJW+om7V4m+6i7w/ sqEyYF3sm9QBkUfVD46ISx44r+Ybc+Pe/3hRpngiAmilCC7UHM9/OOvbuK1s+RgY7SJ+ cgJJVqBg59SHacJX4jy9ZwT//KC4LWY0gTXOij5GnRubW6SoAN84Nw9zj278WId9iqNg vq3n4zMZQiukAbZGJ1cepHNYKXOiAh5AuySl2YcyP/KUibo0LGoRL2nSL/kRMhD5ho2j oPJCwnek7s1HWOT+BjkhmSoK6uomDiSkYxifz8sxIV08zuYBQx70hc01DXT58QtvdJH3 57Pw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:arc-authentication-results; bh=iLulQbh+zCpfdAk5sN6+a/SsAaDl1Wqx538JpGE1FBU=; b=ItyUHbQZlrxsslP9IFALUWg/dTwNP4z9JJEOcBszFxgNqkrXqVDrr8xa82L3BZIcyy 8yY/1nn7HT4ZFuJ7BsIw4U+z+tECNEciv61RVeJ7Db7EzsNektkZatYVUf6wCC1JhMzM pmHhJcrZknj8tMTl/jruZqqMJGh7W5BzKV7c1r/blF9+P9Tp3tZsaa4Itz/PlFMuoUAX 1skS7+rr+QG/k1sMfi0BzEZcYdSytpAPm5cvAnyPkOEdjrSZUNcN7cVTxI91x5BkmWfd CQ6qbyYOX/lFvLz7eurK17MogZLAJLwpoTmwrFRqmc/SVV6KXbsvYFelgb7ELmXjbkP/ omqw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=HKR3gQvs; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id d65si3007837ybf.218.2017.12.11.05.12.13 for (version=TLS1 cipher=AES128-SHA bits=128/128); Mon, 11 Dec 2017 05:12:14 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=HKR3gQvs; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:52805 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eONsT-0002Y1-Gv for patch@linaro.org; Mon, 11 Dec 2017 08:12:13 -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) 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-Received: by 10.223.176.113 with SMTP id g46mr333830wra.267.1512997595854; Mon, 11 Dec 2017 05:06:35 -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) From: =?utf-8?q?Alex_Benn=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 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_Benn=C3=A9e?= , qemu-devel@nongnu.org, Aurelien Jarno Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" 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ée --- fpu/softfloat.c | 358 +++++++++++++++++++++++++----------------------- include/fpu/softfloat.h | 30 ++-- 2 files changed, 195 insertions(+), 193 deletions(-) -- 2.15.1 Reviewed-by: Richard Henderson 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) #undef FLOAT_TO_INT -/*---------------------------------------------------------------------------- -| 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. -*----------------------------------------------------------------------------*/ +/* + * 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. + */ static uint64_t uint64_pack_decomposed(decomposed_parts p, float_status *s) { @@ -1433,6 +1434,7 @@ static uint64_t uint64_pack_decomposed(decomposed_parts p, float_status *s) return 0; case float_class_normal: if (p.sign) { + s->float_exception_flags |= float_flag_invalid; return 0; } if (p.exp < DECOMPOSED_BINARY_POINT) { @@ -1440,6 +1442,7 @@ static uint64_t uint64_pack_decomposed(decomposed_parts p, float_status *s) } else if (p.exp < 64) { return p.frac << (p.exp - DECOMPOSED_BINARY_POINT); } else { + s->float_exception_flags |= float_flag_invalid; return UINT64_MAX; } default: @@ -1450,13 +1453,21 @@ static uint64_t uint64_pack_decomposed(decomposed_parts p, float_status *s) static uint16_t uint16_pack_decomposed(decomposed_parts p, float_status *s) { uint64_t r = uint64_pack_decomposed(p, s); - return r > UINT16_MAX ? UINT16_MAX : r; + if (r > UINT16_MAX) { + s->float_exception_flags |= float_flag_invalid; + r = UINT16_MAX; + } + return r; } static uint32_t uint32_pack_decomposed(decomposed_parts p, float_status *s) { uint64_t r = uint64_pack_decomposed(p, s); - return r > UINT32_MAX ? UINT32_MAX : r; + if (r > UINT32_MAX) { + s->float_exception_flags |= float_flag_invalid; + r = UINT32_MAX; + } + return r; } #define FLOAT_TO_UINT(fsz, isz) \ @@ -1489,6 +1500,168 @@ FLOAT_TO_UINT(64, 64) #undef FLOAT_TO_UINT +/* + * 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 == 0) { + r.cls = float_class_zero; + } else if (a == (1ULL << 63)) { + r.cls = float_class_normal; + r.sign = true; + r.frac = DECOMPOSED_IMPLICIT_BIT; + r.exp = 63; + } else { + uint64_t f; + if (a < 0) { + f = -a; + r.sign = true; + } else { + f = a; + r.sign = false; + } + int shift = clz64(f) - 1; + r.cls = float_class_normal; + r.exp = (DECOMPOSED_BINARY_POINT - shift); + r.frac = f << shift; + } + + return r; +} + +float16 int64_to_float16(int64_t a, float_status *status) +{ + decomposed_parts pa = 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 = 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 = 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 == 0) { + r.cls = float_class_zero; + } else { + int spare_bits = clz64(a) - 1; + r.sign = false; + r.cls = float_class_normal; + r.exp = DECOMPOSED_BINARY_POINT - spare_bits; + if (spare_bits < 0) { + shift64RightJamming(a, -spare_bits, &a); + r.frac = a; + } else { + r.frac = a << spare_bits; + } + } + + return r; +} + +float16 uint64_to_float16(uint64_t a, float_status *status) +{ + decomposed_parts pa = 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 = 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 = 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 zSign, int32_t zExp, } -/*---------------------------------------------------------------------------- -| Returns the result of converting the 32-bit two's complement integer `a' -| to the single-precision floating-point format. The conversion is performed -| 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 == 0 ) return float32_zero; - if ( a == (int32_t) 0x80000000 ) return packFloat32( 1, 0x9E, 0 ); - zSign = ( a < 0 ); - return normalizeRoundAndPackFloat32(zSign, 0x9C, zSign ? -a : a, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 32-bit two's complement integer `a' -| to the double-precision floating-point format. The conversion is performed -| 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 == 0 ) return float64_zero; - zSign = ( a < 0 ); - absA = zSign ? - a : a; - shiftCount = countLeadingZeros32( absA ) + 21; - zSig = absA; - return packFloat64( zSign, 0x432 - shiftCount, zSig<= 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 += 7; - if (shiftcount < 0) { - shift64RightJamming(a, -shiftcount, &a); - } else { - a <<= 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 performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 uint64_to_float64(uint64_t a, float_status *status) -{ - int exp = 0x43C; - int shiftcount; - - if (a == 0) { - return float64_zero; - } - - shiftcount = countLeadingZeros64(a) - 1; - if (shiftcount < 0) { - shift64RightJamming(a, -shiftcount, &a); - } else { - a <<= 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 performed @@ -6705,19 +6732,6 @@ int float128_unordered_quiet(float128 a, float128 b, float_status *status) return 0; } -/* 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 *status); float64 uint64_to_float64(uint64_t, float_status *status); float128 uint64_to_float128(uint64_t, float_status *status); -/* 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 *status); 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); /*---------------------------------------------------------------------------- | Software half-precision operations.