diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2017-03-04 16:31:14 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2017-03-04 16:31:14 +0000 |
commit | 17783ac828adc694d986698d2d7014aedfeb48c6 (patch) | |
tree | 26dd4777eb9f4c8a7882a1cb5bc171e7c89a239e /target/ppc/fpu_helper.c | |
parent | eeb61d4f8270a6849d9a584fc83da3869b79066d (diff) | |
parent | 992d7e976c7eca2b3129cd4bae4a0d350a8065fa (diff) |
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.9-20170303' into staging
ppc patch queuye for 2017-03-03
This will probably be my last pull request before the hard freeze. It
has some new work, but that has all been posted in draft before the
soft freeze, so I think it's reasonable to include in qemu-2.9.
This batch has:
* A substantial amount of POWER9 work
* Implements the legacy (hash) MMU for POWER9
* Some more preliminaries for implementing the POWER9 radix
MMU
* POWER9 has_work
* Basic POWER9 compatibility mode handling
* Removal of some premature tests
* Some cleanups and fixes to the existing MMU code to make the
POWER9 work simpler
* A bugfix for TCG multiply adds on power
* Allow pseries guests to access PCIe extended config space
This also includes a code-motion not strictly in ppc code - moving
getrampagesize() from ppc code to exec.c. This will make some future
VFIO improvements easier, Paolo said it was ok to merge via my tree.
# gpg: Signature made Fri 03 Mar 2017 03:20:36 GMT
# gpg: using RSA key 0x6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>"
# gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>"
# gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>"
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392
* remotes/dgibson/tags/ppc-for-2.9-20170303:
target/ppc: rewrite f[n]m[add,sub] using float64_muladd
spapr: Small cleanup of PPC MMU enums
spapr_pci: Advertise access to PCIe extended config space
target/ppc: Rework hash mmu page fault code and add defines for clarity
target/ppc: Move no-execute and guarded page checking into new function
target/ppc: Add execute permission checking to access authority check
target/ppc: Add Instruction Authority Mask Register Check
hw/ppc/spapr: Add POWER9 to pseries cpu models
target/ppc/POWER9: Add cpu_has_work function for POWER9
target/ppc/POWER9: Add POWER9 pa-features definition
target/ppc/POWER9: Add POWER9 mmu fault handler
target/ppc: Don't gen an SDR1 on POWER9 and rework register creation
target/ppc: Add patb_entry to sPAPRMachineState
target/ppc/POWER9: Add POWERPC_MMU_V3 bit
powernv: Don't test POWER9 CPU yet
exec, kvm, target-ppc: Move getrampagesize() to common code
target/ppc: Add POWER9/ISAv3.00 to compat_table
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/ppc/fpu_helper.c')
-rw-r--r-- | target/ppc/fpu_helper.c | 213 |
1 files changed, 46 insertions, 167 deletions
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c index 58aee640c3..0535ad0814 100644 --- a/target/ppc/fpu_helper.c +++ b/target/ppc/fpu_helper.c @@ -743,178 +743,62 @@ uint64_t helper_frim(CPUPPCState *env, uint64_t arg) return do_fri(env, arg, float_round_down); } -/* fmadd - fmadd. */ -uint64_t helper_fmadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2, - uint64_t arg3) +static void float64_maddsub_update_excp(CPUPPCState *env, float64 arg1, + float64 arg2, float64 arg3, + unsigned int madd_flags) { - CPU_DoubleU farg1, farg2, farg3; - - farg1.ll = arg1; - farg2.ll = arg2; - farg3.ll = arg3; - - if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) || - (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) { - /* Multiplication of zero by infinity */ - farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1); - } else { - if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) || - float64_is_signaling_nan(farg2.d, &env->fp_status) || - float64_is_signaling_nan(farg3.d, &env->fp_status))) { - /* sNaN operation */ - float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); - } - /* This is the way the PowerPC specification defines it */ - float128 ft0_128, ft1_128; - - ft0_128 = float64_to_float128(farg1.d, &env->fp_status); - ft1_128 = float64_to_float128(farg2.d, &env->fp_status); - ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status); - if (unlikely(float128_is_infinity(ft0_128) && - float64_is_infinity(farg3.d) && - float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) { - /* Magnitude subtraction of infinities */ - farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1); - } else { - ft1_128 = float64_to_float128(farg3.d, &env->fp_status); - ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status); - farg1.d = float128_to_float64(ft0_128, &env->fp_status); - } - } - - return farg1.ll; -} - -/* fmsub - fmsub. */ -uint64_t helper_fmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2, - uint64_t arg3) -{ - CPU_DoubleU farg1, farg2, farg3; - - farg1.ll = arg1; - farg2.ll = arg2; - farg3.ll = arg3; - - if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) || - (float64_is_zero(farg1.d) && - float64_is_infinity(farg2.d)))) { + if (unlikely((float64_is_infinity(arg1) && float64_is_zero(arg2)) || + (float64_is_zero(arg1) && float64_is_infinity(arg2)))) { /* Multiplication of zero by infinity */ - farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1); - } else { - if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) || - float64_is_signaling_nan(farg2.d, &env->fp_status) || - float64_is_signaling_nan(farg3.d, &env->fp_status))) { - /* sNaN operation */ - float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); + arg1 = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1); + } else if (unlikely(float64_is_signaling_nan(arg1, &env->fp_status) || + float64_is_signaling_nan(arg2, &env->fp_status) || + float64_is_signaling_nan(arg3, &env->fp_status))) { + /* sNaN operation */ + float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); + } else if ((float64_is_infinity(arg1) || float64_is_infinity(arg2)) && + float64_is_infinity(arg3)) { + uint8_t aSign, bSign, cSign; + + aSign = float64_is_neg(arg1); + bSign = float64_is_neg(arg2); + cSign = float64_is_neg(arg3); + if (madd_flags & float_muladd_negate_c) { + cSign ^= 1; } - /* This is the way the PowerPC specification defines it */ - float128 ft0_128, ft1_128; - - ft0_128 = float64_to_float128(farg1.d, &env->fp_status); - ft1_128 = float64_to_float128(farg2.d, &env->fp_status); - ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status); - if (unlikely(float128_is_infinity(ft0_128) && - float64_is_infinity(farg3.d) && - float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) { - /* Magnitude subtraction of infinities */ - farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1); - } else { - ft1_128 = float64_to_float128(farg3.d, &env->fp_status); - ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status); - farg1.d = float128_to_float64(ft0_128, &env->fp_status); + if (aSign ^ bSign ^ cSign) { + float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1); } } - return farg1.ll; } -/* fnmadd - fnmadd. */ -uint64_t helper_fnmadd(CPUPPCState *env, uint64_t arg1, uint64_t arg2, - uint64_t arg3) -{ - CPU_DoubleU farg1, farg2, farg3; - - farg1.ll = arg1; - farg2.ll = arg2; - farg3.ll = arg3; - - if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) || - (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) { - /* Multiplication of zero by infinity */ - farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1); - } else { - if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) || - float64_is_signaling_nan(farg2.d, &env->fp_status) || - float64_is_signaling_nan(farg3.d, &env->fp_status))) { - /* sNaN operation */ - float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); - } - /* This is the way the PowerPC specification defines it */ - float128 ft0_128, ft1_128; - - ft0_128 = float64_to_float128(farg1.d, &env->fp_status); - ft1_128 = float64_to_float128(farg2.d, &env->fp_status); - ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status); - if (unlikely(float128_is_infinity(ft0_128) && - float64_is_infinity(farg3.d) && - float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) { - /* Magnitude subtraction of infinities */ - farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1); - } else { - ft1_128 = float64_to_float128(farg3.d, &env->fp_status); - ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status); - farg1.d = float128_to_float64(ft0_128, &env->fp_status); - } - if (likely(!float64_is_any_nan(farg1.d))) { - farg1.d = float64_chs(farg1.d); - } - } - return farg1.ll; +#define FPU_FMADD(op, madd_flags) \ +uint64_t helper_##op(CPUPPCState *env, uint64_t arg1, \ + uint64_t arg2, uint64_t arg3) \ +{ \ + uint32_t flags; \ + float64 ret = float64_muladd(arg1, arg2, arg3, madd_flags, \ + &env->fp_status); \ + flags = get_float_exception_flags(&env->fp_status); \ + if (flags) { \ + if (flags & float_flag_invalid) { \ + float64_maddsub_update_excp(env, arg1, arg2, arg3, \ + madd_flags); \ + } \ + float_check_status(env); \ + } \ + return ret; \ } -/* fnmsub - fnmsub. */ -uint64_t helper_fnmsub(CPUPPCState *env, uint64_t arg1, uint64_t arg2, - uint64_t arg3) -{ - CPU_DoubleU farg1, farg2, farg3; - - farg1.ll = arg1; - farg2.ll = arg2; - farg3.ll = arg3; +#define MADD_FLGS 0 +#define MSUB_FLGS float_muladd_negate_c +#define NMADD_FLGS float_muladd_negate_result +#define NMSUB_FLGS (float_muladd_negate_c | float_muladd_negate_result) - if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) || - (float64_is_zero(farg1.d) && - float64_is_infinity(farg2.d)))) { - /* Multiplication of zero by infinity */ - farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXIMZ, 1); - } else { - if (unlikely(float64_is_signaling_nan(farg1.d, &env->fp_status) || - float64_is_signaling_nan(farg2.d, &env->fp_status) || - float64_is_signaling_nan(farg3.d, &env->fp_status))) { - /* sNaN operation */ - float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1); - } - /* This is the way the PowerPC specification defines it */ - float128 ft0_128, ft1_128; - - ft0_128 = float64_to_float128(farg1.d, &env->fp_status); - ft1_128 = float64_to_float128(farg2.d, &env->fp_status); - ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status); - if (unlikely(float128_is_infinity(ft0_128) && - float64_is_infinity(farg3.d) && - float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) { - /* Magnitude subtraction of infinities */ - farg1.ll = float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1); - } else { - ft1_128 = float64_to_float128(farg3.d, &env->fp_status); - ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status); - farg1.d = float128_to_float64(ft0_128, &env->fp_status); - } - if (likely(!float64_is_any_nan(farg1.d))) { - farg1.d = float64_chs(farg1.d); - } - } - return farg1.ll; -} +FPU_FMADD(fmadd, MADD_FLGS) +FPU_FMADD(fnmadd, NMADD_FLGS) +FPU_FMADD(fmsub, MSUB_FLGS) +FPU_FMADD(fnmsub, NMSUB_FLGS) /* frsp - frsp. */ uint64_t helper_frsp(CPUPPCState *env, uint64_t arg) @@ -2384,11 +2268,6 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \ float_check_status(env); \ } -#define MADD_FLGS 0 -#define MSUB_FLGS float_muladd_negate_c -#define NMADD_FLGS float_muladd_negate_result -#define NMSUB_FLGS (float_muladd_negate_c | float_muladd_negate_result) - VSX_MADD(xsmaddadp, 1, float64, VsrD(0), MADD_FLGS, 1, 1, 0) VSX_MADD(xsmaddmdp, 1, float64, VsrD(0), MADD_FLGS, 0, 1, 0) VSX_MADD(xsmsubadp, 1, float64, VsrD(0), MSUB_FLGS, 1, 1, 0) |