qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/9] target-alpha exception improvements
@ 2014-07-03 20:28 Richard Henderson
  2014-07-03 20:28 ` [Qemu-devel] [PATCH v2 1/9] target-alpha: Forget installed round mode after MT_FPCR Richard Henderson
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Richard Henderson @ 2014-07-03 20:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, viro

I never got around to actually posting v1, although I sent a link to the
branch, buried in another thread.  I've rebased the branch and added 3
more patches to cover more issued raised by Al since the v1.

I've used this to clean up all of the errors in glibc mainline wrt
math/test-double.out, due to code that should have failed on real ev6
hw as well.

I still see a few spurrious underflow errors in math/test-float.out,
and I believe it to be an error in float64_to_float32 wrt FLT_MIN,
but I havn't had time to verify that.

Al and Peter, if you could run the mainline glibc math tests on real
hardware, I'd be most grateful.


r~


Richard Henderson (9):
  target-alpha: Forget installed round mode after MT_FPCR
  target-alpha: Set PC correctly for floating-point exceptions
  target-alpha: Store IOV exception in fp_status
  target-alpha: Set fpcr_exc_status even for disabled exceptions
  target-alpha: Set EXC_M_SWC for exceptions from /S insns
  target-alpha: Raise IOV from CVTTQ
  target-alpha: Fix cvttq vs large integers
  target-alpha: Fix cvttq vs inf
  target-alpha: Fix integer overflow checking insns

 include/fpu/softfloat.h   |  13 ++---
 target-alpha/fpu_helper.c |  91 +++++++++++++++++-----------------
 target-alpha/helper.c     |   8 +++
 target-alpha/helper.h     |   8 +--
 target-alpha/int_helper.c |  59 +---------------------
 target-alpha/mem_helper.c |   9 +++-
 target-alpha/translate.c  | 123 ++++++++++++++++++++++++++++------------------
 7 files changed, 149 insertions(+), 162 deletions(-)

-- 
1.9.3

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v2 1/9] target-alpha: Forget installed round mode after MT_FPCR
  2014-07-03 20:28 [Qemu-devel] [PATCH v2 0/9] target-alpha exception improvements Richard Henderson
@ 2014-07-03 20:28 ` Richard Henderson
  2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 2/9] target-alpha: Set PC correctly for floating-point exceptions Richard Henderson
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2014-07-03 20:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, viro

When we use QUAL_RM_D, we copy fpcr_dyn_round to float_status.
When we install a new FPCR value, we update fpcr_dyn_round.
Reset the status of the cache so that we re-copy for the next
fp insn that requires dynamic rounding.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-alpha/translate.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index cc81e77..0bd903c 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2196,6 +2196,11 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             /* MT_FPCR */
             va = load_fpr(ctx, ra);
             gen_helper_store_fpcr(cpu_env, va);
+            if (ctx->tb_rm == QUAL_RM_D) {
+                /* Re-do the copy of the rounding mode to fp_status
+                   the next time we use dynamic rounding.  */
+                ctx->tb_rm = -1;
+            }
             break;
         case 0x025:
             /* MF_FPCR */
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v2 2/9] target-alpha: Set PC correctly for floating-point exceptions
  2014-07-03 20:28 [Qemu-devel] [PATCH v2 0/9] target-alpha exception improvements Richard Henderson
  2014-07-03 20:28 ` [Qemu-devel] [PATCH v2 1/9] target-alpha: Forget installed round mode after MT_FPCR Richard Henderson
@ 2014-07-03 20:29 ` Richard Henderson
  2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 3/9] target-alpha: Store IOV exception in fp_status Richard Henderson
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2014-07-03 20:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, viro

PC should be one past the faulting insn.  Add better commentary
for the machine-check exception path.

Reported-by: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-alpha/helper.c     | 2 ++
 target-alpha/mem_helper.c | 9 ++++++++-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 7c053a3..8d1df2d 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -527,6 +527,8 @@ void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, uintptr_t retaddr,
     env->error_code = error;
     if (retaddr) {
         cpu_restore_state(cs, retaddr);
+        /* Floating-point exceptions (our only users) point to the next PC.  */
+        env->pc += 4;
     }
     cpu_loop_exit(cs);
 }
diff --git a/target-alpha/mem_helper.c b/target-alpha/mem_helper.c
index fc4f57a..7b5e30d 100644
--- a/target-alpha/mem_helper.c
+++ b/target-alpha/mem_helper.c
@@ -128,7 +128,14 @@ void alpha_cpu_unassigned_access(CPUState *cs, hwaddr addr,
 
     env->trap_arg0 = addr;
     env->trap_arg1 = is_write ? 1 : 0;
-    dynamic_excp(env, 0, EXCP_MCHK, 0);
+    cs->exception_index = EXCP_MCHK;
+    env->error_code = 0;
+
+    /* ??? We should cpu_restore_state to the faulting insn, but this hook
+       does not have access to the retaddr value from the orignal helper.
+       It's all moot until the QEMU PALcode grows an MCHK handler.  */
+
+    cpu_loop_exit(cs);
 }
 
 /* try to fill the TLB and return an exception if error. If retaddr is
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v2 3/9] target-alpha: Store IOV exception in fp_status
  2014-07-03 20:28 [Qemu-devel] [PATCH v2 0/9] target-alpha exception improvements Richard Henderson
  2014-07-03 20:28 ` [Qemu-devel] [PATCH v2 1/9] target-alpha: Forget installed round mode after MT_FPCR Richard Henderson
  2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 2/9] target-alpha: Set PC correctly for floating-point exceptions Richard Henderson
@ 2014-07-03 20:29 ` Richard Henderson
  2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 4/9] target-alpha: Set fpcr_exc_status even for disabled exceptions Richard Henderson
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2014-07-03 20:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, viro

We were not representing the IOV (integer overflow) exception at all.
For ease of implementation, allocate a generic bit in softfloat, even
though softfloat will never raise the exception itself.

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

Reported-by: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 include/fpu/softfloat.h   | 13 +++++++------
 target-alpha/fpu_helper.c |  3 +++
 target-alpha/helper.c     |  6 ++++++
 3 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index 77177c5..946fd3e 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -159,12 +159,13 @@ enum {
 | Software IEC/IEEE floating-point exception flags.
 *----------------------------------------------------------------------------*/
 enum {
-    float_flag_invalid   =  1,
-    float_flag_divbyzero =  4,
-    float_flag_overflow  =  8,
-    float_flag_underflow = 16,
-    float_flag_inexact   = 32,
-    float_flag_input_denormal = 64,
+    float_flag_invalid         = 1,
+    float_flag_int_overflow    = 2,
+    float_flag_divbyzero       = 4,
+    float_flag_overflow        = 8,
+    float_flag_underflow       = 16,
+    float_flag_inexact         = 32,
+    float_flag_input_denormal  = 64,
     float_flag_output_denormal = 128
 };
 
diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c
index d2d776c..aa83766 100644
--- a/target-alpha/fpu_helper.c
+++ b/target-alpha/fpu_helper.c
@@ -53,6 +53,9 @@ static inline void inline_fp_exc_raise(CPUAlphaState *env, uintptr_t retaddr,
         if (exc & float_flag_invalid) {
             hw_exc |= EXC_M_INV;
         }
+        if (exc & float_flag_int_overflow) {
+            hw_exc |= EXC_M_IOV;
+        }
         if (exc & float_flag_divbyzero) {
             hw_exc |= EXC_M_DZE;
         }
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 8d1df2d..6bcde21 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -36,6 +36,9 @@ uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env)
         if (t & float_flag_invalid) {
             r |= FPCR_INV;
         }
+        if (t & float_flag_int_overflow) {
+            r |= FPCR_IOV;
+        }
         if (t & float_flag_divbyzero) {
             r |= FPCR_DZE;
         }
@@ -103,6 +106,9 @@ void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val)
     if (val & FPCR_INV) {
         t |= float_flag_invalid;
     }
+    if (val & FPCR_IOV) {
+        t |= float_flag_int_overflow;
+    }
     if (val & FPCR_DZE) {
         t |= float_flag_divbyzero;
     }
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v2 4/9] target-alpha: Set fpcr_exc_status even for disabled exceptions
  2014-07-03 20:28 [Qemu-devel] [PATCH v2 0/9] target-alpha exception improvements Richard Henderson
                   ` (2 preceding siblings ...)
  2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 3/9] target-alpha: Store IOV exception in fp_status Richard Henderson
@ 2014-07-03 20:29 ` Richard Henderson
  2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 5/9] target-alpha: Set EXC_M_SWC for exceptions from /S insns Richard Henderson
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2014-07-03 20:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, viro

The qualifiers can suppress the raising of exceptions, but real
hardware still records that the exceptions occurred.

Reported-by: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-alpha/fpu_helper.c | 67 ++++++++++++++++++++++++++---------------------
 target-alpha/translate.c  | 41 ++++++++++-------------------
 2 files changed, 51 insertions(+), 57 deletions(-)

diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c
index aa83766..efc5dfa 100644
--- a/target-alpha/fpu_helper.c
+++ b/target-alpha/fpu_helper.c
@@ -44,50 +44,57 @@ uint32_t helper_fp_exc_get(CPUAlphaState *env)
     return get_float_exception_flags(&FP_STATUS);
 }
 
-static inline void inline_fp_exc_raise(CPUAlphaState *env, uintptr_t retaddr,
-                                       uint32_t exc, uint32_t regno)
+static inline void fp_exc_raise1(CPUAlphaState *env, uintptr_t retaddr,
+                                 uint32_t exc, uint32_t regno)
 {
-    if (exc) {
-        uint32_t hw_exc = 0;
-
-        if (exc & float_flag_invalid) {
-            hw_exc |= EXC_M_INV;
-        }
-        if (exc & float_flag_int_overflow) {
-            hw_exc |= EXC_M_IOV;
-        }
-        if (exc & float_flag_divbyzero) {
-            hw_exc |= EXC_M_DZE;
-        }
-        if (exc & float_flag_overflow) {
-            hw_exc |= EXC_M_FOV;
-        }
-        if (exc & float_flag_underflow) {
-            hw_exc |= EXC_M_UNF;
-        }
-        if (exc & float_flag_inexact) {
-            hw_exc |= EXC_M_INE;
-        }
-
-        arith_excp(env, retaddr, hw_exc, 1ull << regno);
+    uint32_t hw_exc = 0;
+    if (exc & float_flag_invalid) {
+        hw_exc |= EXC_M_INV;
+    }
+    if (exc & float_flag_int_overflow) {
+        hw_exc |= EXC_M_IOV;
     }
+    if (exc & float_flag_divbyzero) {
+        hw_exc |= EXC_M_DZE;
+    }
+    if (exc & float_flag_overflow) {
+        hw_exc |= EXC_M_FOV;
+    }
+    if (exc & float_flag_underflow) {
+        hw_exc |= EXC_M_UNF;
+    }
+    if (exc & float_flag_inexact) {
+        hw_exc |= EXC_M_INE;
+    }
+    arith_excp(env, retaddr, hw_exc, 1ull << regno);
 }
 
 /* Raise exceptions for ieee fp insns without software completion.
    In that case there are no exceptions that don't trap; the mask
    doesn't apply.  */
-void helper_fp_exc_raise(CPUAlphaState *env, uint32_t exc, uint32_t regno)
+void helper_fp_exc_raise(CPUAlphaState *env, uint32_t ignore, uint32_t regno)
 {
-    inline_fp_exc_raise(env, GETPC(), exc, regno);
+    uint32_t exc = (uint8_t)env->fp_status.float_exception_flags;
+    if (exc) {
+        env->fpcr_exc_status |= exc;
+        exc &= ~ignore;
+        if (exc) {
+            fp_exc_raise1(env, GETPC(), exc, regno, 0);
+        }
+    }
 }
 
 /* Raise exceptions for ieee fp insns with software completion.  */
-void helper_fp_exc_raise_s(CPUAlphaState *env, uint32_t exc, uint32_t regno)
+void helper_fp_exc_raise_s(CPUAlphaState *env, uint32_t ignore, uint32_t regno)
 {
+    uint32_t exc = (uint8_t)env->fp_status.float_exception_flags;
     if (exc) {
         env->fpcr_exc_status |= exc;
-        exc &= ~env->fpcr_exc_mask;
-        inline_fp_exc_raise(env, GETPC(), exc, regno);
+        exc &= ~ignore;
+        if (exc) {
+            exc &= ~env->fpcr_exc_mask;
+            fp_exc_raise1(env, GETPC(), exc, regno);
+        }
     }
 }
 
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 0bd903c..1c2d72e 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -672,26 +672,24 @@ static void gen_fp_exc_clear(void)
 #endif
 }
 
-static void gen_fp_exc_raise_ignore(int rc, int fn11, int ignore)
+static void gen_fp_exc_raise(int rc, int fn11)
 {
     /* ??? We ought to be able to do something with imprecise exceptions.
        E.g. notice we're still in the trap shadow of something within the
        TB and do not generate the code to signal the exception; end the TB
        when an exception is forced to arrive, either by consumption of a
        register value or TRAPB or EXCB.  */
-    TCGv_i32 exc = tcg_temp_new_i32();
-    TCGv_i32 reg;
+    TCGv_i32 reg, ign;
+    uint32_t ignore = 0;
 
-#if defined(CONFIG_SOFTFLOAT_INLINE)
-    tcg_gen_ld8u_i32(exc, cpu_env,
-                     offsetof(CPUAlphaState, fp_status.float_exception_flags));
-#else
-    gen_helper_fp_exc_get(exc, cpu_env);
-#endif
-
-    if (ignore) {
-        tcg_gen_andi_i32(exc, exc, ~ignore);
+    if (!(fn11 & QUAL_U)) {
+        /* Note that QUAL_U == QUAL_V, so ignore either.  */
+        ignore |= float_flag_underflow | float_flag_int_overflow;
+    }
+    if (!(fn11 & QUAL_I)) {
+        ignore |= float_flag_inexact;
     }
+    ign = tcg_const_i32(ignore);
 
     /* ??? Pass in the regno of the destination so that the helper can
        set EXC_MASK, which contains a bitmask of destination registers
@@ -699,20 +697,14 @@ static void gen_fp_exc_raise_ignore(int rc, int fn11, int ignore)
        does not require this.  We do need it for a guest kernel's entArith,
        or if we were to do something clever with imprecise exceptions.  */
     reg = tcg_const_i32(rc + 32);
-
     if (fn11 & QUAL_S) {
-        gen_helper_fp_exc_raise_s(cpu_env, exc, reg);
+        gen_helper_fp_exc_raise_s(cpu_env, ign, reg);
     } else {
-        gen_helper_fp_exc_raise(cpu_env, exc, reg);
+        gen_helper_fp_exc_raise(cpu_env, ign, reg);
     }
 
     tcg_temp_free_i32(reg);
-    tcg_temp_free_i32(exc);
-}
-
-static inline void gen_fp_exc_raise(int rc, int fn11)
-{
-    gen_fp_exc_raise_ignore(rc, fn11, fn11 & QUAL_I ? 0 : float_flag_inexact);
+    tcg_temp_free_i32(ign);
 }
 
 static void gen_fcvtlq(TCGv vc, TCGv vb)
@@ -773,7 +765,6 @@ IEEE_ARITH2(cvtts)
 static void gen_fcvttq(DisasContext *ctx, int rb, int rc, int fn11)
 {
     TCGv vb, vc;
-    int ignore = 0;
 
     /* No need to set flushzero, since we have an integer output.  */
     gen_fp_exc_clear();
@@ -788,20 +779,16 @@ static void gen_fcvttq(DisasContext *ctx, int rb, int rc, int fn11)
         break;
     case QUAL_V | QUAL_RM_C:
     case QUAL_S | QUAL_V | QUAL_RM_C:
-        ignore = float_flag_inexact;
-        /* FALLTHRU */
     case QUAL_S | QUAL_V | QUAL_I | QUAL_RM_C:
         gen_helper_cvttq_svic(vc, cpu_env, vb);
         break;
     default:
         gen_qual_roundmode(ctx, fn11);
         gen_helper_cvttq(vc, cpu_env, vb);
-        ignore |= (fn11 & QUAL_V ? 0 : float_flag_overflow);
-        ignore |= (fn11 & QUAL_I ? 0 : float_flag_inexact);
         break;
     }
 
-    gen_fp_exc_raise_ignore(rc, fn11, ignore);
+    gen_fp_exc_raise(rc, fn11);
 }
 
 static void gen_ieee_intcvt(DisasContext *ctx,
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v2 5/9] target-alpha: Set EXC_M_SWC for exceptions from /S insns
  2014-07-03 20:28 [Qemu-devel] [PATCH v2 0/9] target-alpha exception improvements Richard Henderson
                   ` (3 preceding siblings ...)
  2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 4/9] target-alpha: Set fpcr_exc_status even for disabled exceptions Richard Henderson
@ 2014-07-03 20:29 ` Richard Henderson
  2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 6/9] target-alpha: Raise IOV from CVTTQ Richard Henderson
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2014-07-03 20:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, viro

Previously forgotten, the kernel needs the software completion bit to
know that it needs to emulate software completion qualified insns.

Reported-by: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-alpha/fpu_helper.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c
index efc5dfa..8bd4c08 100644
--- a/target-alpha/fpu_helper.c
+++ b/target-alpha/fpu_helper.c
@@ -45,9 +45,8 @@ uint32_t helper_fp_exc_get(CPUAlphaState *env)
 }
 
 static inline void fp_exc_raise1(CPUAlphaState *env, uintptr_t retaddr,
-                                 uint32_t exc, uint32_t regno)
+                                 uint32_t exc, uint32_t regno, uint32_t hw_exc)
 {
-    uint32_t hw_exc = 0;
     if (exc & float_flag_invalid) {
         hw_exc |= EXC_M_INV;
     }
@@ -93,7 +92,7 @@ void helper_fp_exc_raise_s(CPUAlphaState *env, uint32_t ignore, uint32_t regno)
         exc &= ~ignore;
         if (exc) {
             exc &= ~env->fpcr_exc_mask;
-            fp_exc_raise1(env, GETPC(), exc, regno);
+            fp_exc_raise1(env, GETPC(), exc, regno, EXC_M_SWC);
         }
     }
 }
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v2 6/9] target-alpha: Raise IOV from CVTTQ
  2014-07-03 20:28 [Qemu-devel] [PATCH v2 0/9] target-alpha exception improvements Richard Henderson
                   ` (4 preceding siblings ...)
  2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 5/9] target-alpha: Set EXC_M_SWC for exceptions from /S insns Richard Henderson
@ 2014-07-03 20:29 ` Richard Henderson
  2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 7/9] target-alpha: Fix cvttq vs large integers Richard Henderson
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2014-07-03 20:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, viro

Floating-point overflow is a different bit from integer overflow.

Reported-by: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-alpha/fpu_helper.c | 25 ++++++++++---------------
 target-alpha/helper.h     |  1 -
 target-alpha/translate.c  | 17 ++++-------------
 3 files changed, 14 insertions(+), 29 deletions(-)

diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c
index 8bd4c08..19f3ebc 100644
--- a/target-alpha/fpu_helper.c
+++ b/target-alpha/fpu_helper.c
@@ -693,12 +693,10 @@ uint64_t helper_cvtqs(CPUAlphaState *env, uint64_t a)
 
 /* Implement float64 to uint64 conversion without saturation -- we must
    supply the truncated result.  This behaviour is used by the compiler
-   to get unsigned conversion for free with the same instruction.
-
-   The VI flag is set when overflow or inexact exceptions should be raised.  */
+   to get unsigned conversion for free with the same instruction.  */
 
 static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a,
-                                    int roundmode, int VI)
+                                    int roundmode)
 {
     uint64_t frac, ret = 0;
     uint32_t exp, sign, exc = 0;
@@ -713,7 +711,8 @@ static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a,
             goto do_underflow;
         }
     } else if (exp == 0x7ff) {
-        exc = (frac ? float_flag_invalid : VI ? float_flag_overflow : 0);
+        exc = (frac ? float_flag_invalid
+               : float_flag_int_overflow | float_flag_inexact);
     } else {
         /* Restore implicit bit.  */
         frac |= 0x10000000000000ull;
@@ -722,10 +721,11 @@ static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a,
         if (shift >= 0) {
             /* 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 (VI && (ret >> shift) != frac) {
-                    exc = float_flag_overflow;
+                if ((ret >> shift) == frac) {
+                    exc = 0;
                 }
             }
         } else {
@@ -748,7 +748,7 @@ static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a,
             }
 
             if (round) {
-                exc = (VI ? float_flag_inexact : 0);
+                exc = float_flag_inexact;
                 switch (roundmode) {
                 case float_round_nearest_even:
                     if (round == (1ull << 63)) {
@@ -782,17 +782,12 @@ static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a,
 
 uint64_t helper_cvttq(CPUAlphaState *env, uint64_t a)
 {
-    return inline_cvttq(env, a, FP_STATUS.float_rounding_mode, 1);
+    return inline_cvttq(env, a, FP_STATUS.float_rounding_mode);
 }
 
 uint64_t helper_cvttq_c(CPUAlphaState *env, uint64_t a)
 {
-    return inline_cvttq(env, a, float_round_to_zero, 0);
-}
-
-uint64_t helper_cvttq_svic(CPUAlphaState *env, uint64_t a)
-{
-    return inline_cvttq(env, a, float_round_to_zero, 1);
+    return inline_cvttq(env, a, float_round_to_zero);
 }
 
 uint64_t helper_cvtqt(CPUAlphaState *env, uint64_t a)
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index a451cfe..173db01 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -83,7 +83,6 @@ DEF_HELPER_FLAGS_2(cvtqg, TCG_CALL_NO_RWG, i64, env, i64)
 
 DEF_HELPER_FLAGS_2(cvttq, TCG_CALL_NO_RWG, i64, env, i64)
 DEF_HELPER_FLAGS_2(cvttq_c, TCG_CALL_NO_RWG, i64, env, i64)
-DEF_HELPER_FLAGS_2(cvttq_svic, TCG_CALL_NO_RWG, i64, env, i64)
 
 DEF_HELPER_FLAGS_2(setroundmode, TCG_CALL_NO_RWG, void, env, i32)
 DEF_HELPER_FLAGS_2(setflushzero, TCG_CALL_NO_RWG, void, env, i32)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 1c2d72e..183573d 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -771,23 +771,14 @@ static void gen_fcvttq(DisasContext *ctx, int rb, int rc, int fn11)
     vb = gen_ieee_input(ctx, rb, fn11, 0);
     vc = dest_fpr(ctx, rc);
 
-    /* Almost all integer conversions use cropped rounding, and most
-       also do not have integer overflow enabled.  Special case that.  */
-    switch (fn11) {
-    case QUAL_RM_C:
+    /* Almost all integer conversions use cropped rounding;
+       special case that.  */
+    if ((fn11 & QUAL_RM_MASK) == QUAL_RM_C) {
         gen_helper_cvttq_c(vc, cpu_env, vb);
-        break;
-    case QUAL_V | QUAL_RM_C:
-    case QUAL_S | QUAL_V | QUAL_RM_C:
-    case QUAL_S | QUAL_V | QUAL_I | QUAL_RM_C:
-        gen_helper_cvttq_svic(vc, cpu_env, vb);
-        break;
-    default:
+    } else {
         gen_qual_roundmode(ctx, fn11);
         gen_helper_cvttq(vc, cpu_env, vb);
-        break;
     }
-
     gen_fp_exc_raise(rc, fn11);
 }
 
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v2 7/9] target-alpha: Fix cvttq vs large integers
  2014-07-03 20:28 [Qemu-devel] [PATCH v2 0/9] target-alpha exception improvements Richard Henderson
                   ` (5 preceding siblings ...)
  2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 6/9] target-alpha: Raise IOV from CVTTQ Richard Henderson
@ 2014-07-03 20:29 ` Richard Henderson
  2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 8/9] target-alpha: Fix cvttq vs inf Richard Henderson
  2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 9/9] target-alpha: Fix integer overflow checking insns Richard Henderson
  8 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2014-07-03 20:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, viro

The range +- 2**63 - 2**64 was returning the wrong truncated
result.  We also incorrectly signaled overflow for -2**63.

Reported-by: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-alpha/fpu_helper.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c
index 19f3ebc..2b6c96b 100644
--- a/target-alpha/fpu_helper.c
+++ b/target-alpha/fpu_helper.c
@@ -721,12 +721,12 @@ static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a,
         if (shift >= 0) {
             /* 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) {
+            if (shift < 64) {
                 ret = frac << shift;
-                if ((ret >> shift) == frac) {
-                    exc = 0;
-                }
+            }
+            /* Check for overflow.  Note the special case of -0x1p63.  */
+            if (shift >= 11 && a != 0xC3E0000000000000ull) {
+                exc = float_flag_int_overflow | float_flag_inexact;
             }
         } else {
             uint64_t round;
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v2 8/9] target-alpha: Fix cvttq vs inf
  2014-07-03 20:28 [Qemu-devel] [PATCH v2 0/9] target-alpha exception improvements Richard Henderson
                   ` (6 preceding siblings ...)
  2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 7/9] target-alpha: Fix cvttq vs large integers Richard Henderson
@ 2014-07-03 20:29 ` Richard Henderson
  2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 9/9] target-alpha: Fix integer overflow checking insns Richard Henderson
  8 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2014-07-03 20:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, viro

We should raise INV for infinities as well, not OVR+INE.

Reported-by: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-alpha/fpu_helper.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c
index 2b6c96b..9b297de 100644
--- a/target-alpha/fpu_helper.c
+++ b/target-alpha/fpu_helper.c
@@ -711,8 +711,7 @@ static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a,
             goto do_underflow;
         }
     } else if (exp == 0x7ff) {
-        exc = (frac ? float_flag_invalid
-               : float_flag_int_overflow | float_flag_inexact);
+        exc = float_flag_invalid;
     } else {
         /* Restore implicit bit.  */
         frac |= 0x10000000000000ull;
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v2 9/9] target-alpha: Fix integer overflow checking insns
  2014-07-03 20:28 [Qemu-devel] [PATCH v2 0/9] target-alpha exception improvements Richard Henderson
                   ` (7 preceding siblings ...)
  2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 8/9] target-alpha: Fix cvttq vs inf Richard Henderson
@ 2014-07-03 20:29 ` Richard Henderson
  8 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2014-07-03 20:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, viro

We need to write the result to the destination register before
raising any exception.  Thus inline the code for each insn, and
check for any exception after we're done.

Reported-by: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-alpha/helper.h     |  7 +-----
 target-alpha/int_helper.c | 59 ++--------------------------------------------
 target-alpha/translate.c  | 60 +++++++++++++++++++++++++++++++++++++++++------
 3 files changed, 56 insertions(+), 70 deletions(-)

diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 173db01..2cc100b 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -1,12 +1,7 @@
 DEF_HELPER_3(excp, noreturn, env, int, int)
 DEF_HELPER_FLAGS_1(load_pcc, TCG_CALL_NO_RWG_SE, i64, env)
 
-DEF_HELPER_FLAGS_3(addqv, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_3(addlv, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_3(subqv, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_3(sublv, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_3(mullv, TCG_CALL_NO_WG, i64, env, i64, i64)
-DEF_HELPER_FLAGS_3(mulqv, TCG_CALL_NO_WG, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(check_overflow, TCG_CALL_NO_WG, void, env, i64, i64)
 
 DEF_HELPER_FLAGS_1(ctpop, TCG_CALL_NO_RWG_SE, i64, i64)
 DEF_HELPER_FLAGS_1(ctlz, TCG_CALL_NO_RWG_SE, i64, i64)
diff --git a/target-alpha/int_helper.c b/target-alpha/int_helper.c
index 7a205eb..8e4537f 100644
--- a/target-alpha/int_helper.c
+++ b/target-alpha/int_helper.c
@@ -249,64 +249,9 @@ uint64_t helper_unpkbw(uint64_t op1)
             | ((op1 & 0xff000000) << 24));
 }
 
-uint64_t helper_addqv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+void helper_check_overflow(CPUAlphaState *env, uint64_t op1, uint64_t op2)
 {
-    uint64_t tmp = op1;
-    op1 += op2;
-    if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) {
+    if (unlikely(op1 != op2)) {
         arith_excp(env, GETPC(), EXC_M_IOV, 0);
     }
-    return op1;
-}
-
-uint64_t helper_addlv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
-{
-    uint64_t tmp = op1;
-    op1 = (uint32_t)(op1 + op2);
-    if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) {
-        arith_excp(env, GETPC(), EXC_M_IOV, 0);
-    }
-    return op1;
-}
-
-uint64_t helper_subqv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
-{
-    uint64_t res;
-    res = op1 - op2;
-    if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) {
-        arith_excp(env, GETPC(), EXC_M_IOV, 0);
-    }
-    return res;
-}
-
-uint64_t helper_sublv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
-{
-    uint32_t res;
-    res = op1 - op2;
-    if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) {
-        arith_excp(env, GETPC(), EXC_M_IOV, 0);
-    }
-    return res;
-}
-
-uint64_t helper_mullv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
-{
-    int64_t res = (int64_t)op1 * (int64_t)op2;
-
-    if (unlikely((int32_t)res != res)) {
-        arith_excp(env, GETPC(), EXC_M_IOV, 0);
-    }
-    return (int64_t)((int32_t)res);
-}
-
-uint64_t helper_mulqv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
-{
-    uint64_t tl, th;
-
-    muls64(&tl, &th, op1, op2);
-    /* If th != 0 && th != -1, then we had an overflow */
-    if (unlikely((th + 1) > 1)) {
-        arith_excp(env, GETPC(), EXC_M_IOV, 0);
-    }
-    return tl;
 }
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 183573d..6ea33f3 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1377,7 +1377,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
     uint16_t fn11;
     uint8_t opc, ra, rb, rc, fpfn, fn7, lit;
     bool islit;
-    TCGv va, vb, vc, tmp;
+    TCGv va, vb, vc, tmp, tmp2;
     TCGv_i32 t32;
     ExitStatus ret;
 
@@ -1589,11 +1589,23 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             break;
         case 0x40:
             /* ADDL/V */
-            gen_helper_addlv(vc, cpu_env, va, vb);
+            tmp = tcg_temp_new();
+            tcg_gen_ext32s_i64(tmp, va);
+            tcg_gen_ext32s_i64(vc, vb);
+            tcg_gen_add_i64(tmp, tmp, vc);
+            tcg_gen_ext32s_i64(vc, tmp);
+            gen_helper_check_overflow(cpu_env, vc, tmp);
+            tcg_temp_free(tmp);
             break;
         case 0x49:
             /* SUBL/V */
-            gen_helper_sublv(vc, cpu_env, va, vb);
+            tmp = tcg_temp_new();
+            tcg_gen_ext32s_i64(tmp, va);
+            tcg_gen_ext32s_i64(vc, vb);
+            tcg_gen_sub_i64(tmp, tmp, vc);
+            tcg_gen_ext32s_i64(vc, tmp);
+            gen_helper_check_overflow(cpu_env, vc, tmp);
+            tcg_temp_free(tmp);
             break;
         case 0x4D:
             /* CMPLT */
@@ -1601,11 +1613,33 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             break;
         case 0x60:
             /* ADDQ/V */
-            gen_helper_addqv(vc, cpu_env, va, vb);
+            tmp = tcg_temp_new();
+            tmp2 = tcg_temp_new();
+            tcg_gen_eqv_i64(tmp, va, vb);
+            tcg_gen_mov_i64(tmp2, va);
+            tcg_gen_add_i64(vc, va, vb);
+            tcg_gen_xor_i64(tmp2, tmp2, vc);
+            tcg_gen_and_i64(tmp, tmp, tmp2);
+            tcg_gen_shri_i64(tmp, tmp, 63);
+            tcg_gen_movi_i64(tmp2, 0);
+            gen_helper_check_overflow(cpu_env, tmp, tmp2);
+            tcg_temp_free(tmp);
+            tcg_temp_free(tmp2);
             break;
         case 0x69:
             /* SUBQ/V */
-            gen_helper_subqv(vc, cpu_env, va, vb);
+            tmp = tcg_temp_new();
+            tmp2 = tcg_temp_new();
+            tcg_gen_xor_i64(tmp, va, vb);
+            tcg_gen_mov_i64(tmp2, va);
+            tcg_gen_sub_i64(vc, va, vb);
+            tcg_gen_xor_i64(tmp2, tmp2, vc);
+            tcg_gen_and_i64(tmp, tmp, tmp2);
+            tcg_gen_shri_i64(tmp, tmp, 63);
+            tcg_gen_movi_i64(tmp2, 0);
+            gen_helper_check_overflow(cpu_env, tmp, tmp2);
+            tcg_temp_free(tmp);
+            tcg_temp_free(tmp2);
             break;
         case 0x6D:
             /* CMPLE */
@@ -1900,11 +1934,23 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             break;
         case 0x40:
             /* MULL/V */
-            gen_helper_mullv(vc, cpu_env, va, vb);
+            tmp = tcg_temp_new();
+            tcg_gen_ext32s_i64(tmp, va);
+            tcg_gen_ext32s_i64(vc, vb);
+            tcg_gen_mul_i64(tmp, tmp, vc);
+            tcg_gen_ext32s_i64(vc, tmp);
+            gen_helper_check_overflow(cpu_env, vc, tmp);
+            tcg_temp_free(tmp);
             break;
         case 0x60:
             /* MULQ/V */
-            gen_helper_mulqv(vc, cpu_env, va, vb);
+            tmp = tcg_temp_new();
+            tmp2 = tcg_temp_new();
+            tcg_gen_muls2_i64(vc, tmp, va, vb);
+            tcg_gen_sari_i64(tmp2, vc, 63);
+            gen_helper_check_overflow(cpu_env, tmp, tmp2);
+            tcg_temp_free(tmp);
+            tcg_temp_free(tmp2);
             break;
         default:
             goto invalid_opc;
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2014-07-03 20:29 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-07-03 20:28 [Qemu-devel] [PATCH v2 0/9] target-alpha exception improvements Richard Henderson
2014-07-03 20:28 ` [Qemu-devel] [PATCH v2 1/9] target-alpha: Forget installed round mode after MT_FPCR Richard Henderson
2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 2/9] target-alpha: Set PC correctly for floating-point exceptions Richard Henderson
2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 3/9] target-alpha: Store IOV exception in fp_status Richard Henderson
2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 4/9] target-alpha: Set fpcr_exc_status even for disabled exceptions Richard Henderson
2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 5/9] target-alpha: Set EXC_M_SWC for exceptions from /S insns Richard Henderson
2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 6/9] target-alpha: Raise IOV from CVTTQ Richard Henderson
2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 7/9] target-alpha: Fix cvttq vs large integers Richard Henderson
2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 8/9] target-alpha: Fix cvttq vs inf Richard Henderson
2014-07-03 20:29 ` [Qemu-devel] [PATCH v2 9/9] target-alpha: Fix integer overflow checking insns Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).