1
From 03d182e8ce2e933553fe1c962ef94534f7388299 Mon Sep 17 00:00:00 2001
2
From: Peter Maydell <peter.maydell@linaro.org>
3
Date: Tue, 7 Jan 2014 17:17:49 +0000
4
Subject: [PATCH 091/158] softfloat: Only raise Invalid when conversions to int
7
We implement a number of float-to-integer conversions using conversion
8
to an integer type with a wider range and then a check against the
9
narrower range we are actually converting to. If we find the result to
10
be out of range we correctly raise the Invalid exception, but we must
11
also suppress other exceptions which might have been raised by the
12
conversion function we called.
14
This won't throw away exceptions we should have preserved, because for
15
the 'core' exception flags the IEEE spec mandates that the only valid
16
combinations of exception that can be raised by a single operation are
17
Inexact + Overflow and Inexact + Underflow. For the non-IEEE softfloat
18
flag for input denormals, we can guarantee that that flag won't have
19
been set for out of range float-to-int conversions because a squashed
20
denormal by definition goes to plus or minus zero, which is always in
21
range after conversion to integer zero.
23
This bug has been fixed for some of the float-to-int conversion routines
24
by previous patches; fix it for the remaining functions as well, so
25
that they all restore the pre-conversion status flags prior to raising
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
30
Reviewed-by: Richard Henderson <rth@twiddle.net>
32
fpu/softfloat.c | 28 ++++++++++++++++------------
33
1 file changed, 16 insertions(+), 12 deletions(-)
35
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
36
index e72da1a..4f5e9d0 100644
39
@@ -6509,17 +6509,18 @@ uint32 float32_to_uint32( float32 a STATUS_PARAM )
43
+ int old_exc_flags = get_float_exception_flags(status);
45
v = float32_to_int64(a STATUS_VAR);
48
- float_raise( float_flag_invalid STATUS_VAR);
49
} else if (v > 0xffffffff) {
51
- float_raise( float_flag_invalid STATUS_VAR);
56
+ set_float_exception_flags(old_exc_flags, status);
57
+ float_raise(float_flag_invalid STATUS_VAR);
61
@@ -6527,17 +6528,18 @@ uint32 float32_to_uint32_round_to_zero( float32 a STATUS_PARAM )
65
+ int old_exc_flags = get_float_exception_flags(status);
67
v = float32_to_int64_round_to_zero(a STATUS_VAR);
70
- float_raise( float_flag_invalid STATUS_VAR);
71
} else if (v > 0xffffffff) {
73
- float_raise( float_flag_invalid STATUS_VAR);
78
+ set_float_exception_flags(old_exc_flags, status);
79
+ float_raise(float_flag_invalid STATUS_VAR);
83
@@ -6585,17 +6587,18 @@ uint_fast16_t float32_to_uint16_round_to_zero(float32 a STATUS_PARAM)
87
+ int old_exc_flags = get_float_exception_flags(status);
89
v = float32_to_int64_round_to_zero(a STATUS_VAR);
92
- float_raise( float_flag_invalid STATUS_VAR);
93
} else if (v > 0xffff) {
95
- float_raise( float_flag_invalid STATUS_VAR);
100
+ set_float_exception_flags(old_exc_flags, status);
101
+ float_raise(float_flag_invalid STATUS_VAR);
105
@@ -6679,17 +6682,18 @@ uint_fast16_t float64_to_uint16_round_to_zero(float64 a STATUS_PARAM)
109
+ int old_exc_flags = get_float_exception_flags(status);
111
v = float64_to_int64_round_to_zero(a STATUS_VAR);
114
- float_raise( float_flag_invalid STATUS_VAR);
115
} else if (v > 0xffff) {
117
- float_raise( float_flag_invalid STATUS_VAR);
122
+ set_float_exception_flags(old_exc_flags, status);
123
+ float_raise(float_flag_invalid STATUS_VAR);