aboutsummaryrefslogtreecommitdiff
path: root/fpu/softfloat-parts.c.inc
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2023-05-27 07:19:07 -0700
committerRichard Henderson <richard.henderson@linaro.org>2023-07-01 08:26:54 +0200
commite2041f4d5de01cb03b52908d36e9602b8c4a2479 (patch)
tree400f8bcf2d1326b8099154fbc07c8dccfea360c6 /fpu/softfloat-parts.c.inc
parente665cf72fe6357945fdbecf747dac58c0c7c7c66 (diff)
fpu: Add float64_to_int{32,64}_modulo
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>
Diffstat (limited to 'fpu/softfloat-parts.c.inc')
-rw-r--r--fpu/softfloat-parts.c.inc78
1 files changed, 78 insertions, 0 deletions
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
@@ -1182,6 +1182,84 @@ static uint64_t partsN(float_to_uint)(FloatPartsN *p, FloatRoundMode rmode,
}
/*
+ * 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
*
* Returns the result of converting the two's complement integer `a'