[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 58/76] softfloat: Only raise Invalid when conversions
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PULL 58/76] softfloat: Only raise Invalid when conversions to int are out of range |
Date: |
Tue, 7 Jan 2014 20:03:54 +0000 |
We implement a number of float-to-integer conversions using conversion
to an integer type with a wider range and then a check against the
narrower range we are actually converting to. If we find the result to
be out of range we correctly raise the Invalid exception, but we must
also suppress other exceptions which might have been raised by the
conversion function we called.
This won't throw away exceptions we should have preserved, because for
the 'core' exception flags the IEEE spec mandates that the only valid
combinations of exception that can be raised by a single operation are
Inexact + Overflow and Inexact + Underflow. For the non-IEEE softfloat
flag for input denormals, we can guarantee that that flag won't have
been set for out of range float-to-int conversions because a squashed
denormal by definition goes to plus or minus zero, which is always in
range after conversion to integer zero.
This bug has been fixed for some of the float-to-int conversion routines
by previous patches; fix it for the remaining functions as well, so
that they all restore the pre-conversion status flags prior to raising
Invalid.
Signed-off-by: Peter Maydell <address@hidden>
Reviewed-by: Aurelien Jarno <address@hidden>
Reviewed-by: Richard Henderson <address@hidden>
---
fpu/softfloat.c | 28 ++++++++++++++++------------
1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 2364513..6312e0c 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6509,17 +6509,18 @@ uint32 float32_to_uint32( float32 a STATUS_PARAM )
{
int64_t v;
uint32 res;
+ int old_exc_flags = get_float_exception_flags(status);
v = float32_to_int64(a STATUS_VAR);
if (v < 0) {
res = 0;
- float_raise( float_flag_invalid STATUS_VAR);
} else if (v > 0xffffffff) {
res = 0xffffffff;
- float_raise( float_flag_invalid STATUS_VAR);
} else {
- res = v;
+ return v;
}
+ set_float_exception_flags(old_exc_flags, status);
+ float_raise(float_flag_invalid STATUS_VAR);
return res;
}
@@ -6527,17 +6528,18 @@ uint32 float32_to_uint32_round_to_zero( float32 a
STATUS_PARAM )
{
int64_t v;
uint32 res;
+ int old_exc_flags = get_float_exception_flags(status);
v = float32_to_int64_round_to_zero(a STATUS_VAR);
if (v < 0) {
res = 0;
- float_raise( float_flag_invalid STATUS_VAR);
} else if (v > 0xffffffff) {
res = 0xffffffff;
- float_raise( float_flag_invalid STATUS_VAR);
} else {
- res = v;
+ return v;
}
+ set_float_exception_flags(old_exc_flags, status);
+ float_raise(float_flag_invalid STATUS_VAR);
return res;
}
@@ -6585,17 +6587,18 @@ uint_fast16_t float32_to_uint16_round_to_zero(float32 a
STATUS_PARAM)
{
int64_t v;
uint_fast16_t res;
+ int old_exc_flags = get_float_exception_flags(status);
v = float32_to_int64_round_to_zero(a STATUS_VAR);
if (v < 0) {
res = 0;
- float_raise( float_flag_invalid STATUS_VAR);
} else if (v > 0xffff) {
res = 0xffff;
- float_raise( float_flag_invalid STATUS_VAR);
} else {
- res = v;
+ return v;
}
+ set_float_exception_flags(old_exc_flags, status);
+ float_raise(float_flag_invalid STATUS_VAR);
return res;
}
@@ -6679,17 +6682,18 @@ uint_fast16_t float64_to_uint16_round_to_zero(float64 a
STATUS_PARAM)
{
int64_t v;
uint_fast16_t res;
+ int old_exc_flags = get_float_exception_flags(status);
v = float64_to_int64_round_to_zero(a STATUS_VAR);
if (v < 0) {
res = 0;
- float_raise( float_flag_invalid STATUS_VAR);
} else if (v > 0xffff) {
res = 0xffff;
- float_raise( float_flag_invalid STATUS_VAR);
} else {
- res = v;
+ return v;
}
+ set_float_exception_flags(old_exc_flags, status);
+ float_raise(float_flag_invalid STATUS_VAR);
return res;
}
--
1.8.5
- [Qemu-devel] [PULL 22/76] linux-user: AArch64: define TARGET_CLONE_BACKWARDS, (continued)
- [Qemu-devel] [PULL 22/76] linux-user: AArch64: define TARGET_CLONE_BACKWARDS, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 57/76] softfloat: Fix float64_to_uint64, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 30/76] target-arm: A64: Add "Floating-point data-processing (3 source)" insns, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 33/76] target-arm: A64: Add support for floating point conditional compare, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 38/76] char/cadence_uart: Fix reset., Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 24/76] .travis.yml: Add aarch64-* targets, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 27/76] target-arm: A64: Fix vector register access on bigendian hosts, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 50/76] target-arm: fix build with gcc 4.8.2, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 39/76] char/cadence_uart: s/r_fifo/rx_fifo, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 31/76] target-arm: A64: Add fmov (scalar, immediate) instruction, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 58/76] softfloat: Only raise Invalid when conversions to int are out of range,
Peter Maydell <=
- [Qemu-devel] [PULL 29/76] target-arm: A64: Add "Floating-point data-processing (2 source)" insns, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 40/76] char/cadence_uart: Simplify status generation, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 09/76] target-arm: A64: Add decoder skeleton for FP instructions, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 46/76] char/cadence_uart: Implement Tx flow control, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 45/76] char/cadence_uart: Delete redundant rx rst logic, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 42/76] char/cadence_uart: Remove TX timer & add TX FIFO state, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 41/76] char/cadence_uart: Define Missing SR/ISR fields, Peter Maydell, 2014/01/07
- [Qemu-devel] [PULL 55/76] softfloat: Add 16 bit integer to float conversions, Peter Maydell, 2014/01/07