Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1475761/?format=api
{ "id": 1475761, "url": "http://patchwork.ozlabs.org/api/patches/1475761/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20210508014802.892561-46-richard.henderson@linaro.org/", "project": { "id": 14, "url": "http://patchwork.ozlabs.org/api/projects/14/?format=api", "name": "QEMU Development", "link_name": "qemu-devel", "list_id": "qemu-devel.nongnu.org", "list_email": "qemu-devel@nongnu.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20210508014802.892561-46-richard.henderson@linaro.org>", "list_archive_url": null, "date": "2021-05-08T01:47:35", "name": "[45/72] softfloat: Move round_to_int to softfloat-parts.c.inc", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "3f242827b25536e6ee0eeb74555ee85adbab1037", "submitter": { "id": 72104, "url": "http://patchwork.ozlabs.org/api/people/72104/?format=api", "name": "Richard Henderson", "email": "richard.henderson@linaro.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20210508014802.892561-46-richard.henderson@linaro.org/mbox/", "series": [ { "id": 242770, "url": "http://patchwork.ozlabs.org/api/series/242770/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=242770", "date": "2021-05-08T01:46:53", "name": "Convert floatx80 and float128 to FloatParts", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/242770/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1475761/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1475761/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org", "Authentication-Results": [ "ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=<UNKNOWN>)", "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256\n header.s=google header.b=zXI42KrX;\n\tdkim-atps=neutral" ], "Received": [ "from lists.gnu.org (lists.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 4FcWZ45TdTz9sTD\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 8 May 2021 12:32:44 +1000 (AEST)", "from localhost ([::1]:50192 helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>)\n\tid 1lfClm-0000jB-On\n\tfor incoming@patchwork.ozlabs.org; Fri, 07 May 2021 22:32:42 -0400", "from eggs.gnu.org ([2001:470:142:3::10]:41486)\n by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <richard.henderson@linaro.org>)\n id 1lfC81-0002rQ-PE\n for qemu-devel@nongnu.org; Fri, 07 May 2021 21:51:37 -0400", "from mail-pl1-x634.google.com ([2607:f8b0:4864:20::634]:41903)\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)\n (Exim 4.90_1) (envelope-from <richard.henderson@linaro.org>)\n id 1lfC7y-0005R4-Kt\n for qemu-devel@nongnu.org; Fri, 07 May 2021 21:51:37 -0400", "by mail-pl1-x634.google.com with SMTP id z18so2558961plg.8\n for <qemu-devel@nongnu.org>; Fri, 07 May 2021 18:51:34 -0700 (PDT)", "from localhost.localdomain ([71.212.144.24])\n by smtp.gmail.com with ESMTPSA id 204sm5861396pfw.158.2021.05.07.18.51.32\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Fri, 07 May 2021 18:51:32 -0700 (PDT)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google;\n h=from:to:cc:subject:date:message-id:in-reply-to:references\n :mime-version:content-transfer-encoding;\n bh=lD4M3xdqIE8r914VjTd/jttQJ/e/mxQ3BCpgAvIfUlU=;\n b=zXI42KrXmJ8wWhg4UQfr5JLQwGxQRljTYOqIcseHFB6flqYrTX6QR7xJTTa8K/lqL+\n BlZlA/VcbzdmZk3eRcVSVoYAAyUgaSUVWW5jTRSz2NZKgk078m3E2BQd4+rd6Iq5jnhv\n TviTToJ8Wtra1A/vSXAIbI8XdGoRufTsvhvUAW0dHvmAS3qsEfCqSDFqkLqUzRmKe703\n VNgHPlh6o2U7XUZ7nSTg4qAcV3aS16/b5QSw+BQsxTxvXXMm8QB2z91Cyktq1g+2rk4n\n SHecCQmNLQ0AwUc+RuKbHXS80UUIHZ6YlexNWTmhDwHtVVP+XvTR0ur+e9sjiTWw9pQ3\n bMkw==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20161025;\n h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n :references:mime-version:content-transfer-encoding;\n bh=lD4M3xdqIE8r914VjTd/jttQJ/e/mxQ3BCpgAvIfUlU=;\n b=nWfvdbt9ypVi81Gw4ThxuSONze4gflznSSxhQdTKufJKLht9AiZ4rkGFXWDqbH3FQ+\n CRvXsB2WnqCMbNzfGrmE4OFO4sovjAg6rpXE+iADQMMBjOOzHqbhR/prNWwqUp8IAksy\n LB+wHjDuvlTPZowWyDiWar8pmPcJWkBs0qs73emAIGnKyNYyqdIqpAz8BSRsj2n7hLvv\n BKbul2Jq93MkTH9UZfpFwxLy32bYMbsDq20pOJ7afDayXtH5eYgV0zX7lFgXL+4FmAF1\n Pfxb0GorRiD8PLwezjdJ9gZZaECOpjKlAnUzhBPHi26x1OZDBJTvR7caoHCm2vhMq3Nu\n xYHg==", "X-Gm-Message-State": "AOAM530vu7hLk8F4xfmy0t7t2kPSKQ105Wx/sPiFdc84rlALM+BTx6bL\n NJF+BVsM5QRXfufyzL8wC311LOUzJ1Od/A==", "X-Google-Smtp-Source": "\n ABdhPJz5FxD8L84om6uMp78Uo7JOGt+lwpvSQLN9Do886HfngG/T+wKHbQ4Y3e6VzkTOGUAArCoAIQ==", "X-Received": "by 2002:a17:90b:2390:: with SMTP id\n mr16mr13836588pjb.133.1620438693131;\n Fri, 07 May 2021 18:51:33 -0700 (PDT)", "From": "Richard Henderson <richard.henderson@linaro.org>", "To": "qemu-devel@nongnu.org", "Subject": "[PATCH 45/72] softfloat: Move round_to_int to softfloat-parts.c.inc", "Date": "Fri, 7 May 2021 18:47:35 -0700", "Message-Id": "<20210508014802.892561-46-richard.henderson@linaro.org>", "X-Mailer": "git-send-email 2.25.1", "In-Reply-To": "<20210508014802.892561-1-richard.henderson@linaro.org>", "References": "<20210508014802.892561-1-richard.henderson@linaro.org>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Received-SPF": "pass client-ip=2607:f8b0:4864:20::634;\n envelope-from=richard.henderson@linaro.org; helo=mail-pl1-x634.google.com", "X-Spam_score_int": "-20", "X-Spam_score": "-2.1", "X-Spam_bar": "--", "X-Spam_report": "(-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001,\n SPF_PASS=-0.001 autolearn=ham autolearn_force=no", "X-Spam_action": "no action", "X-BeenThere": "qemu-devel@nongnu.org", "X-Mailman-Version": "2.1.23", "Precedence": "list", "List-Id": "<qemu-devel.nongnu.org>", "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>", "List-Archive": "<https://lists.nongnu.org/archive/html/qemu-devel>", "List-Post": "<mailto:qemu-devel@nongnu.org>", "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>", "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>", "Cc": "alex.bennee@linaro.org, david@redhat.com", "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org", "Sender": "\"Qemu-devel\"\n <qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>" }, "content": "At the same time, convert to pointers, split out\nparts$N_round_to_int_normal, define a macro for\nparts_round_to_int using QEMU_GENERIC.\n\nThis necessarily meant some rearrangement to the\nrount_to_{,u}int_and_pack routines, so go ahead and\nconvert to parts_round_to_int_normal, which in turn\nallows cleaning up of the raised exception handling.\n\nSigned-off-by: Richard Henderson <richard.henderson@linaro.org>\n---\n fpu/softfloat.c | 434 ++++++++++----------------------------\n fpu/softfloat-parts.c.inc | 157 ++++++++++++++\n 2 files changed, 263 insertions(+), 328 deletions(-)", "diff": "diff --git a/fpu/softfloat.c b/fpu/softfloat.c\nindex 1b86111279..ce96ea753c 100644\n--- a/fpu/softfloat.c\n+++ b/fpu/softfloat.c\n@@ -810,6 +810,24 @@ static FloatParts128 *parts128_div(FloatParts128 *a, FloatParts128 *b,\n #define parts_div(A, B, S) \\\n PARTS_GENERIC_64_128(div, A)(A, B, S)\n \n+static bool parts64_round_to_int_normal(FloatParts64 *a, FloatRoundMode rm,\n+ int scale, int frac_size);\n+static bool parts128_round_to_int_normal(FloatParts128 *a, FloatRoundMode r,\n+ int scale, int frac_size);\n+\n+#define parts_round_to_int_normal(A, R, C, F) \\\n+ PARTS_GENERIC_64_128(round_to_int_normal, A)(A, R, C, F)\n+\n+static void parts64_round_to_int(FloatParts64 *a, FloatRoundMode rm,\n+ int scale, float_status *s,\n+ const FloatFmt *fmt);\n+static void parts128_round_to_int(FloatParts128 *a, FloatRoundMode r,\n+ int scale, float_status *s,\n+ const FloatFmt *fmt);\n+\n+#define parts_round_to_int(A, R, C, S, F) \\\n+ PARTS_GENERIC_64_128(round_to_int, A)(A, R, C, S, F)\n+\n /*\n * Helper functions for softfloat-parts.c.inc, per-size operations.\n */\n@@ -2284,153 +2302,52 @@ float128 float64_to_float128(float64 a, float_status *s)\n }\n \n /*\n- * Rounds the floating-point value `a' to an integer, and returns the\n- * result as a floating-point value. The operation is performed\n- * according to the IEC/IEEE Standard for Binary Floating-Point\n- * Arithmetic.\n+ * Round to integral value\n */\n \n-static FloatParts64 round_to_int(FloatParts64 a, FloatRoundMode rmode,\n- int scale, float_status *s)\n-{\n- switch (a.cls) {\n- case float_class_qnan:\n- case float_class_snan:\n- parts_return_nan(&a, s);\n- break;\n-\n- case float_class_zero:\n- case float_class_inf:\n- /* already \"integral\" */\n- break;\n-\n- case float_class_normal:\n- scale = MIN(MAX(scale, -0x10000), 0x10000);\n- a.exp += scale;\n-\n- if (a.exp >= DECOMPOSED_BINARY_POINT) {\n- /* already integral */\n- break;\n- }\n- if (a.exp < 0) {\n- bool one;\n- /* all fractional */\n- float_raise(float_flag_inexact, s);\n- switch (rmode) {\n- case float_round_nearest_even:\n- one = a.exp == -1 && a.frac > DECOMPOSED_IMPLICIT_BIT;\n- break;\n- case float_round_ties_away:\n- one = a.exp == -1 && a.frac >= DECOMPOSED_IMPLICIT_BIT;\n- break;\n- case float_round_to_zero:\n- one = false;\n- break;\n- case float_round_up:\n- one = !a.sign;\n- break;\n- case float_round_down:\n- one = a.sign;\n- break;\n- case float_round_to_odd:\n- one = true;\n- break;\n- default:\n- g_assert_not_reached();\n- }\n-\n- if (one) {\n- a.frac = DECOMPOSED_IMPLICIT_BIT;\n- a.exp = 0;\n- } else {\n- a.cls = float_class_zero;\n- }\n- } else {\n- uint64_t frac_lsb = DECOMPOSED_IMPLICIT_BIT >> a.exp;\n- uint64_t frac_lsbm1 = frac_lsb >> 1;\n- uint64_t rnd_even_mask = (frac_lsb - 1) | frac_lsb;\n- uint64_t rnd_mask = rnd_even_mask >> 1;\n- uint64_t inc;\n-\n- switch (rmode) {\n- case float_round_nearest_even:\n- inc = ((a.frac & rnd_even_mask) != frac_lsbm1 ? frac_lsbm1 : 0);\n- break;\n- case float_round_ties_away:\n- inc = frac_lsbm1;\n- break;\n- case float_round_to_zero:\n- inc = 0;\n- break;\n- case float_round_up:\n- inc = a.sign ? 0 : rnd_mask;\n- break;\n- case float_round_down:\n- inc = a.sign ? rnd_mask : 0;\n- break;\n- case float_round_to_odd:\n- inc = a.frac & frac_lsb ? 0 : rnd_mask;\n- break;\n- default:\n- g_assert_not_reached();\n- }\n-\n- if (a.frac & rnd_mask) {\n- float_raise(float_flag_inexact, s);\n- if (uadd64_overflow(a.frac, inc, &a.frac)) {\n- a.frac >>= 1;\n- a.frac |= DECOMPOSED_IMPLICIT_BIT;\n- a.exp++;\n- }\n- a.frac &= ~rnd_mask;\n- }\n- }\n- break;\n- default:\n- g_assert_not_reached();\n- }\n- return a;\n-}\n-\n float16 float16_round_to_int(float16 a, float_status *s)\n {\n- FloatParts64 pa, pr;\n+ FloatParts64 p;\n \n- float16_unpack_canonical(&pa, a, s);\n- pr = round_to_int(pa, s->float_rounding_mode, 0, s);\n- return float16_round_pack_canonical(&pr, s);\n+ float16_unpack_canonical(&p, a, s);\n+ parts_round_to_int(&p, s->float_rounding_mode, 0, s, &float16_params);\n+ return float16_round_pack_canonical(&p, s);\n }\n \n float32 float32_round_to_int(float32 a, float_status *s)\n {\n- FloatParts64 pa, pr;\n+ FloatParts64 p;\n \n- float32_unpack_canonical(&pa, a, s);\n- pr = round_to_int(pa, s->float_rounding_mode, 0, s);\n- return float32_round_pack_canonical(&pr, s);\n+ float32_unpack_canonical(&p, a, s);\n+ parts_round_to_int(&p, s->float_rounding_mode, 0, s, &float32_params);\n+ return float32_round_pack_canonical(&p, s);\n }\n \n float64 float64_round_to_int(float64 a, float_status *s)\n {\n- FloatParts64 pa, pr;\n+ FloatParts64 p;\n \n- float64_unpack_canonical(&pa, a, s);\n- pr = round_to_int(pa, s->float_rounding_mode, 0, s);\n- return float64_round_pack_canonical(&pr, s);\n+ float64_unpack_canonical(&p, a, s);\n+ parts_round_to_int(&p, s->float_rounding_mode, 0, s, &float64_params);\n+ return float64_round_pack_canonical(&p, s);\n }\n \n-/*\n- * Rounds the bfloat16 value `a' to an integer, and returns the\n- * result as a bfloat16 value.\n- */\n-\n bfloat16 bfloat16_round_to_int(bfloat16 a, float_status *s)\n {\n- FloatParts64 pa, pr;\n+ FloatParts64 p;\n \n- bfloat16_unpack_canonical(&pa, a, s);\n- pr = round_to_int(pa, s->float_rounding_mode, 0, s);\n- return bfloat16_round_pack_canonical(&pr, s);\n+ bfloat16_unpack_canonical(&p, a, s);\n+ parts_round_to_int(&p, s->float_rounding_mode, 0, s, &bfloat16_params);\n+ return bfloat16_round_pack_canonical(&p, s);\n+}\n+\n+float128 float128_round_to_int(float128 a, float_status *s)\n+{\n+ FloatParts128 p;\n+\n+ float128_unpack_canonical(&p, a, s);\n+ parts_round_to_int(&p, s->float_rounding_mode, 0, s, &float128_params);\n+ return float128_round_pack_canonical(&p, s);\n }\n \n /*\n@@ -2444,48 +2361,58 @@ bfloat16 bfloat16_round_to_int(bfloat16 a, float_status *s)\n * is returned.\n */\n \n-static int64_t round_to_int_and_pack(FloatParts64 in, FloatRoundMode rmode,\n+static int64_t round_to_int_and_pack(FloatParts64 p, FloatRoundMode rmode,\n int scale, int64_t min, int64_t max,\n float_status *s)\n {\n+ int flags = 0;\n uint64_t r;\n- int orig_flags = get_float_exception_flags(s);\n- FloatParts64 p = round_to_int(in, rmode, scale, s);\n \n switch (p.cls) {\n case float_class_snan:\n case float_class_qnan:\n- s->float_exception_flags = orig_flags | float_flag_invalid;\n- return max;\n+ flags = float_flag_invalid;\n+ r = max;\n+ break;\n+\n case float_class_inf:\n- s->float_exception_flags = orig_flags | float_flag_invalid;\n- return p.sign ? min : max;\n+ flags = float_flag_invalid;\n+ r = p.sign ? min : max;\n+ break;\n+\n case float_class_zero:\n return 0;\n+\n case float_class_normal:\n+ /* TODO: 62 = N - 2, frac_size for rounding */\n+ if (parts_round_to_int_normal(&p, rmode, scale, 62)) {\n+ flags = float_flag_inexact;\n+ }\n+\n if (p.exp <= DECOMPOSED_BINARY_POINT) {\n r = p.frac >> (DECOMPOSED_BINARY_POINT - p.exp);\n } else {\n r = UINT64_MAX;\n }\n if (p.sign) {\n- if (r <= -(uint64_t) min) {\n- return -r;\n+ if (r <= -(uint64_t)min) {\n+ r = -r;\n } else {\n- s->float_exception_flags = orig_flags | float_flag_invalid;\n- return min;\n- }\n- } else {\n- if (r <= max) {\n- return r;\n- } else {\n- s->float_exception_flags = orig_flags | float_flag_invalid;\n- return max;\n+ flags = float_flag_invalid;\n+ r = min;\n }\n+ } else if (r > max) {\n+ flags = float_flag_invalid;\n+ r = max;\n }\n+ break;\n+\n default:\n g_assert_not_reached();\n }\n+\n+ float_raise(flags, s);\n+ return r;\n }\n \n int8_t float16_to_int8_scalbn(float16 a, FloatRoundMode rmode, int scale,\n@@ -2748,49 +2675,59 @@ int64_t bfloat16_to_int64_round_to_zero(bfloat16 a, float_status *s)\n * flag.\n */\n \n-static uint64_t round_to_uint_and_pack(FloatParts64 in, FloatRoundMode rmode,\n+static uint64_t round_to_uint_and_pack(FloatParts64 p, FloatRoundMode rmode,\n int scale, uint64_t max,\n float_status *s)\n {\n- int orig_flags = get_float_exception_flags(s);\n- FloatParts64 p = round_to_int(in, rmode, scale, s);\n+ int flags = 0;\n uint64_t r;\n \n switch (p.cls) {\n case float_class_snan:\n case float_class_qnan:\n- s->float_exception_flags = orig_flags | float_flag_invalid;\n- return max;\n+ flags = float_flag_invalid;\n+ r = max;\n+ break;\n+\n case float_class_inf:\n- s->float_exception_flags = orig_flags | float_flag_invalid;\n- return p.sign ? 0 : max;\n+ flags = float_flag_invalid;\n+ r = p.sign ? 0 : max;\n+ break;\n+\n case float_class_zero:\n return 0;\n+\n case float_class_normal:\n+ /* TODO: 62 = N - 2, frac_size for rounding */\n+ if (parts_round_to_int_normal(&p, rmode, scale, 62)) {\n+ flags = float_flag_inexact;\n+ if (p.cls == float_class_zero) {\n+ r = 0;\n+ break;\n+ }\n+ }\n+\n if (p.sign) {\n- s->float_exception_flags = orig_flags | float_flag_invalid;\n- return 0;\n- }\n-\n- if (p.exp <= DECOMPOSED_BINARY_POINT) {\n- r = p.frac >> (DECOMPOSED_BINARY_POINT - p.exp);\n+ flags = float_flag_invalid;\n+ r = 0;\n+ } else if (p.exp > DECOMPOSED_BINARY_POINT) {\n+ flags = float_flag_invalid;\n+ r = max;\n } else {\n- s->float_exception_flags = orig_flags | float_flag_invalid;\n- return max;\n+ r = p.frac >> (DECOMPOSED_BINARY_POINT - p.exp);\n+ if (r > max) {\n+ flags = float_flag_invalid;\n+ r = max;\n+ }\n }\n+ break;\n \n- /* For uint64 this will never trip, but if p.exp is too large\n- * to shift a decomposed fraction we shall have exited via the\n- * 3rd leg above.\n- */\n- if (r > max) {\n- s->float_exception_flags = orig_flags | float_flag_invalid;\n- return max;\n- }\n- return r;\n default:\n g_assert_not_reached();\n }\n+\n+ float_raise(flags, s);\n+ return r;\n }\n \n uint8_t float16_to_uint8_scalbn(float16 a, FloatRoundMode rmode, int scale,\n@@ -6955,165 +6892,6 @@ floatx80 float128_to_floatx80(float128 a, float_status *status)\n \n }\n \n-/*----------------------------------------------------------------------------\n-| Rounds the quadruple-precision floating-point value `a' to an integer, and\n-| returns the result as a quadruple-precision floating-point value. The\n-| operation is performed according to the IEC/IEEE Standard for Binary\n-| Floating-Point Arithmetic.\n-*----------------------------------------------------------------------------*/\n-\n-float128 float128_round_to_int(float128 a, float_status *status)\n-{\n- bool aSign;\n- int32_t aExp;\n- uint64_t lastBitMask, roundBitsMask;\n- float128 z;\n-\n- aExp = extractFloat128Exp( a );\n- if ( 0x402F <= aExp ) {\n- if ( 0x406F <= aExp ) {\n- if ( ( aExp == 0x7FFF )\n- && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) )\n- ) {\n- return propagateFloat128NaN(a, a, status);\n- }\n- return a;\n- }\n- lastBitMask = 1;\n- lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1;\n- roundBitsMask = lastBitMask - 1;\n- z = a;\n- switch (status->float_rounding_mode) {\n- case float_round_nearest_even:\n- if ( lastBitMask ) {\n- add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low );\n- if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;\n- }\n- else {\n- if ( (int64_t) z.low < 0 ) {\n- ++z.high;\n- if ( (uint64_t) ( z.low<<1 ) == 0 ) z.high &= ~1;\n- }\n- }\n- break;\n- case float_round_ties_away:\n- if (lastBitMask) {\n- add128(z.high, z.low, 0, lastBitMask >> 1, &z.high, &z.low);\n- } else {\n- if ((int64_t) z.low < 0) {\n- ++z.high;\n- }\n- }\n- break;\n- case float_round_to_zero:\n- break;\n- case float_round_up:\n- if (!extractFloat128Sign(z)) {\n- add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low);\n- }\n- break;\n- case float_round_down:\n- if (extractFloat128Sign(z)) {\n- add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low);\n- }\n- break;\n- case float_round_to_odd:\n- /*\n- * Note that if lastBitMask == 0, the last bit is the lsb\n- * of high, and roundBitsMask == -1.\n- */\n- if ((lastBitMask ? z.low & lastBitMask : z.high & 1) == 0) {\n- add128(z.high, z.low, 0, roundBitsMask, &z.high, &z.low);\n- }\n- break;\n- default:\n- abort();\n- }\n- z.low &= ~ roundBitsMask;\n- }\n- else {\n- if ( aExp < 0x3FFF ) {\n- if ( ( ( (uint64_t) ( a.high<<1 ) ) | a.low ) == 0 ) return a;\n- float_raise(float_flag_inexact, status);\n- aSign = extractFloat128Sign( a );\n- switch (status->float_rounding_mode) {\n- case float_round_nearest_even:\n- if ( ( aExp == 0x3FFE )\n- && ( extractFloat128Frac0( a )\n- | extractFloat128Frac1( a ) )\n- ) {\n- return packFloat128( aSign, 0x3FFF, 0, 0 );\n- }\n- break;\n- case float_round_ties_away:\n- if (aExp == 0x3FFE) {\n- return packFloat128(aSign, 0x3FFF, 0, 0);\n- }\n- break;\n- case float_round_down:\n- return\n- aSign ? packFloat128( 1, 0x3FFF, 0, 0 )\n- : packFloat128( 0, 0, 0, 0 );\n- case float_round_up:\n- return\n- aSign ? packFloat128( 1, 0, 0, 0 )\n- : packFloat128( 0, 0x3FFF, 0, 0 );\n-\n- case float_round_to_odd:\n- return packFloat128(aSign, 0x3FFF, 0, 0);\n-\n- case float_round_to_zero:\n- break;\n- }\n- return packFloat128( aSign, 0, 0, 0 );\n- }\n- lastBitMask = 1;\n- lastBitMask <<= 0x402F - aExp;\n- roundBitsMask = lastBitMask - 1;\n- z.low = 0;\n- z.high = a.high;\n- switch (status->float_rounding_mode) {\n- case float_round_nearest_even:\n- z.high += lastBitMask>>1;\n- if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) {\n- z.high &= ~ lastBitMask;\n- }\n- break;\n- case float_round_ties_away:\n- z.high += lastBitMask>>1;\n- break;\n- case float_round_to_zero:\n- break;\n- case float_round_up:\n- if (!extractFloat128Sign(z)) {\n- z.high |= ( a.low != 0 );\n- z.high += roundBitsMask;\n- }\n- break;\n- case float_round_down:\n- if (extractFloat128Sign(z)) {\n- z.high |= (a.low != 0);\n- z.high += roundBitsMask;\n- }\n- break;\n- case float_round_to_odd:\n- if ((z.high & lastBitMask) == 0) {\n- z.high |= (a.low != 0);\n- z.high += roundBitsMask;\n- }\n- break;\n- default:\n- abort();\n- }\n- z.high &= ~ roundBitsMask;\n- }\n- if ( ( z.low != a.low ) || ( z.high != a.high ) ) {\n- float_raise(float_flag_inexact, status);\n- }\n- return z;\n-\n-}\n-\n /*----------------------------------------------------------------------------\n | Returns the remainder of the quadruple-precision floating-point value `a'\n | with respect to the corresponding value `b'. The operation is performed\ndiff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc\nindex f8165d92f9..b2c4624d8c 100644\n--- a/fpu/softfloat-parts.c.inc\n+++ b/fpu/softfloat-parts.c.inc\n@@ -594,3 +594,160 @@ static FloatPartsN *partsN(div)(FloatPartsN *a, FloatPartsN *b,\n a->cls = float_class_inf;\n return a;\n }\n+\n+/*\n+ * Rounds the floating-point value `a' to an integer, and returns the\n+ * result as a floating-point value. The operation is performed\n+ * according to the IEC/IEEE Standard for Binary Floating-Point\n+ * Arithmetic.\n+ *\n+ * parts_round_to_int_normal is an internal helper function for\n+ * normal numbers only, returning true for inexact but not directly\n+ * raising float_flag_inexact.\n+ */\n+static bool partsN(round_to_int_normal)(FloatPartsN *a, FloatRoundMode rmode,\n+ int scale, int frac_size)\n+{\n+ uint64_t frac_lsb, frac_lsbm1, rnd_even_mask, rnd_mask, inc;\n+ int shift_adj;\n+\n+ scale = MIN(MAX(scale, -0x10000), 0x10000);\n+ a->exp += scale;\n+\n+ if (a->exp < 0) {\n+ bool one;\n+\n+ /* All fractional */\n+ switch (rmode) {\n+ case float_round_nearest_even:\n+ one = false;\n+ if (a->exp == -1) {\n+ FloatPartsN tmp;\n+ /* Shift left one, discarding DECOMPOSED_IMPLICIT_BIT */\n+ frac_add(&tmp, a, a);\n+ /* Anything remaining means frac > 0.5. */\n+ one = !frac_eqz(&tmp);\n+ }\n+ break;\n+ case float_round_ties_away:\n+ one = a->exp == -1;\n+ break;\n+ case float_round_to_zero:\n+ one = false;\n+ break;\n+ case float_round_up:\n+ one = !a->sign;\n+ break;\n+ case float_round_down:\n+ one = a->sign;\n+ break;\n+ case float_round_to_odd:\n+ one = true;\n+ break;\n+ default:\n+ g_assert_not_reached();\n+ }\n+\n+ frac_clear(a);\n+ a->exp = 0;\n+ if (one) {\n+ a->frac_hi = DECOMPOSED_IMPLICIT_BIT;\n+ } else {\n+ a->cls = float_class_zero;\n+ }\n+ return true;\n+ }\n+\n+ if (a->exp >= frac_size) {\n+ /* All integral */\n+ return false;\n+ }\n+\n+ if (N > 64 && a->exp < N - 64) {\n+ /*\n+ * Rounding is not in the low word -- shift lsb to bit 2,\n+ * which leaves room for sticky and rounding bit.\n+ */\n+ shift_adj = (N - 1) - (a->exp + 2);\n+ frac_shrjam(a, shift_adj);\n+ frac_lsb = 1 << 2;\n+ } else {\n+ shift_adj = 0;\n+ frac_lsb = DECOMPOSED_IMPLICIT_BIT >> (a->exp & 63);\n+ }\n+\n+ frac_lsbm1 = frac_lsb >> 1;\n+ rnd_mask = frac_lsb - 1;\n+ rnd_even_mask = rnd_mask | frac_lsb;\n+\n+ if (!(a->frac_lo & rnd_mask)) {\n+ /* Fractional bits already clear, undo the shift above. */\n+ frac_shl(a, shift_adj);\n+ return false;\n+ }\n+\n+ switch (rmode) {\n+ case float_round_nearest_even:\n+ inc = ((a->frac_lo & rnd_even_mask) != frac_lsbm1 ? frac_lsbm1 : 0);\n+ break;\n+ case float_round_ties_away:\n+ inc = frac_lsbm1;\n+ break;\n+ case float_round_to_zero:\n+ inc = 0;\n+ break;\n+ case float_round_up:\n+ inc = a->sign ? 0 : rnd_mask;\n+ break;\n+ case float_round_down:\n+ inc = a->sign ? rnd_mask : 0;\n+ break;\n+ case float_round_to_odd:\n+ inc = a->frac_lo & frac_lsb ? 0 : rnd_mask;\n+ break;\n+ default:\n+ g_assert_not_reached();\n+ }\n+\n+ if (shift_adj == 0) {\n+ if (frac_addi(a, a, inc)) {\n+ frac_shr(a, 1);\n+ a->frac_hi |= DECOMPOSED_IMPLICIT_BIT;\n+ a->exp++;\n+ }\n+ a->frac_lo &= ~rnd_mask;\n+ } else {\n+ frac_addi(a, a, inc);\n+ a->frac_lo &= ~rnd_mask;\n+ /* Be careful shifting back, not to overflow */\n+ frac_shl(a, shift_adj - 1);\n+ if (a->frac_hi & DECOMPOSED_IMPLICIT_BIT) {\n+ a->exp++;\n+ } else {\n+ frac_add(a, a, a);\n+ }\n+ }\n+ return true;\n+}\n+\n+static void partsN(round_to_int)(FloatPartsN *a, FloatRoundMode rmode,\n+ int scale, float_status *s,\n+ const FloatFmt *fmt)\n+{\n+ switch (a->cls) {\n+ case float_class_qnan:\n+ case float_class_snan:\n+ parts_return_nan(a, s);\n+ break;\n+ case float_class_zero:\n+ case float_class_inf:\n+ break;\n+ case float_class_normal:\n+ if (parts_round_to_int_normal(a, rmode, scale, fmt->frac_size)) {\n+ float_raise(float_flag_inexact, s);\n+ }\n+ break;\n+ default:\n+ g_assert_not_reached();\n+ }\n+}\n", "prefixes": [ "45/72" ] }