The trap qualifiers (/U, /V, /I) control whether an exception traps,
but EV6 still records every exception in the FPCR status bits. Commit
471d493047 ("target-alpha: Set fpcr_exc_status even for disabled
exceptions") made helper_fp_exc_raise follow this, but in
helper_fp_exc_raise_s it only added a second "exc &= ~ignore" and left
the mask in the initializer, so for insns with software completion the
masked exceptions still never reached env->fpcr.
The most visible effect is on inexact: the IEEE-mode code generated by
gcc -mieee (e.g. ADDT/SU, DIVT/SUD) has no /I qualifier, so FE_INEXACT
was never set. Many of glibc's math tests fail because of that, and
the narrowing functions such as f32addf64 return results 1ulp off
because their round-to-odd step depends on inexact.
Record all exceptions first and only then apply the ignore mask, as
helper_fp_exc_raise does. Which exceptions trap is unchanged.
Fixes: 471d493047 ("target-alpha: Set fpcr_exc_status even for disabled
exceptions")
Signed-off-by: Matt Turner <[email protected]>
---
target/alpha/fpu_helper.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/target/alpha/fpu_helper.c b/target/alpha/fpu_helper.c
index 529eadca9f..643ce641e8 100644
--- a/target/alpha/fpu_helper.c
+++ b/target/alpha/fpu_helper.c
@@ -86,9 +86,17 @@ 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 = env->error_code & ~ignore;
+ uint32_t exc = env->error_code;
if (exc) {
+ /*
+ * The qualifiers can suppress the raising of exceptions,
+ * but real hardware still records that they occurred.
+ */
env->fpcr |= exc;
+ exc &= ~ignore;
+ if (!exc) {
+ return;
+ }
exc &= env->fpcr_exc_enable;
/*
* In system mode, the software handler gets invoked
--
2.55.0