[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [PULL 08/26] target/ppc: Honor fpscr_ze semantics and tidy fr
From: |
David Gibson |
Subject: |
[Qemu-ppc] [PULL 08/26] target/ppc: Honor fpscr_ze semantics and tidy fre, fresqrt |
Date: |
Tue, 21 Aug 2018 14:33:25 +1000 |
From: Richard Henderson <address@hidden>
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>
Signed-off-by: David Gibson <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 44f3fed17d..5af5241ab0 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -879,18 +879,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;
-
- farg.ll = arg;
+ /* "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);
- 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. */
@@ -913,27 +922,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;
-
- farg.ll = arg;
+ /* "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);
- 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] [PULL 10/26] target/ppc: bcdsub fix sign when result is zero, (continued)
- [Qemu-ppc] [PULL 10/26] target/ppc: bcdsub fix sign when result is zero, David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 04/26] target/ppc: Honor fpscr_ze semantics and tidy fdiv, David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 14/26] spapr: Add a pseries-3.1 machine type, David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 03/26] target/ppc: Enable fp exceptions for user-only, David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 23/26] mac_oldworld: don't use legacy fw_cfg_init_mem() function, David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 24/26] mac_newworld: don't use legacy fw_cfg_init_mem() function, David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 06/26] target/ppc: Tidy helper_fadd, helper_fsub, David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 17/26] hw/ppc/ppc_boards: Don't use old_mmio for ref405ep_fpga, David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 12/26] xics: don't include "target/ppc/cpu-qom.h" in "hw/ppc/xics.h", David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 13/26] target/ppc: simplify bcdadd/sub functions, David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 08/26] target/ppc: Honor fpscr_ze semantics and tidy fre, fresqrt,
David Gibson <=
- [Qemu-ppc] [PULL 05/26] target/ppc: Tidy helper_fmul, David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 20/26] hw/ppc: deprecate the machine type 'prep', replaced by '40p', David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 18/26] hw/ppc/ppc405_uc: Convert away from old_mmio, David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 22/26] 40p: don't use legacy fw_cfg_init_mem() function, David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 16/26] hw/ppc/prep: Remove ifdeffed-out stub of XCSR code, David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 26/26] ppc: add DBCR based debugging, David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 19/26] spapr: introduce a IRQ controller backend to the machine, David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 15/26] spapr: introduce a fixed IRQ number space, David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 09/26] target/ppc: Use non-arithmetic conversions for fp load/store, David Gibson, 2018/08/21
- [Qemu-ppc] [PULL 25/26] spapr_pci: factorize the use of SPAPR_MACHINE_GET_CLASS(), David Gibson, 2018/08/21