target-ppc: Add VSX ISA2.06 xdiv Instructions

This patch adds the VSX floating point divide instructions defined
by V2.06 of the PowerPC ISA: xsdivdp, xvdivdp, xvdivsp.

Signed-off-by: Tom Musta <tommusta@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
Tom Musta 2014-01-02 16:21:23 -06:00 committed by Alexander Graf
parent 5e591d8812
commit 4b98eeef50
3 changed files with 58 additions and 0 deletions

View file

@ -1855,3 +1855,52 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
VSX_MUL(xsmuldp, 1, float64, f64, 1)
VSX_MUL(xvmuldp, 2, float64, f64, 0)
VSX_MUL(xvmulsp, 4, float32, f32, 0)
/* VSX_DIV - VSX floating point divide
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
* fld - vsr_t field (f32 or f64)
* sfprf - set FPRF
*/
#define VSX_DIV(op, nels, tp, fld, sfprf) \
void helper_##op(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); \
helper_reset_fpstatus(env); \
\
for (i = 0; i < nels; i++) { \
float_status tstat = env->fp_status; \
set_float_exception_flags(0, &tstat); \
xt.fld[i] = tp##_div(xa.fld[i], xb.fld[i], &tstat); \
env->fp_status.float_exception_flags |= tstat.float_exception_flags; \
\
if (unlikely(tstat.float_exception_flags & float_flag_invalid)) { \
if (tp##_is_infinity(xa.fld[i]) && tp##_is_infinity(xb.fld[i])) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXIDI, sfprf); \
} else if (tp##_is_zero(xa.fld[i]) && \
tp##_is_zero(xb.fld[i])) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXZDZ, sfprf); \
} else if (tp##_is_signaling_nan(xa.fld[i]) || \
tp##_is_signaling_nan(xb.fld[i])) { \
fload_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, sfprf); \
} \
} \
\
if (sfprf) { \
helper_compute_fprf(env, xt.fld[i], sfprf); \
} \
} \
\
putVSR(xT(opcode), &xt, env); \
helper_float_check_status(env); \
}
VSX_DIV(xsdivdp, 1, float64, f64, 1)
VSX_DIV(xvdivdp, 2, float64, f64, 0)
VSX_DIV(xvdivsp, 4, float32, f32, 0)