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>
This commit is contained in:
parent
4b65b6e769
commit
c3f24257e3
@ -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); \
|
||||
|
Loading…
Reference in New Issue
Block a user