From nobody Sat Oct 25 21:46:07 2025 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; 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 1521663409619368.0415619782606; Wed, 21 Mar 2018 13:16:49 -0700 (PDT) Received: from localhost ([::1]:57142 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eykA8-0006WV-LI for importer@patchew.org; Wed, 21 Mar 2018 16:16:44 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42173) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk5W-0002A1-0M for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:12:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyk5Q-0000y8-R4 for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:57 -0400 Received: from out5-smtp.messagingengine.com ([66.111.4.29]:57315) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyk5Q-0000xG-K5 for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:52 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id D0FD720DB5; Wed, 21 Mar 2018 16:11:50 -0400 (EDT) Received: from frontend1 ([10.202.2.160]) by compute4.internal (MEProxy); Wed, 21 Mar 2018 16:11:50 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id 6242E7E16D; Wed, 21 Mar 2018 16:11:50 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=mesmtp; bh=9IL+AYyx+viZ1Z OzzoSiZkXUiMJrd3t5Je3ADr8ZVfE=; b=P/I7/q0/BlQZSeA/m/IjV07FCWC0BS pwht/MeXLXT1T0ZrfX6QCRphj8+cHeqkz/Q4fkJV6oWhUjfz/AF6G/jZlDL9dc8l pdwUri21hs9N1OwEZOqy3IWwaEG25ytZX1vXzqsir/YhxJZr2na+xqYT3/Tsj3WV ZGkCwtGhk1jW0= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=9IL+AYyx+viZ1ZOzzoSiZkXUiMJrd3t5Je3ADr8ZVfE=; b=LjrSdGnz AFLJ8ozs4VJsm9wQzgQ/0PeqdBcavxeEylNJ0ux/+EbEvL8KbrhX/dKU4eFgLMoH nJwsV58mINM870YcwERtnDXnjY14YzdcRX88SEq8M5EuJRdEIY/kyynyuvyvQEK9 34z/kHBNAfbAZ9M6ovvkOyXOGoZ+RDAkvBr2j4u8Jo0DoQl/zGi8y9YM0wqRHMz9 qCPse+u2UMPrx6KDSTXcB/G2/gdZcJz6usGX4faV5CeSIFHUqxUZnq1eMNA+qO54 2EP0lFIIiKhPkMT6Y+xo2jqcE3WEAaZkX3niJUBJH6KYSvqh6S7Gn0Gvz+liLRDv KNb6ow7HzVwz3A== X-ME-Sender: From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 21 Mar 2018 16:11:36 -0400 Message-Id: <1521663109-32262-2-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1521663109-32262-1-git-send-email-cota@braap.org> References: <1521663109-32262-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.29 Subject: [Qemu-devel] [PATCH v1 01/14] tests: add fp-bench, a collection of simple floating-point microbenchmarks 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 , Mark Cave-Ayland , Richard Henderson , Laurent Vivier , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Aurelien Jarno Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This will allow us to measure the performance impact of FP emulation optimizations. Signed-off-by: Emilio G. Cota Reviewed-by: Alex Benn=C3=A9e --- tests/fp-bench.c | 290 +++++++++++++++++++++++++++++++++++++++++++++= ++++ tests/.gitignore | 1 + tests/Makefile.include | 3 +- 3 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 tests/fp-bench.c diff --git a/tests/fp-bench.c b/tests/fp-bench.c new file mode 100644 index 0000000..a782093 --- /dev/null +++ b/tests/fp-bench.c @@ -0,0 +1,290 @@ +/* + * fp-bench.c - A collection of simple floating point microbenchmarks. + * + * Copyright (C) 2018, Emilio G. Cota + * + * License: GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#include "qemu/osdep.h" +#include "qemu/atomic.h" + +#include + +#include +#include +#include +#include +#include +#include + +/* amortize the computation of random inputs */ +#define OPS_PER_ITER (1000ULL) + +#define SEED_A 0xdeadfacedeadface +#define SEED_B 0xbadc0feebadc0fee +#define SEED_C 0xbeefdeadbeefdead + +enum op { + OP_ADD, + OP_SUB, + OP_MUL, + OP_DIV, + OP_FMA, + OP_SQRT, +}; + +static const char * const op_names[] =3D { + [OP_ADD] =3D "add", + [OP_SUB] =3D "sub", + [OP_MUL] =3D "mul", + [OP_DIV] =3D "div", + [OP_FMA] =3D "fma", + [OP_SQRT] =3D "sqrt", +}; + +static uint64_t n_ops =3D 10000000; +static enum op op; +static const char *precision =3D "float"; + +static const char commands_string[] =3D + " -n =3D number of floating point operations\n" + " -o =3D floating point operation (add, sub, mul, div, fma, sqrt). Def= ault: add\n" + " -p =3D precision (float|single, double). Default: float"; + +static void usage_complete(int argc, char *argv[]) +{ + fprintf(stderr, "Usage: %s [options]\n", argv[0]); + fprintf(stderr, "options:\n%s\n", commands_string); + exit(-1); +} + +static void set_op(const char *name) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(op_names); i++) { + if (strcmp(name, op_names[i]) =3D=3D 0) { + op =3D i; + return; + } + } + fprintf(stderr, "Unsupported op '%s'\n", name); + exit(EXIT_FAILURE); +} + +static inline int64_t get_clock_realtime(void) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000); +} + +/* + * From: https://en.wikipedia.org/wiki/Xorshift + * This is faster than rand_r(), and gives us a wider range (RAND_MAX is o= nly + * guaranteed to be >=3D INT_MAX). + */ +static uint64_t xorshift64star(uint64_t x) +{ + x ^=3D x >> 12; /* a */ + x ^=3D x << 25; /* b */ + x ^=3D x >> 27; /* c */ + return x * UINT64_C(2685821657736338717); +} + +static inline bool u32_is_normal(uint32_t x) +{ + return ((x + 0x00800000) & 0x7fffffff) >=3D 0x01000000; +} + +static inline bool u64_is_normal(uint64_t x) +{ + return ((x + (1ULL << 52)) & -1ULL >> 1) >=3D 1ULL << 53; +} + +static inline float get_random_float(uint64_t *x) +{ + uint64_t r =3D *x; + uint32_t r32; + + do { + r =3D xorshift64star(r); + } while (!u32_is_normal(r)); + *x =3D r; + r32 =3D r; + return *(float *)&r32; +} + +static inline double get_random_double(uint64_t *x) +{ + uint64_t r =3D *x; + + do { + r =3D xorshift64star(r); + } while (!u64_is_normal(r)); + *x =3D r; + return *(double *)&r; +} + +/* + * Disable optimizations (e.g. "a OP b" outside of the inner loop) with + * volatile. + */ +#define GEN_BENCH_1OPF(NAME, FUNC, PRECISION) \ + static void NAME(volatile PRECISION *res) \ + { \ + uint64_t ra =3D SEED_A; \ + uint64_t i, j; \ + \ + for (i =3D 0; i < n_ops; i +=3D OPS_PER_ITER) { = \ + volatile PRECISION a =3D glue(get_random_, PRECISION)(&ra); \ + \ + for (j =3D 0; j < OPS_PER_ITER; j++) { \ + *res =3D FUNC(a); \ + } \ + } \ + } + +GEN_BENCH_1OPF(bench_float_sqrt, sqrtf, float) +GEN_BENCH_1OPF(bench_double_sqrt, sqrt, double) +#undef GEN_BENCH_1OPF + +#define GEN_BENCH_2OP(NAME, OP, PRECISION) \ + static void NAME(volatile PRECISION *res) \ + { \ + uint64_t ra =3D SEED_A; \ + uint64_t rb =3D SEED_B; \ + uint64_t i, j; \ + \ + for (i =3D 0; i < n_ops; i +=3D OPS_PER_ITER) { = \ + volatile PRECISION a =3D glue(get_random_, PRECISION)(&ra); \ + volatile PRECISION b =3D glue(get_random_, PRECISION)(&rb); \ + \ + for (j =3D 0; j < OPS_PER_ITER; j++) { \ + *res =3D a OP b; \ + } \ + } \ + } + +GEN_BENCH_2OP(bench_float_add, +, float) +GEN_BENCH_2OP(bench_float_sub, -, float) +GEN_BENCH_2OP(bench_float_mul, *, float) +GEN_BENCH_2OP(bench_float_div, /, float) + +GEN_BENCH_2OP(bench_double_add, +, double) +GEN_BENCH_2OP(bench_double_sub, -, double) +GEN_BENCH_2OP(bench_double_mul, *, double) +GEN_BENCH_2OP(bench_double_div, /, double) + +#define GEN_BENCH_3OPF(NAME, FUNC, PRECISION) \ + static void NAME(volatile PRECISION *res) \ + { \ + uint64_t ra =3D SEED_A; \ + uint64_t rb =3D SEED_B; \ + uint64_t rc =3D SEED_C; \ + uint64_t i, j; \ + \ + for (i =3D 0; i < n_ops; i +=3D OPS_PER_ITER) { = \ + volatile PRECISION a =3D glue(get_random_, PRECISION)(&ra); \ + volatile PRECISION b =3D glue(get_random_, PRECISION)(&rb); \ + volatile PRECISION c =3D glue(get_random_, PRECISION)(&rc); \ + \ + for (j =3D 0; j < OPS_PER_ITER; j++) { \ + *res =3D FUNC(a, b, c); \ + } \ + } \ + } + +GEN_BENCH_3OPF(bench_float_fma, fmaf, float) +GEN_BENCH_3OPF(bench_double_fma, fma, double) +#undef GEN_BENCH_3OPF + +static void parse_args(int argc, char *argv[]) +{ + int c; + + for (;;) { + c =3D getopt(argc, argv, "n:ho:p:"); + if (c < 0) { + break; + } + switch (c) { + case 'h': + usage_complete(argc, argv); + exit(0); + case 'n': + n_ops =3D atoll(optarg); + if (n_ops < OPS_PER_ITER) { + n_ops =3D OPS_PER_ITER; + } + n_ops -=3D n_ops % OPS_PER_ITER; + break; + case 'o': + set_op(optarg); + break; + case 'p': + precision =3D optarg; + if (strcmp(precision, "float") && + strcmp(precision, "single") && + strcmp(precision, "double")) { + fprintf(stderr, "Unsupported precision '%s'\n", precision); + exit(EXIT_FAILURE); + } + break; + } + } +} + +#define CALL_BENCH(OP, PRECISION, RESP) \ + do { \ + switch (OP) { \ + case OP_ADD: \ + glue(glue(bench_, PRECISION), _add)(RESP); \ + break; \ + case OP_SUB: \ + glue(glue(bench_, PRECISION), _sub)(RESP); \ + break; \ + case OP_MUL: \ + glue(glue(bench_, PRECISION), _mul)(RESP); \ + break; \ + case OP_DIV: \ + glue(glue(bench_, PRECISION), _div)(RESP); \ + break; \ + case OP_FMA: \ + glue(glue(bench_, PRECISION), _fma)(RESP); \ + break; \ + case OP_SQRT: \ + glue(glue(bench_, PRECISION), _sqrt)(RESP); \ + break; \ + default: \ + g_assert_not_reached(); \ + } \ + } while (0) + +int main(int argc, char *argv[]) +{ + int64_t t0, t1; + double resd; + + parse_args(argc, argv); + if (!strcmp(precision, "float") || !strcmp(precision, "single")) { + float res; + t0 =3D get_clock_realtime(); + CALL_BENCH(op, float, &res); + t1 =3D get_clock_realtime(); + resd =3D res; + } else if (!strcmp(precision, "double")) { + t0 =3D get_clock_realtime(); + CALL_BENCH(op, double, &resd); + t1 =3D get_clock_realtime(); + } else { + g_assert_not_reached(); + } + printf("%.2f MFlops\n", (double)n_ops / (t1 - t0) * 1e3); + if (resd) { + return 0; + } + return 0; +} diff --git a/tests/.gitignore b/tests/.gitignore index 18e58b2..df69175 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -12,6 +12,7 @@ check-qobject check-qstring check-qom-interface check-qom-proplist +fp-bench qht-bench rcutorture test-aio diff --git a/tests/Makefile.include b/tests/Makefile.include index ef9b88c..f6121ee 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -587,7 +587,7 @@ test-obj-y =3D tests/check-qnum.o tests/check-qstring.o= tests/check-qdict.o \ tests/rcutorture.o tests/test-rcu-list.o \ tests/test-qdist.o tests/test-shift128.o \ tests/test-qht.o tests/qht-bench.o tests/test-qht-par.o \ - tests/atomic_add-bench.o + tests/atomic_add-bench.o tests/fp-bench.o =20 $(test-obj-y): QEMU_INCLUDES +=3D -Itests QEMU_CFLAGS +=3D -I$(SRC_PATH)/tests @@ -639,6 +639,7 @@ tests/test-qht-par$(EXESUF): tests/test-qht-par.o tests= /qht-bench$(EXESUF) $(tes tests/qht-bench$(EXESUF): tests/qht-bench.o $(test-util-obj-y) tests/test-bufferiszero$(EXESUF): tests/test-bufferiszero.o $(test-util-ob= j-y) tests/atomic_add-bench$(EXESUF): tests/atomic_add-bench.o $(test-util-obj-= y) +tests/fp-bench$(EXESUF): tests/fp-bench.o $(test-util-obj-y) =20 tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \ hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\ --=20 2.7.4 From nobody Sat Oct 25 21:46:07 2025 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; 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 152166341255375.31958872117218; Wed, 21 Mar 2018 13:16:52 -0700 (PDT) Received: from localhost ([::1]:57144 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eykAF-0006aF-Db for importer@patchew.org; Wed, 21 Mar 2018 16:16:51 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42168) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk5V-00029z-Vh for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:12:02 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyk5Q-0000yQ-TO for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:57 -0400 Received: from out5-smtp.messagingengine.com ([66.111.4.29]:54791) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyk5Q-0000xO-M5 for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:52 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 2118620C00; Wed, 21 Mar 2018 16:11:51 -0400 (EDT) Received: from frontend2 ([10.202.2.161]) by compute4.internal (MEProxy); Wed, 21 Mar 2018 16:11:51 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id A7976241A9; Wed, 21 Mar 2018 16:11:50 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=mesmtp; bh=LkWLuI9MCr2FHn Vf+WpVcjpFR96HPeAMlyuuWS1aVY4=; b=2QzHaaowMDzE1SaCPBpJKqR+gbhZsz aqXQ/MOMeEqVZF5vgFjrCPd1aXR7kIXMWUGDPht+x0xx+Y0WdqsZhnvmufbeFDBJ 7HCfXnerrHKofbuyKoPx01A4YBmi1A1a0iDdNAWdM1L6eooAXD/4E16KcFnC+JMu Zql6rAhZ0zDoQ= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=LkWLuI9MCr2FHnVf+WpVcjpFR96HPeAMlyuuWS1aVY4=; b=O5ZeMFAC GIcm9FTzxh8EfUtWcNN4lixWbkRqj5a3gohfleFjfBbl7Pq3UjRBlVrf5s3Rc9q0 f1nCZNAOspjmoUHdbX++UlPh8Yf9yC/Y0sOx+tCciE6+NAtmZdPIO17N6yvPLJpt Pf5erUEXr/DnylT8h29BqYzMxosdewzSNgcMwEkegqpW3kDixFvvL7mKcGonyn5V Tm5e3ymjzANaciM3+upbi02ZsLW9SNC3V6yCnX13Pw5gY6Jvz345PBkA4OHYj7OE 6tK42Cl8noxvU/v3l8WnorI/27TFu4ebL6OF+ZvkKQvfLi+U/UmC9sw+TBD8H9cN frtJrI6yV11B1Q== X-ME-Sender: From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 21 Mar 2018 16:11:37 -0400 Message-Id: <1521663109-32262-3-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1521663109-32262-1-git-send-email-cota@braap.org> References: <1521663109-32262-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.29 Subject: [Qemu-devel] [PATCH v1 02/14] tests: add fp-test, a floating point test suite 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 , Mark Cave-Ayland , Richard Henderson , Laurent Vivier , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Aurelien Jarno Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This will allow us to run correctness tests against our FP implementation. The test can be run in two modes (called "testers"): host and soft. With the former we check the results and FP flags on the host machine against the model. With the latter we check QEMU's fpu primitives against the model. Note that in soft mode we are not instantiating any particular CPU (hence the HW_POISON_H hack to avoid macro poisoning); for that we need to run the test in host mode under QEMU. The input files are taken from IBM's FPGen test suite: https://www.research.ibm.com/haifa/projects/verification/fpgen/ I see no license file in there so I am just downloading them with wget. We might want to keep a copy on a qemu server though, in case IBM takes those files down in the future. The "IBM" syntax of those files (for now the only syntax supported in fp-test) is documented here: https://www.research.ibm.com/haifa/projects/verification/fpgen/papers/ieee-= test-suite-v2.pdf Note that the syntax document has some inaccuracies; the appended parsing code works around some of those. The exception flag (-e) is important: many of the optimizations included in the following commits assume that the inexact flag is set, so "-e x" is necessary in order to test those code paths. The whitelist flag (-w) points to a file with test cases to be ignored. I have put some whitelist files online, but we should have them on a QEMU-related server. Thus, a typical of fp-test is as follows: $ cd qemu/build/tests/fp-test $ make -j && \ ./fp-test -t soft ibm/*.fptest \ -w whitelist.txt \ -e x If we want to test after-rounding tininess detection, then we need to pass "-a -w whitelist-tininess-after.txt" in addition to the above. (NB. we can pass "-w" as many times as we want.) The patch immediately after this one fixes a mismatch against the model in softfloat, but after that is applied the above should finish with a 0 return code, and print something like: All tests OK. Tests passed: 76572. Not handled: 51237, whitelisted: 2662 The tests pass on "host" mode on x86_64 and aarch64 machines. On an IBM Power8 machine some exception flags are different from the model files, which is interesting given that the model comes from IBM. Running on host mode under QEMU reports flag mismatches (e.g. for x86_64-linux-user), but that isn't too surprising given how little love the i386 frontend gets. Host mode under aarch64-linux-user passes OK. Flush-to-zero and flush-inputs-to-zero modes can be tested with the -z and -Z flags. Note however that the IBM input files are only IEEE-compliant, so for now I've tested these modes by diff'ing the reported errors against the model files. We should look into generating files for these non-standard modes to make testing these modes less painful. Signed-off-by: Emilio G. Cota --- configure | 2 + tests/fp-test/fp-test.c | 1159 ++++++++++++++++++++++++++++++++++++++++++= ++++ tests/.gitignore | 1 + tests/fp-test/.gitignore | 3 + tests/fp-test/Makefile | 34 ++ 5 files changed, 1199 insertions(+) create mode 100644 tests/fp-test/fp-test.c create mode 100644 tests/fp-test/.gitignore create mode 100644 tests/fp-test/Makefile diff --git a/configure b/configure index 6f3921c..8ea3825 100755 --- a/configure +++ b/configure @@ -7046,12 +7046,14 @@ fi =20 # build tree in object directory in case the source is not in the current = directory DIRS=3D"tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/q= api-schema tests/tcg/xtensa tests/qemu-iotests tests/vm" +DIRS=3D"$DIRS tests/fp-test" DIRS=3D"$DIRS docs docs/interop fsdev scsi" DIRS=3D"$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw" DIRS=3D"$DIRS roms/seabios roms/vgabios" FILES=3D"Makefile tests/tcg/Makefile qdict-test-data.txt" FILES=3D"$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit" FILES=3D"$FILES tests/tcg/lm32/Makefile tests/tcg/xtensa/Makefile po/Makef= ile" +FILES=3D"$FILES tests/fp-test/Makefile" FILES=3D"$FILES pc-bios/optionrom/Makefile pc-bios/keymaps" FILES=3D"$FILES pc-bios/spapr-rtas/Makefile" FILES=3D"$FILES pc-bios/s390-ccw/Makefile" diff --git a/tests/fp-test/fp-test.c b/tests/fp-test/fp-test.c new file mode 100644 index 0000000..27637c4 --- /dev/null +++ b/tests/fp-test/fp-test.c @@ -0,0 +1,1159 @@ +/* + * fp-test.c - Floating point test suite. + * + * Copyright (C) 2018, Emilio G. Cota + * + * License: GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#ifndef HW_POISON_H +#error Must define HW_POISON_H to work around TARGET_* poisoning +#endif + +#include "qemu/osdep.h" +#include "fpu/softfloat.h" + +#include +#include + +enum error { + ERROR_NONE, + ERROR_NOT_HANDLED, + ERROR_WHITELISTED, + ERROR_COMMENT, + ERROR_INPUT, + ERROR_RESULT, + ERROR_EXCEPTIONS, + ERROR_MAX, +}; + +enum input_fmt { + INPUT_FMT_IBM, +}; + +struct input { + const char * const name; + enum error (*test_line)(const char *line); +}; + +enum precision { + PREC_FLOAT, + PREC_DOUBLE, + PREC_QUAD, + PREC_FLOAT_TO_DOUBLE, +}; + +struct op_desc { + const char * const name; + int n_operands; +}; + +enum op { + OP_ADD, + OP_SUB, + OP_MUL, + OP_MULADD, + OP_DIV, + OP_SQRT, + OP_MINNUM, + OP_MAXNUM, + OP_MAXNUMMAG, + OP_ABS, + OP_IS_NAN, + OP_IS_INF, + OP_FLOAT_TO_DOUBLE, +}; + +static const struct op_desc ops[] =3D { + [OP_ADD] =3D { "+", 2 }, + [OP_SUB] =3D { "-", 2 }, + [OP_MUL] =3D { "*", 2 }, + [OP_MULADD] =3D { "*+", 3 }, + [OP_DIV] =3D { "/", 2 }, + [OP_SQRT] =3D { "V", 1 }, + [OP_MINNUM] =3D { "C", 2 }, + [OP_MAXNUMMAG] =3D { ">A", 2 }, + [OP_ABS] =3D { "A", 1 }, + [OP_IS_NAN] =3D { "?N", 1 }, + [OP_IS_INF] =3D { "?i", 1 }, + [OP_FLOAT_TO_DOUBLE] =3D { "cff", 1 }, +}; + +/* + * We could enumerate all the types here. But really we only care about + * QNaN and SNaN since only those can vary across ISAs. + */ +enum op_type { + OP_TYPE_NUMBER, + OP_TYPE_QNAN, + OP_TYPE_SNAN, +}; + +struct operand { + uint64_t val; + enum op_type type; +}; + +struct test_op { + struct operand operands[3]; + struct operand expected_result; + enum precision prec; + enum op op; + signed char round; + uint8_t trapped_exceptions; + uint8_t exceptions; + bool expected_result_is_valid; +}; + +typedef enum error (*tester_func_t)(struct test_op *); + +struct tester { + tester_func_t func; + const char *name; +}; + +struct whitelist { + char **lines; + size_t n; + GHashTable *ht; +}; + +static uint64_t test_stats[ERROR_MAX]; +static struct whitelist whitelist; +static uint8_t default_exceptions; +static bool die_on_error =3D true; +static struct float_status soft_status =3D { + .float_detect_tininess =3D float_tininess_before_rounding, +}; + +static inline float u64_to_float(uint64_t v) +{ + uint32_t v32 =3D v; + uint32_t *v32p =3D &v32; + + return *(float *)v32p; +} + +static inline double u64_to_double(uint64_t v) +{ + uint64_t *vp =3D &v; + + return *(double *)vp; +} + +static inline uint64_t float_to_u64(float f) +{ + float *fp =3D &f; + + return *(uint32_t *)fp; +} + +static inline uint64_t double_to_u64(double d) +{ + double *dp =3D &d; + + return *(uint64_t *)dp; +} + +static inline bool is_err(enum error err) +{ + return err !=3D ERROR_NONE && + err !=3D ERROR_NOT_HANDLED && + err !=3D ERROR_WHITELISTED && + err !=3D ERROR_COMMENT; +} + +static int host_exceptions_translate(int host_flags) +{ + int flags =3D 0; + + if (host_flags & FE_INEXACT) { + flags |=3D float_flag_inexact; + } + if (host_flags & FE_UNDERFLOW) { + flags |=3D float_flag_underflow; + } + if (host_flags & FE_OVERFLOW) { + flags |=3D float_flag_overflow; + } + if (host_flags & FE_DIVBYZERO) { + flags |=3D float_flag_divbyzero; + } + if (host_flags & FE_INVALID) { + flags |=3D float_flag_invalid; + } + return flags; +} + +static inline uint8_t host_get_exceptions(void) +{ + return host_exceptions_translate(fetestexcept(FE_ALL_EXCEPT)); +} + +static void host_set_exceptions(uint8_t flags) +{ + int host_flags =3D 0; + + if (flags & float_flag_inexact) { + host_flags |=3D FE_INEXACT; + } + if (flags & float_flag_underflow) { + host_flags |=3D FE_UNDERFLOW; + } + if (flags & float_flag_overflow) { + host_flags |=3D FE_OVERFLOW; + } + if (flags & float_flag_divbyzero) { + host_flags |=3D FE_DIVBYZERO; + } + if (flags & float_flag_invalid) { + host_flags |=3D FE_INVALID; + } + feraiseexcept(host_flags); +} + +#define STANDARD_EXCEPTIONS \ + (float_flag_inexact | float_flag_underflow | \ + float_flag_overflow | float_flag_divbyzero | float_flag_invalid) +#define FMT_EXCEPTIONS "%s%s%s%s%s%s" +#define PR_EXCEPTIONS(x) \ + ((x) & STANDARD_EXCEPTIONS ? "" : "none"), \ + (((x) & float_flag_inexact) ? "x" : ""), \ + (((x) & float_flag_underflow) ? "u" : ""), \ + (((x) & float_flag_overflow) ? "o" : ""), \ + (((x) & float_flag_divbyzero) ? "z" : ""), \ + (((x) & float_flag_invalid) ? "i" : "") + +static enum error tester_check(const struct test_op *t, uint64_t res64, + bool res_is_nan, uint8_t flags) +{ + enum error err =3D ERROR_NONE; + + if (t->expected_result_is_valid) { + if (t->expected_result.type =3D=3D OP_TYPE_QNAN || + t->expected_result.type =3D=3D OP_TYPE_SNAN) { + if (!res_is_nan) { + err =3D ERROR_RESULT; + goto out; + } + } else if (res64 !=3D t->expected_result.val) { + err =3D ERROR_RESULT; + goto out; + } + } + if (t->exceptions && flags !=3D (t->exceptions | default_exceptions)) { + err =3D ERROR_EXCEPTIONS; + goto out; + } + + out: + if (is_err(err)) { + int i; + + fprintf(stderr, "%s ", ops[t->op].name); + for (i =3D 0; i < ops[t->op].n_operands; i++) { + fprintf(stderr, "0x%" PRIx64 "%s", t->operands[i].val, + i < ops[t->op].n_operands - 1 ? " " : ""); + } + fprintf(stderr, ", expected: 0x%" PRIx64 ", returned: 0x%" PRIx64, + t->expected_result.val, res64); + if (err =3D=3D ERROR_EXCEPTIONS) { + fprintf(stderr, ", expected exceptions: " FMT_EXCEPTIONS + ", returned: " FMT_EXCEPTIONS, + PR_EXCEPTIONS(t->exceptions), PR_EXCEPTIONS(flags)); + } + fprintf(stderr, "\n"); + } + return err; +} + +static enum error host_tester(struct test_op *t) +{ + uint64_t res64; + bool result_is_nan; + uint8_t flags =3D 0; + + feclearexcept(FE_ALL_EXCEPT); + if (default_exceptions) { + host_set_exceptions(default_exceptions); + } + + if (t->prec =3D=3D PREC_FLOAT) { + float a, b, c; + float *in[] =3D { &a, &b, &c }; + float res; + int i; + + g_assert(ops[t->op].n_operands <=3D ARRAY_SIZE(in)); + for (i =3D 0; i < ops[t->op].n_operands; i++) { + /* use the host's QNaN/SNaN patterns */ + if (t->operands[i].type =3D=3D OP_TYPE_QNAN) { + *in[i] =3D __builtin_nanf(""); + } else if (t->operands[i].type =3D=3D OP_TYPE_SNAN) { + *in[i] =3D __builtin_nansf(""); + } else { + *in[i] =3D u64_to_float(t->operands[i].val); + } + } + + if (t->expected_result.type =3D=3D OP_TYPE_QNAN) { + t->expected_result.val =3D float_to_u64(__builtin_nanf("")); + } else if (t->expected_result.type =3D=3D OP_TYPE_SNAN) { + t->expected_result.val =3D float_to_u64(__builtin_nansf("")); + } + + switch (t->op) { + case OP_ADD: + res =3D a + b; + break; + case OP_SUB: + res =3D a - b; + break; + case OP_MUL: + res =3D a * b; + break; + case OP_MULADD: + res =3D fmaf(a, b, c); + break; + case OP_DIV: + res =3D a / b; + break; + case OP_SQRT: + res =3D sqrtf(a); + break; + case OP_ABS: + res =3D fabsf(a); + break; + case OP_IS_NAN: + res =3D !!isnan(a); + break; + case OP_IS_INF: + res =3D !!isinf(a); + break; + default: + return ERROR_NOT_HANDLED; + } + flags =3D host_get_exceptions(); + res64 =3D float_to_u64(res); + result_is_nan =3D isnan(res); + } else if (t->prec =3D=3D PREC_DOUBLE) { + double a, b, c; + double *in[] =3D { &a, &b, &c }; + double res; + int i; + + g_assert(ops[t->op].n_operands <=3D ARRAY_SIZE(in)); + for (i =3D 0; i < ops[t->op].n_operands; i++) { + /* use the host's QNaN/SNaN patterns */ + if (t->operands[i].type =3D=3D OP_TYPE_QNAN) { + *in[i] =3D __builtin_nan(""); + } else if (t->operands[i].type =3D=3D OP_TYPE_SNAN) { + *in[i] =3D __builtin_nans(""); + } else { + *in[i] =3D u64_to_double(t->operands[i].val); + } + } + + if (t->expected_result.type =3D=3D OP_TYPE_QNAN) { + t->expected_result.val =3D double_to_u64(__builtin_nan("")); + } else if (t->expected_result.type =3D=3D OP_TYPE_SNAN) { + t->expected_result.val =3D double_to_u64(__builtin_nans("")); + } + + switch (t->op) { + case OP_ADD: + res =3D a + b; + break; + case OP_SUB: + res =3D a - b; + break; + case OP_MUL: + res =3D a * b; + break; + case OP_MULADD: + res =3D fma(a, b, c); + break; + case OP_DIV: + res =3D a / b; + break; + case OP_SQRT: + res =3D sqrt(a); + break; + case OP_ABS: + res =3D fabs(a); + break; + case OP_IS_NAN: + res =3D !!isnan(a); + break; + case OP_IS_INF: + res =3D !!isinf(a); + break; + default: + return ERROR_NOT_HANDLED; + } + flags =3D host_get_exceptions(); + res64 =3D double_to_u64(res); + result_is_nan =3D isnan(res); + } else if (t->prec =3D=3D PREC_FLOAT_TO_DOUBLE) { + float a; + double res; + + if (t->operands[0].type =3D=3D OP_TYPE_QNAN) { + a =3D __builtin_nanf(""); + } else if (t->operands[0].type =3D=3D OP_TYPE_SNAN) { + a =3D __builtin_nansf(""); + } else { + a =3D u64_to_float(t->operands[0].val); + } + + if (t->expected_result.type =3D=3D OP_TYPE_QNAN) { + t->expected_result.val =3D double_to_u64(__builtin_nan("")); + } else if (t->expected_result.type =3D=3D OP_TYPE_SNAN) { + t->expected_result.val =3D double_to_u64(__builtin_nans("")); + } + + switch (t->op) { + case OP_FLOAT_TO_DOUBLE: + res =3D a; + break; + default: + return ERROR_NOT_HANDLED; + } + flags =3D host_get_exceptions(); + res64 =3D double_to_u64(res); + result_is_nan =3D isnan(res); + } else { + return ERROR_NOT_HANDLED; /* XXX */ + } + return tester_check(t, res64, result_is_nan, flags); +} + +static enum error soft_tester(struct test_op *t) +{ + float_status *s =3D &soft_status; + uint64_t res64; + enum error err =3D ERROR_NONE; + bool result_is_nan; + + s->float_rounding_mode =3D t->round; + s->float_exception_flags =3D default_exceptions; + + if (t->prec =3D=3D PREC_FLOAT) { + float32 a, b, c; + float32 *in[] =3D { &a, &b, &c }; + float32 res; + int i; + + g_assert(ops[t->op].n_operands <=3D ARRAY_SIZE(in)); + for (i =3D 0; i < ops[t->op].n_operands; i++) { + *in[i] =3D t->operands[i].val; + } + + switch (t->op) { + case OP_ADD: + res =3D float32_add(a, b, s); + break; + case OP_SUB: + res =3D float32_sub(a, b, s); + break; + case OP_MUL: + res =3D float32_mul(a, b, s); + break; + case OP_MULADD: + res =3D float32_muladd(a, b, c, 0, s); + break; + case OP_DIV: + res =3D float32_div(a, b, s); + break; + case OP_SQRT: + res =3D float32_sqrt(a, s); + break; + case OP_MINNUM: + res =3D float32_minnum(a, b, s); + break; + case OP_MAXNUM: + res =3D float32_maxnum(a, b, s); + break; + case OP_MAXNUMMAG: + res =3D float32_maxnummag(a, b, s); + break; + case OP_IS_NAN: + { + float f =3D !!float32_is_any_nan(a); + + res =3D float_to_u64(f); + break; + } + case OP_IS_INF: + { + float f =3D !!float32_is_infinity(a); + + res =3D float_to_u64(f); + break; + } + case OP_ABS: + /* Fall-through: float32_abs does not handle NaN's */ + default: + return ERROR_NOT_HANDLED; + } + res64 =3D res; + result_is_nan =3D isnan(*(float *)&res); + } else if (t->prec =3D=3D PREC_DOUBLE) { + float64 a, b, c; + float64 *in[] =3D { &a, &b, &c }; + int i; + + g_assert(ops[t->op].n_operands <=3D ARRAY_SIZE(in)); + for (i =3D 0; i < ops[t->op].n_operands; i++) { + *in[i] =3D t->operands[i].val; + } + + switch (t->op) { + case OP_ADD: + res64 =3D float64_add(a, b, s); + break; + case OP_SUB: + res64 =3D float64_sub(a, b, s); + break; + case OP_MUL: + res64 =3D float64_mul(a, b, s); + break; + case OP_MULADD: + res64 =3D float64_muladd(a, b, c, 0, s); + break; + case OP_DIV: + res64 =3D float64_div(a, b, s); + break; + case OP_SQRT: + res64 =3D float64_sqrt(a, s); + break; + case OP_MINNUM: + res64 =3D float64_minnum(a, b, s); + break; + case OP_MAXNUM: + res64 =3D float64_maxnum(a, b, s); + break; + case OP_MAXNUMMAG: + res64 =3D float64_maxnummag(a, b, s); + break; + case OP_IS_NAN: + { + double d =3D !!float64_is_any_nan(a); + + res64 =3D double_to_u64(d); + break; + } + case OP_IS_INF: + { + double d =3D !!float64_is_infinity(a); + + res64 =3D double_to_u64(d); + break; + } + case OP_ABS: + /* Fall-through: float64_abs does not handle NaN's */ + default: + return ERROR_NOT_HANDLED; + } + result_is_nan =3D isnan(*(double *)&res64); + } else if (t->prec =3D=3D PREC_FLOAT_TO_DOUBLE) { + float32 a =3D t->operands[0].val; + + switch (t->op) { + case OP_FLOAT_TO_DOUBLE: + res64 =3D float32_to_float64(a, s); + break; + default: + return ERROR_NOT_HANDLED; + } + result_is_nan =3D isnan(*(double *)&res64); + } else { + return ERROR_NOT_HANDLED; /* XXX */ + } + return tester_check(t, res64, result_is_nan, s->float_exception_flags); + return err; +} + +static const struct tester valid_testers[] =3D { + [0] =3D { + .name =3D "soft", + .func =3D soft_tester, + }, + [1] =3D { + .name =3D "host", + .func =3D host_tester, + }, +}; +static const struct tester *tester =3D &valid_testers[0]; + +static int ibm_get_exceptions(const char *p, uint8_t *excp) +{ + while (*p) { + switch (*p) { + case 'x': + *excp |=3D float_flag_inexact; + break; + case 'u': + *excp |=3D float_flag_underflow; + break; + case 'o': + *excp |=3D float_flag_overflow; + break; + case 'z': + *excp |=3D float_flag_divbyzero; + break; + case 'i': + *excp |=3D float_flag_invalid; + break; + default: + return 1; + } + p++; + } + return 0; +} + +static uint64_t fp_choose(enum precision prec, uint64_t f, uint64_t d) +{ + switch (prec) { + case PREC_FLOAT: + return f; + case PREC_DOUBLE: + return d; + default: + g_assert_not_reached(); + } +} + +static int +ibm_fp_hex(const char *p, enum precision prec, struct operand *ret) +{ + int len; + + ret->type =3D OP_TYPE_NUMBER; + + /* QNaN */ + if (unlikely(!strcmp("Q", p))) { + ret->val =3D fp_choose(prec, 0xffc00000, 0xfff8000000000000); + ret->type =3D OP_TYPE_QNAN; + return 0; + } + /* SNaN */ + if (unlikely(!strcmp("S", p))) { + ret->val =3D fp_choose(prec, 0xffb00000, 0xfff7000000000000); + ret->type =3D OP_TYPE_SNAN; + return 0; + } + if (unlikely(!strcmp("+Zero", p))) { + ret->val =3D fp_choose(prec, 0x00000000, 0x0000000000000000); + return 0; + } + if (unlikely(!strcmp("-Zero", p))) { + ret->val =3D fp_choose(prec, 0x80000000, 0x8000000000000000); + return 0; + } + if (unlikely(!strcmp("+inf", p) || !strcmp("+Inf", p))) { + ret->val =3D fp_choose(prec, 0x7f800000, 0x7ff0000000000000); + return 0; + } + if (unlikely(!strcmp("-inf", p) || !strcmp("-Inf", p))) { + ret->val =3D fp_choose(prec, 0xff800000, 0xfff0000000000000); + return 0; + } + + len =3D strlen(p); + + if (strchr(p, 'P')) { + bool negative =3D p[0] =3D=3D '-'; + char *pos; + bool denormal; + + if (len <=3D 4) { + return 1; + } + denormal =3D p[1] =3D=3D '0'; + if (prec =3D=3D PREC_FLOAT) { + uint32_t exponent; + uint32_t significand; + uint32_t h; + + significand =3D strtoul(&p[3], &pos, 16); + if (*pos !=3D 'P') { + return 1; + } + pos++; + exponent =3D strtol(pos, &pos, 10) + 127; + if (pos !=3D p + len) { + return 1; + } + /* + * When there's a leading zero, we have a denormal number. We'd + * expect the input (unbiased) exponent to be -127, but for so= me + * reason -126 is used. Correct that here. + */ + if (denormal) { + if (exponent !=3D 1) { + return 1; + } + exponent =3D 0; + } + h =3D negative ? (1 << 31) : 0; + h |=3D exponent << 23; + h |=3D significand; + ret->val =3D h; + return 0; + } else if (prec =3D=3D PREC_DOUBLE) { + uint64_t exponent; + uint64_t significand; + uint64_t h; + + significand =3D strtoul(&p[3], &pos, 16); + if (*pos !=3D 'P') { + return 1; + } + pos++; + exponent =3D strtol(pos, &pos, 10) + 1023; + if (pos !=3D p + len) { + return 1; + } + if (denormal) { + return 1; /* XXX */ + } + h =3D negative ? (1ULL << 63) : 0; + h |=3D exponent << 52; + h |=3D significand; + ret->val =3D h; + return 0; + } else { /* XXX */ + return 1; + } + } else if (strchr(p, 'e')) { + char *pos; + + if (prec =3D=3D PREC_FLOAT) { + float f =3D strtof(p, &pos); + + if (*pos) { + return 1; + } + ret->val =3D float_to_u64(f); + return 0; + } + if (prec =3D=3D PREC_DOUBLE) { + double d =3D strtod(p, &pos); + + if (*pos) { + return 1; + } + ret->val =3D double_to_u64(d); + return 0; + } + return 0; + } else if (!strcmp(p, "0x0")) { + if (prec =3D=3D PREC_FLOAT) { + ret->val =3D float_to_u64(0.0); + } else if (prec =3D=3D PREC_DOUBLE) { + ret->val =3D double_to_u64(0.0); + } else { + g_assert_not_reached(); + } + return 0; + } else if (!strcmp(p, "0x1")) { + if (prec =3D=3D PREC_FLOAT) { + ret->val =3D float_to_u64(1.0); + } else if (prec =3D=3D PREC_DOUBLE) { + ret->val =3D double_to_u64(1.0); + } else { + g_assert_not_reached(); + } + return 0; + } + return 1; +} + +static int find_op(const char *name, enum op *op) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(ops); i++) { + if (strcmp(ops[i].name, name) =3D=3D 0) { + *op =3D i; + return 0; + } + } + return 1; +} + +/* Syntax of IBM FP test cases: + * https://www.research.ibm.com/haifa/projects/verification/fpgen/syntax.t= xt + */ +static enum error ibm_test_line(const char *line) +{ + struct test_op t; + /* at most nine fields; this should be more than enough for each field= */ + char s[9][64]; + char *p; + int n, field; + int i; + + /* data lines start with either b32 or d(64|128) */ + if (unlikely(line[0] !=3D 'b' && line[0] !=3D 'd')) { + return ERROR_COMMENT; + } + n =3D sscanf(line, "%63s %63s %63s %63s %63s %63s %63s %63s %63s", + s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8]); + if (unlikely(n < 5 || n > 9)) { + return ERROR_INPUT; + } + + field =3D 0; + p =3D s[field]; + if (unlikely(strlen(p) < 4)) { + return ERROR_INPUT; + } + if (strcmp("b32b64cff", p) =3D=3D 0) { + t.prec =3D PREC_FLOAT_TO_DOUBLE; + if (find_op(&p[6], &t.op)) { + return ERROR_NOT_HANDLED; + } + } else { + if (strncmp("b32", p, 3) =3D=3D 0) { + t.prec =3D PREC_FLOAT; + } else if (strncmp("d64", p, 3) =3D=3D 0) { + t.prec =3D PREC_DOUBLE; + } else if (strncmp("d128", p, 4) =3D=3D 0) { + return ERROR_NOT_HANDLED; /* XXX */ + } else { + return ERROR_INPUT; + } + if (find_op(&p[3], &t.op)) { + return ERROR_NOT_HANDLED; + } + } + + field =3D 1; + p =3D s[field]; + if (!strncmp("=3D0", p, 2)) { + t.round =3D float_round_nearest_even; + } else { + return ERROR_NOT_HANDLED; /* XXX */ + } + + /* The trapped exceptions field is optional */ + t.trapped_exceptions =3D 0; + field =3D 2; + p =3D s[field]; + if (ibm_get_exceptions(p, &t.trapped_exceptions)) { + if (unlikely(n =3D=3D 9)) { + return ERROR_INPUT; + } + } else { + field++; + } + + for (i =3D 0; i < ops[t.op].n_operands; i++) { + enum precision prec =3D t.prec =3D=3D PREC_FLOAT_TO_DOUBLE ? + PREC_FLOAT : t.prec; + + p =3D s[field++]; + if (ibm_fp_hex(p, prec, &t.operands[i])) { + return ERROR_INPUT; + } + } + + p =3D s[field++]; + if (strcmp("->", p)) { + return ERROR_INPUT; + } + + p =3D s[field++]; + if (unlikely(strcmp("#", p) =3D=3D 0)) { + t.expected_result_is_valid =3D false; + } else { + enum precision prec =3D t.prec =3D=3D PREC_FLOAT_TO_DOUBLE ? + PREC_DOUBLE : t.prec; + + if (ibm_fp_hex(p, prec, &t.expected_result)) { + return ERROR_INPUT; + } + t.expected_result_is_valid =3D true; + } + + /* + * A 0 here means "do not check the exceptions", i.e. it does NOT mean + * "there should be no exceptions raised". + */ + t.exceptions =3D 0; + /* the expected exceptions field is optional */ + if (field =3D=3D n - 1) { + p =3D s[field++]; + if (ibm_get_exceptions(p, &t.exceptions)) { + return ERROR_INPUT; + } + } + + /* + * We ignore "trapped exceptions" because we're not testing the trappi= ng + * mechanism of the host CPU. + * We test though that the exception bits are correctly set. + */ + if (t.trapped_exceptions) { + return ERROR_NOT_HANDLED; + } + return tester->func(&t); +} + +static const struct input valid_input_types[] =3D { + [INPUT_FMT_IBM] =3D { + .name =3D "ibm", + .test_line =3D ibm_test_line, + }, +}; + +static const struct input *input_type =3D &valid_input_types[INPUT_FMT_IBM= ]; + +static bool line_is_whitelisted(const char *line) +{ + if (whitelist.ht =3D=3D NULL) { + return false; + } + return !!g_hash_table_lookup(whitelist.ht, line); +} + +static void test_file(const char *filename) +{ + static char line[256]; + unsigned int i; + FILE *fp; + + fp =3D fopen(filename, "r"); + if (fp =3D=3D NULL) { + fprintf(stderr, "cannot open file '%s': %s\n", + filename, strerror(errno)); + exit(EXIT_FAILURE); + } + i =3D 0; + while (fgets(line, sizeof(line), fp)) { + enum error err; + + i++; + if (unlikely(line_is_whitelisted(line))) { + test_stats[ERROR_WHITELISTED]++; + continue; + } + err =3D input_type->test_line(line); + if (unlikely(is_err(err))) { + switch (err) { + case ERROR_INPUT: + fprintf(stderr, "error: malformed input @ %s:%d:\n", + filename, i); + break; + case ERROR_RESULT: + fprintf(stderr, "error: result mismatch for input @ %s:%d:= \n", + filename, i); + break; + case ERROR_EXCEPTIONS: + fprintf(stderr, "error: flags mismatch for input @ %s:%d:\= n", + filename, i); + break; + default: + g_assert_not_reached(); + } + fprintf(stderr, "%s", line); + if (die_on_error) { + exit(EXIT_FAILURE); + } + } + test_stats[err]++; + } + if (fclose(fp)) { + fprintf(stderr, "warning: cannot close file '%s': %s\n", + filename, strerror(errno)); + } +} + +static void set_input_fmt(const char *optarg) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(valid_input_types); i++) { + const struct input *type =3D &valid_input_types[i]; + + if (strcmp(optarg, type->name) =3D=3D 0) { + input_type =3D type; + return; + } + } + fprintf(stderr, "Unknown input format '%s'", optarg); + exit(EXIT_FAILURE); +} + +static void set_tester(const char *optarg) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(valid_testers); i++) { + const struct tester *t =3D &valid_testers[i]; + + if (strcmp(optarg, t->name) =3D=3D 0) { + tester =3D t; + return; + } + } + fprintf(stderr, "Unknown tester '%s'", optarg); + exit(EXIT_FAILURE); +} + +static void whitelist_add_line(const char *orig_line) +{ + char *line; + bool inserted; + + if (whitelist.ht =3D=3D NULL) { + whitelist.ht =3D g_hash_table_new(g_str_hash, g_str_equal); + } + line =3D g_hash_table_lookup(whitelist.ht, orig_line); + if (unlikely(line !=3D NULL)) { + return; + } + whitelist.n++; + whitelist.lines =3D g_realloc_n(whitelist.lines, whitelist.n, sizeof(l= ine)); + line =3D strdup(orig_line); + whitelist.lines[whitelist.n - 1] =3D line; + /* if we pass key =3D=3D val GLib will not reserve space for the value= */ + inserted =3D g_hash_table_insert(whitelist.ht, line, line); + g_assert(inserted); +} + +static void set_whitelist(const char *filename) +{ + FILE *fp; + static char line[256]; + + fp =3D fopen(filename, "r"); + if (fp =3D=3D NULL) { + fprintf(stderr, "warning: cannot open white list file '%s': %s\n", + filename, strerror(errno)); + return; + } + while (fgets(line, sizeof(line), fp)) { + if (isspace(line[0]) || line[0] =3D=3D '#') { + continue; + } + whitelist_add_line(line); + } + if (fclose(fp)) { + fprintf(stderr, "warning: cannot close file '%s': %s\n", + filename, strerror(errno)); + } +} + +static void set_default_exceptions(const char *str) +{ + if (ibm_get_exceptions(str, &default_exceptions)) { + fprintf(stderr, "Invalid exception '%s'\n", str); + exit(EXIT_FAILURE); + } +} + +static void usage_complete(int argc, char *argv[]) +{ + fprintf(stderr, "Usage: %s [options] file1 [file2 ...]\n", argv[0]); + fprintf(stderr, "options:\n"); + fprintf(stderr, " -a =3D Perform tininess detection after rounding " + "(soft tester only). Default: before\n"); + fprintf(stderr, " -n =3D do not die on error. Default: dies on error\= n"); + fprintf(stderr, " -e =3D default exception flags (xiozu). Default: no= ne\n"); + fprintf(stderr, " -f =3D format of the input file(s). Default: %s\n", + valid_input_types[0].name); + fprintf(stderr, " -t =3D tester. Default: %s\n", valid_testers[0].nam= e); + fprintf(stderr, " -w =3D path to file with test cases to be whitelist= ed\n"); + fprintf(stderr, " -z =3D flush inputs to zero (soft tester only). " + "Default: disabled\n"); + fprintf(stderr, " -Z =3D flush output to zero (soft tester only). " + "Default: disabled\n"); +} + +static void parse_opts(int argc, char *argv[]) +{ + int c; + + for (;;) { + c =3D getopt(argc, argv, "ae:f:hnt:w:zZ"); + if (c < 0) { + return; + } + switch (c) { + case 'a': + soft_status.float_detect_tininess =3D float_tininess_after_rou= nding; + break; + case 'e': + set_default_exceptions(optarg); + break; + case 'f': + set_input_fmt(optarg); + break; + case 'h': + usage_complete(argc, argv); + exit(EXIT_SUCCESS); + case 'n': + die_on_error =3D false; + break; + case 't': + set_tester(optarg); + break; + case 'w': + set_whitelist(optarg); + break; + case 'z': + soft_status.flush_inputs_to_zero =3D 1; + break; + case 'Z': + soft_status.flush_to_zero =3D 1; + break; + } + } + g_assert_not_reached(); +} + +static uint64_t count_errors(void) +{ + uint64_t ret =3D 0; + int i; + + for (i =3D ERROR_INPUT; i < ERROR_MAX; i++) { + ret +=3D test_stats[i]; + } + return ret; +} + +int main(int argc, char *argv[]) +{ + uint64_t n_errors; + int i; + + if (argc =3D=3D 1) { + usage_complete(argc, argv); + exit(EXIT_FAILURE); + } + parse_opts(argc, argv); + for (i =3D optind; i < argc; i++) { + test_file(argv[i]); + } + + n_errors =3D count_errors(); + if (n_errors) { + printf("Tests failed: %"PRIu64". Parsing: %"PRIu64 + ", result:%"PRIu64", flags:%"PRIu64"\n", + n_errors, test_stats[ERROR_INPUT], test_stats[ERROR_RESULT], + test_stats[ERROR_EXCEPTIONS]); + } else { + printf("All tests OK.\n"); + } + printf("Tests passed: %" PRIu64 ". Not handled: %" PRIu64 + ", whitelisted: %"PRIu64 "\n", + test_stats[ERROR_NONE], test_stats[ERROR_NOT_HANDLED], + test_stats[ERROR_WHITELISTED]); + return !!n_errors; +} diff --git a/tests/.gitignore b/tests/.gitignore index df69175..f9b0f08 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -97,5 +97,6 @@ test-netfilter test-filter-mirror test-filter-redirector *-test +!fp-test qapi-schema/*.test.* vm/*.img diff --git a/tests/fp-test/.gitignore b/tests/fp-test/.gitignore new file mode 100644 index 0000000..e1e175c --- /dev/null +++ b/tests/fp-test/.gitignore @@ -0,0 +1,3 @@ +ibm +whitelist.txt +fp-test diff --git a/tests/fp-test/Makefile b/tests/fp-test/Makefile new file mode 100644 index 0000000..703434f --- /dev/null +++ b/tests/fp-test/Makefile @@ -0,0 +1,34 @@ +BUILD_DIR=3D$(CURDIR)/../.. + +include ../../config-host.mak +include $(SRC_PATH)/rules.mak + +$(call set-vpath, $(SRC_PATH)/tests/fp-test $(SRC_PATH)/fpu) + +QEMU_INCLUDES +=3D -I../.. +QEMU_INCLUDES +=3D -I$(SRC_PATH)/fpu +# work around TARGET_* poisoning +QEMU_CFLAGS +=3D -DHW_POISON_H + +IBMFP :=3D ibm-fptests.zip + +OBJS :=3D fp-test$(EXESUF) + +WHITELIST_FILES :=3D whitelist.txt whitelist-tininess-after.txt + +all: $(OBJS) ibm $(WHITELIST_FILES) + +ibm: + wget -nv -O $(IBMFP) http://www.haifa.il.ibm.com/projects/verification/fp= gen/download/test_suite.zip + mkdir -p $@ + unzip $(IBMFP) -d $@ + rm -rf $(IBMFP) + +# XXX: upload this to a qemu server, or just commit it. +$(WHITELIST_FILES): + wget -nv -O $@ http://www.cs.columbia.edu/~cota/qemu/fpbench-$@ + +fp-test$(EXESUF): fp-test.o softfloat.o + +clean: + rm -f *.o *.d $(OBJS) --=20 2.7.4 From nobody Sat Oct 25 21:46:07 2025 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; 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 (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1521663240400341.3209531464495; Wed, 21 Mar 2018 13:14:00 -0700 (PDT) Received: from localhost ([::1]:57123 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk7O-0003Pc-Ad for importer@patchew.org; Wed, 21 Mar 2018 16:13:54 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42163) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk5V-00029w-U3 for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyk5Q-0000yF-Qj for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:57 -0400 Received: from out5-smtp.messagingengine.com ([66.111.4.29]:53503) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyk5Q-0000xT-M0 for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:52 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 3BE20213C6; Wed, 21 Mar 2018 16:11:51 -0400 (EDT) Received: from frontend1 ([10.202.2.160]) by compute4.internal (MEProxy); Wed, 21 Mar 2018 16:11:51 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id E4AEA7E0D6; Wed, 21 Mar 2018 16:11:50 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=mesmtp; bh=9WDOUEu01Mhi1L AxfrmvsEgvZoNghKOj8zGaKXDlGSo=; b=VOyblbxyBhr8k7A9z5rWLCGX1x9UvE sWmhf0C/K9CxZnG7IACRBW9kTXOtC7kPaH14aqv2kpSFBKw6PANuk2VX1fgnj1De GdLY85EiZUS/0rpnkCfrR9bykKWE6CIQWut/Vf9JhA/ikl1066dXz7f+i8KmUf6D Zq4ZyFfvEooo8= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=9WDOUEu01Mhi1LAxfrmvsEgvZoNghKOj8zGaKXDlGSo=; b=Nruj6aif 6+X6UmdjPyNFwd4xZ3pfm9/DYVpkjDNakqS/dTaJ6rXI+DWrXx/3xqvpqOxsr/ow 84d1S4v3mtJ/99WSOfP6T0J3JPMKTHnYW8fAtSMSPsCFXob82M6Ls9jUA6d0Fwx4 oquwB5hh+fDIt9q6N5FGhsFPWotrdniJPtl6G/Dn/27P4xhEgKbKD4q+be1qKTcG +iomPvd400k4tAyPY+pjeZ1k3WPHrAtl2D7MvtuuQo3X0KEdtGcmIvs3Se0YbUni eRos6rbiyYllkhEx8b0IQL9RAJhp37GM7PZA0mrNSDO80dF8afuoec1yigtOrvjg iZ1yD85sByXxoQ== X-ME-Sender: From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 21 Mar 2018 16:11:38 -0400 Message-Id: <1521663109-32262-4-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1521663109-32262-1-git-send-email-cota@braap.org> References: <1521663109-32262-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.29 Subject: [Qemu-devel] [PATCH v1 03/14] softfloat: fix {min, max}nummag for same-abs-value inputs 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 , Mark Cave-Ayland , Richard Henderson , Laurent Vivier , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Aurelien Jarno Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Before 8936006 ("fpu/softfloat: re-factor minmax", 2018-02-21), we used to return +Zero for maxnummag(-Zero,+Zero); after that commit, we return -Zero. Fix it by making {min,max}nummag consistent with {min,max}num, deferring to the latter when the absolute value of the operands is the same. With this fix we now pass fp-test. Signed-off-by: Emilio G. Cota Reviewed-by: Alex Benn=C3=A9e --- fpu/softfloat.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index e124df9..ee615a9 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1700,7 +1700,6 @@ static FloatParts minmax_floats(FloatParts a, FloatPa= rts b, bool ismin, return pick_nan(a, b, s); } else { int a_exp, b_exp; - bool a_sign, b_sign; =20 switch (a.cls) { case float_class_normal: @@ -1731,20 +1730,22 @@ static FloatParts minmax_floats(FloatParts a, Float= Parts b, bool ismin, break; } =20 - a_sign =3D a.sign; - b_sign =3D b.sign; - if (ismag) { - a_sign =3D b_sign =3D 0; + if (ismag && (a_exp !=3D b_exp || a.frac !=3D b.frac)) { + bool a_less =3D a_exp < b_exp; + if (a_exp =3D=3D b_exp) { + a_less =3D a.frac < b.frac; + } + return a_less ^ ismin ? b : a; } =20 - if (a_sign =3D=3D b_sign) { + if (a.sign =3D=3D b.sign) { bool a_less =3D a_exp < b_exp; if (a_exp =3D=3D b_exp) { a_less =3D a.frac < b.frac; } - return a_sign ^ a_less ^ ismin ? b : a; + return a.sign ^ a_less ^ ismin ? b : a; } else { - return a_sign ^ ismin ? b : a; + return a.sign ^ ismin ? b : a; } } } --=20 2.7.4 From nobody Sat Oct 25 21:46:07 2025 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; 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 1521663572060721.074921506914; Wed, 21 Mar 2018 13:19:32 -0700 (PDT) Received: from localhost ([::1]:57153 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eykCl-0000ZW-5G for importer@patchew.org; Wed, 21 Mar 2018 16:19:27 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42159) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk5V-00029t-TA for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:12:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyk5R-0000z4-77 for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:57 -0400 Received: from out5-smtp.messagingengine.com ([66.111.4.29]:44607) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyk5R-0000xa-1J for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:53 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 6E952213F1; Wed, 21 Mar 2018 16:11:51 -0400 (EDT) Received: from frontend2 ([10.202.2.161]) by compute4.internal (MEProxy); Wed, 21 Mar 2018 16:11:51 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id 2181E240B3; Wed, 21 Mar 2018 16:11:51 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=mesmtp; bh=xNojSElq0plZMo iDZJRhftjHP17Q66UvAhwP52IUQQE=; b=0/5JACDNPp43LyeC9k/xsQWRNggm/M c5t4XL0htKI1hxnbQSVJelcU4I3lNkIMRinB1VseulbfGpbQPG28jVaXs7x4QXg7 /dTpFmoZ2bWLBSvR9YfsgBwNX28XY6yjC+FcVcxu4iS9K++J7BwcdoW9d+7iaAWt xuHPDLqM4QZII= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=xNojSElq0plZMoiDZJRhftjHP17Q66UvAhwP52IUQQE=; b=Wnvd+++4 Tht/I/jHCaR+/PdF3rVb5/sxhhGWdeGYel/0dAbxln+C0lkmtNQgAhwJhihd74la vNgPxSLX58sHXm0SZjmBU+3AZ5KK/mZbx8EhAv59Gh+eYUjKZLK7oQOmEStodQ4f Lrhn692SOe8DSoLPX7QSLHZ/wbqzE19UYeqVUL4IKH0Na3+U7M7rkBZxmX5oVoZE ZacN/IltQNsxi/87pBLUvTwh0nUzJmAH2konZxi70ps8abYconIz7SpirEFDwcMD 4rZEI2UlRh5YhsWzpe/viCyNJyJGHb0hiivs9Qrb+0muyH3IAFPgBeqZKN/jtLbZ vzQRA54YF/EGbQ== X-ME-Sender: From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 21 Mar 2018 16:11:39 -0400 Message-Id: <1521663109-32262-5-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1521663109-32262-1-git-send-email-cota@braap.org> References: <1521663109-32262-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.29 Subject: [Qemu-devel] [PATCH v1 04/14] fp-test: add muladd variants 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 , Mark Cave-Ayland , Richard Henderson , Laurent Vivier , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Aurelien Jarno Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" These are a few muladd-related operations that the original IBM syntax does not specify; model files for these are in muladd.fptest. Signed-off-by: Emilio G. Cota --- tests/fp-test/fp-test.c | 24 +++++++++++++++++++++ tests/fp-test/muladd.fptest | 51 +++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 75 insertions(+) create mode 100644 tests/fp-test/muladd.fptest diff --git a/tests/fp-test/fp-test.c b/tests/fp-test/fp-test.c index 27637c4..2200d40 100644 --- a/tests/fp-test/fp-test.c +++ b/tests/fp-test/fp-test.c @@ -53,6 +53,9 @@ enum op { OP_SUB, OP_MUL, OP_MULADD, + OP_MULADD_NEG_ADDEND, + OP_MULADD_NEG_PRODUCT, + OP_MULADD_NEG_RESULT, OP_DIV, OP_SQRT, OP_MINNUM, @@ -69,6 +72,9 @@ static const struct op_desc ops[] =3D { [OP_SUB] =3D { "-", 2 }, [OP_MUL] =3D { "*", 2 }, [OP_MULADD] =3D { "*+", 3 }, + [OP_MULADD_NEG_ADDEND] =3D { "*+nc", 3 }, + [OP_MULADD_NEG_PRODUCT] =3D { "*+np", 3 }, + [OP_MULADD_NEG_RESULT] =3D { "*+nr", 3 }, [OP_DIV] =3D { "/", 2 }, [OP_SQRT] =3D { "V", 1 }, [OP_MINNUM] =3D { " Q i +b32*+nc =3D0 -1.7FFFFFP127 -Inf +Inf -> Q i +b32*+nc =3D0 -1.6C9AE7P113 -Inf +Inf -> Q i +b32*+nc =3D0 -1.000000P-126 -Inf +Inf -> Q i +b32*+nc =3D0 -0.7FFFFFP-126 -Inf +Inf -> Q i +b32*+nc =3D0 -0.1B977AP-126 -Inf +Inf -> Q i +b32*+nc =3D0 -0.000001P-126 -Inf +Inf -> Q i +b32*+nc =3D0 -1.000000P0 -Inf +Inf -> Q i +b32*+nc =3D0 -Zero -Inf +Inf -> Q i +b32*+nc =3D0 +Zero -Inf +Inf -> Q i +b32*+nc =3D0 -Zero -1.000000P-126 +1.7FFFFFP127 -> -1.7FFFFFP127 +b32*+nc =3D0 +Zero -1.000000P-126 +1.7FFFFFP127 -> -1.7FFFFFP127 +b32*+nc =3D0 -1.000000P-126 -1.7FFFFFP127 -1.4B9156P109 -> +1.4B9156P109 x +b32*+nc =3D0 -0.7FFFFFP-126 -1.7FFFFFP127 -1.51BA59P-113 -> +1.7FFFFDP1 x +b32*+nc =3D0 -0.3D6B57P-126 -1.7FFFFFP127 -1.265398P-67 -> +1.75AD5BP0 x +b32*+nc =3D0 -0.000001P-126 -1.7FFFFFP127 -1.677330P-113 -> +1.7FFFFFP-22 x + +# np =3D=3D negate product +b32*+np =3D0 +Inf -Inf -Inf -> Q i +b32*+np =3D0 +1.7FFFFFP127 -Inf -Inf -> Q i +b32*+np =3D0 +1.6C9AE7P113 -Inf -Inf -> Q i +b32*+np =3D0 +1.000000P-126 -Inf -Inf -> Q i +b32*+np =3D0 +0.7FFFFFP-126 -Inf -Inf -> Q i +b32*+np =3D0 +0.1B977AP-126 -Inf -Inf -> Q i +b32*+np =3D0 +0.000001P-126 -Inf -Inf -> Q i +b32*+np =3D0 +1.000000P0 -Inf -Inf -> Q i +b32*+np =3D0 +Zero -Inf -Inf -> Q i +b32*+np =3D0 +Zero -Inf -Inf -> Q i +b32*+np =3D0 -Zero -1.000000P-126 -1.7FFFFFP127 -> -1.7FFFFFP127 +b32*+np =3D0 +Zero -1.000000P-126 -1.7FFFFFP127 -> -1.7FFFFFP127 +b32*+np =3D0 -1.3A6A89P-18 +1.24E7AEP9 -0.7FFFFFP-126 -> +1.7029E9P-9 x + +# nr =3D=3D negate result +b32*+nr =3D0 -Inf -Inf -Inf -> Q i +b32*+nr =3D0 -1.7FFFFFP127 -Inf -Inf -> Q i +b32*+nr =3D0 -1.6C9AE7P113 -Inf -Inf -> Q i +b32*+nr =3D0 -1.000000P-126 -Inf -Inf -> Q i +b32*+nr =3D0 -0.7FFFFFP-126 -Inf -Inf -> Q i +b32*+nr =3D0 -0.1B977AP-126 -Inf -Inf -> Q i +b32*+nr =3D0 -0.000001P-126 -Inf -Inf -> Q i +b32*+nr =3D0 -1.000000P0 -Inf -Inf -> Q i +b32*+nr =3D0 -Zero -Inf -Inf -> Q i +b32*+nr =3D0 -Zero -Inf -Inf -> Q i +b32*+nr =3D0 +Zero -1.000000P-126 -1.7FFFFFP127 -> +1.7FFFFFP127 +b32*+nr =3D0 -Zero -1.000000P-126 -1.7FFFFFP127 -> +1.7FFFFFP127 +b32*+nr =3D0 -1.000000P-126 -1.7FFFFFP127 -1.4B9156P109 -> +1.4B9156P109 x +b32*+nr =3D0 -0.7FFFFFP-126 -1.7FFFFFP127 -1.51BA59P-113 -> -1.7FFFFDP1 x +b32*+nr =3D0 -0.3D6B57P-126 -1.7FFFFFP127 -1.265398P-67 -> -1.75AD5BP0 x +b32*+nr =3D0 -0.000001P-126 -1.7FFFFFP127 -1.677330P-113 -> -1.7FFFFFP-22 x +b32*+nr =3D0 +1.72E53AP-33 -1.7FFFFFP127 -1.5AA684P-2 -> +1.72E539P95 x --=20 2.7.4 From nobody Sat Oct 25 21:46:07 2025 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; 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 1521663571959574.0406835608429; Wed, 21 Mar 2018 13:19:31 -0700 (PDT) Received: from localhost ([::1]:57154 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eykCk-0000Zi-Nc for importer@patchew.org; Wed, 21 Mar 2018 16:19:26 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42170) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk5V-0002A0-VP for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyk5R-0000z9-7h for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:57 -0400 Received: from out5-smtp.messagingengine.com ([66.111.4.29]:53047) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyk5R-0000y5-2Q for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:53 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 9F8B7213FE; Wed, 21 Mar 2018 16:11:51 -0400 (EDT) Received: from frontend1 ([10.202.2.160]) by compute4.internal (MEProxy); Wed, 21 Mar 2018 16:11:51 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id 5C11B7E0D6; Wed, 21 Mar 2018 16:11:51 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=mesmtp; bh=HE6UXBNwo14DCL f/TfCGmr0p+OqBXwgdhS2NsZpDOFY=; b=HZNdTwA7cRrLMjJA8iIZ1M/l4nQril wP3QjINLbqsOXPajzHpUB2g5Nd+XoQwskQZwqUDbumz7cnPtvYyg0wI8iexnronp VHqFSesG6Rcc+Do08pSAfuSkzKEpS7GYQRDuZ7W5TvcqkhWejFKc8Dc+u8uHXge4 Tg0berO0kd4jM= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=HE6UXBNwo14DCLf/TfCGmr0p+OqBXwgdhS2NsZpDOFY=; b=NSSmZZp9 QqAieDxBdhIh3M1n5b+B0JU7U5rOjL9+MxoWKphzOMnx8gPrfZHVNMmmmJvFH4zk zgBVFAbYFaXLLyBybLvV4s/Qct1XvusvDJp5uyahr4CuEPpg5eLQHmACTwYj0EEF NLW3xUjuxLiz1lF78DjIR5QnqYIEGToPDLcigIxs8pv7ZGyzZrdlNHcIeqdywxyl F+nie0HgrgQG80KmVP2MaR1XJVi1nXKiqm7HzpPdXsD0+AT/5b+seLdjorh07tQL m56MSqNlxW/eHcpGwLblDT/51fEdthCs885cAl/nD6zB131MtpefoCCSLxcQrO+s enW7bCcDr8jRwQ== X-ME-Sender: From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 21 Mar 2018 16:11:40 -0400 Message-Id: <1521663109-32262-6-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1521663109-32262-1-git-send-email-cota@braap.org> References: <1521663109-32262-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.29 Subject: [Qemu-devel] [PATCH v1 05/14] softfloat: add float32_is_normal and float64_is_normal 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 , Mark Cave-Ayland , Richard Henderson , Laurent Vivier , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Aurelien Jarno Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This paves the way for upcoming work. Signed-off-by: Emilio G. Cota Reviewed-by: Alex Benn=C3=A9e --- include/fpu/softfloat.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 36626a5..7b9d31c 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -402,6 +402,11 @@ static inline int float32_is_zero(float32 a) return (float32_val(a) & 0x7fffffff) =3D=3D 0; } =20 +static inline bool float32_is_normal(float32 a) +{ + return ((float32_val(a) + 0x00800000) & 0x7fffffff) >=3D 0x01000000; +} + static inline int float32_is_any_nan(float32 a) { return ((float32_val(a) & ~(1 << 31)) > 0x7f800000UL); @@ -531,6 +536,11 @@ static inline int float64_is_zero(float64 a) return (float64_val(a) & 0x7fffffffffffffffLL) =3D=3D 0; } =20 +static inline bool float64_is_normal(float64 a) +{ + return ((float64_val(a) + (1ULL << 52)) & -1ULL >> 1) >=3D 1ULL << 53; +} + static inline int float64_is_any_nan(float64 a) { return ((float64_val(a) & ~(1ULL << 63)) > 0x7ff0000000000000ULL); --=20 2.7.4 From nobody Sat Oct 25 21:46:07 2025 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; 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 (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1521663245797242.89764663561948; Wed, 21 Mar 2018 13:14:05 -0700 (PDT) Received: from localhost ([::1]:57122 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk7P-0003Ou-ER for importer@patchew.org; Wed, 21 Mar 2018 16:13:55 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42164) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk5V-00029x-V7 for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyk5R-0000yy-6f for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:57 -0400 Received: from out5-smtp.messagingengine.com ([66.111.4.29]:53301) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyk5R-0000y4-0N for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:53 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id C627A20C2B; Wed, 21 Mar 2018 16:11:51 -0400 (EDT) Received: from frontend2 ([10.202.2.161]) by compute4.internal (MEProxy); Wed, 21 Mar 2018 16:11:51 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id 8B7A4240B3; Wed, 21 Mar 2018 16:11:51 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=mesmtp; bh=tSx/mS+tOkT0qr FlNGeSdHUK1T5YsIS7exhwkkK1Cfk=; b=UOoZv04Gcu7mfMSAQDpY0fenzIlWpm ZkBGpPJ3XAZSTP3e4EGGXYymrtuRfP6gnkgpVCaIOPdMSA060iDdkXAMZQL4sK3y ipsJ+8wGZF9J7TMIPr4ZLq6ZsqZyaH6wsBRM5W5RB7aR4+iFhY8k3qDUu3MfHFl1 ne+mga9caoX0U= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=tSx/mS+tOkT0qrFlNGeSdHUK1T5YsIS7exhwkkK1Cfk=; b=hFobb4tt /Ufwn/jHbEEQSQLMAJEb06OWLuDRji9NKHA9yklPNVyoIAgNEZugZpF4bcTHR/vW GhxqjLhSCSFpAjKRLUr8WCxmHPPNM1uP0iG6zp+a5CTQeZAt3Ro6S9Lcka1NP5iU C0yT27Go8cbW4i2sWUVS0pUYH8OJJ19nqd5G/AYznCrQ3/OXRr38e4/FvYpgwqCu M7NgWdHyKIFBv7WyLeA9K3SuPepfG8fxYdVooWAaUKsT+Ya3VWvqhfrhn3iw/WYY lLPj74xAQrgfrIq+BUK5pXhnwdicWzLg+/HnX0gz49OFgihSp/bjfjVwq41kLpyn 2Retn4ACXa+32g== X-ME-Sender: From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 21 Mar 2018 16:11:41 -0400 Message-Id: <1521663109-32262-7-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1521663109-32262-1-git-send-email-cota@braap.org> References: <1521663109-32262-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.29 Subject: [Qemu-devel] [PATCH v1 06/14] softfloat: add float32_is_denormal and float64_is_denormal 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 , Mark Cave-Ayland , Richard Henderson , Laurent Vivier , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Aurelien Jarno Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This paves the way for upcoming work. Signed-off-by: Emilio G. Cota Reviewed-by: Alex Benn=C3=A9e --- include/fpu/softfloat.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 7b9d31c..8fb44a8 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -417,6 +417,11 @@ static inline int float32_is_zero_or_denormal(float32 = a) return (float32_val(a) & 0x7f800000) =3D=3D 0; } =20 +static inline bool float32_is_denormal(float32 a) +{ + return float32_is_zero_or_denormal(a) && !float32_is_zero(a); +} + static inline float32 float32_set_sign(float32 a, int sign) { return make_float32((float32_val(a) & 0x7fffffff) | (sign << 31)); @@ -551,6 +556,11 @@ static inline int float64_is_zero_or_denormal(float64 = a) return (float64_val(a) & 0x7ff0000000000000LL) =3D=3D 0; } =20 +static inline bool float64_is_denormal(float64 a) +{ + return float64_is_zero_or_denormal(a) && !float64_is_zero(a); +} + static inline float64 float64_set_sign(float64 a, int sign) { return make_float64((float64_val(a) & 0x7fffffffffffffffULL) --=20 2.7.4 From nobody Sat Oct 25 21:46:07 2025 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; 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 1521664114624705.4678697468104; Wed, 21 Mar 2018 13:28:34 -0700 (PDT) Received: from localhost ([::1]:57211 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eykLZ-0007g0-9D for importer@patchew.org; Wed, 21 Mar 2018 16:28:33 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42160) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk5V-00029u-TY for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:12:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyk5R-0000zE-9B for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:57 -0400 Received: from out5-smtp.messagingengine.com ([66.111.4.29]:60729) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyk5R-0000yA-1v for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:53 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 1E42C2140B; Wed, 21 Mar 2018 16:11:52 -0400 (EDT) Received: from frontend1 ([10.202.2.160]) by compute4.internal (MEProxy); Wed, 21 Mar 2018 16:11:52 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id C53BA7E16D; Wed, 21 Mar 2018 16:11:51 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=mesmtp; bh=ftaBGbC7QTUEqs J/+mluIqhvF47nKZxEUKe71/TIfPE=; b=0j4jlSG1kx+/LMEOCdOj39+ixYNaw+ eio5/eayD3DaviLjW6MTSdSCLzApHcI4YRXkPo4qPa629i2PLQvqkcLBr7Xw7+4b j8n2AC3FIU9WFc5t8YaZ4EIbfIPC8hV6y7WMcjN+KRYH7lMUY2ZuDfWonAVljg/U oC8RAnDHnSWe8= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=ftaBGbC7QTUEqsJ/+mluIqhvF47nKZxEUKe71/TIfPE=; b=moESHW4L 57u8iZt6LHmDCqlGUjJHRIOBZgJJXfrQpzNKIaMEeCc/sYPEiMahJ1kjQ4ZyUkxD 7VynJzAefA9FbovqiJWYVr5nwVwWtz91IPBO+AB2WNya8Fb4vSXRHLJg8uvjvV3/ jzkSMgvlQfUmDJ4V2YUt7/9UCTax6iSjspXy5PXuRArvPgDJ2hFx7Se9NhSaV2Bq JdRKSN9A95gMAHi1UUBGICGhN9y92FUMC5rGmIcObwjXz2zjUwHG1gNT85Y2Mqes wPw0KsORISBQrwuI8dcQIRXANW8RWMHCui/qNn730yDyYFI5ibxiI3Oar4gBrNwh Fa3q+V6NSMsR7w== X-ME-Sender: From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 21 Mar 2018 16:11:42 -0400 Message-Id: <1521663109-32262-8-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1521663109-32262-1-git-send-email-cota@braap.org> References: <1521663109-32262-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.29 Subject: [Qemu-devel] [PATCH v1 07/14] fpu: introduce hostfloat 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 , Mark Cave-Ayland , Richard Henderson , Laurent Vivier , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Aurelien Jarno Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The appended paves the way for leveraging the host FPU for a subset of guest FP operations. For most guest workloads (e.g. FP flags aren't ever cleared, inexact occurs often and rounding is set to the default [to nearest]) this will yield sizable performance speedups. The approach followed here avoids checking the FP exception flags register. See the comment at the top of hostfloat.c for details. This assumes that QEMU is running on an IEEE754-compliant FPU and that the rounding is set to the default (to nearest). The implementation-dependent specifics of the FPU should not matter; things like tininess detection and snan representation are still dealt with in soft-fp. However, this approach will break on most hosts if we compile QEMU with flags such as -ffast-math. We control the flags so this should be easy to enforce though. The licensing in softfloat.h is complicated at best, so to keep things simple I'm adding this as a separate, GPL'ed file. This patch just adds some boilerplate code; subsequent patches add operations, one per commit to ease bisection. Signed-off-by: Emilio G. Cota --- Makefile.target | 2 +- include/fpu/hostfloat.h | 14 +++++++ include/fpu/softfloat.h | 1 + fpu/hostfloat.c | 96 +++++++++++++++++++++++++++++++++++++++++++= ++++ target/m68k/Makefile.objs | 2 +- tests/fp-test/Makefile | 2 +- 6 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 include/fpu/hostfloat.h create mode 100644 fpu/hostfloat.c diff --git a/Makefile.target b/Makefile.target index 6549481..efcdfb9 100644 --- a/Makefile.target +++ b/Makefile.target @@ -97,7 +97,7 @@ obj-$(CONFIG_TCG) +=3D tcg/tcg.o tcg/tcg-op.o tcg/tcg-op-= vec.o tcg/tcg-op-gvec.o obj-$(CONFIG_TCG) +=3D tcg/tcg-common.o tcg/optimize.o obj-$(CONFIG_TCG_INTERPRETER) +=3D tcg/tci.o obj-$(CONFIG_TCG_INTERPRETER) +=3D disas/tci.o -obj-y +=3D fpu/softfloat.o +obj-y +=3D fpu/softfloat.o fpu/hostfloat.o obj-y +=3D target/$(TARGET_BASE_ARCH)/ obj-y +=3D disas.o obj-$(call notempty,$(TARGET_XML_FILES)) +=3D gdbstub-xml.o diff --git a/include/fpu/hostfloat.h b/include/fpu/hostfloat.h new file mode 100644 index 0000000..b01291b --- /dev/null +++ b/include/fpu/hostfloat.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2018, Emilio G. Cota + * + * License: GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#ifndef HOSTFLOAT_H +#define HOSTFLOAT_H + +#ifndef SOFTFLOAT_H +#error fpu/hostfloat.h must only be included from softfloat.h +#endif + +#endif /* HOSTFLOAT_H */ diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 8fb44a8..8963b68 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -95,6 +95,7 @@ enum { }; =20 #include "fpu/softfloat-types.h" +#include "fpu/hostfloat.h" =20 static inline void set_float_detect_tininess(int val, float_status *status) { diff --git a/fpu/hostfloat.c b/fpu/hostfloat.c new file mode 100644 index 0000000..cab0341 --- /dev/null +++ b/fpu/hostfloat.c @@ -0,0 +1,96 @@ +/* + * hostfloat.c - FP primitives that use the host's FPU whenever possible. + * + * Copyright (C) 2018, Emilio G. Cota + * + * License: GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + * Fast emulation of guest FP instructions is challenging for two reasons. + * First, FP instruction semantics are similar but not identical, particul= arly + * when handling NaNs. Second, emulating at reasonable speed the guest FP + * exception flags is not trivial: reading the host's flags register with a + * feclearexcept & fetestexcept pair is slow [slightly slower than soft-fp= ], + * and trapping on every FP exception is not fast nor pleasant to work wit= h. + * + * This module leverages the host FPU for a subset of the operations. To + * do this it follows the main idea presented in this paper: + * + * Guo, Yu-Chuan, et al. "Translating the ARM Neon and VFP instructions in= a + * binary translator." Software: Practice and Experience 46.12 (2016):1591= -1615. + * + * The idea is thus to leverage the host FPU to (1) compute FP operations + * and (2) identify whether FP exceptions occurred while avoiding + * expensive exception flag register accesses. + * + * An important optimization shown in the paper is that given that excepti= on + * flags are rarely cleared by the guest, we can avoid recomputing some fl= ags. + * This is particularly useful for the inexact flag, which is very frequen= tly + * raised in floating-point workloads. + * + * We optimize the code further by deferring to soft-fp whenever FP + * exception detection might get hairy. Fortunately this is not common. + */ +#include + +#include "qemu/osdep.h" +#include "fpu/softfloat.h" + +#define GEN_TYPE_CONV(name, to_t, from_t) \ + static inline to_t name(from_t a) \ + { \ + to_t r =3D *(to_t *)&a; \ + return r; \ + } + +GEN_TYPE_CONV(float32_to_float, float, float32) +GEN_TYPE_CONV(float64_to_double, double, float64) +GEN_TYPE_CONV(float_to_float32, float32, float) +GEN_TYPE_CONV(double_to_float64, float64, double) +#undef GEN_TYPE_CONV + +#define GEN_INPUT_FLUSH(soft_t) \ + static inline __attribute__((always_inline)) void \ + soft_t ## _input_flush__nocheck(soft_t *a, float_status *s) \ + { \ + if (unlikely(soft_t ## _is_denormal(*a))) { \ + *a =3D soft_t ## _set_sign(soft_t ## _zero, \ + soft_t ## _is_neg(*a)); \ + s->float_exception_flags |=3D float_flag_input_denormal; \ + } \ + } \ + \ + static inline __attribute__((always_inline)) void \ + soft_t ## _input_flush1(soft_t *a, float_status *s) \ + { \ + if (likely(!s->flush_inputs_to_zero)) { \ + return; \ + } \ + soft_t ## _input_flush__nocheck(a, s); \ + } \ + \ + static inline __attribute__((always_inline)) void \ + soft_t ## _input_flush2(soft_t *a, soft_t *b, float_status *s) \ + { \ + if (likely(!s->flush_inputs_to_zero)) { \ + return; \ + } \ + soft_t ## _input_flush__nocheck(a, s); \ + soft_t ## _input_flush__nocheck(b, s); \ + } \ + \ + static inline __attribute__((always_inline)) void \ + soft_t ## _input_flush3(soft_t *a, soft_t *b, soft_t *c, \ + float_status *s) \ + { \ + if (likely(!s->flush_inputs_to_zero)) { \ + return; \ + } \ + soft_t ## _input_flush__nocheck(a, s); \ + soft_t ## _input_flush__nocheck(b, s); \ + soft_t ## _input_flush__nocheck(c, s); \ + } + +GEN_INPUT_FLUSH(float32) +GEN_INPUT_FLUSH(float64) +#undef GEN_INPUT_FLUSH diff --git a/target/m68k/Makefile.objs b/target/m68k/Makefile.objs index ac61948..2868b11 100644 --- a/target/m68k/Makefile.objs +++ b/target/m68k/Makefile.objs @@ -1,5 +1,5 @@ obj-y +=3D m68k-semi.o obj-y +=3D translate.o op_helper.o helper.o cpu.o -obj-y +=3D fpu_helper.o softfloat.o +obj-y +=3D fpu_helper.o softfloat.o hostfloat.o obj-y +=3D gdbstub.o obj-$(CONFIG_SOFTMMU) +=3D monitor.o diff --git a/tests/fp-test/Makefile b/tests/fp-test/Makefile index 703434f..187cfcc 100644 --- a/tests/fp-test/Makefile +++ b/tests/fp-test/Makefile @@ -28,7 +28,7 @@ ibm: $(WHITELIST_FILES): wget -nv -O $@ http://www.cs.columbia.edu/~cota/qemu/fpbench-$@ =20 -fp-test$(EXESUF): fp-test.o softfloat.o +fp-test$(EXESUF): fp-test.o softfloat.o hostfloat.o =20 clean: rm -f *.o *.d $(OBJS) --=20 2.7.4 From nobody Sat Oct 25 21:46:07 2025 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; 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 (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1521663240335372.5832166134976; Wed, 21 Mar 2018 13:14:00 -0700 (PDT) Received: from localhost ([::1]:57126 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk7Q-0003Qo-Dm for importer@patchew.org; Wed, 21 Mar 2018 16:13:56 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42162) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk5V-00029v-U1 for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:12:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyk5R-0000zH-Ap for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:57 -0400 Received: from out5-smtp.messagingengine.com ([66.111.4.29]:52375) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyk5R-0000y7-2s for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:53 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 6352120FAF; Wed, 21 Mar 2018 16:11:52 -0400 (EDT) Received: from frontend2 ([10.202.2.161]) by compute4.internal (MEProxy); Wed, 21 Mar 2018 16:11:52 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id 0696224149; Wed, 21 Mar 2018 16:11:52 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=mesmtp; bh=29Je6dlTaWBQ73 vq9b69fzbKtN3aCHYbAz7K8cUUw9o=; b=P6gssXWhcRp6Duop1dBMc4sG2lwapM +dyxHpnPn6k3vtGmBeJW/1WTGPaFB2RtVQ/jzYN86N1VlFf1OBDHIS/Cx9RGdZgv cCAak5quEGGc9DBk1lYgFiQfAi4TDXGZ+DFYyiBtiJemXTT70vR/nZ7rIqiuSfXu xwW2SH0Obt8QQ= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=29Je6dlTaWBQ73vq9b69fzbKtN3aCHYbAz7K8cUUw9o=; b=Rt8NHJbz KU1povWJ+IAY5rwyjuUIqkP4Uizz0gPmSZGtzFks4HJPAhjfk0HK/m5fKqoQIaJO RpFeRNhOfd9hmIpHqr53g9wV6tWSI2zr6kV9uGOPhqsDFz45zC2Gm5bleA7boFz4 j8PHyV8/hcrhtCvfpy3+Px3OaNoFOGFMw+A0JPc6HGmBXNr1vrVhDCwBQDBqZScG Jt8jH0fRgJeKXx7AYtJIpqMvbQ7Tohig6IWIMIkQ7x2yJcHbVB4iERQBXgFjwqor h9+fGToXX4vQlP8sZl9VBUyFDhRjBFj2Hpz1MiAIOQoFAyUkVb6BkfiKdwh1K3cF 5hevdTj1dWkW4g== X-ME-Sender: From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 21 Mar 2018 16:11:43 -0400 Message-Id: <1521663109-32262-9-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1521663109-32262-1-git-send-email-cota@braap.org> References: <1521663109-32262-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.29 Subject: [Qemu-devel] [PATCH v1 08/14] hostfloat: support float32/64 addition and subtraction 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 , Mark Cave-Ayland , Richard Henderson , Laurent Vivier , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Aurelien Jarno Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Performance results (single and double precision) for fp-bench run under aarch64-linux-user on an Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz host: - before: add-single: 86.74 MFlops add-double: 86.46 MFlops sub-single: 83.33 MFlops sub-double: 84.57 MFlops - after: add-single: 188.26 MFlops add-double: 186.60 MFlops sub-single: 186.19 MFlops sub-double: 187.77 MFlops Signed-off-by: Emilio G. Cota --- include/fpu/hostfloat.h | 6 ++++++ include/fpu/softfloat.h | 8 ++++---- fpu/hostfloat.c | 50 +++++++++++++++++++++++++++++++++++++++++++++= ++++ fpu/softfloat.c | 16 ++++++++-------- 4 files changed, 68 insertions(+), 12 deletions(-) diff --git a/include/fpu/hostfloat.h b/include/fpu/hostfloat.h index b01291b..db49efa 100644 --- a/include/fpu/hostfloat.h +++ b/include/fpu/hostfloat.h @@ -11,4 +11,10 @@ #error fpu/hostfloat.h must only be included from softfloat.h #endif =20 +float32 float32_add(float32 a, float32 b, float_status *status); +float32 float32_sub(float32 a, float32 b, float_status *status); + +float64 float64_add(float64 a, float64 b, float_status *status); +float64 float64_sub(float64 a, float64 b, float_status *status); + #endif /* HOSTFLOAT_H */ diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 8963b68..eb7e9bc 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -342,8 +342,8 @@ float128 float32_to_float128(float32, float_status *sta= tus); | Software IEC/IEEE single-precision operations. *-------------------------------------------------------------------------= ---*/ float32 float32_round_to_int(float32, float_status *status); -float32 float32_add(float32, float32, float_status *status); -float32 float32_sub(float32, float32, float_status *status); +float32 soft_float32_add(float32, float32, float_status *status); +float32 soft_float32_sub(float32, float32, float_status *status); float32 float32_mul(float32, float32, float_status *status); float32 float32_div(float32, float32, float_status *status); float32 float32_rem(float32, float32, float_status *status); @@ -482,8 +482,8 @@ float128 float64_to_float128(float64, float_status *sta= tus); *-------------------------------------------------------------------------= ---*/ 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 soft_float64_add(float64, float64, float_status *status); +float64 soft_float64_sub(float64, float64, float_status *status); float64 float64_mul(float64, float64, float_status *status); float64 float64_div(float64, float64, float_status *status); float64 float64_rem(float64, float64, float_status *status); diff --git a/fpu/hostfloat.c b/fpu/hostfloat.c index cab0341..502552b 100644 --- a/fpu/hostfloat.c +++ b/fpu/hostfloat.c @@ -94,3 +94,53 @@ GEN_TYPE_CONV(double_to_float64, float64, double) GEN_INPUT_FLUSH(float32) GEN_INPUT_FLUSH(float64) #undef GEN_INPUT_FLUSH + +#define GEN_FPU_ADDSUB(add_name, sub_name, soft_t, host_t, \ + host_abs_func, min_normal) \ + static inline __attribute__((always_inline)) soft_t \ + fpu_ ## soft_t ## _addsub(soft_t a, soft_t b, bool subtract, \ + float_status *s) \ + { \ + soft_t ## _input_flush2(&a, &b, s); \ + if (likely((soft_t ## _is_normal(a) || soft_t ## _is_zero(a)) && \ + (soft_t ## _is_normal(b) || soft_t ## _is_zero(b)) && \ + s->float_exception_flags & float_flag_inexact && \ + s->float_rounding_mode =3D=3D float_round_nearest_even)= ) { \ + host_t ha =3D soft_t ## _to_ ## host_t(a); \ + host_t hb =3D soft_t ## _to_ ## host_t(b); \ + host_t hr; \ + soft_t r; \ + \ + if (subtract) { \ + hb =3D -hb; \ + } \ + hr =3D ha + hb; \ + r =3D host_t ## _to_ ## soft_t(hr); \ + if (unlikely(soft_t ## _is_infinity(r))) { \ + s->float_exception_flags |=3D float_flag_overflow; \ + } else if (unlikely(host_abs_func(hr) <=3D min_normal)) { \ + goto soft; \ + } \ + return r; \ + } \ + soft: \ + if (subtract) { \ + return soft_ ## soft_t ## _sub(a, b, s); \ + } else { \ + return soft_ ## soft_t ## _add(a, b, s); \ + } \ + } \ + \ + soft_t add_name(soft_t a, soft_t b, float_status *status) \ + { \ + return fpu_ ## soft_t ## _addsub(a, b, false, status); \ + } \ + \ + soft_t sub_name(soft_t a, soft_t b, float_status *status) \ + { \ + return fpu_ ## soft_t ## _addsub(a, b, true, status); \ + } \ + +GEN_FPU_ADDSUB(float32_add, float32_sub, float32, float, fabsf, FLT_MIN) +GEN_FPU_ADDSUB(float64_add, float64_sub, float64, double, fabs, DBL_MIN) +#undef GEN_FPU_ADDSUB diff --git a/fpu/softfloat.c b/fpu/softfloat.c index ee615a9..bd82adf 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -738,8 +738,8 @@ float16 __attribute__((flatten)) float16_add(float16 a= , float16 b, return float16_round_pack_canonical(pr, status); } =20 -float32 __attribute__((flatten)) float32_add(float32 a, float32 b, - float_status *status) +float32 __attribute__((flatten)) soft_float32_add(float32 a, float32 b, + float_status *status) { FloatParts pa =3D float32_unpack_canonical(a, status); FloatParts pb =3D float32_unpack_canonical(b, status); @@ -748,8 +748,8 @@ float32 __attribute__((flatten)) float32_add(float32 a,= float32 b, return float32_round_pack_canonical(pr, status); } =20 -float64 __attribute__((flatten)) float64_add(float64 a, float64 b, - float_status *status) +float64 __attribute__((flatten)) soft_float64_add(float64 a, float64 b, + float_status *status) { FloatParts pa =3D float64_unpack_canonical(a, status); FloatParts pb =3D float64_unpack_canonical(b, status); @@ -768,8 +768,8 @@ float16 __attribute__((flatten)) float16_sub(float16 a,= float16 b, return float16_round_pack_canonical(pr, status); } =20 -float32 __attribute__((flatten)) float32_sub(float32 a, float32 b, - float_status *status) +float32 __attribute__((flatten)) soft_float32_sub(float32 a, float32 b, + float_status *status) { FloatParts pa =3D float32_unpack_canonical(a, status); FloatParts pb =3D float32_unpack_canonical(b, status); @@ -778,8 +778,8 @@ float32 __attribute__((flatten)) float32_sub(float32 a,= float32 b, return float32_round_pack_canonical(pr, status); } =20 -float64 __attribute__((flatten)) float64_sub(float64 a, float64 b, - float_status *status) +float64 __attribute__((flatten)) soft_float64_sub(float64 a, float64 b, + float_status *status) { FloatParts pa =3D float64_unpack_canonical(a, status); FloatParts pb =3D float64_unpack_canonical(b, status); --=20 2.7.4 From nobody Sat Oct 25 21:46:07 2025 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; 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 1521663239936129.2255928929892; Wed, 21 Mar 2018 13:13:59 -0700 (PDT) Received: from localhost ([::1]:57124 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk7Q-0003QR-V9 for importer@patchew.org; Wed, 21 Mar 2018 16:13:57 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42180) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk5W-0002A4-0O for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:12:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyk5R-0000zT-E8 for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:57 -0400 Received: from out5-smtp.messagingengine.com ([66.111.4.29]:33073) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyk5R-0000yO-6V for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:53 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id A32E321447; Wed, 21 Mar 2018 16:11:52 -0400 (EDT) Received: from frontend1 ([10.202.2.160]) by compute4.internal (MEProxy); Wed, 21 Mar 2018 16:11:52 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id 4C3567E0D6; Wed, 21 Mar 2018 16:11:52 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=mesmtp; bh=5rGPVB1l0E/Z52 9afKzfxIsYSbSoafsT8C/UClg+nck=; b=XAforwM4F6MHcrW8UdJp14gk2Ct1yJ tbf9GQLir6HXD5PT2LzjbX/Wb0nZRtVYtCcU2dfTESeuhHoumf/bsZ+3Ds+dGt3D clwh933cs/L3Bv6gWaxzay6U7un8xKmgjtNdG/F4gKFUwzTA+cXRMyA2FsSE0sGV Q2vBqdzgRA4G4= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=5rGPVB1l0E/Z529afKzfxIsYSbSoafsT8C/UClg+nck=; b=leKpg0+T x/I17KyI5qdCrAA4Sd3ABk51bMZgE17CMeNSEq2doALv2gOVQWOWCmI/AsRZUe80 uppqdOoXJPsqcg3FsOqCO7/fpzlb9KFUzsL1CA/2H+r+ZOiUaELs6tm2jm9Dgfaf +PtdOId16RSrg0b98MVcT1Ujop13M/MSqfbJwl1LSoKbV0T0+Gh7jb9hsC9LNlmd tDh5Cz4LitDVahHMDa8+pzeP4AfK0Z58mjKk93iWH7ZlQ9wXVUIc3WzkUAGTrSjI fAxibYdE2oAh7cJkJemAV3QzxAXA2C/+FaWBrpm6cyxjBwcLgYwXOrnQXq3T175q hqnTrAWlhG8WUg== X-ME-Sender: From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 21 Mar 2018 16:11:44 -0400 Message-Id: <1521663109-32262-10-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1521663109-32262-1-git-send-email-cota@braap.org> References: <1521663109-32262-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.29 Subject: [Qemu-devel] [PATCH v1 09/14] hostfloat: support float32/64 multiplication 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 , Mark Cave-Ayland , Richard Henderson , Laurent Vivier , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Aurelien Jarno Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Note that special-casing "a_is_zero || b_is_zero" pays off--see the last patch in this series for performance numbers on that. Performance results for fp-bench run under aarch64-linux-user on an Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz host: - before: mul-single: 86.17 MFlops mul-double: 87.74 MFlops - after: mul-single: 114.74 MFlops mul-double: 112.33 MFlops Signed-off-by: Emilio G. Cota --- include/fpu/hostfloat.h | 2 ++ include/fpu/softfloat.h | 4 ++-- fpu/hostfloat.c | 34 ++++++++++++++++++++++++++++++++++ fpu/softfloat.c | 8 ++++---- 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/include/fpu/hostfloat.h b/include/fpu/hostfloat.h index db49efa..7049f7e 100644 --- a/include/fpu/hostfloat.h +++ b/include/fpu/hostfloat.h @@ -13,8 +13,10 @@ =20 float32 float32_add(float32 a, float32 b, float_status *status); float32 float32_sub(float32 a, float32 b, float_status *status); +float32 float32_mul(float32 a, float32 b, float_status *status); =20 float64 float64_add(float64 a, float64 b, float_status *status); float64 float64_sub(float64 a, float64 b, float_status *status); +float64 float64_mul(float64 a, float64 b, float_status *status); =20 #endif /* HOSTFLOAT_H */ diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index eb7e9bc..2b07ae8 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -344,7 +344,7 @@ float128 float32_to_float128(float32, float_status *sta= tus); float32 float32_round_to_int(float32, float_status *status); float32 soft_float32_add(float32, float32, float_status *status); float32 soft_float32_sub(float32, float32, float_status *status); -float32 float32_mul(float32, float32, float_status *status); +float32 soft_float32_mul(float32, float32, float_status *status); float32 float32_div(float32, float32, float_status *status); float32 float32_rem(float32, float32, float_status *status); float32 float32_muladd(float32, float32, float32, int, float_status *statu= s); @@ -484,7 +484,7 @@ float64 float64_round_to_int(float64, float_status *sta= tus); float64 float64_trunc_to_int(float64, float_status *status); float64 soft_float64_add(float64, float64, float_status *status); float64 soft_float64_sub(float64, float64, float_status *status); -float64 float64_mul(float64, float64, float_status *status); +float64 soft_float64_mul(float64, float64, float_status *status); float64 float64_div(float64, float64, float_status *status); float64 float64_rem(float64, float64, float_status *status); float64 float64_muladd(float64, float64, float64, int, float_status *statu= s); diff --git a/fpu/hostfloat.c b/fpu/hostfloat.c index 502552b..985d6f1 100644 --- a/fpu/hostfloat.c +++ b/fpu/hostfloat.c @@ -144,3 +144,37 @@ GEN_INPUT_FLUSH(float64) GEN_FPU_ADDSUB(float32_add, float32_sub, float32, float, fabsf, FLT_MIN) GEN_FPU_ADDSUB(float64_add, float64_sub, float64, double, fabs, DBL_MIN) #undef GEN_FPU_ADDSUB + +#define GEN_FPU_MUL(name, soft_t, host_t, host_abs_func, min_normal) \ + soft_t name(soft_t a, soft_t b, float_status *s) \ + { \ + soft_t ## _input_flush2(&a, &b, s); \ + if (likely((soft_t ## _is_normal(a) || soft_t ## _is_zero(a)) && \ + (soft_t ## _is_normal(b) || soft_t ## _is_zero(b)) && \ + s->float_exception_flags & float_flag_inexact && \ + s->float_rounding_mode =3D=3D float_round_nearest_even)= ) { \ + if (soft_t ## _is_zero(a) || soft_t ## _is_zero(b)) { \ + bool signbit =3D soft_t ## _is_neg(a) ^ soft_t ## _is_neg(= b); \ + \ + return soft_t ## _set_sign(soft_t ## _zero, signbit); \ + } else { \ + host_t ha =3D soft_t ## _to_ ## host_t(a); \ + host_t hb =3D soft_t ## _to_ ## host_t(b); \ + host_t hr =3D ha * hb; \ + soft_t r =3D host_t ## _to_ ## soft_t(hr); \ + \ + if (unlikely(soft_t ## _is_infinity(r))) { \ + s->float_exception_flags |=3D float_flag_overflow; \ + } else if (unlikely(host_abs_func(hr) <=3D min_normal)) { \ + goto soft; \ + } \ + return r; \ + } \ + } \ + soft: \ + return soft_ ## soft_t ## _mul(a, b, s); \ + } + +GEN_FPU_MUL(float32_mul, float32, float, fabsf, FLT_MIN) +GEN_FPU_MUL(float64_mul, float64, double, fabs, DBL_MIN) +#undef GEN_FPU_MUL diff --git a/fpu/softfloat.c b/fpu/softfloat.c index bd82adf..e3f2918 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -849,8 +849,8 @@ float16 __attribute__((flatten)) float16_mul(float16 a,= float16 b, return float16_round_pack_canonical(pr, status); } =20 -float32 __attribute__((flatten)) float32_mul(float32 a, float32 b, - float_status *status) +float32 __attribute__((flatten)) +soft_float32_mul(float32 a, float32 b, float_status *status) { FloatParts pa =3D float32_unpack_canonical(a, status); FloatParts pb =3D float32_unpack_canonical(b, status); @@ -859,8 +859,8 @@ float32 __attribute__((flatten)) float32_mul(float32 a,= float32 b, return float32_round_pack_canonical(pr, status); } =20 -float64 __attribute__((flatten)) float64_mul(float64 a, float64 b, - float_status *status) +float64 __attribute__((flatten)) +soft_float64_mul(float64 a, float64 b, float_status *status) { FloatParts pa =3D float64_unpack_canonical(a, status); FloatParts pb =3D float64_unpack_canonical(b, status); --=20 2.7.4 From nobody Sat Oct 25 21:46:07 2025 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; 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 (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 152166386428017.28213175554265; Wed, 21 Mar 2018 13:24:24 -0700 (PDT) Received: from localhost ([::1]:57188 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eykHQ-0004WJ-Cd for importer@patchew.org; Wed, 21 Mar 2018 16:24:16 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42157) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk5V-00029q-Sc for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:12:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyk5R-0000zb-EA for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:57 -0400 Received: from out5-smtp.messagingengine.com ([66.111.4.29]:34761) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyk5R-0000yR-6S for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:53 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id CC7A6213BA; Wed, 21 Mar 2018 16:11:52 -0400 (EDT) Received: from frontend2 ([10.202.2.161]) by compute4.internal (MEProxy); Wed, 21 Mar 2018 16:11:52 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id 82CBE24149; Wed, 21 Mar 2018 16:11:52 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=mesmtp; bh=ek9piP889EJ37z qkZ5hXxltUx2T2xnUB13A0VRBFSiU=; b=fFSAvKNzALfUD9SoNu9rf/sXSXIxi/ +zaNAQ8ibpncxYADNit6S+NmU6Wt31OVEwOHdHUJiaEXJI4J78mbyr8nhX5HMxhn a/oZOotO+kwQQYP02KyguI5jBxQA7z5IakSvjSzsQKy5tLzEPW4PhHEfFbPo3DuE s14P8TM9VNdw8= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=ek9piP889EJ37zqkZ5hXxltUx2T2xnUB13A0VRBFSiU=; b=Xe9kdAyB ZG/X1wJuTpuJPx9HdsCi0KwNFX41fKrwCDa0J0f8aC5WWaEt8+pvM1S4g6CCGMEE lrCRphgdfeI1IQ0kycgYMQuW/jGiU9yxEq7CJwnjvGuwWOyZZD7Z6UpaouzOSkDn JAuvpx+cTjDGE89gSk3AxvWwBPyyvz2UXCsCwkxMf9EbP4TN4NLsQVWRD3x/VXBz fJrub4ve79gJ48fjpJhr0jkjO5hR5SYbR1Vd9ABw+dhaY43/npMMYi2XAd0WLde5 yHJZo+vBDK10H0+ZcV2xX2ZIZ4oDXpveVoMjJeIzBZT19LhFnrV/cYwQYhEqkQ9p CUlnmKOZSeS0ug== X-ME-Sender: From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 21 Mar 2018 16:11:45 -0400 Message-Id: <1521663109-32262-11-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1521663109-32262-1-git-send-email-cota@braap.org> References: <1521663109-32262-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.29 Subject: [Qemu-devel] [PATCH v1 10/14] hostfloat: support float32/64 division 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 , Mark Cave-Ayland , Richard Henderson , Laurent Vivier , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Aurelien Jarno Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Performance results for fp-bench run under aarch64-linux-user on an Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz host: - before: div-single: 29.77 MFlops div-double: 29.85 MFlops - after: div-single: 85.90 MFlops div-double: 86.10 MFlops Signed-off-by: Emilio G. Cota --- include/fpu/hostfloat.h | 2 ++ include/fpu/softfloat.h | 4 ++-- fpu/hostfloat.c | 28 ++++++++++++++++++++++++++++ fpu/softfloat.c | 4 ++-- 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/include/fpu/hostfloat.h b/include/fpu/hostfloat.h index 7049f7e..61a8525 100644 --- a/include/fpu/hostfloat.h +++ b/include/fpu/hostfloat.h @@ -14,9 +14,11 @@ float32 float32_add(float32 a, float32 b, float_status *status); float32 float32_sub(float32 a, float32 b, float_status *status); float32 float32_mul(float32 a, float32 b, float_status *status); +float32 float32_div(float32 a, float32 b, float_status *status); =20 float64 float64_add(float64 a, float64 b, float_status *status); float64 float64_sub(float64 a, float64 b, float_status *status); float64 float64_mul(float64 a, float64 b, float_status *status); +float64 float64_div(float64 a, float64 b, float_status *status); =20 #endif /* HOSTFLOAT_H */ diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 2b07ae8..a690a57 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -345,7 +345,7 @@ float32 float32_round_to_int(float32, float_status *sta= tus); float32 soft_float32_add(float32, float32, float_status *status); float32 soft_float32_sub(float32, float32, float_status *status); float32 soft_float32_mul(float32, float32, float_status *status); -float32 float32_div(float32, float32, float_status *status); +float32 soft_float32_div(float32, float32, float_status *status); float32 float32_rem(float32, float32, float_status *status); float32 float32_muladd(float32, float32, float32, int, float_status *statu= s); float32 float32_sqrt(float32, float_status *status); @@ -485,7 +485,7 @@ float64 float64_trunc_to_int(float64, float_status *sta= tus); float64 soft_float64_add(float64, float64, float_status *status); float64 soft_float64_sub(float64, float64, float_status *status); float64 soft_float64_mul(float64, float64, float_status *status); -float64 float64_div(float64, float64, float_status *status); +float64 soft_float64_div(float64, float64, float_status *status); float64 float64_rem(float64, float64, float_status *status); float64 float64_muladd(float64, float64, float64, int, float_status *statu= s); float64 float64_sqrt(float64, float_status *status); diff --git a/fpu/hostfloat.c b/fpu/hostfloat.c index 985d6f1..ff980ac 100644 --- a/fpu/hostfloat.c +++ b/fpu/hostfloat.c @@ -178,3 +178,31 @@ GEN_FPU_ADDSUB(float64_add, float64_sub, float64, doub= le, fabs, DBL_MIN) GEN_FPU_MUL(float32_mul, float32, float, fabsf, FLT_MIN) GEN_FPU_MUL(float64_mul, float64, double, fabs, DBL_MIN) #undef GEN_FPU_MUL + +#define GEN_FPU_DIV(name, soft_t, host_t, host_abs_func, min_normal) \ + soft_t name(soft_t a, soft_t b, float_status *s) \ + { \ + soft_t ## _input_flush2(&a, &b, s); \ + if (likely(soft_t ## _is_normal(a) && \ + soft_t ## _is_normal(b) && \ + s->float_exception_flags & float_flag_inexact && \ + s->float_rounding_mode =3D=3D float_round_nearest_even)= ) { \ + host_t ha =3D soft_t ## _to_ ## host_t(a); \ + host_t hb =3D soft_t ## _to_ ## host_t(b); \ + host_t hr =3D ha / hb; \ + soft_t r =3D host_t ## _to_ ## soft_t(hr); \ + \ + if (unlikely(soft_t ## _is_infinity(r))) { \ + s->float_exception_flags |=3D float_flag_overflow; \ + } else if (unlikely(host_abs_func(hr) <=3D min_normal)) { \ + goto soft; \ + } \ + return r; \ + } \ + soft: \ + return soft_ ## soft_t ## _div(a, b, s); \ + } + +GEN_FPU_DIV(float32_div, float32, float, fabsf, FLT_MIN) +GEN_FPU_DIV(float64_div, float64, double, fabs, DBL_MIN) +#undef GEN_FPU_DIV diff --git a/fpu/softfloat.c b/fpu/softfloat.c index e3f2918..ebc59be 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1176,7 +1176,7 @@ float16 float16_div(float16 a, float16 b, float_statu= s *status) return float16_round_pack_canonical(pr, status); } =20 -float32 float32_div(float32 a, float32 b, float_status *status) +float32 soft_float32_div(float32 a, float32 b, float_status *status) { FloatParts pa =3D float32_unpack_canonical(a, status); FloatParts pb =3D float32_unpack_canonical(b, status); @@ -1185,7 +1185,7 @@ float32 float32_div(float32 a, float32 b, float_statu= s *status) return float32_round_pack_canonical(pr, status); } =20 -float64 float64_div(float64 a, float64 b, float_status *status) +float64 soft_float64_div(float64 a, float64 b, float_status *status) { FloatParts pa =3D float64_unpack_canonical(a, status); FloatParts pb =3D float64_unpack_canonical(b, status); --=20 2.7.4 From nobody Sat Oct 25 21:46:07 2025 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; 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 1521663715575786.1721265413948; Wed, 21 Mar 2018 13:21:55 -0700 (PDT) Received: from localhost ([::1]:57173 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eykF8-0002au-NR for importer@patchew.org; Wed, 21 Mar 2018 16:21:54 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42166) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk5V-00029y-V2 for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:12:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyk5R-0000zj-Jb for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:57 -0400 Received: from out5-smtp.messagingengine.com ([66.111.4.29]:60427) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyk5R-0000yo-EL for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:53 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 175F220B68; Wed, 21 Mar 2018 16:11:53 -0400 (EDT) Received: from frontend1 ([10.202.2.160]) by compute4.internal (MEProxy); Wed, 21 Mar 2018 16:11:53 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id BC41F7E16D; Wed, 21 Mar 2018 16:11:52 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=mesmtp; bh=czROA3sfcXl803 Txm8o1ZlytOz64EDcDZtHrEn9VYWg=; b=nZzxKRCTZbrQmIa0UKQgNY+TrQKf2G lnTPML0Hi8JRLzfmR8nNL7Z6s2WtAH8trkPLdVYEVn50hWP/PSxk+HT/F25bfF01 rb9gIsD74WiFdlJp/tNl8d/5q6H1kpJmwbJ8g1VpQnHQom/mrqA0vs6D7o6Jiqhx ntHxA4NNlVat8= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=czROA3sfcXl803Txm8o1ZlytOz64EDcDZtHrEn9VYWg=; b=JPX4AsF6 Y5tPa38KMQG1ept8buHAHLMCmb1oj3LR3psQL9OKHjOqkwRJqLxfNZrQsXx75eQ6 DRk6YZ+YUG5SOrFWOb4Xkbvtz6wGZY1UE6Dnm5KfwSn3er3CKN2cnmssxCSrYcjN wa2ha1vfF70V3pHn0d2c+dIh4/P2jB0/NGCjJccQeGdx8/33666PVdREyh2ivkHC Wl/SI881Vaey3OxsVGD4YTA4nMNQ4mMwhYGbaNMsMmGTjpjkckC6KGbDpQTxlrOm UDUEKxKtxiLSqlICD6bgIkQRI5xYhVKSgsPAwHBHaS7aPHO0vZF6iWMFaHoYtDt/ MQdbRlQJmQJVMA== X-ME-Sender: From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 21 Mar 2018 16:11:46 -0400 Message-Id: <1521663109-32262-12-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1521663109-32262-1-git-send-email-cota@braap.org> References: <1521663109-32262-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.29 Subject: [Qemu-devel] [PATCH v1 11/14] hostfloat: support float32/64 fused multiply-add 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 , Mark Cave-Ayland , Richard Henderson , Laurent Vivier , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Aurelien Jarno Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Note that special-casing "a_is_zero || b_is_zero" pays off--see the last patch in this series for performance numbers on that. Performance results for fp-bench run under aarch64-linux-user on an aarch64 host: - before: fma-single: 53.05 MFlops fma-double: 51.89 MFlops - after: fma-single: 113.93 MFlops fma-double: 113.04 MFlops Signed-off-by: Emilio G. Cota --- include/fpu/hostfloat.h | 2 ++ include/fpu/softfloat.h | 4 ++-- fpu/hostfloat.c | 64 +++++++++++++++++++++++++++++++++++++++++++++= ++++ fpu/softfloat.c | 10 ++++---- 4 files changed, 74 insertions(+), 6 deletions(-) diff --git a/include/fpu/hostfloat.h b/include/fpu/hostfloat.h index 61a8525..c006576 100644 --- a/include/fpu/hostfloat.h +++ b/include/fpu/hostfloat.h @@ -15,10 +15,12 @@ float32 float32_add(float32 a, float32 b, float_status = *status); float32 float32_sub(float32 a, float32 b, float_status *status); float32 float32_mul(float32 a, float32 b, float_status *status); float32 float32_div(float32 a, float32 b, float_status *status); +float32 float32_muladd(float32 a, float32 b, float32 c, int f, float_statu= s *s); =20 float64 float64_add(float64 a, float64 b, float_status *status); float64 float64_sub(float64 a, float64 b, float_status *status); float64 float64_mul(float64 a, float64 b, float_status *status); float64 float64_div(float64 a, float64 b, float_status *status); +float64 float64_muladd(float64 a, float64 b, float64 c, int f, float_statu= s *s); =20 #endif /* HOSTFLOAT_H */ diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index a690a57..866bd3b 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -347,7 +347,7 @@ float32 soft_float32_sub(float32, float32, float_status= *status); float32 soft_float32_mul(float32, float32, float_status *status); float32 soft_float32_div(float32, float32, float_status *status); float32 float32_rem(float32, float32, float_status *status); -float32 float32_muladd(float32, float32, float32, int, float_status *statu= s); +float32 soft_float32_muladd(float32, float32, float32, int, float_status *= s); float32 float32_sqrt(float32, float_status *status); float32 float32_exp2(float32, float_status *status); float32 float32_log2(float32, float_status *status); @@ -487,7 +487,7 @@ float64 soft_float64_sub(float64, float64, float_status= *status); float64 soft_float64_mul(float64, float64, float_status *status); float64 soft_float64_div(float64, float64, float_status *status); float64 float64_rem(float64, float64, float_status *status); -float64 float64_muladd(float64, float64, float64, int, float_status *statu= s); +float64 soft_float64_muladd(float64, float64, float64, int, float_status *= s); float64 float64_sqrt(float64, float_status *status); float64 float64_log2(float64, float_status *status); int float64_eq(float64, float64, float_status *status); diff --git a/fpu/hostfloat.c b/fpu/hostfloat.c index ff980ac..a56b70a 100644 --- a/fpu/hostfloat.c +++ b/fpu/hostfloat.c @@ -206,3 +206,67 @@ GEN_FPU_MUL(float64_mul, float64, double, fabs, DBL_MI= N) GEN_FPU_DIV(float32_div, float32, float, fabsf, FLT_MIN) GEN_FPU_DIV(float64_div, float64, double, fabs, DBL_MIN) #undef GEN_FPU_DIV + +/* + * When (a || b) =3D=3D 0, there's no need to check for overflow, since we + * know the addend is normal || zero and the product is zero. + */ +#define GEN_FPU_FMA(name, soft_t, host_t, host_fma_f, host_abs_f, min_norm= al) \ + soft_t name(soft_t a, soft_t b, soft_t c, int flags, float_status *s) \ + { \ + soft_t ## _input_flush3(&a, &b, &c, s); \ + if (likely((soft_t ## _is_normal(a) || soft_t ## _is_zero(a)) && \ + (soft_t ## _is_normal(b) || soft_t ## _is_zero(b)) && \ + (soft_t ## _is_normal(c) || soft_t ## _is_zero(c)) && \ + !(flags & float_muladd_halve_result) && \ + s->float_exception_flags & float_flag_inexact && \ + s->float_rounding_mode =3D=3D float_round_nearest_even)= ) { \ + if (soft_t ## _is_zero(a) || soft_t ## _is_zero(b)) { \ + soft_t p, r; \ + host_t hp, hc, hr; \ + bool prod_sign; \ + \ + prod_sign =3D soft_t ## _is_neg(a) ^ soft_t ## _is_neg(b);= \ + prod_sign ^=3D !!(flags & float_muladd_negate_product); \ + p =3D soft_t ## _set_sign(soft_t ## _zero, prod_sign); \ + \ + if (flags & float_muladd_negate_c) { \ + c =3D soft_t ## _chs(c); \ + } \ + \ + hp =3D soft_t ## _to_ ## host_t(p); \ + hc =3D soft_t ## _to_ ## host_t(c); \ + hr =3D hp + hc; \ + r =3D host_t ## _to_ ## soft_t(hr); \ + return flags & float_muladd_negate_result ? \ + soft_t ## _chs(r) : r; \ + } else { \ + host_t ha, hb, hc, hr; \ + soft_t r; \ + soft_t sa =3D flags & float_muladd_negate_product ? \ + soft_t ## _chs(a) : a; \ + soft_t sc =3D flags & float_muladd_negate_c ? \ + soft_t ## _chs(c) : c; \ + \ + ha =3D soft_t ## _to_ ## host_t(sa); \ + hb =3D soft_t ## _to_ ## host_t(b); \ + hc =3D soft_t ## _to_ ## host_t(sc); \ + hr =3D host_fma_f(ha, hb, hc); \ + r =3D host_t ## _to_ ## soft_t(hr); \ + \ + if (unlikely(soft_t ## _is_infinity(r))) { \ + s->float_exception_flags |=3D float_flag_overflow; \ + } else if (unlikely(host_abs_f(hr) <=3D min_normal)) { \ + goto soft; \ + } \ + return flags & float_muladd_negate_result ? \ + soft_t ## _chs(r) : r; \ + } \ + } \ + soft: \ + return soft_ ## soft_t ## _muladd(a, b, c, flags, s); \ + } + +GEN_FPU_FMA(float32_muladd, float32, float, fmaf, fabsf, FLT_MIN) +GEN_FPU_FMA(float64_muladd, float64, double, fma, fabs, DBL_MIN) +#undef GEN_FPU_FMA diff --git a/fpu/softfloat.c b/fpu/softfloat.c index ebc59be..da81ec9 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1084,8 +1084,9 @@ float16 __attribute__((flatten)) float16_muladd(float= 16 a, float16 b, float16 c, return float16_round_pack_canonical(pr, status); } =20 -float32 __attribute__((flatten)) float32_muladd(float32 a, float32 b, floa= t32 c, - int flags, float_status *s= tatus) +float32 __attribute__((flatten)) +soft_float32_muladd(float32 a, float32 b, float32 c, int flags, + float_status *status) { FloatParts pa =3D float32_unpack_canonical(a, status); FloatParts pb =3D float32_unpack_canonical(b, status); @@ -1095,8 +1096,9 @@ float32 __attribute__((flatten)) float32_muladd(float= 32 a, float32 b, float32 c, return float32_round_pack_canonical(pr, status); } =20 -float64 __attribute__((flatten)) float64_muladd(float64 a, float64 b, floa= t64 c, - int flags, float_status *s= tatus) +float64 __attribute__((flatten)) +soft_float64_muladd(float64 a, float64 b, float64 c, int flags, + float_status *status) { FloatParts pa =3D float64_unpack_canonical(a, status); FloatParts pb =3D float64_unpack_canonical(b, status); --=20 2.7.4 From nobody Sat Oct 25 21:46:07 2025 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; 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 1521663972748194.8720183907309; Wed, 21 Mar 2018 13:26:12 -0700 (PDT) Received: from localhost ([::1]:57199 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eykJH-0005rh-UN for importer@patchew.org; Wed, 21 Mar 2018 16:26:11 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42175) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk5V-0002A2-W5 for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:12:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyk5R-0000zw-Sq for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:57 -0400 Received: from out5-smtp.messagingengine.com ([66.111.4.29]:56221) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyk5R-0000zX-L8 for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:53 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 57FAB20EE8; Wed, 21 Mar 2018 16:11:53 -0400 (EDT) Received: from frontend2 ([10.202.2.161]) by compute4.internal (MEProxy); Wed, 21 Mar 2018 16:11:53 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id 0020A24149; Wed, 21 Mar 2018 16:11:52 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=mesmtp; bh=Btu4u/YybuN3ka O7dJPioMEkIlmiRGGI4+iG88D8HrA=; b=c7l0AcngpOJ05nYLe81xGo/ukbxwsB L7CNWTklUwDbelpW4JsRZHE/jXBjO9L3YcPiwOMBgMWBXIEtf41XohGPI2MbMMh+ LsubJINtzX8ZJhLUqYt8d7KGJXeCg2fAS/R/aNO29W5gpc/5yKEOLlSVZV2wk3zB cc35pZNcPN9SE= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=Btu4u/YybuN3kaO7dJPioMEkIlmiRGGI4+iG88D8HrA=; b=HEmwlY7E xAq+cwRVSPe+YuDOciNaqyKnxi21z9Ew3RuZQHOsg70BiVNW7PY8YMO90pUzvGPR QGoDu9rarcdCJpfWv5yCJ1LSGydARcmrLr+tlZFn5eJgJfv4aslI90g623dm/Ncy 2kmbATrmXuHYSNz59MEg8MfwCe5MSCaJd7KLG7K7RSWeRaF2IUJfUAfSRcs7RrNH ztX8OxMeti3i0ld3NpLz96o16pevuJVwVFdzxW98hR6f5RKmRtmHszdwQd+mWy36 tMEKLdfpzEm6mIKE1DBVZYsY4Qqg/wja6RbmDING6M5qL1Cn6T9ezrCAnFZ7DVQk ZY8XRqU3WuYNrA== X-ME-Sender: From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 21 Mar 2018 16:11:47 -0400 Message-Id: <1521663109-32262-13-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1521663109-32262-1-git-send-email-cota@braap.org> References: <1521663109-32262-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.29 Subject: [Qemu-devel] [PATCH v1 12/14] hostfloat: support float32/64 square root 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 , Mark Cave-Ayland , Richard Henderson , Laurent Vivier , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Aurelien Jarno Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Performance results for fp-bench run under aarch64-linux-user on an Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz host: - before: sqrt-single: 13.23 MFlops sqrt-double: 13.24 MFlops - after: sqrt-single: 15.02 MFlops sqrt-double: 15.07 MFlops Note that sqrt in soft-ft is relatively fast, which means that fp-bench is not very sensitive to changes to sqrt's emulation speed. Signed-off-by: Emilio G. Cota --- include/fpu/hostfloat.h | 2 ++ include/fpu/softfloat.h | 4 ++-- fpu/hostfloat.c | 20 ++++++++++++++++++++ fpu/softfloat.c | 6 ++++-- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/include/fpu/hostfloat.h b/include/fpu/hostfloat.h index c006576..b1e0689 100644 --- a/include/fpu/hostfloat.h +++ b/include/fpu/hostfloat.h @@ -16,11 +16,13 @@ float32 float32_sub(float32 a, float32 b, float_status = *status); float32 float32_mul(float32 a, float32 b, float_status *status); float32 float32_div(float32 a, float32 b, float_status *status); float32 float32_muladd(float32 a, float32 b, float32 c, int f, float_statu= s *s); +float32 float32_sqrt(float32 a, float_status *status); =20 float64 float64_add(float64 a, float64 b, float_status *status); float64 float64_sub(float64 a, float64 b, float_status *status); float64 float64_mul(float64 a, float64 b, float_status *status); float64 float64_div(float64 a, float64 b, float_status *status); float64 float64_muladd(float64 a, float64 b, float64 c, int f, float_statu= s *s); +float64 float64_sqrt(float64 a, float_status *status); =20 #endif /* HOSTFLOAT_H */ diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 866bd3b..8d5a50a 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -348,7 +348,7 @@ float32 soft_float32_mul(float32, float32, float_status= *status); float32 soft_float32_div(float32, float32, float_status *status); float32 float32_rem(float32, float32, float_status *status); float32 soft_float32_muladd(float32, float32, float32, int, float_status *= s); -float32 float32_sqrt(float32, float_status *status); +float32 soft_float32_sqrt(float32, float_status *status); float32 float32_exp2(float32, float_status *status); float32 float32_log2(float32, float_status *status); int float32_eq(float32, float32, float_status *status); @@ -488,7 +488,7 @@ float64 soft_float64_mul(float64, float64, float_status= *status); float64 soft_float64_div(float64, float64, float_status *status); float64 float64_rem(float64, float64, float_status *status); float64 soft_float64_muladd(float64, float64, float64, int, float_status *= s); -float64 float64_sqrt(float64, float_status *status); +float64 soft_float64_sqrt(float64, float_status *status); float64 float64_log2(float64, float_status *status); int float64_eq(float64, float64, float_status *status); int float64_le(float64, float64, float_status *status); diff --git a/fpu/hostfloat.c b/fpu/hostfloat.c index a56b70a..974bd57 100644 --- a/fpu/hostfloat.c +++ b/fpu/hostfloat.c @@ -270,3 +270,23 @@ GEN_FPU_DIV(float64_div, float64, double, fabs, DBL_MI= N) GEN_FPU_FMA(float32_muladd, float32, float, fmaf, fabsf, FLT_MIN) GEN_FPU_FMA(float64_muladd, float64, double, fma, fabs, DBL_MIN) #undef GEN_FPU_FMA + +#define GEN_FPU_SQRT(name, soft_t, host_t, host_sqrt_func) \ + soft_t name(soft_t a, float_status *s) \ + { \ + soft_t ## _input_flush1(&a, s); \ + if (likely((soft_t ## _is_normal(a) || soft_t ## _is_zero(a)) && \ + !soft_t ## _is_neg(a) && \ + s->float_exception_flags & float_flag_inexact && \ + s->float_rounding_mode =3D=3D float_round_nearest_even)= ) { \ + host_t ha =3D soft_t ## _to_ ## host_t(a); \ + host_t hr =3D host_sqrt_func(ha); \ + \ + return host_t ## _to_ ## soft_t(hr); \ + } \ + return soft_ ## soft_t ## _sqrt(a, s); \ + } + +GEN_FPU_SQRT(float32_sqrt, float32, float, sqrtf) +GEN_FPU_SQRT(float64_sqrt, float64, double, sqrt) +#undef GEN_FPU_SQRT diff --git a/fpu/softfloat.c b/fpu/softfloat.c index da81ec9..096b658 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1980,14 +1980,16 @@ float16 __attribute__((flatten)) float16_sqrt(float= 16 a, float_status *status) return float16_round_pack_canonical(pr, status); } =20 -float32 __attribute__((flatten)) float32_sqrt(float32 a, float_status *sta= tus) +float32 __attribute__((flatten)) +soft_float32_sqrt(float32 a, float_status *status) { FloatParts pa =3D float32_unpack_canonical(a, status); FloatParts pr =3D sqrt_float(pa, status, &float32_params); return float32_round_pack_canonical(pr, status); } =20 -float64 __attribute__((flatten)) float64_sqrt(float64 a, float_status *sta= tus) +float64 __attribute__((flatten)) +soft_float64_sqrt(float64 a, float_status *status) { FloatParts pa =3D float64_unpack_canonical(a, status); FloatParts pr =3D sqrt_float(pa, status, &float64_params); --=20 2.7.4 From nobody Sat Oct 25 21:46:07 2025 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; 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 1521663409494592.9726176246503; Wed, 21 Mar 2018 13:16:49 -0700 (PDT) Received: from localhost ([::1]:57143 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eykA8-0006Wg-G5 for importer@patchew.org; Wed, 21 Mar 2018 16:16:44 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42158) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk5V-00029r-Se for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyk5S-00010C-5P for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:57 -0400 Received: from out5-smtp.messagingengine.com ([66.111.4.29]:53645) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyk5R-0000zo-VB for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:54 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id AA1072137C; Wed, 21 Mar 2018 16:11:53 -0400 (EDT) Received: from frontend1 ([10.202.2.160]) by compute4.internal (MEProxy); Wed, 21 Mar 2018 16:11:53 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id 531307E16D; Wed, 21 Mar 2018 16:11:53 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=mesmtp; bh=jyVOrLBDxucWUl FfmEpddkwQJN3dvZrGeWIqXlRBTq4=; b=n+x9div1m69BcY27uAqq8VrA4/hHlZ hpPA2CCLkwKKRYrg19+5AHWw4Fe2ngQ41gmnDsBVWTjizA8bjwLltAFcClz1RTgg LntaYNFyueg3CWdBZk32HCdalJNugUS6xtc2ILAyc7lkk8WhDevasr7fw1AgKiAs SfW+rMOdwIq30= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=jyVOrLBDxucWUlFfmEpddkwQJN3dvZrGeWIqXlRBTq4=; b=gGP9oF4r LtctocXX2FpTeVXGyt3Fj5boKJTrCNT1bBl1w/2wudxDr2cq+eo4y/lLmXV5UEuA lmkAdNTe9MefCqZDjhCsQIDHSQ5Cgrv1V49cjAqVaK3ExqvK/Rs6MflHGobHFnoc Zg9cGFLLwl0ysEcc36MBmhdw3k8QfxMnufZOL+jATeksU37FBtDUYGxChMDTHn5+ MXcH798QGotVdojgpGKUfBh8JtDWFBXE5ff5iu4pra0SvnpeBc6q+lE4qyTFyC6t bF22T4E2tVZJR3D+i8foezhDKMA9l8L5nXYbXcscIVgTsVpKDKGIZLtwQ3R4OZ1S g0gFpBW/TKEx2g== X-ME-Sender: From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 21 Mar 2018 16:11:48 -0400 Message-Id: <1521663109-32262-14-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1521663109-32262-1-git-send-email-cota@braap.org> References: <1521663109-32262-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.29 Subject: [Qemu-devel] [PATCH v1 13/14] hostfloat: support float32/64 comparison 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 , Mark Cave-Ayland , Richard Henderson , Laurent Vivier , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Aurelien Jarno Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Performance results included in the following commit's log. Signed-off-by: Emilio G. Cota --- include/fpu/hostfloat.h | 4 ++++ include/fpu/softfloat.h | 6 ++---- fpu/hostfloat.c | 36 ++++++++++++++++++++++++++++++++++++ fpu/softfloat.c | 34 ++++++++++++++++++++-------------- 4 files changed, 62 insertions(+), 18 deletions(-) diff --git a/include/fpu/hostfloat.h b/include/fpu/hostfloat.h index b1e0689..aa555f6 100644 --- a/include/fpu/hostfloat.h +++ b/include/fpu/hostfloat.h @@ -17,6 +17,8 @@ float32 float32_mul(float32 a, float32 b, float_status *s= tatus); float32 float32_div(float32 a, float32 b, float_status *status); float32 float32_muladd(float32 a, float32 b, float32 c, int f, float_statu= s *s); float32 float32_sqrt(float32 a, float_status *status); +int float32_compare(float32 a, float32 b, float_status *s); +int float32_compare_quiet(float32 a, float32 b, float_status *s); =20 float64 float64_add(float64 a, float64 b, float_status *status); float64 float64_sub(float64 a, float64 b, float_status *status); @@ -24,5 +26,7 @@ float64 float64_mul(float64 a, float64 b, float_status *s= tatus); float64 float64_div(float64 a, float64 b, float_status *status); float64 float64_muladd(float64 a, float64 b, float64 c, int f, float_statu= s *s); float64 float64_sqrt(float64 a, float_status *status); +int float64_compare(float64 a, float64 b, float_status *s); +int float64_compare_quiet(float64 a, float64 b, float_status *s); =20 #endif /* HOSTFLOAT_H */ diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index 8d5a50a..cb57942 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -359,8 +359,7 @@ int float32_eq_quiet(float32, float32, float_status *st= atus); int float32_le_quiet(float32, float32, float_status *status); int float32_lt_quiet(float32, float32, float_status *status); int float32_unordered_quiet(float32, float32, float_status *status); -int float32_compare(float32, float32, float_status *status); -int float32_compare_quiet(float32, float32, float_status *status); +int soft_float32_compare(float32, float32, bool is_quiet, float_status *st= atus); float32 float32_min(float32, float32, float_status *status); float32 float32_max(float32, float32, float_status *status); float32 float32_minnum(float32, float32, float_status *status); @@ -498,8 +497,7 @@ int float64_eq_quiet(float64, float64, float_status *st= atus); int float64_le_quiet(float64, float64, float_status *status); int float64_lt_quiet(float64, float64, float_status *status); int float64_unordered_quiet(float64, float64, float_status *status); -int float64_compare(float64, float64, float_status *status); -int float64_compare_quiet(float64, float64, float_status *status); +int soft_float64_compare(float64, float64, bool is_quiet, float_status *st= atus); float64 float64_min(float64, float64, float_status *status); float64 float64_max(float64, float64, float_status *status); float64 float64_minnum(float64, float64, float_status *status); diff --git a/fpu/hostfloat.c b/fpu/hostfloat.c index 974bd57..139e419 100644 --- a/fpu/hostfloat.c +++ b/fpu/hostfloat.c @@ -290,3 +290,39 @@ GEN_FPU_FMA(float64_muladd, float64, double, fma, fabs= , DBL_MIN) GEN_FPU_SQRT(float32_sqrt, float32, float, sqrtf) GEN_FPU_SQRT(float64_sqrt, float64, double, sqrt) #undef GEN_FPU_SQRT + +#define GEN_FPU_COMPARE(name, soft_t, host_t) \ + static inline __attribute__((always_inline)) int \ + fpu_ ## name(soft_t a, soft_t b, bool is_quiet, float_status *s) \ + { \ + soft_t ## _input_flush2(&a, &b, s); \ + if (unlikely(soft_t ## _is_any_nan(a) || \ + soft_t ## _is_any_nan(b))) { \ + return soft_ ## name(a, b, is_quiet, s); \ + } else { \ + host_t ha =3D soft_t ## _to_ ## host_t(a); \ + host_t hb =3D soft_t ## _to_ ## host_t(b); \ + \ + if (isgreater(ha, hb)) { \ + return float_relation_greater; \ + } \ + if (isless(ha, hb)) { \ + return float_relation_less; \ + } \ + return float_relation_equal; \ + } \ + } \ + \ + int name(soft_t a, soft_t b, float_status *s) \ + { \ + return fpu_ ## name(a, b, false, s); \ + } \ + \ + int name ## _quiet(soft_t a, soft_t b, float_status *s) \ + { \ + return fpu_ ## name(a, b, true, s); \ + } + +GEN_FPU_COMPARE(float32_compare, float32, float) +GEN_FPU_COMPARE(float64_compare, float64, double) +#undef GEN_FPU_COMPARE diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 096b658..1a32216 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -1844,28 +1844,34 @@ static int compare_floats(FloatParts a, FloatParts = b, bool is_quiet, } } =20 -#define COMPARE(sz) \ -int float ## sz ## _compare(float ## sz a, float ## sz b, \ - float_status *s) \ +#define COMPARE(storage_class, sz) \ +storage_class int \ +soft_float ## sz ## _compare(float ## sz a, float ## sz b, \ + bool is_quiet, float_status *s) \ { \ FloatParts pa =3D float ## sz ## _unpack_canonical(a, s); \ FloatParts pb =3D float ## sz ## _unpack_canonical(b, s); \ - return compare_floats(pa, pb, false, s); \ -} \ -int float ## sz ## _compare_quiet(float ## sz a, float ## sz b, \ - float_status *s) \ -{ \ - FloatParts pa =3D float ## sz ## _unpack_canonical(a, s); \ - FloatParts pb =3D float ## sz ## _unpack_canonical(b, s); \ - return compare_floats(pa, pb, true, s); \ + return compare_floats(pa, pb, is_quiet, s); \ } =20 -COMPARE(16) -COMPARE(32) -COMPARE(64) +COMPARE(static, 16) +COMPARE(, 32) +COMPARE(, 64) =20 #undef COMPARE =20 +int __attribute__((flatten)) +float16_compare(float16 a, float16 b, float_status *s) +{ + return soft_float16_compare(a, b, false, s); +} + +int __attribute__((flatten)) +float16_compare_quiet(float16 a, float16 b, float_status *s) +{ + return soft_float16_compare(a, b, true, s); +} + /* Multiply A by 2 raised to the power N. */ static FloatParts scalbn_decomposed(FloatParts a, int n, float_status *s) { --=20 2.7.4 From nobody Sat Oct 25 21:46:07 2025 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; 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 1521664229987566.7229811158281; Wed, 21 Mar 2018 13:30:29 -0700 (PDT) Received: from localhost ([::1]:57229 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eykNR-00013x-1F for importer@patchew.org; Wed, 21 Mar 2018 16:30:29 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42176) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eyk5W-0002A3-06 for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:12:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eyk5S-00010L-EX for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:57 -0400 Received: from out5-smtp.messagingengine.com ([66.111.4.29]:55663) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eyk5S-000108-9k for qemu-devel@nongnu.org; Wed, 21 Mar 2018 16:11:54 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 01B37213DF; Wed, 21 Mar 2018 16:11:54 -0400 (EDT) Received: from frontend2 ([10.202.2.161]) by compute4.internal (MEProxy); Wed, 21 Mar 2018 16:11:54 -0400 Received: from localhost (flamenco.cs.columbia.edu [128.59.20.216]) by mail.messagingengine.com (Postfix) with ESMTPA id 912F924149; Wed, 21 Mar 2018 16:11:53 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=braap.org; h=cc :date:from:in-reply-to:message-id:references:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=mesmtp; bh=h704yc7vEQ8f8P F0/OgX+aHAzMzBcJ4EZgSDsBGCSm8=; b=sDfHlw1evxM7l0UvDcCY1d8OC3802X pf2PLdA8+tHOcFYeK+MfHUw+RYnUq+AihzAfDSslxw6kI6BDy8aBKN9EP14gcXwf NX20ZgdVfzGjDyOOyknpixQDMZQ53R6wX+6tUFRN5nwHuGLSDL5drVgga23rIf6R 0WizJnh3//TWw= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=h704yc7vEQ8f8PF0/OgX+aHAzMzBcJ4EZgSDsBGCSm8=; b=D6Z6Xdqm QxDpJ5zAx5T0JRk5ZraSe25ptgrAjI8hPrPN/Czmyvt84OktUkBp6H0cp95wOmwK ZBR+kt0+PbpfCL+/BOYP/1Vo0oVWv93NASG+okQ+tkilwbo//rHMeKElSW2/NJwf fvyKExrcdBZR0LA8/9SM0nCUvUxEQX4Q2+98xOdo0Ea9cVfm214C5CIev1uf9732 p92NIG/YxfTSNh/AnO3yHPxx/ZrLmYljlrUEMXAUloUINAq53d3ckmZ6XUEwouER PjKLfeIIfdazr3iHeTjf7HWVYlA3J8jfYPi13sgdub3/Edxh6jEtz1GrIGTbo7+m vRi0+6zrLSlj/Q== X-ME-Sender: From: "Emilio G. Cota" To: qemu-devel@nongnu.org Date: Wed, 21 Mar 2018 16:11:49 -0400 Message-Id: <1521663109-32262-15-git-send-email-cota@braap.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1521663109-32262-1-git-send-email-cota@braap.org> References: <1521663109-32262-1-git-send-email-cota@braap.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.29 Subject: [Qemu-devel] [PATCH v1 14/14] hostfloat: support float32_to_float64 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 , Mark Cave-Ayland , Richard Henderson , Laurent Vivier , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Aurelien Jarno Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Performance improvement for SPEC06fp for the last few commits: qemu-aarch64 SPEC06fp (test set) speedup ove= r QEMU f6d81cdec8 Host: Intel(R) Core(TM) i7-6700K CPU = @ 4.00GHz error bars: 95% confidence inte= rval 5 +-+---+-----+----+-----+-----+-----+-----+----+-----+-----+-----+----= +-----+-----+-----+-----+----+-----+---+-+ 4.5 +-+..........................+&&+....................................= .......................................+-+ 3.5 +-+................+++.......@@&...............+++...................= .........................+++dsub +-+ 2 3 +-+....+++.++++++%%&=3D+......+@@&....+++...=3D=3D+..&&=3D...........= ...............................++&=3D+++++++ +-+ 2 +-+..%%@&+.%%@=3D++%%&=3D.......+%@&..%%@&+.%%@=3D++%%&=3D.++&&+.....= ..++&=3D+.+++++.......+&&=3D.%%@&+.%%@=3D +%%@=3D++%%&=3D+-+ 1.5 +-+++$%@&+#$%@=3D+#$%&=3D##$%&**#$@&**#%@&**$%@=3D**$%&=3D##%@&**#+&&= **#%@=3D**$%@=3D+++&&=3D##$@&**#%@&**#%@=3D*+f%@=3D*#$%&=3D+-+ 0 1 +-+**#%@&**$%@=3D**$%&=3D*#$%&**#$@&**#%@&**$%@=3D**$%&=3D*#$@&**#$@&= **#%@=3D**$%@=3D*#$%&=3D*#$@&**#%@&**#%@=3D+sqr@=3D*#$%&=3D+-+ 0 +-+**#%@&**$%@=3D**$%&=3D*#$%&**#$@&**#%@&**$%@=3D**$%&=3D*#$@&**#$@&= **#%@=3D**$%@=3D*#$%&=3D*#$@&**#%@&**#%@=3D*+cmp=3D*#$%&=3D+-+ 410.bw416.gam433.434.z435.436.cac437.lesli444.447.de450.so453454.ca459.Ge= msF465.tont470.lb4482.sph+f32f64ean png: https://imgur.com/5BErNz7 That is, a final geomean speedup of 2.21X. The floating point workloads from nbench show similar improvements: qemu-aarch64 NBench score; higher is= better Host: Intel(R) Core(TM) i7-6700K CPU @= 4.00GHz 16 +-+-------------------+---------------------+----------------------+--= -------------------+-------------------+-+ 14 +-+..............................................=3D=3D=3D=3D**.......= .....@@@&&&=3D=3D**................................+-+ 12 +-+.........................................@@@@&&..=3D.*............@= .@..&.=3D.*..................+before +-+ 10 +-+.........................................@..@.&..=3D.*............@= .@..&.=3D.*............@@@&&&=3D=3D***ub +-+ 8 +-+....................................$$$$%%..@.&..=3D.*............@= .@..&.=3D.*............@.@..&+=3D +*ul +-+ 6 +-+...................@@@@&&=3D=3D=3D**..***##..$.%..@.&..=3D.*..++###= #$$%%%.@..&.=3D.*....####$$%%%.@..&+=3D +*iv +-+ 4 +-+............###$$$%%..@.&..=3D.*..*+*.#..$.%..@.&..=3D.*..***..#.$.= .%.@..&.=3D.*..***..#.$..%.@..&+=3D +*ma +-+ 2 +-+.........****.#..$.%..@.&..=3D.*..*.*.#..$.%..@.&..=3D.*..*.*..#.$.= .%.@..&.=3D.*..*.*..#.$..%.@..&+=3D+s*rt +-+ 0 +-+---------****##$$$%%@@@&&=3D=3D=3D**--***##$$$%%@@@&&=3D=3D=3D**--*= **###$$%%%@@&&&=3D=3D**--***###$$%%%@@&&&=3D=3D***mp-------+-+ FOURIER NEURAL NET LU DECOMPOSITION = gmean +f32f64 png: https://imgur.com/KjLHumh That is, a ~2.6X speedup. [error bars here are just the standard deviation = of just a few measurements; this explains the noisy results.] Results for the i386 target are very similar; the only major difference is that they're much more sensitive to the multiplication optimization, since the i386 target does not currently use floatX_muladd (aka fma). Below are the x86_64 SPEC06fp results, although note that they are from a development branch, so each bar does not match the patches in this, and the final numbers might be slightly different from those you'd get with these patches. qemu-x86_64 SPEC06fp (train set) speedup ove= r QEMU f6d81cdec8 Host: Intel(R) Core(TM) i7-6700K CPU = @ 4.00GHz error bars: 95% confidence inte= rval 4 +-+---+-----+----+-----+-----+%%---+-----+----+-----+-----+-----+----= +-----+-----+-----+-----+----+-----+---+-+ 3.5 +-+..........................$$%.....................................= .......................................+-+ 3 +-+............**$$$......+**#$%............**$$++...................= ...............+add+sub++%%+sq+++ +-+ 2.5 +-+..+++.**##$%**#+$%......**#$%..+$$%..++%%**#$%%.............+++.**= #$$%........$$%+**$$%+###$%is#$$% $$%%+-+ 1.5 +-+***#$%**.#$%**#.$%..$$%+**#$%***#$%**##$%**#$.%**#$%+++$$%***#$%**= #+$%..$$++**#$%+fas$%path$%ul(0$%**#$ %+-+ 1 +-+*+*#$%**+#$%**#+$%**#$%+**#$%*+*#$%**+#$%**#$+%**#$%-**#$%*+*#$%**= #+$%**#$%%**#$%+**+f%2 to %4+div%**#$+%+-+ 0.5 +-+*.*#$%**.#$%**#.$%**#$%.**#$%*.*#$%**.#$%**#$.%**#$%.**#$%*.*#$%**= #.$%**#$.%**#$%.**#$%**.#$%**#.$%**#$.%+-+ 0 +-+***#$%**##$%**#$$%**#$%-**#$%***#$%**##$%**#$%%**#$%-**#$%***#$%**= #$$%**#$%%**#$%-**#$%**##$%**#$$%**#$%%+-+ 410.bw416.gam433.434.z435.436.cac437.lesli444.447.de450.so453454.ca459.Ge= msF465.tont470.lb4482.sphinxgeomean png: https://imgur.com/MfvTb3H Two points are worth mentioning: - Special-casing 0-inputs for multiplication pays off handsomely (the same thing happens for FMA for targets that use it). I was surprised to see that some benchmarks (e.g. GemsFDTD) compute >99% of their multiplications with at least one operand being Zero (and this is without flush-to-zero!). - Avoiding comparisons via the host FPU (i.e. using soft_t ## _is_normal() instead of glibc's isnormal()) gives a small speedup. Finally, the same results using native execution time as the baseline, where we plot the slowdown instead of the speedup. We bring down the slowdown of SPEC06fp w.r.t. native from ~21X to ~10X: qemu-x86_64 SPEC06fp (train set) slowdown over nat= ive (lower is better) Host: Intel(R) Core(TM) i7-6700K CPU @= 4.00GHz error bars: 95% confidence inter= val 90 +-+---+-----+-----+----+-----+-----+-----+-----+-----+----+-----+-----= +-----+-----+-----+----+-----+-----+---+-+ 80 +-+.......................+**.........................................= .......................................+-+ 70 +-+........................**.........................................= ...............+ before +-+ 50 +-+........................**.........................................= ...............+add+sub+mul+sqrt +-+ 40 +-+......+++...............**................................+++......= ...............+ +integer isinf +-+ 30 +-+**+...**+...............**#$%@**.........**+..............+**++....= .........**+...+fast path mul(0++** +-+ 10 +-+**#$%@**#$%@**$$@@**#$%@**#$%@**#$%**#$%+**#$%@**#$%@**#$%+**#$%@**= #$%@*#$%@**#$%@**#+f@2 to @4+div@**#$%@+-+ 0 +-+**#$%@**#$%@**#$%@**#$%@**#$%@**#$%**#$%@**#$%@**#$%@**#$%@**#$%@**= #$%@*#$%@**#$%@**#$%@**#$%@**#$%@**#$%@+-+ 410.bw416.game433434.z435.436.cac437.leslie444.447.d450.so453.454.ca459.Ge= msF465.tont470.l48482.sphinxgeomean png: https://imgur.com/iTmVkJL All png's shown above can be found here: https://imgur.com/a/YSxxR Signed-off-by: Emilio G. Cota --- include/fpu/hostfloat.h | 2 ++ include/fpu/softfloat.h | 2 +- fpu/hostfloat.c | 14 ++++++++++++++ fpu/softfloat.c | 2 +- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/include/fpu/hostfloat.h b/include/fpu/hostfloat.h index aa555f6..79e9b6c 100644 --- a/include/fpu/hostfloat.h +++ b/include/fpu/hostfloat.h @@ -29,4 +29,6 @@ float64 float64_sqrt(float64 a, float_status *status); int float64_compare(float64 a, float64 b, float_status *s); int float64_compare_quiet(float64 a, float64 b, float_status *s); =20 +float64 float32_to_float64(float32, float_status *status); + #endif /* HOSTFLOAT_H */ diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index cb57942..b0a4d75 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -334,7 +334,7 @@ int64_t float32_to_int64(float32, float_status *status); uint64_t float32_to_uint64(float32, float_status *status); uint64_t float32_to_uint64_round_to_zero(float32, float_status *status); int64_t float32_to_int64_round_to_zero(float32, float_status *status); -float64 float32_to_float64(float32, float_status *status); +float64 soft_float32_to_float64(float32, float_status *status); floatx80 float32_to_floatx80(float32, float_status *status); float128 float32_to_float128(float32, float_status *status); =20 diff --git a/fpu/hostfloat.c b/fpu/hostfloat.c index 139e419..b635839 100644 --- a/fpu/hostfloat.c +++ b/fpu/hostfloat.c @@ -326,3 +326,17 @@ GEN_FPU_SQRT(float64_sqrt, float64, double, sqrt) GEN_FPU_COMPARE(float32_compare, float32, float) GEN_FPU_COMPARE(float64_compare, float64, double) #undef GEN_FPU_COMPARE + +float64 float32_to_float64(float32 a, float_status *status) +{ + if (likely(float32_is_normal(a))) { + float f =3D *(float *)&a; + double r =3D f; + + return *(float64 *)&r; + } else if (float32_is_zero(a)) { + return float64_set_sign(float64_zero, float32_is_neg(a)); + } else { + return soft_float32_to_float64(a, status); + } +} diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 1a32216..cf8d6ec 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -3149,7 +3149,7 @@ float128 uint64_to_float128(uint64_t a, float_status = *status) | Arithmetic. *-------------------------------------------------------------------------= ---*/ =20 -float64 float32_to_float64(float32 a, float_status *status) +float64 soft_float32_to_float64(float32 a, float_status *status) { flag aSign; int aExp; --=20 2.7.4