[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [PATCH 6/7] target/ppc: Honor fpscr_ze semantics and tidy fre
From: |
Richard Henderson |
Subject: |
[Qemu-ppc] [PATCH 6/7] target/ppc: Honor fpscr_ze semantics and tidy fre, fresqrt |
Date: |
Tue, 3 Jul 2018 08:17:31 -0700 |
Divide by zero, exception taken, leaves the destination register
unmodified. Therefore we must raise the exception before returning
from the respective helpers.
>From helper_fre, divide by zero exception not taken, return the
documented +/- 0.5.
At the same time, tidy the invalid exception checking so that we
rely on softfloat for initial argument validation, and select the
kind of invalid operand exception only when we know we must.
At the same time, pass and return float64 values directly rather
than bounce through the CPU_DoubleU union.
Signed-off-by: Richard Henderson <address@hidden>
---
target/ppc/fpu_helper.c | 62 ++++++++++++++++++++++++-----------------
1 file changed, 37 insertions(+), 25 deletions(-)
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index c8a2dd6408..1e195487d3 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -871,18 +871,27 @@ float64 helper_fsqrt(CPUPPCState *env, float64 arg)
}
/* fre - fre. */
-uint64_t helper_fre(CPUPPCState *env, uint64_t arg)
+float64 helper_fre(CPUPPCState *env, float64 arg)
{
- CPU_DoubleU farg;
+ /* "Estimate" the reciprocal with actual division. */
+ float64 ret = float64_div(float64_one, arg, &env->fp_status);
+ int status = get_float_exception_flags(&env->fp_status);
- farg.ll = arg;
-
- if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
- /* sNaN reciprocal */
- float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+ if (unlikely(status)) {
+ if (status & float_flag_invalid) {
+ if (float64_is_signaling_nan(arg, &env->fp_status)) {
+ /* sNaN reciprocal */
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+ }
+ }
+ if (status & float_flag_divbyzero) {
+ float_zero_divide_excp(env, GETPC());
+ /* For FPSCR.ZE == 0, the result is 1/2. */
+ ret = float64_set_sign(float64_half, float64_is_neg(arg));
+ }
}
- farg.d = float64_div(float64_one, farg.d, &env->fp_status);
- return farg.d;
+
+ return ret;
}
/* fres - fres. */
@@ -905,27 +914,30 @@ uint64_t helper_fres(CPUPPCState *env, uint64_t arg)
}
/* frsqrte - frsqrte. */
-uint64_t helper_frsqrte(CPUPPCState *env, uint64_t arg)
+float64 helper_frsqrte(CPUPPCState *env, float64 arg)
{
- CPU_DoubleU farg;
+ /* "Estimate" the reciprocal with actual division. */
+ float64 rets = float64_sqrt(arg, &env->fp_status);
+ float64 retd = float64_div(float64_one, rets, &env->fp_status);
+ int status = get_float_exception_flags(&env->fp_status);
- farg.ll = arg;
-
- if (unlikely(float64_is_any_nan(farg.d))) {
- if (unlikely(float64_is_signaling_nan(farg.d, &env->fp_status))) {
- /* sNaN reciprocal square root */
- float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
- farg.ll = float64_snan_to_qnan(farg.ll);
+ if (unlikely(status)) {
+ if (status & float_flag_invalid) {
+ if (float64_is_signaling_nan(arg, &env->fp_status)) {
+ /* sNaN reciprocal */
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+ } else {
+ /* Square root of a negative nonzero number */
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
+ }
+ }
+ if (status & float_flag_divbyzero) {
+ /* Reciprocal of (square root of) zero. */
+ float_zero_divide_excp(env, GETPC());
}
- } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
- /* Reciprocal square root of a negative nonzero number */
- farg.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
- } else {
- farg.d = float64_sqrt(farg.d, &env->fp_status);
- farg.d = float64_div(float64_one, farg.d, &env->fp_status);
}
- return farg.ll;
+ return retd;
}
/* fsel - fsel. */
--
2.17.1
- [Qemu-ppc] [PATCH for-3.1 0/7] target/ppc fp cleanups, Richard Henderson, 2018/07/03
- [Qemu-ppc] [PATCH 1/7] target/ppc: Enable fp exceptions for user-only, Richard Henderson, 2018/07/03
- [Qemu-ppc] [PATCH 2/7] target/ppc: Honor fpscr_ze semantics and tidy fdiv, Richard Henderson, 2018/07/03
- [Qemu-ppc] [PATCH 4/7] target/ppc: Tidy helper_fadd, helper_fsub, Richard Henderson, 2018/07/03
- [Qemu-ppc] [PATCH 3/7] target/ppc: Tidy helper_fmul, Richard Henderson, 2018/07/03
- [Qemu-ppc] [PATCH 5/7] target/ppc: Tidy helper_fsqrt, Richard Henderson, 2018/07/03
- [Qemu-ppc] [PATCH 6/7] target/ppc: Honor fpscr_ze semantics and tidy fre, fresqrt,
Richard Henderson <=
- [Qemu-ppc] [PATCH 7/7] target/ppc: Use non-arithmetic conversions for fp load/store, Richard Henderson, 2018/07/03
Re: [Qemu-ppc] [PATCH for-3.1 0/7] target/ppc fp cleanups, David Gibson, 2018/07/04
Re: [Qemu-ppc] [Qemu-devel] [PATCH for-3.1 0/7] target/ppc fp cleanups, Alex Bennée, 2018/07/04