qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [RFC] alpha qemu arithmetic exceptions


From: Al Viro
Subject: Re: [Qemu-devel] [RFC] alpha qemu arithmetic exceptions
Date: Mon, 30 Jun 2014 21:56:35 +0100
User-agent: Mutt/1.5.21 (2010-09-15)

On Mon, Jun 30, 2014 at 11:39:43AM -0700, Richard Henderson wrote:

> Looks good.
> 
> I've split it up into a couple of smaller patches, made some sylistic tweaks
> and pushed it to
> 
>   git://github.com/rth7680/qemu.git axp-next
> 
> I'm starting to do some testing now, but a glance though would be helpful.
> Especially to see if I didn't make some silly mistake in the process.

The only problem I see at a glance is that CVTTQ should raise IOV|INE in
ranges 2^63..2^64-1 and -2^64+1..-2^63-1 as well.  That's what this
        || ((int64_t)(ret-sign) < 0)
thing there was about and yes, it does match the behaviour of actual hardware
(verified both on EV45 and EV67).

FWIW, it might be better to do what float64_to_int64_round_to_zero() is doing -
i.e.
        if (shift >= 0) {
                if (shift < 64)
                        ret = frac << shift;
                if (shift < 11 || a == LIT64(0xC3E0000000000000))
                        exc = 0;
        }
since frac is between 1ULL<<52 and (1ULL<<53)-1, i.e. shift greater than 11
is guaranteed to overflow, shift less than 11 is guaranteed not to and shift
exactly 11 won't overflow only in one case - frac == 1ULL<<52, sign = 1 (i.e.
when we have -2^63 there).  BTW, shift == 63 is interesting - we certainly
overflow, but we want the result to be 0 or 2^63 depending on the least
significant bit of mantissa, not "always 0".  IOW, 0x4720000000000000 should
yield IOV|INE, with result being 0 and 0x4720000000000001 - IOV|INE and
result 0x8000000000000000.  Again, verified on actual hardware; the last
patch I posted had been incorrect in the last case (both cases yield 0 with it,
same as in mainline qemu).

Incremental on top of your branch would be

diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c
--- a/target-alpha/fpu_helper.c
+++ b/target-alpha/fpu_helper.c
@@ -722,12 +722,10 @@ static inline uint64_t inline_cvttq(CPUAlphaState *env, 
uint64_t a,
             /* In this case the number is so large that we must shift
                the fraction left.  There is no rounding to do.  */
             exc = float_flag_int_overflow | float_flag_inexact;
-            if (shift < 63) {
-                ret = frac << shift;
-                if ((ret >> shift) == frac) {
-                    exc = 0;
-                }
-            }
+           if (shift < 64)
+               ret = frac << shift;
+            if (shift < 11 || a == LIT64( 0xC3E0000000000000))
+                exc = 0;
         } else {
             uint64_t round;
 



reply via email to

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