From 2c2c940ef86fba9a26081eab8faaf911da5fb26c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 3 Jul 2018 04:07:06 -0400 Subject: [PATCH] target/arm: Implement SVE floating-point round to integral value Backports commit cda3c75322c6fae1cc5b367ee6d7acf2cbdbcf2b from qemu --- qemu/aarch64.h | 6 +++ qemu/aarch64eb.h | 6 +++ qemu/header_gen.py | 6 +++ qemu/target/arm/helper-sve.h | 14 ++++++ qemu/target/arm/sve.decode | 9 ++++ qemu/target/arm/sve_helper.c | 8 ++++ qemu/target/arm/translate-sve.c | 78 +++++++++++++++++++++++++++++++++ 7 files changed, 127 insertions(+) diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 1c5aecf6..63ca1ec6 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -3650,6 +3650,12 @@ #define helper_sve_fnmls_zpzzz_d helper_sve_fnmls_zpzzz_d_aarch64 #define helper_sve_fnmls_zpzzz_h helper_sve_fnmls_zpzzz_h_aarch64 #define helper_sve_fnmls_zpzzz_s helper_sve_fnmls_zpzzz_s_aarch64 +#define helper_sve_frint_d helper_sve_frint_d_aarch64 +#define helper_sve_frint_h helper_sve_frint_h_aarch64 +#define helper_sve_frint_s helper_sve_frint_s_aarch64 +#define helper_sve_frintx_d helper_sve_frintx_d_aarch64 +#define helper_sve_frintx_h helper_sve_frintx_h_aarch64 +#define helper_sve_frintx_s helper_sve_frintx_s_aarch64 #define helper_sve_fscalbn_d helper_sve_fscalbn_d_aarch64 #define helper_sve_fscalbn_h helper_sve_fscalbn_h_aarch64 #define helper_sve_fscalbn_s helper_sve_fscalbn_s_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index 359bf809..e83897fd 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -3650,6 +3650,12 @@ #define helper_sve_fnmls_zpzzz_d helper_sve_fnmls_zpzzz_d_aarch64eb #define helper_sve_fnmls_zpzzz_h helper_sve_fnmls_zpzzz_h_aarch64eb #define helper_sve_fnmls_zpzzz_s helper_sve_fnmls_zpzzz_s_aarch64eb +#define helper_sve_frint_d helper_sve_frint_d_aarch64eb +#define helper_sve_frint_h helper_sve_frint_h_aarch64eb +#define helper_sve_frint_s helper_sve_frint_s_aarch64eb +#define helper_sve_frintx_d helper_sve_frintx_d_aarch64eb +#define helper_sve_frintx_h helper_sve_frintx_h_aarch64eb +#define helper_sve_frintx_s helper_sve_frintx_s_aarch64eb #define helper_sve_fscalbn_d helper_sve_fscalbn_d_aarch64eb #define helper_sve_fscalbn_h helper_sve_fscalbn_h_aarch64eb #define helper_sve_fscalbn_s helper_sve_fscalbn_s_aarch64eb diff --git a/qemu/header_gen.py b/qemu/header_gen.py index c35db23c..fcb6b067 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -3671,6 +3671,12 @@ aarch64_symbols = ( 'helper_sve_fnmls_zpzzz_d', 'helper_sve_fnmls_zpzzz_h', 'helper_sve_fnmls_zpzzz_s', + 'helper_sve_frint_d', + 'helper_sve_frint_h', + 'helper_sve_frint_s', + 'helper_sve_frintx_d', + 'helper_sve_frintx_h', + 'helper_sve_frintx_s', 'helper_sve_fscalbn_d', 'helper_sve_fscalbn_h', 'helper_sve_fscalbn_s', diff --git a/qemu/target/arm/helper-sve.h b/qemu/target/arm/helper-sve.h index 37fa9eb9..36168c5b 100644 --- a/qemu/target/arm/helper-sve.h +++ b/qemu/target/arm/helper-sve.h @@ -985,6 +985,20 @@ DEF_HELPER_FLAGS_5(sve_fcvtzu_sd, TCG_CALL_NO_RWG, DEF_HELPER_FLAGS_5(sve_fcvtzu_dd, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(sve_frint_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(sve_frint_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(sve_frint_d, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(sve_frintx_h, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(sve_frintx_s, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_5(sve_frintx_d, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) + DEF_HELPER_FLAGS_5(sve_scvt_hh, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_5(sve_scvt_sh, TCG_CALL_NO_RWG, diff --git a/qemu/target/arm/sve.decode b/qemu/target/arm/sve.decode index a6a1ea96..366c5935 100644 --- a/qemu/target/arm/sve.decode +++ b/qemu/target/arm/sve.decode @@ -845,6 +845,15 @@ FCVTZU_sd 01100101 11 011 10 1 101 ... ..... ..... @rd_pg_rn_e0 FCVTZS_dd 01100101 11 011 11 0 101 ... ..... ..... @rd_pg_rn_e0 FCVTZU_dd 01100101 11 011 11 1 101 ... ..... ..... @rd_pg_rn_e0 +# SVE floating-point round to integral value +FRINTN 01100101 .. 000 000 101 ... ..... ..... @rd_pg_rn +FRINTP 01100101 .. 000 001 101 ... ..... ..... @rd_pg_rn +FRINTM 01100101 .. 000 010 101 ... ..... ..... @rd_pg_rn +FRINTZ 01100101 .. 000 011 101 ... ..... ..... @rd_pg_rn +FRINTA 01100101 .. 000 100 101 ... ..... ..... @rd_pg_rn +FRINTX 01100101 .. 000 110 101 ... ..... ..... @rd_pg_rn +FRINTI 01100101 .. 000 111 101 ... ..... ..... @rd_pg_rn + # SVE integer convert to floating-point SCVTF_hh 01100101 01 010 01 0 101 ... ..... ..... @rd_pg_rn_e0 SCVTF_sh 01100101 01 010 10 0 101 ... ..... ..... @rd_pg_rn_e0 diff --git a/qemu/target/arm/sve_helper.c b/qemu/target/arm/sve_helper.c index fa02b45b..7329a1f6 100644 --- a/qemu/target/arm/sve_helper.c +++ b/qemu/target/arm/sve_helper.c @@ -4143,6 +4143,14 @@ DO_ZPZ_FP(sve_fcvtzu_sd, uint64_t, , vfp_float32_to_uint64_rtz) DO_ZPZ_FP(sve_fcvtzu_ds, uint64_t, , helper_vfp_touizd) DO_ZPZ_FP(sve_fcvtzu_dd, uint64_t, , vfp_float64_to_uint64_rtz) +DO_ZPZ_FP(sve_frint_h, uint16_t, H1_2, helper_advsimd_rinth) +DO_ZPZ_FP(sve_frint_s, uint32_t, H1_4, helper_rints) +DO_ZPZ_FP(sve_frint_d, uint64_t, , helper_rintd) + +DO_ZPZ_FP(sve_frintx_h, uint16_t, H1_2, float16_round_to_int) +DO_ZPZ_FP(sve_frintx_s, uint32_t, H1_4, float32_round_to_int) +DO_ZPZ_FP(sve_frintx_d, uint64_t, , float64_round_to_int) + DO_ZPZ_FP(sve_scvt_hh, uint16_t, H1_2, int16_to_float16) DO_ZPZ_FP(sve_scvt_sh, uint32_t, H1_4, int32_to_float16) DO_ZPZ_FP(sve_scvt_ss, uint32_t, H1_4, int32_to_float32) diff --git a/qemu/target/arm/translate-sve.c b/qemu/target/arm/translate-sve.c index 16790ca3..929363fa 100644 --- a/qemu/target/arm/translate-sve.c +++ b/qemu/target/arm/translate-sve.c @@ -4197,6 +4197,84 @@ static bool trans_FCVTZU_dd(DisasContext *s, arg_rpr_esz *a, uint32_t insn) return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvtzu_dd); } +static gen_helper_gvec_3_ptr * const frint_fns[3] = { + gen_helper_sve_frint_h, + gen_helper_sve_frint_s, + gen_helper_sve_frint_d +}; + +static bool trans_FRINTI(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +{ + if (a->esz == 0) { + return false; + } + return do_zpz_ptr(s, a->rd, a->rn, a->pg, a->esz == MO_16, + frint_fns[a->esz - 1]); +} + +static bool trans_FRINTX(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +{ + static gen_helper_gvec_3_ptr * const fns[3] = { + gen_helper_sve_frintx_h, + gen_helper_sve_frintx_s, + gen_helper_sve_frintx_d + }; + if (a->esz == 0) { + return false; + } + return do_zpz_ptr(s, a->rd, a->rn, a->pg, a->esz == MO_16, fns[a->esz - 1]); +} + +static bool do_frint_mode(DisasContext *s, arg_rpr_esz *a, int mode) +{ + if (a->esz == 0) { + return false; + } + if (sve_access_check(s)) { + TCGContext *tcg_ctx = s->uc->tcg_ctx; + unsigned vsz = vec_full_reg_size(s); + TCGv_i32 tmode = tcg_const_i32(tcg_ctx, mode); + TCGv_ptr status = get_fpstatus_ptr(tcg_ctx, a->esz == MO_16); + + gen_helper_set_rmode(tcg_ctx, tmode, tmode, status); + + tcg_gen_gvec_3_ptr(tcg_ctx, vec_full_reg_offset(s, a->rd), + vec_full_reg_offset(s, a->rn), + pred_full_reg_offset(s, a->pg), + status, vsz, vsz, 0, frint_fns[a->esz - 1]); + + gen_helper_set_rmode(tcg_ctx, tmode, tmode, status); + tcg_temp_free_i32(tcg_ctx, tmode); + tcg_temp_free_ptr(tcg_ctx, status); + } + return true; +} + +static bool trans_FRINTN(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +{ + return do_frint_mode(s, a, float_round_nearest_even); +} + +static bool trans_FRINTP(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +{ + return do_frint_mode(s, a, float_round_up); +} + +static bool trans_FRINTM(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +{ + return do_frint_mode(s, a, float_round_down); +} + +static bool trans_FRINTZ(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +{ + return do_frint_mode(s, a, float_round_to_zero); +} + +static bool trans_FRINTA(DisasContext *s, arg_rpr_esz *a, uint32_t insn) +{ + return do_frint_mode(s, a, float_round_ties_away); +} + static bool trans_SCVTF_hh(DisasContext *s, arg_rpr_esz *a, uint32_t insn) { return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_scvt_hh);