From: Al Viro <viro@ZenIV.linux.org.uk>
To: Richard Henderson <rth@twiddle.net>
Cc: Peter Maydell <peter.maydell@linaro.org>,
QEMU Developers <qemu-devel@nongnu.org>
Subject: Re: [Qemu-devel] [RFC] alpha qemu arithmetic exceptions
Date: Sat, 5 Jul 2014 23:55:13 +0100 [thread overview]
Message-ID: <20140705225513.GY18016@ZenIV.linux.org.uk> (raw)
In-Reply-To: <20140705210951.GX18016@ZenIV.linux.org.uk>
On Sat, Jul 05, 2014 at 10:09:51PM +0100, Al Viro wrote:
> Anyway, the current delta (on top of 26f86) follows; seems to get IEEE
> insns behave on non-finite arguments as they do on 21264. The main
> exception is that register bitmask supplied to trap isn't calculated in
> a bunch of cases; since its main purpose is to help locating the trapping
> insn and we report precise traps (amask feature bit 9), it's probably not
> an interesting problem. Current Linux kernel definitely won't look at that
> thing under qemu; an old one might, but it would have to be something
> older than 2.3... <checks the history> than 2.2.8, actually. And the impact
> is that insns with /S getting a denorm argument won't be properly emulated
> and you'll get SIGFPE. Again, it has to be a really old kernel (older than
> May 1999) to be affected at all.
... and a followup (and the last part of exception handling for non-VAX
insn inputs, AFAICS) - CVTQL.
* whether it triggers a trap or not, it sets IOV and INE on overflow.
* in case of trap it does *not* bugger off immediately - result is
calculated, stored and only then we trap.
* trap summary word is different from cvtql/v and cvtql/sv. IOW, it's yet
another case of "we think that IEEE semantics is stupid and if you need it,
you'd damn better ask for it explicitly". Note that cvtql/v sets IOV|INE and
hits SIGFPE no matter what, while cvtql/sv set INV instead and triggers SIGFPE
only if FP_INVALID is enabled. All difference is kernel-side and it's
triggered by EXC_M_SWC in summary word.
AFAICS, that should be it for IEEE and shared insns, as far as exceptions
on inputs are concerned.
Combined delta follows:
diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c
index 9b297de..25c83b5 100644
--- a/target-alpha/fpu_helper.c
+++ b/target-alpha/fpu_helper.c
@@ -44,6 +44,12 @@ uint32_t helper_fp_exc_get(CPUAlphaState *env)
return get_float_exception_flags(&FP_STATUS);
}
+enum {
+ Exc_Mask = float_flag_invalid | float_flag_int_overflow |
+ float_flag_divbyzero | float_flag_overflow |
+ float_flag_underflow | float_flag_inexact
+};
+
static inline void fp_exc_raise1(CPUAlphaState *env, uintptr_t retaddr,
uint32_t exc, uint32_t regno, uint32_t hw_exc)
{
@@ -73,7 +79,7 @@ static inline void fp_exc_raise1(CPUAlphaState *env, uintptr_t retaddr,
doesn't apply. */
void helper_fp_exc_raise(CPUAlphaState *env, uint32_t ignore, uint32_t regno)
{
- uint32_t exc = (uint8_t)env->fp_status.float_exception_flags;
+ uint32_t exc = (uint8_t)env->fp_status.float_exception_flags & Exc_Mask;
if (exc) {
env->fpcr_exc_status |= exc;
exc &= ~ignore;
@@ -86,7 +92,7 @@ void helper_fp_exc_raise(CPUAlphaState *env, uint32_t ignore, uint32_t regno)
/* Raise exceptions for ieee fp insns with software completion. */
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;
+ uint32_t exc = (uint8_t)env->fp_status.float_exception_flags & Exc_Mask;
if (exc) {
env->fpcr_exc_status |= exc;
exc &= ~ignore;
@@ -105,16 +111,14 @@ void helper_ieee_input(CPUAlphaState *env, uint64_t val)
uint64_t frac = val & 0xfffffffffffffull;
if (exp == 0) {
- /* Denormals without DNZ set raise an exception. */
- if (frac != 0 && !env->fp_status.flush_inputs_to_zero) {
- arith_excp(env, GETPC(), EXC_M_UNF, 0);
+ /* Denormals without /S raise an exception. */
+ if (frac != 0) {
+ arith_excp(env, GETPC(), EXC_M_INV, 0);
}
} else if (exp == 0x7ff) {
/* Infinity or NaN. */
- /* ??? I'm not sure these exception bit flags are correct. I do
- know that the Linux kernel, at least, doesn't rely on them and
- just emulates the insn to figure out what exception to use. */
- arith_excp(env, GETPC(), frac ? EXC_M_INV : EXC_M_FOV, 0);
+ env->fpcr_exc_status |= float_flag_invalid;
+ arith_excp(env, GETPC(), EXC_M_INV, 0);
}
}
@@ -125,16 +129,34 @@ void helper_ieee_input_cmp(CPUAlphaState *env, uint64_t val)
uint64_t frac = val & 0xfffffffffffffull;
if (exp == 0) {
- /* Denormals without DNZ set raise an exception. */
- if (frac != 0 && !env->fp_status.flush_inputs_to_zero) {
- arith_excp(env, GETPC(), EXC_M_UNF, 0);
+ /* Denormals raise an exception. */
+ if (frac != 0) {
+ arith_excp(env, GETPC(), EXC_M_INV, 0);
}
} else if (exp == 0x7ff && frac) {
/* NaN. */
+ env->fpcr_exc_status |= float_flag_invalid;
arith_excp(env, GETPC(), EXC_M_INV, 0);
}
}
+/* Input handing with software completion. Trap for denorms,
+ unless DNZ is set. *IF* we try to support DNOD (which
+ none of the produced hardware did, AFAICS), we'll need
+ to suppress the trap when FPCR.DNOD is set; then the
+ code downstream of that will need to cope with denorms
+ sans flush_input_to_zero. Most of it should work sanely,
+ but there's nothing to compare with...
+*/
+void helper_ieee_input_s(CPUAlphaState *env, uint64_t val)
+{
+ if (unlikely(2 * val - 1 < 0x1fffffffffffff)) {
+ if (!FP_STATUS.flush_inputs_to_zero) {
+ arith_excp(env, GETPC(), EXC_M_INV | EXC_M_SWC, 0);
+ }
+ }
+}
+
/* F floating (VAX) */
static uint64_t float32_to_f(float32 fa)
{
@@ -707,7 +729,8 @@ static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a,
frac = a & 0xfffffffffffffull;
if (exp == 0) {
- if (unlikely(frac != 0)) {
+ if (unlikely(frac != 0) && !FP_STATUS.flush_inputs_to_zero) {
+ /* not going to happen without working DNOD; ifdef out, perhaps? */
goto do_underflow;
}
} else if (exp == 0x7ff) {
@@ -826,7 +849,9 @@ uint64_t helper_cvtqg(CPUAlphaState *env, uint64_t a)
void helper_fcvtql_v_input(CPUAlphaState *env, uint64_t val)
{
+ set_float_exception_flags(0, &FP_STATUS);
if (val != (int32_t)val) {
- arith_excp(env, GETPC(), EXC_M_IOV, 0);
+ float_raise(float_flag_int_overflow, &FP_STATUS);
+ env->fpcr_exc_status |= float_flag_inexact;
}
}
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 2cc100b..596f24d 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -88,6 +88,7 @@ DEF_HELPER_FLAGS_3(fp_exc_raise_s, TCG_CALL_NO_WG, void, env, i32, i32)
DEF_HELPER_FLAGS_2(ieee_input, TCG_CALL_NO_WG, void, env, i64)
DEF_HELPER_FLAGS_2(ieee_input_cmp, TCG_CALL_NO_WG, void, env, i64)
+DEF_HELPER_FLAGS_2(ieee_input_s, TCG_CALL_NO_WG, void, env, i64)
DEF_HELPER_FLAGS_2(fcvtql_v_input, TCG_CALL_NO_WG, void, env, i64)
#if !defined (CONFIG_USER_ONLY)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 6ea33f3..611b293 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -655,7 +655,8 @@ static TCGv gen_ieee_input(DisasContext *ctx, int reg, int fn11, int is_cmp)
} else {
gen_helper_ieee_input(cpu_env, val);
}
- }
+ } else
+ gen_helper_ieee_input_s(cpu_env, val);
}
return val;
}
@@ -2256,24 +2257,15 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
gen_fcmov(ctx, TCG_COND_GT, ra, rb, rc);
break;
case 0x030:
- /* CVTQL */
- REQUIRE_REG_31(ra);
- vc = dest_fpr(ctx, rc);
- vb = load_fpr(ctx, rb);
- gen_fcvtql(vc, vb);
- break;
case 0x130:
- /* CVTQL/V */
case 0x530:
- /* CVTQL/SV */
+ /* CVTQL, CVTQL/V, CVTQL/SV */
REQUIRE_REG_31(ra);
- /* ??? I'm pretty sure there's nothing that /sv needs to do that
- /v doesn't do. The only thing I can think is that /sv is a
- valid instruction merely for completeness in the ISA. */
vc = dest_fpr(ctx, rc);
vb = load_fpr(ctx, rb);
gen_helper_fcvtql_v_input(cpu_env, vb);
gen_fcvtql(vc, vb);
+ gen_fp_exc_raise(rc, fn11);
break;
default:
goto invalid_opc;
next prev parent reply other threads:[~2014-07-05 22:55 UTC|newest]
Thread overview: 68+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-24 4:34 [Qemu-devel] [RFC] alpha qemu arithmetic exceptions Al Viro
2014-06-24 16:52 ` Al Viro
2014-06-24 18:33 ` Richard Henderson
2014-06-24 20:32 ` Al Viro
2014-06-24 20:57 ` Richard Henderson
2014-06-24 21:24 ` Al Viro
2014-06-24 21:32 ` Richard Henderson
2014-06-25 7:01 ` Al Viro
2014-06-25 9:27 ` Peter Maydell
2014-06-25 14:26 ` Al Viro
2014-06-25 17:41 ` Peter Maydell
2014-06-26 5:55 ` Al Viro
2014-06-30 18:39 ` Richard Henderson
2014-06-30 20:56 ` Al Viro
2014-07-01 4:34 ` Al Viro
2014-07-01 5:00 ` Al Viro
2014-07-01 14:31 ` Richard Henderson
2014-07-01 17:03 ` Richard Henderson
2014-07-01 17:50 ` Al Viro
2014-07-01 18:23 ` Peter Maydell
2014-07-01 18:30 ` Richard Henderson
2014-07-01 19:08 ` Peter Maydell
2014-07-02 4:05 ` Al Viro
2014-07-02 5:50 ` Al Viro
2014-07-02 6:17 ` Al Viro
2014-07-02 15:26 ` Richard Henderson
2014-07-02 15:49 ` Al Viro
2014-07-02 14:59 ` Richard Henderson
2014-07-02 15:20 ` Al Viro
2014-07-03 6:51 ` Al Viro
2014-07-03 18:25 ` Al Viro
2014-07-03 20:19 ` Richard Henderson
2014-07-03 22:47 ` Al Viro
2014-07-03 23:05 ` Peter Maydell
2014-07-03 23:22 ` Al Viro
2014-07-04 0:50 ` Al Viro
2014-07-04 4:30 ` Richard Henderson
2014-07-04 7:29 ` Al Viro
2014-07-05 1:40 ` Al Viro
2014-07-05 5:26 ` Al Viro
2014-07-05 21:09 ` Al Viro
2014-07-05 22:55 ` Al Viro [this message]
2014-07-07 14:11 ` Richard Henderson
2014-07-07 15:06 ` Al Viro
2014-07-07 16:20 ` Richard Henderson
2014-07-08 4:20 ` Al Viro
2014-07-08 6:03 ` Richard Henderson
2014-07-08 6:54 ` Al Viro
2014-07-08 7:13 ` Al Viro
2014-07-08 8:05 ` Peter Maydell
2014-07-08 14:53 ` Richard Henderson
2014-07-08 16:13 ` Al Viro
2014-07-08 16:33 ` Peter Maydell
2014-07-08 17:20 ` Al Viro
2014-07-08 19:32 ` Peter Maydell
2014-07-08 20:12 ` Al Viro
2014-07-09 9:19 ` Alex Bennée
2014-07-09 9:04 ` Alex Bennée
2014-07-08 18:12 ` Richard Henderson
2014-07-08 19:02 ` Al Viro
2014-07-08 19:04 ` Richard Henderson
2014-07-08 20:20 ` Al Viro
2014-07-09 4:59 ` Richard Henderson
2014-07-09 5:47 ` Al Viro
2014-07-09 15:14 ` Richard Henderson
2014-07-09 16:41 ` Al Viro
2014-06-24 18:23 ` Richard Henderson
2014-06-24 20:47 ` Al Viro
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140705225513.GY18016@ZenIV.linux.org.uk \
--to=viro@zeniv.linux.org.uk \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=rth@twiddle.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.