From patchwork Mon Dec 11 12:57:04 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: 121408 Delivered-To: patch@linaro.org Received: by 10.140.22.227 with SMTP id 90csp2769809qgn; Mon, 11 Dec 2017 05:09:25 -0800 (PST) X-Google-Smtp-Source: ACJfBos5VrobQldJwcT/Q3Amp7JxXk3Uu8BvVdCai2Oout7MZVrwyodCUmurt9XV36staBGSSnpy X-Received: by 10.37.185.142 with SMTP id r14mr205388ybg.431.1512997765897; Mon, 11 Dec 2017 05:09:25 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1512997765; cv=none; d=google.com; s=arc-20160816; b=LGTzUyDpNgezN29KtmCA+GOPrgWNBLUjDKrTLdim/VN47zpviys68suggn3LEyOSe+ jLG2IO7FcbmONZOmw6BZISYaHzvrtVPwXY+QaJjFK0dUDeWVzsUVk+b2iiANhr+DefvN e9OyFvOTj+3WEulwEAIO2ePbwNktbJSsTpTEcVSXhHPfgAzmf9spS7TDmOyd2/zMg6Wj 1lV7+pwo1Jk+YyOXqTYfKpKrrMmkam4UAXboxEkhMLDLX8vBjLlrj04rRez7/EJgmpMT cC/YCp/rx78H2tE3UCNzIEE7oivsV5oznmXok2Jnwi6c8obBaVUxzCu9J4KrfK5O2HkW yMYQ== 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=+uZGALX/x/xsxWW578zb4ZzlC+JEia9ZYfI/M+V+akI=; b=hHBwQPaxn3CNZJrsDwvptlKRsBtjJMBNht7XgWAeR+/xNfl4Y6+yhITr7qM9xd53Qo sKT79/pm4SuymsCpb5OBdC6RS3QDixTwE5OqgmQc6vUsRPBMORXGI0llQ5oS7DGIXUbY P+1fyCV7PjaZHW0lmIfGPgipIYiFKEc0UPYioDSW45q/g7BY0Z/bFojo/aPNfwmHw+Wz KP39q2Br17f2dHLuicYFW86fkAWDEQq4VoeS5Bjfhmc9Sv5Q5e7AN4H8UYrBSejt746k jndwRDvB6AvToj6kDt6Vlp9UNqjUAPt30mqtSh6pwqKYfl4/4IMKqjJyIEZ+EaVhWyH7 d9Ww== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=QA1fknCB; 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 z127si2910617ybz.616.2017.12.11.05.09.25 for (version=TLS1 cipher=AES128-SHA bits=128/128); Mon, 11 Dec 2017 05:09:25 -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=QA1fknCB; 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]:52700 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eONpl-0007xw-8q for patch@linaro.org; Mon, 11 Dec 2017 08:09:25 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55033) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eONn5-0005KQ-UC for qemu-devel@nongnu.org; Mon, 11 Dec 2017 08:06:41 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eONn4-0006BT-7K for qemu-devel@nongnu.org; Mon, 11 Dec 2017 08:06:39 -0500 Received: from mail-wr0-x242.google.com ([2a00:1450:400c:c0c::242]:41797) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eONn3-0006AI-Th for qemu-devel@nongnu.org; Mon, 11 Dec 2017 08:06:38 -0500 Received: by mail-wr0-x242.google.com with SMTP id z18so17510781wrb.8 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=+uZGALX/x/xsxWW578zb4ZzlC+JEia9ZYfI/M+V+akI=; b=QA1fknCB8Ue7/AnD+F4fJwAnriXvAeiLVicbGttG6Gl1Cnge2EbnpxkHFdWzyn7OOJ joiypVD6GaleslVjblhHk/aJiO9BZht87RtA3SV9jbl+sFgO5reuep6Ast/cS5wJe5df 3Op1qUCOY0BIFqlAKepeGoPMcGo4v+Sc84ato= 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=+uZGALX/x/xsxWW578zb4ZzlC+JEia9ZYfI/M+V+akI=; b=nny4uU8Rz+qP/k2RtB6pAh0izP4k3OvKUGWXGSGQD6qEDvxlyyupHjM7tk0RFUe4CR 7r4lS2l7iRUIXYC+c15zufpy0WoBK1D072eclDgOAaUsIh8Wz0Vohp/L85+79BSFA5q6 2YtEZejINwM+ZNUEYJARD12Sqt9AmG3n/spchgCZCdcgFfdRw+9vJSQHxeZwkQZOmbHU q6lHaH0/NIpaVnQFHngmnDDtcFDrbvQ+HgweunhB3gNPCsIVue2LnMPyuFDrV+blut6f 2PshTLeF/L7LlDmb9kAHrsIEkvqZ4QgCW/IfQQ/+AEt89/v1y5aF4o3O1OULlATFu+Vz wpVg== X-Gm-Message-State: AKGB3mL79WIFTkA5tc0y4KkRgwbk/NaG+cUB/2DfHDQiGEDqXRCgASmy fc7n/fhb6gqzbLkheeTK7Nhikw== X-Received: by 10.223.134.116 with SMTP id 49mr356356wrw.85.1512997596657; Mon, 11 Dec 2017 05:06:36 -0800 (PST) Received: from zen.linaro.local ([81.128.185.34]) by smtp.gmail.com with ESMTPSA id r14sm15447434wra.71.2017.12.11.05.06.34 (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 B78AC3E1059; 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:04 +0000 Message-Id: <20171211125705.16120-19-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::242 Subject: [Qemu-devel] [PATCH v1 18/19] fpu/softfloat: re-factor minmax 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" Let's do the same re-factor treatment for minmax functions. I still use the MACRO trick to expand but now all the checking code is common. Signed-off-by: Alex Bennée --- fpu/softfloat.c | 242 ++++++++++++++++++++++++++---------------------- include/fpu/softfloat.h | 6 ++ 2 files changed, 137 insertions(+), 111 deletions(-) -- 2.15.1 diff --git a/fpu/softfloat.c b/fpu/softfloat.c index b7ea56dfa5..5eba996932 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1662,6 +1662,137 @@ float64 uint16_to_float64(uint16_t a, float_status *status) return uint64_to_float64((uint64_t) a, status); } +/* Float Min/Max */ +/* min() and max() functions. These can't be implemented as + * 'compare and pick one input' because that would mishandle + * NaNs and +0 vs -0. + * + * minnum() and maxnum() functions. These are similar to the min() + * and max() functions but if one of the arguments is a QNaN and + * the other is numerical then the numerical argument is returned. + * SNaNs will get quietened before being returned. + * minnum() and maxnum correspond to the IEEE 754-2008 minNum() + * and maxNum() operations. min() and max() are the typical min/max + * semantics provided by many CPUs which predate that specification. + * + * minnummag() and maxnummag() functions correspond to minNumMag() + * and minNumMag() from the IEEE-754 2008. + */ +static decomposed_parts minmax_decomposed(decomposed_parts a, + decomposed_parts b, + bool ismin, bool ieee, bool ismag, + float_status *s) +{ + if (a.cls >= float_class_qnan + || + b.cls >= float_class_qnan) + { + if (ieee) { + /* Takes two floating-point values `a' and `b', one of + * which is a NaN, and returns the appropriate NaN + * result. If either `a' or `b' is a signaling NaN, + * the invalid exception is raised. + */ + if (a.cls == float_class_snan || b.cls == float_class_snan) { + s->float_exception_flags |= float_flag_invalid; + if (s->default_nan_mode) { + a.cls = float_class_msnan; + return a; + } + } else if (a.cls >= float_class_qnan + && + b.cls < float_class_qnan) { + return b; + } else if (b.cls >= float_class_qnan + && + a.cls < float_class_qnan) { + return a; + } + } + return pick_nan_parts(a, b, s); + } + + /* Handle zero cases */ + if (a.cls == float_class_zero || b.cls == float_class_zero) { + if (a.cls == float_class_normal) { + if (a.sign) { + return ismin ? a : b; + } else { + return ismin ? b : a; + } + } else if (b.cls == float_class_normal) { + if (b.sign) { + return ismin ? b : a; + } else { + return ismin ? a : b; + } + } + } + + if (ismag) { + /* Magnitude, ignore sign */ + bool a_less; + if (a.exp == b.exp) { + a_less = a.frac < b.frac; + } else { + a_less = a.exp < b.exp; + } + return a_less == ismin ? a : b; + } + if (a.sign != b.sign) { + if (ismin) { + return a.sign ? a : b; + } else { + return a.sign ? b : a; + } + } else { + bool a_less; + if (a.exp == b.exp) { + a_less = a.frac < b.frac; + } else { + a_less = a.exp < b.exp; + } + if (ismin) { + return a.sign ^ a_less ? a : b; + } else { + return a.sign ^ a_less ? b : a; + } + } +} + +#define MINMAX(sz, name, ismin, isiee, ismag) \ +float ## sz float ## sz ## _ ## name(float ## sz a, float ## sz b, float_status *s) \ +{ \ + decomposed_parts pa = float ## sz ## _unpack_canonical(a, s); \ + decomposed_parts pb = float ## sz ## _unpack_canonical(b, s); \ + decomposed_parts pr = minmax_decomposed(pa, pb, ismin, isiee, ismag, s); \ + \ + return float ## sz ## _round_pack_canonical(pr, s); \ +} + +MINMAX(16, min, true, false, false) +MINMAX(16, minnum, true, true, false) +MINMAX(16, minnummag, true, true, true) +MINMAX(16, max, false, false, false) +MINMAX(16, maxnum, false, true, false) +MINMAX(16, maxnummag, false, true, true) + +MINMAX(32, min, true, false, false) +MINMAX(32, minnum, true, true, false) +MINMAX(32, minnummag, true, true, true) +MINMAX(32, max, false, false, false) +MINMAX(32, maxnum, false, true, false) +MINMAX(32, maxnummag, false, true, true) + +MINMAX(64, min, true, false, false) +MINMAX(64, minnum, true, true, false) +MINMAX(64, minnummag, true, true, true) +MINMAX(64, max, false, false, false) +MINMAX(64, maxnum, false, true, false) +MINMAX(64, maxnummag, false, true, true) + +#undef MINMAX + /* Multiply A by 2 raised to the power N. */ static decomposed_parts scalbn_decomposed(decomposed_parts a, int n, float_status *s) @@ -6911,117 +7042,6 @@ int float128_compare_quiet(float128 a, float128 b, float_status *status) return float128_compare_internal(a, b, 1, status); } -/* min() and max() functions. These can't be implemented as - * 'compare and pick one input' because that would mishandle - * NaNs and +0 vs -0. - * - * minnum() and maxnum() functions. These are similar to the min() - * and max() functions but if one of the arguments is a QNaN and - * the other is numerical then the numerical argument is returned. - * SNaNs will get quietened before being returned. - * minnum() and maxnum correspond to the IEEE 754-2008 minNum() - * and maxNum() operations. min() and max() are the typical min/max - * semantics provided by many CPUs which predate that specification. - * - * minnummag() and maxnummag() functions correspond to minNumMag() - * and minNumMag() from the IEEE-754 2008. - */ -#define MINMAX(s) \ -static inline float ## s float ## s ## _minmax(float ## s a, float ## s b, \ - int ismin, int isieee, \ - int ismag, \ - float_status *status) \ -{ \ - flag aSign, bSign; \ - uint ## s ## _t av, bv, aav, abv; \ - a = float ## s ## _squash_input_denormal(a, status); \ - b = float ## s ## _squash_input_denormal(b, status); \ - if (float ## s ## _is_any_nan(a) || \ - float ## s ## _is_any_nan(b)) { \ - if (isieee) { \ - if (float ## s ## _is_signaling_nan(a, status) || \ - float ## s ## _is_signaling_nan(b, status)) { \ - return propagateFloat ## s ## NaN(a, b, status); \ - } else if (float ## s ## _is_quiet_nan(a, status) && \ - !float ## s ##_is_any_nan(b)) { \ - return b; \ - } else if (float ## s ## _is_quiet_nan(b, status) && \ - !float ## s ## _is_any_nan(a)) { \ - return a; \ - } \ - } \ - return propagateFloat ## s ## NaN(a, b, status); \ - } \ - aSign = extractFloat ## s ## Sign(a); \ - bSign = extractFloat ## s ## Sign(b); \ - av = float ## s ## _val(a); \ - bv = float ## s ## _val(b); \ - if (ismag) { \ - aav = float ## s ## _abs(av); \ - abv = float ## s ## _abs(bv); \ - if (aav != abv) { \ - if (ismin) { \ - return (aav < abv) ? a : b; \ - } else { \ - return (aav < abv) ? b : a; \ - } \ - } \ - } \ - if (aSign != bSign) { \ - if (ismin) { \ - return aSign ? a : b; \ - } else { \ - return aSign ? b : a; \ - } \ - } else { \ - if (ismin) { \ - return (aSign ^ (av < bv)) ? a : b; \ - } else { \ - return (aSign ^ (av < bv)) ? b : a; \ - } \ - } \ -} \ - \ -float ## s float ## s ## _min(float ## s a, float ## s b, \ - float_status *status) \ -{ \ - return float ## s ## _minmax(a, b, 1, 0, 0, status); \ -} \ - \ -float ## s float ## s ## _max(float ## s a, float ## s b, \ - float_status *status) \ -{ \ - return float ## s ## _minmax(a, b, 0, 0, 0, status); \ -} \ - \ -float ## s float ## s ## _minnum(float ## s a, float ## s b, \ - float_status *status) \ -{ \ - return float ## s ## _minmax(a, b, 1, 1, 0, status); \ -} \ - \ -float ## s float ## s ## _maxnum(float ## s a, float ## s b, \ - float_status *status) \ -{ \ - return float ## s ## _minmax(a, b, 0, 1, 0, status); \ -} \ - \ -float ## s float ## s ## _minnummag(float ## s a, float ## s b, \ - float_status *status) \ -{ \ - return float ## s ## _minmax(a, b, 1, 1, 1, status); \ -} \ - \ -float ## s float ## s ## _maxnummag(float ## s a, float ## s b, \ - float_status *status) \ -{ \ - return float ## s ## _minmax(a, b, 0, 1, 1, status); \ -} - -MINMAX(32) -MINMAX(64) - - floatx80 floatx80_scalbn(floatx80 a, int n, float_status *status) { flag aSign; diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index c1224aab8c..ba248ffa39 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -354,6 +354,12 @@ float16 float16_mul(float16, float16, float_status *status); float16 float16_muladd(float16, float16, float16, int, float_status *status); float16 float16_div(float16, float16, float_status *status); float16 float16_scalbn(float16, int, float_status *status); +float16 float16_min(float16, float16, float_status *status); +float16 float16_max(float16, float16, float_status *status); +float16 float16_minnum(float16, float16, float_status *status); +float16 float16_maxnum(float16, float16, float_status *status); +float16 float16_minnummag(float16, float16, float_status *status); +float16 float16_maxnummag(float16, float16, float_status *status); int float16_is_quiet_nan(float16, float_status *status); int float16_is_signaling_nan(float16, float_status *status);