Patchwork [V4,03/22] softfloat: Fix float64_to_uint64_round_to_zero

login
register
mail settings
Submitter Tom Musta
Date Dec. 18, 2013, 8:19 p.m.
Message ID <1387397961-4894-4-git-send-email-tommusta@gmail.com>
Download mbox | patch
Permalink /patch/303036/
State New
Headers show

Comments

Tom Musta - Dec. 18, 2013, 8:19 p.m.
The float64_to_uint64_round_to_zero routine is incorrect.

For example, the following test pattern:

    46697351FF4AEC29 / 0x1.97351ff4aec29p+103

currently produces 8000000000000000 instead of FFFFFFFFFFFFFFFF.

This patch re-implements the routine to temporarily force the
rounding mode and use the float64_to_uint64 routine.

This contribution can be licensed under either the softfloat-2a or -2b
license.

Signed-off-by: Tom Musta <tommusta@gmail.com>
---
 fpu/softfloat.c |   12 +++++-------
 1 files changed, 5 insertions(+), 7 deletions(-)
Peter Maydell - Dec. 19, 2013, 9:43 p.m.
On 18 December 2013 20:19, Tom Musta <tommusta@gmail.com> wrote:
> The float64_to_uint64_round_to_zero routine is incorrect.
>
> For example, the following test pattern:
>
>     46697351FF4AEC29 / 0x1.97351ff4aec29p+103
>
> currently produces 8000000000000000 instead of FFFFFFFFFFFFFFFF.
>
> This patch re-implements the routine to temporarily force the
> rounding mode and use the float64_to_uint64 routine.
>
> This contribution can be licensed under either the softfloat-2a or -2b
> license.
>
> Signed-off-by: Tom Musta <tommusta@gmail.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

The other approach would be to make all the conversion
functions explicitly take the rounding mode parameter
(and in some ways that might be closer to the set of
functionality IEE754-2008 describes), but this is a
simple change and saving and restoring rounding mode
is very cheap.

thanks
-- PMM

Patch

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 1ff59d0..1b614ae 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6675,13 +6675,11 @@  uint64_t float64_to_uint64(float64 a STATUS_PARAM)
 
 uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM)
 {
-    int64_t v;
-
-    v = float64_val(int64_to_float64(INT64_MIN STATUS_VAR));
-    v += float64_val(a);
-    v = float64_to_int64_round_to_zero(make_float64(v) STATUS_VAR);
-
-    return v - INT64_MIN;
+    signed char current_rounding_mode = STATUS(float_rounding_mode);
+    set_float_rounding_mode(float_round_to_zero STATUS_VAR);
+    int64_t v = float64_to_uint64(a STATUS_VAR);
+    set_float_rounding_mode(current_rounding_mode STATUS_VAR);
+    return v;
 }
 
 #define COMPARE(s, nan_exp)                                                  \