target/arm: Handle FPCR.NEP for scalar FABS and FNEG

Handle FPCR.NEP merging for scalar FABS and FNEG; this requires
an extra parameter to do_fp1_scalar_int(), since FMOV scalar
does not have the merging behaviour.

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:24 +00:00
parent 13ab4eb190
commit 64339259a9

View File

@ -8426,21 +8426,30 @@ typedef struct FPScalar1Int {
} FPScalar1Int; } FPScalar1Int;
static bool do_fp1_scalar_int(DisasContext *s, arg_rr_e *a, static bool do_fp1_scalar_int(DisasContext *s, arg_rr_e *a,
const FPScalar1Int *f) const FPScalar1Int *f,
bool merging)
{ {
switch (a->esz) { switch (a->esz) {
case MO_64: case MO_64:
if (fp_access_check(s)) { if (fp_access_check(s)) {
TCGv_i64 t = read_fp_dreg(s, a->rn); TCGv_i64 t = read_fp_dreg(s, a->rn);
f->gen_d(t, t); f->gen_d(t, t);
write_fp_dreg(s, a->rd, t); if (merging) {
write_fp_dreg_merging(s, a->rd, a->rd, t);
} else {
write_fp_dreg(s, a->rd, t);
}
} }
break; break;
case MO_32: case MO_32:
if (fp_access_check(s)) { if (fp_access_check(s)) {
TCGv_i32 t = read_fp_sreg(s, a->rn); TCGv_i32 t = read_fp_sreg(s, a->rn);
f->gen_s(t, t); f->gen_s(t, t);
write_fp_sreg(s, a->rd, t); if (merging) {
write_fp_sreg_merging(s, a->rd, a->rd, t);
} else {
write_fp_sreg(s, a->rd, t);
}
} }
break; break;
case MO_16: case MO_16:
@ -8450,7 +8459,11 @@ static bool do_fp1_scalar_int(DisasContext *s, arg_rr_e *a,
if (fp_access_check(s)) { if (fp_access_check(s)) {
TCGv_i32 t = read_fp_hreg(s, a->rn); TCGv_i32 t = read_fp_hreg(s, a->rn);
f->gen_h(t, t); f->gen_h(t, t);
write_fp_sreg(s, a->rd, t); if (merging) {
write_fp_hreg_merging(s, a->rd, a->rd, t);
} else {
write_fp_sreg(s, a->rd, t);
}
} }
break; break;
default: default:
@ -8464,21 +8477,21 @@ static const FPScalar1Int f_scalar_fmov = {
tcg_gen_mov_i32, tcg_gen_mov_i32,
tcg_gen_mov_i64, tcg_gen_mov_i64,
}; };
TRANS(FMOV_s, do_fp1_scalar_int, a, &f_scalar_fmov) TRANS(FMOV_s, do_fp1_scalar_int, a, &f_scalar_fmov, false)
static const FPScalar1Int f_scalar_fabs = { static const FPScalar1Int f_scalar_fabs = {
gen_vfp_absh, gen_vfp_absh,
gen_vfp_abss, gen_vfp_abss,
gen_vfp_absd, gen_vfp_absd,
}; };
TRANS(FABS_s, do_fp1_scalar_int, a, &f_scalar_fabs) TRANS(FABS_s, do_fp1_scalar_int, a, &f_scalar_fabs, true)
static const FPScalar1Int f_scalar_fneg = { static const FPScalar1Int f_scalar_fneg = {
gen_vfp_negh, gen_vfp_negh,
gen_vfp_negs, gen_vfp_negs,
gen_vfp_negd, gen_vfp_negd,
}; };
TRANS(FNEG_s, do_fp1_scalar_int, a, &f_scalar_fneg) TRANS(FNEG_s, do_fp1_scalar_int, a, &f_scalar_fneg, true)
typedef struct FPScalar1 { typedef struct FPScalar1 {
void (*gen_h)(TCGv_i32, TCGv_i32, TCGv_ptr); void (*gen_h)(TCGv_i32, TCGv_i32, TCGv_ptr);