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:17 -0200
committerDavid Gibson <david@gibson.dropbear.id.au>2017-02-22 11:28:27 +1100
commitf6b99afdc33e94cd09ee68979f2db409e7f56517 (patch)
tree1d6505a562249c14f89e79d0d039c913d1689cc1 /target/ppc/fpu_helper.c
parenta4a68476def684f2f424a9ae1daed3de469da7cb (diff)
ppc: implement xssubqp instruction
xssubqp: VSX Scalar Subtract 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.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 5c34438d1d..48973a9db8 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -3430,3 +3430,37 @@ void helper_xssqrtqp(CPUPPCState *env, uint32_t opcode)
putVSR(rD(opcode) + 32, &xt, env);
float_check_status(env);
}
+
+void helper_xssubqp(CPUPPCState *env, uint32_t opcode)
+{
+ ppc_vsr_t xt, xa, xb;
+ float_status tstat;
+
+ getVSR(rA(opcode) + 32, &xa, env);
+ getVSR(rB(opcode) + 32, &xb, env);
+ getVSR(rD(opcode) + 32, &xt, env);
+ helper_reset_fpstatus(env);
+
+ if (unlikely(Rc(opcode) != 0)) {
+ /* TODO: Support xssubqp after round-to-odd is implemented */
+ abort();
+ }
+
+ tstat = env->fp_status;
+ set_float_exception_flags(0, &tstat);
+ xt.f128 = float128_sub(xa.f128, 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_infinity(xa.f128) && float128_is_infinity(xb.f128)) {
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXISI, 1);
+ } else if (float128_is_signaling_nan(xa.f128, &tstat) ||
+ float128_is_signaling_nan(xb.f128, &tstat)) {
+ float_invalid_op_excp(env, POWERPC_EXCP_FP_VXSNAN, 1);
+ }
+ }
+
+ helper_compute_fprf_float128(env, xt.f128);
+ putVSR(rD(opcode) + 32, &xt, env);
+ float_check_status(env);
+}