diff options
author | Tom Musta <tommusta@gmail.com> | 2014-01-02 16:21:31 -0600 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2014-03-05 03:06:31 +0100 |
commit | 959e9c9d1e5507a6c68d0b875d71ef967d3cfd6c (patch) | |
tree | 0a084f1d007779f8d4fdef4bdfe9119a53209eb9 /target-ppc/fpu_helper.c | |
parent | 4f17e9c738321151e6b7aa4d2c25c3f1e2443cca (diff) |
target-ppc: Add VSX xmax/xmin Instructions
This patch adds the VSX floating point maximum and minimum
instructions:
- xsmaxdp, xvmaxdp, xvmaxsp
- xsmindp, xvmindp, xvminsp
Because of the Power ISA definitions of maximum and minimum
on various boundary cases, the standard softfloat comparison
routines (e.g. float64_lt) do not work as well as one might
think. Therefore specific routines for comparing 64 and 32
bit floating point numbers are implemented in the PowerPC
helper code.
Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'target-ppc/fpu_helper.c')
-rw-r--r-- | target-ppc/fpu_helper.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c index eb5d878b43..8ece96651f 100644 --- a/target-ppc/fpu_helper.c +++ b/target-ppc/fpu_helper.c @@ -2288,3 +2288,42 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \ VSX_SCALAR_CMP(xscmpodp, 1) VSX_SCALAR_CMP(xscmpudp, 0) + +#define float64_snan_to_qnan(x) ((x) | 0x0008000000000000ul) +#define float32_snan_to_qnan(x) ((x) | 0x00400000) + +/* VSX_MAX_MIN - VSX floating point maximum/minimum + * name - instruction mnemonic + * op - operation (max or min) + * nels - number of elements (1, 2 or 4) + * tp - type (float32 or float64) + * fld - vsr_t field (f32 or f64) + */ +#define VSX_MAX_MIN(name, op, nels, tp, fld) \ +void helper_##name(CPUPPCState *env, uint32_t opcode) \ +{ \ + ppc_vsr_t xt, xa, xb; \ + int i; \ + \ + getVSR(xA(opcode), &xa, env); \ + getVSR(xB(opcode), &xb, env); \ + getVSR(xT(opcode), &xt, env); \ + \ + for (i = 0; i < nels; i++) { \ + xt.fld[i] = tp##_##op(xa.fld[i], xb.fld[i], &env->fp_status); \ + if (unlikely(tp##_is_signaling_nan(xa.fld[i]) || \ + tp##_is_signaling_nan(xb.fld[i]))) { \ + fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 0); \ + } \ + } \ + \ + putVSR(xT(opcode), &xt, env); \ + helper_float_check_status(env); \ +} + +VSX_MAX_MIN(xsmaxdp, maxnum, 1, float64, f64) +VSX_MAX_MIN(xvmaxdp, maxnum, 2, float64, f64) +VSX_MAX_MIN(xvmaxsp, maxnum, 4, float32, f32) +VSX_MAX_MIN(xsmindp, minnum, 1, float64, f64) +VSX_MAX_MIN(xvmindp, minnum, 2, float64, f64) +VSX_MAX_MIN(xvminsp, minnum, 4, float32, f32) |