summaryrefslogtreecommitdiffstats
path: root/target
diff options
context:
space:
mode:
authorVíctor Colombo2022-09-06 14:55:23 +0200
committerDaniel Henrique Barboza2022-09-20 15:54:06 +0200
commitc3f24257e3c094122a82611db3d7c3e8b25d9153 (patch)
tree66070fba97df44c57a3a7c0d8a6ceafc3bb94285 /target
parenttarget/ppc: Zero second doubleword of VSR registers for FPR insns (diff)
downloadqemu-c3f24257e3c094122a82611db3d7c3e8b25d9153.tar.gz
qemu-c3f24257e3c094122a82611db3d7c3e8b25d9153.tar.xz
qemu-c3f24257e3c094122a82611db3d7c3e8b25d9153.zip
target/ppc: Clear fpstatus flags on helpers missing it
In ppc emulation, exception flags are not cleared at the end of an instruction. Instead, the next instruction is responsible to clear it before its emulation. However, some helpers are not doing it, causing an issue where the previously set exception flags are being used and leading to incorrect values being set in FPSCR. Fix this by clearing fp_status before doing the instruction 'real' work for the following helpers that were missing this behavior: - VSX_CVT_INT_TO_FP_VECTOR - VSX_CVT_FP_TO_FP - VSX_CVT_FP_TO_INT_VECTOR - VSX_CVT_FP_TO_INT2 - VSX_CVT_FP_TO_INT - VSX_CVT_FP_TO_FP_HP - VSX_CVT_FP_TO_FP_VECTOR - VSX_CMP - VSX_ROUND - xscvqpdp - xscvdpsp[n] Signed-off-by: Víctor Colombo <victor.colombo@eldorado.org.br> Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com> Message-Id: <20220906125523.38765-9-victor.colombo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Diffstat (limited to 'target')
-rw-r--r--target/ppc/fpu_helper.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index f07330ffc1..ae25f32d6e 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -2628,6 +2628,8 @@ uint32_t helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \
int all_true = 1; \
int all_false = 1; \
\
+ helper_reset_fpstatus(env); \
+ \
for (i = 0; i < nels; i++) { \
if (unlikely(tp##_is_any_nan(xa->fld) || \
tp##_is_any_nan(xb->fld))) { \
@@ -2681,6 +2683,8 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
ppc_vsr_t t = { }; \
int i; \
\
+ helper_reset_fpstatus(env); \
+ \
for (i = 0; i < nels; i++) { \
t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status); \
if (unlikely(stp##_is_signaling_nan(xb->sfld, \
@@ -2706,6 +2710,8 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
ppc_vsr_t t = { }; \
int i; \
\
+ helper_reset_fpstatus(env); \
+ \
for (i = 0; i < nels; i++) { \
t.VsrW(2 * i) = stp##_to_##ttp(xb->VsrD(i), &env->fp_status); \
if (unlikely(stp##_is_signaling_nan(xb->VsrD(i), \
@@ -2743,6 +2749,8 @@ void helper_##op(CPUPPCState *env, uint32_t opcode, \
ppc_vsr_t t = *xt; \
int i; \
\
+ helper_reset_fpstatus(env); \
+ \
for (i = 0; i < nels; i++) { \
t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status); \
if (unlikely(stp##_is_signaling_nan(xb->sfld, \
@@ -2778,6 +2786,8 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
ppc_vsr_t t = { }; \
int i; \
\
+ helper_reset_fpstatus(env); \
+ \
for (i = 0; i < nels; i++) { \
t.tfld = stp##_to_##ttp(xb->sfld, 1, &env->fp_status); \
if (unlikely(stp##_is_signaling_nan(xb->sfld, \
@@ -2825,6 +2835,8 @@ void helper_XSCVQPDP(CPUPPCState *env, uint32_t ro, ppc_vsr_t *xt,
ppc_vsr_t t = { };
float_status tstat;
+ helper_reset_fpstatus(env);
+
tstat = env->fp_status;
if (ro != 0) {
tstat.float_rounding_mode = float_round_to_odd;
@@ -2846,6 +2858,7 @@ uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb)
{
uint64_t result, sign, exp, frac;
+ helper_reset_fpstatus(env);
float_status tstat = env->fp_status;
set_float_exception_flags(0, &tstat);
@@ -2901,22 +2914,20 @@ uint64_t helper_XSCVSPDPN(uint64_t xb)
#define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, sfi, rnan) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
- int all_flags = env->fp_status.float_exception_flags, flags; \
ppc_vsr_t t = { }; \
- int i; \
+ int i, flags; \
+ \
+ helper_reset_fpstatus(env); \
\
for (i = 0; i < nels; i++) { \
- env->fp_status.float_exception_flags = 0; \
t.tfld = stp##_to_##ttp##_round_to_zero(xb->sfld, &env->fp_status); \
flags = env->fp_status.float_exception_flags; \
if (unlikely(flags & float_flag_invalid)) { \
t.tfld = float_invalid_cvt(env, flags, t.tfld, rnan, 0, GETPC());\
} \
- all_flags |= flags; \
} \
\
*xt = t; \
- env->fp_status.float_exception_flags = all_flags; \
do_float_check_status(env, sfi, GETPC()); \
}
@@ -2968,12 +2979,12 @@ VSX_CVT_FP_TO_INT128(XSCVQPSQZ, int128, 0x8000000000000000ULL);
#define VSX_CVT_FP_TO_INT2(op, nels, stp, ttp, sfi, rnan) \
void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
{ \
- int all_flags = env->fp_status.float_exception_flags, flags; \
ppc_vsr_t t = { }; \
- int i; \
+ int i, flags; \
+ \
+ helper_reset_fpstatus(env); \
\
for (i = 0; i < nels; i++) { \
- env->fp_status.float_exception_flags = 0; \
t.VsrW(2 * i) = stp##_to_##ttp##_round_to_zero(xb->VsrD(i), \
&env->fp_status); \
flags = env->fp_status.float_exception_flags; \
@@ -2982,11 +2993,9 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
rnan, 0, GETPC()); \
} \
t.VsrW(2 * i + 1) = t.VsrW(2 * i); \
- all_flags |= flags; \
} \
\
*xt = t; \
- env->fp_status.float_exception_flags = all_flags; \
do_float_check_status(env, sfi, GETPC()); \
}
@@ -3011,6 +3020,8 @@ void helper_##op(CPUPPCState *env, uint32_t opcode, \
ppc_vsr_t t = { }; \
int flags; \
\
+ helper_reset_fpstatus(env); \
+ \
t.tfld = stp##_to_##ttp##_round_to_zero(xb->sfld, &env->fp_status); \
flags = get_float_exception_flags(&env->fp_status); \
if (flags & float_flag_invalid) { \
@@ -3023,7 +3034,6 @@ void helper_##op(CPUPPCState *env, uint32_t opcode, \
VSX_CVT_FP_TO_INT_VECTOR(xscvqpsdz, float128, int64, f128, VsrD(0), \
0x8000000000000000ULL)
-
VSX_CVT_FP_TO_INT_VECTOR(xscvqpswz, float128, int32, f128, VsrD(0), \
0xffffffff80000000ULL)
VSX_CVT_FP_TO_INT_VECTOR(xscvqpudz, float128, uint64, f128, VsrD(0), 0x0ULL)
@@ -3046,6 +3056,8 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
ppc_vsr_t t = { }; \
int i; \
\
+ helper_reset_fpstatus(env); \
+ \
for (i = 0; i < nels; i++) { \
t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status); \
if (r2sp) { \
@@ -3115,6 +3127,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode, \
{ \
ppc_vsr_t t = *xt; \
\
+ helper_reset_fpstatus(env); \
t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status); \
helper_compute_fprf_##ttp(env, t.tfld); \
\
@@ -3148,6 +3161,8 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \
int i; \
FloatRoundMode curr_rounding_mode; \
\
+ helper_reset_fpstatus(env); \
+ \
if (rmode != FLOAT_ROUND_CURRENT) { \
curr_rounding_mode = get_float_rounding_mode(&env->fp_status); \
set_float_rounding_mode(rmode, &env->fp_status); \