Skip to content

Commit

Permalink
target/arm: Use FPST_A64_F16 for halfprec-to-other conversions
Browse files Browse the repository at this point in the history
We should be using the F16-specific float_status for conversions from
half-precision, because halfprec inputs never set Input Denormal.

Without FEAT_AHP, using the wrong fpst here had no effect, because
the only difference between the A64_F16 and A64 fpst is its handling
of flush-to-zero on input and output, and the helper functions
vfp_fcvt_f16_to_* and vfp_fcvt_*_to_f16 all explicitly squash the
relevant flushing flags, and flush_inputs_to_zero was the only way
that IDC could be set.

With FEAT_AHP, the FPCR.AH=1 behaviour sets IDC for
input_denormal_used, which we will only ignore in
vfp_get_fpsr_from_host() for the A64_F16 fpst; so it matters that we
use that one for f16 inputs (and the normal one for single/double to
f16 conversions).

Signed-off-by: Peter Maydell <[email protected]>
Reviewed-by: Richard Henderson <[email protected]>
Message-id: [email protected]
  • Loading branch information
pm215 committed Jan 28, 2025
1 parent d168a08 commit e07b489
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 5 deletions.
9 changes: 6 additions & 3 deletions target/arm/tcg/translate-a64.c
Original file line number Diff line number Diff line change
Expand Up @@ -8568,7 +8568,7 @@ static bool trans_FCVT_s_sh(DisasContext *s, arg_rr *a)
if (fp_access_check(s)) {
TCGv_i32 tcg_rn = read_fp_hreg(s, a->rn);
TCGv_i32 tcg_rd = tcg_temp_new_i32();
TCGv_ptr tcg_fpst = fpstatus_ptr(FPST_A64);
TCGv_ptr tcg_fpst = fpstatus_ptr(FPST_A64_F16);
TCGv_i32 tcg_ahp = get_ahp_flag();

gen_helper_vfp_fcvt_f16_to_f32(tcg_rd, tcg_rn, tcg_fpst, tcg_ahp);
Expand All @@ -8582,7 +8582,7 @@ static bool trans_FCVT_s_dh(DisasContext *s, arg_rr *a)
if (fp_access_check(s)) {
TCGv_i32 tcg_rn = read_fp_hreg(s, a->rn);
TCGv_i64 tcg_rd = tcg_temp_new_i64();
TCGv_ptr tcg_fpst = fpstatus_ptr(FPST_A64);
TCGv_ptr tcg_fpst = fpstatus_ptr(FPST_A64_F16);
TCGv_i32 tcg_ahp = get_ahp_flag();

gen_helper_vfp_fcvt_f16_to_f64(tcg_rd, tcg_rn, tcg_fpst, tcg_ahp);
Expand Down Expand Up @@ -9511,13 +9511,14 @@ static bool trans_FCVTL_v(DisasContext *s, arg_qrr_e *a)
return true;
}

fpst = fpstatus_ptr(FPST_A64);
if (a->esz == MO_64) {
/* 32 -> 64 bit fp conversion */
TCGv_i64 tcg_res[2];
TCGv_i32 tcg_op = tcg_temp_new_i32();
int srcelt = a->q ? 2 : 0;

fpst = fpstatus_ptr(FPST_A64);

for (pass = 0; pass < 2; pass++) {
tcg_res[pass] = tcg_temp_new_i64();
read_vec_element_i32(s, tcg_op, a->rn, srcelt + pass, MO_32);
Expand All @@ -9532,6 +9533,8 @@ static bool trans_FCVTL_v(DisasContext *s, arg_qrr_e *a)
TCGv_i32 tcg_res[4];
TCGv_i32 ahp = get_ahp_flag();

fpst = fpstatus_ptr(FPST_A64_F16);

for (pass = 0; pass < 4; pass++) {
tcg_res[pass] = tcg_temp_new_i32();
read_vec_element_i32(s, tcg_res[pass], a->rn, srcelt + pass, MO_16);
Expand Down
4 changes: 2 additions & 2 deletions target/arm/tcg/translate-sve.c
Original file line number Diff line number Diff line change
Expand Up @@ -3887,15 +3887,15 @@ TRANS_FEAT(FCMLA_zzxz, aa64_sve, gen_gvec_fpst_zzzz, fcmla_idx_fns[a->esz],
TRANS_FEAT(FCVT_sh, aa64_sve, gen_gvec_fpst_arg_zpz,
gen_helper_sve_fcvt_sh, a, 0, FPST_A64)
TRANS_FEAT(FCVT_hs, aa64_sve, gen_gvec_fpst_arg_zpz,
gen_helper_sve_fcvt_hs, a, 0, FPST_A64)
gen_helper_sve_fcvt_hs, a, 0, FPST_A64_F16)

TRANS_FEAT(BFCVT, aa64_sve_bf16, gen_gvec_fpst_arg_zpz,
gen_helper_sve_bfcvt, a, 0, FPST_A64)

TRANS_FEAT(FCVT_dh, aa64_sve, gen_gvec_fpst_arg_zpz,
gen_helper_sve_fcvt_dh, a, 0, FPST_A64)
TRANS_FEAT(FCVT_hd, aa64_sve, gen_gvec_fpst_arg_zpz,
gen_helper_sve_fcvt_hd, a, 0, FPST_A64)
gen_helper_sve_fcvt_hd, a, 0, FPST_A64_F16)
TRANS_FEAT(FCVT_ds, aa64_sve, gen_gvec_fpst_arg_zpz,
gen_helper_sve_fcvt_ds, a, 0, FPST_A64)
TRANS_FEAT(FCVT_sd, aa64_sve, gen_gvec_fpst_arg_zpz,
Expand Down

0 comments on commit e07b489

Please sign in to comment.