aboutsummaryrefslogtreecommitdiff
path: root/target/ppc/fpu_helper.c
diff options
context:
space:
mode:
authorJose Ricardo Ziviani <joserz@linux.vnet.ibm.com>2017-02-03 20:01:16 -0200
committerDavid Gibson <david@gibson.dropbear.id.au>2017-02-22 11:28:27 +1100
commita4a68476def684f2f424a9ae1daed3de469da7cb (patch)
treeff5bb7b6be81131ee0d383a17a009374fbb3b402 /target/ppc/fpu_helper.c
parent917950d7f54551db9c85c4d06cf559bd19da10a9 (diff)
ppc: implement xssqrtqp instruction
xssqrtqp: VSX Scalar Square Root Quad-Precision. Signed-off-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'target/ppc/fpu_helper.c')
-rw-r--r--target/ppc/fpu_helper.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index b4224428e1..5c34438d1d 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -3392,3 +3392,41 @@ void helper_xsrqpxp(CPUPPCState *env, uint32_t opcode)
putVSR(rD(opcode) + 32, &xt, env);
float_check_status(env);
}
+
+void helper_xssqrtqp(CPUPPCState *env, uint32_t opcode)
+{
+ ppc_vsr_t xb;
+ ppc_vsr_t xt;
+ float_status tstat;
+
+ getVSR(rB(opcode) + 32, &xb, env);
+ memset(&xt, 0, sizeof(xt));
+ helper_reset_fpstatus(env);
+
+ if (unlikely(Rc(opcode) != 0)) {
+ /* TODO: Support xsadddpo after round-to-odd is implemented */
+ abort();
+ }
+
+ tstat = env->fp_status;
+ set_float_exception_flags(0, &tstat);
+ xt.f128 = float128_sqrt(xb.f128, &tstat);
+ env->fp_status.float_exception_flags |= tstat.float_exception_flags;
+
+ if (unlikely(tstat.float_exception_flags & float_flag_invalid)) {
+ if (float128_is_signaling_nan(xb.f128, &tstat)) {
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+ xt.f128 = float128_snan_to_qnan(xb.f128);
+ } else if (float128_is_quiet_nan(xb.f128, &tstat)) {
+ xt.f128 = xb.f128;
+ } else if (float128_is_neg(xb.f128) && !float128_is_zero(xb.f128)) {
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSQRT, 1);
+ set_snan_bit_is_one(0, &env->fp_status);
+ xt.f128 = float128_default_nan(&env->fp_status);
+ }
+ }
+
+ helper_compute_fprf_float128(env, xt.f128);
+ putVSR(rD(opcode) + 32, &xt, env);
+ float_check_status(env);
+}