[Qemu-devel] [PATCH v5 23/35] target/arm: Implement SVE floating-point convert precision

Richard Henderson posted 35 patches 7 years, 7 months ago
There is a newer version of this series
[Qemu-devel] [PATCH v5 23/35] target/arm: Implement SVE floating-point convert precision
Posted by Richard Henderson 7 years, 7 months ago
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/helper-sve.h    | 13 +++++++++++++
 target/arm/sve_helper.c    | 27 +++++++++++++++++++++++++++
 target/arm/translate-sve.c | 30 ++++++++++++++++++++++++++++++
 target/arm/sve.decode      |  8 ++++++++
 4 files changed, 78 insertions(+)

diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h
index aca137fc37..4c379dbb05 100644
--- a/target/arm/helper-sve.h
+++ b/target/arm/helper-sve.h
@@ -942,6 +942,19 @@ DEF_HELPER_FLAGS_6(sve_fmins_s, TCG_CALL_NO_RWG,
 DEF_HELPER_FLAGS_6(sve_fmins_d, TCG_CALL_NO_RWG,
                    void, ptr, ptr, ptr, i64, ptr, i32)
 
+DEF_HELPER_FLAGS_5(sve_fcvt_sh, TCG_CALL_NO_RWG,
+                   void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(sve_fcvt_dh, TCG_CALL_NO_RWG,
+                   void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(sve_fcvt_hs, TCG_CALL_NO_RWG,
+                   void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(sve_fcvt_ds, TCG_CALL_NO_RWG,
+                   void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(sve_fcvt_hd, TCG_CALL_NO_RWG,
+                   void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(sve_fcvt_sd, 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/target/arm/sve_helper.c b/target/arm/sve_helper.c
index 3dc35d8b12..e1bbe1f550 100644
--- a/target/arm/sve_helper.c
+++ b/target/arm/sve_helper.c
@@ -3147,6 +3147,33 @@ void HELPER(NAME)(void *vd, void *vn, void *vg, void *status, uint32_t desc) \
     } while (i != 0);                                                 \
 }
 
+static inline float32 sve_f16_to_f32(float16 f, float_status *s)
+{
+    return float16_to_float32(f, true, s);
+}
+
+static inline float64 sve_f16_to_f64(float16 f, float_status *s)
+{
+    return float16_to_float64(f, true, s);
+}
+
+static inline float16 sve_f32_to_f16(float32 f, float_status *s)
+{
+    return float32_to_float16(f, true, s);
+}
+
+static inline float16 sve_f64_to_f16(float64 f, float_status *s)
+{
+    return float64_to_float16(f, true, s);
+}
+
+DO_ZPZ_FP(sve_fcvt_sh, uint32_t, H1_4, sve_f32_to_f16)
+DO_ZPZ_FP(sve_fcvt_hs, uint32_t, H1_4, sve_f16_to_f32)
+DO_ZPZ_FP(sve_fcvt_dh, uint64_t,     , sve_f64_to_f16)
+DO_ZPZ_FP(sve_fcvt_hd, uint64_t,     , sve_f16_to_f64)
+DO_ZPZ_FP(sve_fcvt_ds, uint64_t,     , float64_to_float32)
+DO_ZPZ_FP(sve_fcvt_sd, uint64_t,     , float32_to_float64)
+
 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/target/arm/translate-sve.c b/target/arm/translate-sve.c
index fb225d56a1..c08c1263f1 100644
--- a/target/arm/translate-sve.c
+++ b/target/arm/translate-sve.c
@@ -3940,6 +3940,36 @@ static bool do_zpz_ptr(DisasContext *s, int rd, int rn, int pg,
     return true;
 }
 
+static bool trans_FCVT_sh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
+{
+    return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvt_sh);
+}
+
+static bool trans_FCVT_hs(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
+{
+    return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_hs);
+}
+
+static bool trans_FCVT_dh(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
+{
+    return do_zpz_ptr(s, a->rd, a->rn, a->pg, true, gen_helper_sve_fcvt_dh);
+}
+
+static bool trans_FCVT_hd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
+{
+    return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_hd);
+}
+
+static bool trans_FCVT_ds(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
+{
+    return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_ds);
+}
+
+static bool trans_FCVT_sd(DisasContext *s, arg_rpr_esz *a, uint32_t insn)
+{
+    return do_zpz_ptr(s, a->rd, a->rn, a->pg, false, gen_helper_sve_fcvt_sd);
+}
+
 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);
diff --git a/target/arm/sve.decode b/target/arm/sve.decode
index e29c598783..fd45f51029 100644
--- a/target/arm/sve.decode
+++ b/target/arm/sve.decode
@@ -816,6 +816,14 @@ FNMLS_zpzzz     01100101 .. 1 ..... 111 ... ..... .....         @rdn_pg_rm_ra
 
 ### SVE FP Unary Operations Predicated Group
 
+# SVE floating-point convert precision
+FCVT_sh         01100101 10 0010 00 101 ... ..... .....         @rd_pg_rn_e0
+FCVT_hs         01100101 10 0010 01 101 ... ..... .....         @rd_pg_rn_e0
+FCVT_dh         01100101 11 0010 00 101 ... ..... .....         @rd_pg_rn_e0
+FCVT_hd         01100101 11 0010 01 101 ... ..... .....         @rd_pg_rn_e0
+FCVT_ds         01100101 11 0010 10 101 ... ..... .....         @rd_pg_rn_e0
+FCVT_sd         01100101 11 0010 11 101 ... ..... .....         @rd_pg_rn_e0
+
 # 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
-- 
2.17.1


Re: [Qemu-devel] [PATCH v5 23/35] target/arm: Implement SVE floating-point convert precision
Posted by Peter Maydell 7 years, 7 months ago
On 21 June 2018 at 02:53, Richard Henderson
<richard.henderson@linaro.org> wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/helper-sve.h    | 13 +++++++++++++
>  target/arm/sve_helper.c    | 27 +++++++++++++++++++++++++++
>  target/arm/translate-sve.c | 30 ++++++++++++++++++++++++++++++
>  target/arm/sve.decode      |  8 ++++++++
>  4 files changed, 78 insertions(+)

> +static inline float32 sve_f16_to_f32(float16 f, float_status *s)
> +{
> +    return float16_to_float32(f, true, s);
> +}
> +
> +static inline float64 sve_f16_to_f64(float16 f, float_status *s)
> +{
> +    return float16_to_float64(f, true, s);
> +}
> +
> +static inline float16 sve_f32_to_f16(float32 f, float_status *s)
> +{
> +    return float32_to_float16(f, true, s);
> +}
> +
> +static inline float16 sve_f64_to_f16(float64 f, float_status *s)
> +{
> +    return float64_to_float16(f, true, s);
> +}

A comment to the effect that the SVE fp-to-fp conversion
routines always use IEEE format halfprec (ie ignore FPCR.AHP)
would be helpful.

Are you sure we have the FPCR.FZ16 handling right here? That
is, do we need the same "use the not-fp16 fpstatus pointer,
and temporarily clear the flush flag for the fp16 end of
the conversion" behaviour that we have in vfp_fcvt_f16_to_f32
and friends ? The pseudocode FPConvertSVE() calls FPConvert(),
which is the "ignore FZ16" codepath I think. The test case would
be (eg) a conversion where the input f16 is denormal and
FPCR.FZ == 1: this should not do the flush-input-to-zero, right?

thanks
-- PMM

Re: [Qemu-devel] [PATCH v5 23/35] target/arm: Implement SVE floating-point convert precision
Posted by Richard Henderson 7 years, 7 months ago
On 06/26/2018 03:44 AM, Peter Maydell wrote:
> A comment to the effect that the SVE fp-to-fp conversion
> routines always use IEEE format halfprec (ie ignore FPCR.AHP)
> would be helpful.

Ok.

> Are you sure we have the FPCR.FZ16 handling right here? That
> is, do we need the same "use the not-fp16 fpstatus pointer,
> and temporarily clear the flush flag for the fp16 end of
> the conversion" behaviour that we have in vfp_fcvt_f16_to_f32
> and friends ? The pseudocode FPConvertSVE() calls FPConvert(),
> which is the "ignore FZ16" codepath I think. The test case would
> be (eg) a conversion where the input f16 is denormal and
> FPCR.FZ == 1: this should not do the flush-input-to-zero, right?

Yes, I read it the same way.  I guess both my and Alex's RISU
test cases didn't exercise this?


r~