target/arm: Handle FPCR.AH in vector FABD

Split the handling of vector FABD so that it calls a different set
of helpers when FPCR.AH is 1, which implement the "no negation of
the sign of a NaN" semantics.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Peter Maydell 2025-02-01 16:39:36 +00:00
parent d091ce2d3f
commit 538deec623
3 changed files with 33 additions and 1 deletions

View File

@ -722,6 +722,10 @@ DEF_HELPER_FLAGS_5(gvec_fabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
DEF_HELPER_FLAGS_5(gvec_fabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
DEF_HELPER_FLAGS_5(gvec_fabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
DEF_HELPER_FLAGS_5(gvec_ah_fabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
DEF_HELPER_FLAGS_5(gvec_ah_fabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
DEF_HELPER_FLAGS_5(gvec_ah_fabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
DEF_HELPER_FLAGS_5(gvec_fceq_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
DEF_HELPER_FLAGS_5(gvec_fceq_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)
DEF_HELPER_FLAGS_5(gvec_fceq_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, fpst, i32)

View File

@ -5888,7 +5888,12 @@ static gen_helper_gvec_3_ptr * const f_vector_fabd[3] = {
gen_helper_gvec_fabd_s,
gen_helper_gvec_fabd_d,
};
TRANS(FABD_v, do_fp3_vector, a, 0, f_vector_fabd)
static gen_helper_gvec_3_ptr * const f_vector_ah_fabd[3] = {
gen_helper_gvec_ah_fabd_h,
gen_helper_gvec_ah_fabd_s,
gen_helper_gvec_ah_fabd_d,
};
TRANS(FABD_v, do_fp3_vector_2fn, a, 0, f_vector_fabd, f_vector_ah_fabd)
static gen_helper_gvec_3_ptr * const f_vector_frecps[3] = {
gen_helper_gvec_recps_h,

View File

@ -1302,6 +1302,25 @@ static float64 float64_abd(float64 op1, float64 op2, float_status *stat)
return float64_abs(float64_sub(op1, op2, stat));
}
/* ABD when FPCR.AH = 1: avoid flipping sign bit of a NaN result */
static float16 float16_ah_abd(float16 op1, float16 op2, float_status *stat)
{
float16 r = float16_sub(op1, op2, stat);
return float16_is_any_nan(r) ? r : float16_abs(r);
}
static float32 float32_ah_abd(float32 op1, float32 op2, float_status *stat)
{
float32 r = float32_sub(op1, op2, stat);
return float32_is_any_nan(r) ? r : float32_abs(r);
}
static float64 float64_ah_abd(float64 op1, float64 op2, float_status *stat)
{
float64 r = float64_sub(op1, op2, stat);
return float64_is_any_nan(r) ? r : float64_abs(r);
}
/*
* Reciprocal step. These are the AArch32 version which uses a
* non-fused multiply-and-subtract.
@ -1389,6 +1408,10 @@ DO_3OP(gvec_fabd_h, float16_abd, float16)
DO_3OP(gvec_fabd_s, float32_abd, float32)
DO_3OP(gvec_fabd_d, float64_abd, float64)
DO_3OP(gvec_ah_fabd_h, float16_ah_abd, float16)
DO_3OP(gvec_ah_fabd_s, float32_ah_abd, float32)
DO_3OP(gvec_ah_fabd_d, float64_ah_abd, float64)
DO_3OP(gvec_fceq_h, float16_ceq, float16)
DO_3OP(gvec_fceq_s, float32_ceq, float32)
DO_3OP(gvec_fceq_d, float64_ceq, float64)