qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] softfloat: Only raise Invalid when conversions


From: Aurelien Jarno
Subject: Re: [Qemu-devel] [PATCH] softfloat: Only raise Invalid when conversions to int are out of range
Date: Sun, 22 Dec 2013 19:03:42 +0100
User-agent: Mutt/1.5.21 (2010-09-15)

On Thu, Dec 19, 2013 at 10:00:18PM +0000, Peter Maydell wrote:
> 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>
> ---
> NB that I've worded the commit message on the assumption that the
> patches Tom Musta has written for PPC bugs go in first; as it happens
> the patches don't actually conflict, though.
> 
> Some of these fix wrong-exception-flags bugs in 32 bit ARM VCVT.
> 
>  fpu/softfloat.c | 28 ++++++++++++++++------------
>  1 file changed, 16 insertions(+), 12 deletions(-)
> 
> diff --git a/fpu/softfloat.c b/fpu/softfloat.c
> index dbda61b..253e6b3 100644
> --- a/fpu/softfloat.c
> +++ b/fpu/softfloat.c
> @@ -6432,17 +6432,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;
>  }
>  
> @@ -6450,17 +6451,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;
>  }
>  
> @@ -6468,17 +6470,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;
>  }
>  
> @@ -6522,17 +6525,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;
>  }
>  

Reviewed-by: Aurelien Jarno <address@hidden>

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
address@hidden                 http://www.aurel32.net



reply via email to

[Prev in Thread] Current Thread [Next in Thread]