From: Richard Henderson <richard.henderson@linaro.org>
To: qemu-devel@nongnu.org
Cc: "Christoph Muellner" <christoph.muellner@vrull.eu>,
"Alex Bennée" <alex.bennee@linaro.org>
Subject: [PULL 05/11] fpu: Add float64_to_int{32,64}_modulo
Date: Sat, 1 Jul 2023 08:55:04 +0200 [thread overview]
Message-ID: <20230701065510.514743-6-richard.henderson@linaro.org> (raw)
In-Reply-To: <20230701065510.514743-1-richard.henderson@linaro.org>
Add versions of float64_to_int* which do not saturate the result.
Reviewed-by: Christoph Muellner <christoph.muellner@vrull.eu>
Tested-by: Christoph Muellner <christoph.muellner@vrull.eu>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-Id: <20230527141910.1885950-2-richard.henderson@linaro.org>
---
include/fpu/softfloat.h | 3 ++
fpu/softfloat.c | 31 ++++++++++++++++
fpu/softfloat-parts.c.inc | 78 +++++++++++++++++++++++++++++++++++++++
3 files changed, 112 insertions(+)
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 3dcf20e3a2..cd130564d8 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -751,6 +751,9 @@ int16_t float64_to_int16_round_to_zero(float64, float_status *status);
int32_t float64_to_int32_round_to_zero(float64, float_status *status);
int64_t float64_to_int64_round_to_zero(float64, float_status *status);
+int32_t float64_to_int32_modulo(float64, FloatRoundMode, float_status *status);
+int64_t float64_to_int64_modulo(float64, FloatRoundMode, float_status *status);
+
uint16_t float64_to_uint16_scalbn(float64, FloatRoundMode, int, float_status *);
uint32_t float64_to_uint32_scalbn(float64, FloatRoundMode, int, float_status *);
uint64_t float64_to_uint64_scalbn(float64, FloatRoundMode, int, float_status *);
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 42e6c188b4..0cc130ae9b 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -852,11 +852,24 @@ static uint64_t parts128_float_to_uint(FloatParts128 *p, FloatRoundMode rmode,
#define parts_float_to_uint(P, R, Z, M, S) \
PARTS_GENERIC_64_128(float_to_uint, P)(P, R, Z, M, S)
+static int64_t parts64_float_to_sint_modulo(FloatParts64 *p,
+ FloatRoundMode rmode,
+ int bitsm1, float_status *s);
+static int64_t parts128_float_to_sint_modulo(FloatParts128 *p,
+ FloatRoundMode rmode,
+ int bitsm1, float_status *s);
+
+#define parts_float_to_sint_modulo(P, R, M, S) \
+ PARTS_GENERIC_64_128(float_to_sint_modulo, P)(P, R, M, S)
+
static void parts64_sint_to_float(FloatParts64 *p, int64_t a,
int scale, float_status *s);
static void parts128_sint_to_float(FloatParts128 *p, int64_t a,
int scale, float_status *s);
+#define parts_float_to_sint(P, R, Z, MN, MX, S) \
+ PARTS_GENERIC_64_128(float_to_sint, P)(P, R, Z, MN, MX, S)
+
#define parts_sint_to_float(P, I, Z, S) \
PARTS_GENERIC_64_128(sint_to_float, P)(P, I, Z, S)
@@ -3409,6 +3422,24 @@ int64_t bfloat16_to_int64_round_to_zero(bfloat16 a, float_status *s)
return bfloat16_to_int64_scalbn(a, float_round_to_zero, 0, s);
}
+int32_t float64_to_int32_modulo(float64 a, FloatRoundMode rmode,
+ float_status *s)
+{
+ FloatParts64 p;
+
+ float64_unpack_canonical(&p, a, s);
+ return parts_float_to_sint_modulo(&p, rmode, 31, s);
+}
+
+int64_t float64_to_int64_modulo(float64 a, FloatRoundMode rmode,
+ float_status *s)
+{
+ FloatParts64 p;
+
+ float64_unpack_canonical(&p, a, s);
+ return parts_float_to_sint_modulo(&p, rmode, 63, s);
+}
+
/*
* Floating-point to unsigned integer conversions
*/
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index 247400031c..527e15e6ab 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -1181,6 +1181,84 @@ static uint64_t partsN(float_to_uint)(FloatPartsN *p, FloatRoundMode rmode,
return r;
}
+/*
+ * Like partsN(float_to_sint), except do not saturate the result.
+ * Instead, return the rounded unbounded precision two's compliment result,
+ * modulo 2**(bitsm1 + 1).
+ */
+static int64_t partsN(float_to_sint_modulo)(FloatPartsN *p,
+ FloatRoundMode rmode,
+ int bitsm1, float_status *s)
+{
+ int flags = 0;
+ uint64_t r;
+ bool overflow = false;
+
+ switch (p->cls) {
+ case float_class_snan:
+ flags |= float_flag_invalid_snan;
+ /* fall through */
+ case float_class_qnan:
+ flags |= float_flag_invalid;
+ r = 0;
+ break;
+
+ case float_class_inf:
+ overflow = true;
+ r = 0;
+ break;
+
+ case float_class_zero:
+ return 0;
+
+ case float_class_normal:
+ /* TODO: N - 2 is frac_size for rounding; could use input fmt. */
+ if (parts_round_to_int_normal(p, rmode, 0, N - 2)) {
+ flags = float_flag_inexact;
+ }
+
+ if (p->exp <= DECOMPOSED_BINARY_POINT) {
+ /*
+ * Because we rounded to integral, and exp < 64,
+ * we know frac_low is zero.
+ */
+ r = p->frac_hi >> (DECOMPOSED_BINARY_POINT - p->exp);
+ if (p->exp < bitsm1) {
+ /* Result in range. */
+ } else if (p->exp == bitsm1) {
+ /* The only in-range value is INT_MIN. */
+ overflow = !p->sign || p->frac_hi != DECOMPOSED_IMPLICIT_BIT;
+ } else {
+ overflow = true;
+ }
+ } else {
+ /* Overflow, but there might still be bits to return. */
+ int shl = p->exp - DECOMPOSED_BINARY_POINT;
+ if (shl < N) {
+ frac_shl(p, shl);
+ r = p->frac_hi;
+ } else {
+ r = 0;
+ }
+ overflow = true;
+ }
+
+ if (p->sign) {
+ r = -r;
+ }
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+
+ if (overflow) {
+ flags = float_flag_invalid | float_flag_invalid_cvti;
+ }
+ float_raise(flags, s);
+ return r;
+}
+
/*
* Integer to float conversions
*
--
2.34.1
next prev parent reply other threads:[~2023-07-01 6:56 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-01 6:54 [PULL 00/11] tcg and misc patch queue Richard Henderson
2023-07-01 6:55 ` [PULL 01/11] ui/dbus: fix build errors in dbus_update_gl_cb and dbus_call_update_gl Richard Henderson
2023-07-01 6:55 ` [PULL 02/11] audio: dbus requires pixman Richard Henderson
2023-07-01 6:55 ` [PULL 03/11] accel/tcg: Fix start page passed to tb_invalidate_phys_page_range__locked Richard Henderson
2023-07-01 6:55 ` [PULL 04/11] accel/tcg: Assert one page in tb_invalidate_phys_page_range__locked Richard Henderson
2023-07-01 6:55 ` Richard Henderson [this message]
2023-07-01 6:55 ` [PULL 06/11] tests/tcg/alpha: Add test for cvttq Richard Henderson
2023-07-01 6:55 ` [PULL 07/11] target/alpha: Use float64_to_int64_modulo for CVTTQ Richard Henderson
2023-07-01 6:55 ` [PULL 08/11] target/arm: Use float64_to_int32_modulo for FJCVTZS Richard Henderson
2023-07-01 6:55 ` [PULL 09/11] tcg: Reduce tcg_assert_listed_vecop() scope Richard Henderson
2023-07-01 6:55 ` [PULL 10/11] target/nios2 : Explicitly ask for target-endian loads and stores Richard Henderson
2023-07-01 6:55 ` [PULL 11/11] linux-user: Avoid mmap of the last byte of the reserved_va Richard Henderson
2023-07-01 8:10 ` [PULL 00/11] tcg and misc patch queue Philippe Mathieu-Daudé
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230701065510.514743-6-richard.henderson@linaro.org \
--to=richard.henderson@linaro.org \
--cc=alex.bennee@linaro.org \
--cc=christoph.muellner@vrull.eu \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).