On 2/24/22 09:16, Víctor Colombo wrote:
Could you please elaborate more on how do you think using
float*_compare and its FloatRelation result would work here?
I noticed do_scalar_cmp modifies CR and sets FPCC flag, which
is not what VSX_SCALAR_CMP do. Using that function would require a
rework.
An option I though would be to bring into VSX_SCALAR_CMP the
important necessary parts, something like this:
#define VSX_SCALAR_CMP(op, tp, cmp, fld, svxvc, expr) ...
r = tp##_compare(xa->fld, xb->fld, &env->fp_status); \
if (expr) { \
memset(&t.fld, 0xFF, sizeof(t.fld)); \
} else if (r == float_relation_unordered) { \
if (env->fp_status.float_exception_flags & float_flag_invalid_snan) { \
float_invalid_op_vxsnan(env, GETPC()); \
if (fpscr_ve == 0 && svxvc) { \
float_invalid_op_vxvc(env, 0, GETPC()); \
} \
} else if (svxvc) { \
if (tp##_is_quiet_nan(xa->fld, &env->fp_status) || \
tp##_is_quiet_nan(xb->fld, &env->fp_status)) { \
float_invalid_op_vxvc(env, 0, GETPC()); \
} \
} \
} \
...
VSX_SCALAR_CMP(XSCMPEQDP, float64, eq, VsrD(0), 0, r == float_relation_equal)
VSX_SCALAR_CMP(XSCMPGEDP, float64, le, VsrD(0), 1, \
r == float_relation_equal || r == float_relation_greater)
VSX_SCALAR_CMP(XSCMPGTDP, float64, lt, VsrD(0), 1, r == float_relation_greater)
I was thinking along the lines of:
bool r;
int flags;
helper_reset_fpstatus(env);
if (svxvc) {
r = tp##cmp(...);
} else {
r = tp##cmp##_quiet(...);
}
flags = get_float_exception_flags(&env->fp_status);
if (unlikely(flags & float_flag_invalid)) {
bool vxvc = svxvc;
if (flags & float_flag_invalid_snan)) {
float_invalid_op_vxsnan(...);
vxvc &= fpscr_ve == 0;
}
if (vxvc) {
float_invalid_op_vxvc(...);
}
}
memset(xt, 0, sizeof(*xt));
memset(&xt->fld, -r, sizeof(xt->fld));
do_float_check_status(...);
r~