diff mbox series

[48/65] target/riscv: Add widening floating-point/integer type-convert instructions for XTheadVector

Message ID 20240412073735.76413-49-eric.huang@linux.alibaba.com
State New
Headers show
Series target/riscv: Support XTheadVector extension | expand

Commit Message

Huang Tao April 12, 2024, 7:37 a.m. UTC
Compared to RVV1.0, XTheadVector lacks .rtz instructions, which specify the
rounding mode of rounding to zero.
Except of lack of similar instructions, the instructions have the same function
as RVV1.0. Overall there are only general differences between XTheadVector and RVV1.0.

Signed-off-by: Huang Tao <eric.huang@linux.alibaba.com>
---
 target/riscv/helper.h                         | 13 +++
 .../riscv/insn_trans/trans_xtheadvector.c.inc | 93 ++++++++++++++++++-
 target/riscv/vector_helper.c                  |  5 +-
 target/riscv/vector_internals.h               |  3 +
 target/riscv/xtheadvector_helper.c            | 44 +++++++++
 5 files changed, 149 insertions(+), 9 deletions(-)
diff mbox series

Patch

diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 18640c4a1e..e2d737c9c4 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -2210,3 +2210,16 @@  DEF_HELPER_5(th_vfcvt_f_xu_v_d, void, ptr, ptr, ptr, env, i32)
 DEF_HELPER_5(th_vfcvt_f_x_v_h, void, ptr, ptr, ptr, env, i32)
 DEF_HELPER_5(th_vfcvt_f_x_v_w, void, ptr, ptr, ptr, env, i32)
 DEF_HELPER_5(th_vfcvt_f_x_v_d, void, ptr, ptr, ptr, env, i32)
+
+DEF_HELPER_5(th_vfwcvt_xu_f_v_h, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(th_vfwcvt_xu_f_v_w, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(th_vfwcvt_x_f_v_h, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(th_vfwcvt_x_f_v_w, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(th_vfwcvt_f_xu_v_b, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(th_vfwcvt_f_xu_v_h, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(th_vfwcvt_f_xu_v_w, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(th_vfwcvt_f_x_v_b, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(th_vfwcvt_f_x_v_h, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(th_vfwcvt_f_x_v_w, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(th_vfwcvt_f_f_v_h, void, ptr, ptr, ptr, env, i32)
+DEF_HELPER_5(th_vfwcvt_f_f_v_w, void, ptr, ptr, ptr, env, i32)
diff --git a/target/riscv/insn_trans/trans_xtheadvector.c.inc b/target/riscv/insn_trans/trans_xtheadvector.c.inc
index 27a06c2cac..72643facb1 100644
--- a/target/riscv/insn_trans/trans_xtheadvector.c.inc
+++ b/target/riscv/insn_trans/trans_xtheadvector.c.inc
@@ -2197,17 +2197,100 @@  GEN_OPFV_TRANS_TH(th_vfcvt_x_f_v, opfv_check_th)
 GEN_OPFV_TRANS_TH(th_vfcvt_f_xu_v, opfv_check_th)
 GEN_OPFV_TRANS_TH(th_vfcvt_f_x_v, opfv_check_th)
 
+/* Widening Floating-Point/Integer Type-Convert Instructions */
+
+/*
+ * If the current SEW does not correspond to a supported IEEE floating-point
+ * type, an illegal instruction exception is raised
+ */
+static bool opfv_widen_check_th(DisasContext *s, arg_rmr *a)
+{
+    return (require_xtheadvector(s) &&
+            vext_check_isa_ill(s) &&
+            th_check_overlap_mask(s, a->rd, a->vm, true) &&
+            th_check_reg(s, a->rd, true) &&
+            th_check_reg(s, a->rs2, false) &&
+            th_check_overlap_group(a->rd, 2 << s->lmul, a->rs2,
+                                   1 << s->lmul) &&
+            (s->lmul < 0x3) && (s->sew < 0x3) && (s->sew != 0));
+}
+
+static bool opfxv_widen_check_th(DisasContext *s, arg_rmr *a)
+{
+    return (require_xtheadvector(s) &&
+            vext_check_isa_ill(s) &&
+            th_check_overlap_mask(s, a->rd, a->vm, true) &&
+            th_check_reg(s, a->rd, true) &&
+            th_check_reg(s, a->rs2, false) &&
+            th_check_overlap_group(a->rd, 2 << s->lmul, a->rs2,
+                                   1 << s->lmul) &&
+            (s->lmul < 0x3) && (s->sew < 0x3));
+}
+
+#define GEN_OPFXV_WIDEN_TRANS_TH(NAME)                             \
+static bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
+{                                                                  \
+    if (opfxv_widen_check_th(s, a)) {                              \
+        uint32_t data = 0;                                         \
+        static gen_helper_gvec_3_ptr * const fns[3] = {            \
+            gen_helper_##NAME##_b,                                 \
+            gen_helper_##NAME##_h,                                 \
+            gen_helper_##NAME##_w,                                 \
+        };                                                         \
+        gen_set_rm(s, RISCV_FRM_DYN);                              \
+                                                                   \
+        data = FIELD_DP32(data, VDATA_TH, MLEN, s->mlen);          \
+        data = FIELD_DP32(data, VDATA_TH, VM, a->vm);              \
+        data = FIELD_DP32(data, VDATA_TH, LMUL, s->lmul);          \
+        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd),                     \
+                           vreg_ofs(s, 0),                         \
+                           vreg_ofs(s, a->rs2), tcg_env,           \
+                           s->cfg_ptr->vlenb,                      \
+                           s->cfg_ptr->vlenb, data,                \
+                           fns[s->sew]);                           \
+        finalize_rvv_inst(s);                                      \
+        return true;                                               \
+    }                                                              \
+    return false;                                                  \
+}
+GEN_OPFXV_WIDEN_TRANS_TH(th_vfwcvt_f_xu_v)
+GEN_OPFXV_WIDEN_TRANS_TH(th_vfwcvt_f_x_v)
+
+#define GEN_OPFV_WIDEN_TRANS_TH(NAME)                              \
+static bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
+{                                                                  \
+    if (opfv_widen_check_th(s, a)) {                               \
+        uint32_t data = 0;                                         \
+        static gen_helper_gvec_3_ptr * const fns[2] = {            \
+            gen_helper_##NAME##_h,                                 \
+            gen_helper_##NAME##_w,                                 \
+        };                                                         \
+        gen_set_rm(s, RISCV_FRM_DYN);                              \
+                                                                   \
+        data = FIELD_DP32(data, VDATA_TH, MLEN, s->mlen);          \
+        data = FIELD_DP32(data, VDATA_TH, VM, a->vm);              \
+        data = FIELD_DP32(data, VDATA_TH, LMUL, s->lmul);          \
+        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd),                     \
+                           vreg_ofs(s, 0),                         \
+                           vreg_ofs(s, a->rs2), tcg_env,           \
+                           s->cfg_ptr->vlenb,                      \
+                           s->cfg_ptr->vlenb, data,                \
+                           fns[s->sew - 1]);                       \
+        finalize_rvv_inst(s);                                      \
+        return true;                                               \
+    }                                                              \
+    return false;                                                  \
+}
+GEN_OPFV_WIDEN_TRANS_TH(th_vfwcvt_xu_f_v)
+GEN_OPFV_WIDEN_TRANS_TH(th_vfwcvt_x_f_v)
+GEN_OPFV_WIDEN_TRANS_TH(th_vfwcvt_f_f_v)
+
 #define TH_TRANS_STUB(NAME)                                \
 static bool trans_##NAME(DisasContext *s, arg_##NAME *a)   \
 {                                                          \
     return require_xtheadvector(s);                        \
 }
 
-TH_TRANS_STUB(th_vfwcvt_xu_f_v)
-TH_TRANS_STUB(th_vfwcvt_x_f_v)
-TH_TRANS_STUB(th_vfwcvt_f_xu_v)
-TH_TRANS_STUB(th_vfwcvt_f_x_v)
-TH_TRANS_STUB(th_vfwcvt_f_f_v)
 TH_TRANS_STUB(th_vfncvt_xu_f_v)
 TH_TRANS_STUB(th_vfncvt_x_f_v)
 TH_TRANS_STUB(th_vfncvt_f_xu_v)
diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index c966600d0c..105c2eb00a 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -4265,10 +4265,7 @@  GEN_VEXT_V_ENV(vfcvt_f_x_v_w, 4)
 GEN_VEXT_V_ENV(vfcvt_f_x_v_d, 8)
 
 /* Widening Floating-Point/Integer Type-Convert Instructions */
-/* (TD, T2, TX2) */
-#define WOP_UU_B uint16_t, uint8_t,  uint8_t
-#define WOP_UU_H uint32_t, uint16_t, uint16_t
-#define WOP_UU_W uint64_t, uint32_t, uint32_t
+
 /*
  * vfwcvt.xu.f.v vd, vs2, vm # Convert float to double-width unsigned integer.
  */
diff --git a/target/riscv/vector_internals.h b/target/riscv/vector_internals.h
index b870e15392..aac96f830c 100644
--- a/target/riscv/vector_internals.h
+++ b/target/riscv/vector_internals.h
@@ -132,6 +132,9 @@  void vext_set_elems_1s(void *base, uint32_t is_agnostic, uint32_t cnt,
 #define OP_UU_H uint16_t, uint16_t, uint16_t
 #define OP_UU_W uint32_t, uint32_t, uint32_t
 #define OP_UU_D uint64_t, uint64_t, uint64_t
+#define WOP_UU_B uint16_t, uint8_t,  uint8_t
+#define WOP_UU_H uint32_t, uint16_t, uint16_t
+#define WOP_UU_W uint64_t, uint32_t, uint32_t
 
 /* (TD, T1, T2, TX1, TX2) */
 #define OP_UUU_B uint8_t, uint8_t, uint8_t, uint8_t, uint8_t
diff --git a/target/riscv/xtheadvector_helper.c b/target/riscv/xtheadvector_helper.c
index 7e98c1ead2..42328a8a58 100644
--- a/target/riscv/xtheadvector_helper.c
+++ b/target/riscv/xtheadvector_helper.c
@@ -3238,3 +3238,47 @@  THCALL(TH_OPFVV1, th_vfcvt_f_x_v_d, OP_UU_D, H8, H8, int64_to_float64)
 GEN_TH_V_ENV(th_vfcvt_f_x_v_h, 2, 2, clearh_th)
 GEN_TH_V_ENV(th_vfcvt_f_x_v_w, 4, 4, clearl_th)
 GEN_TH_V_ENV(th_vfcvt_f_x_v_d, 8, 8, clearq_th)
+
+/* Widening Floating-Point/Integer Type-Convert Instructions */
+
+/* vfwcvt.xu.f.v vd, vs2, vm # Convert float to double-width unsigned integer.*/
+THCALL(TH_OPFVV1, th_vfwcvt_xu_f_v_h, WOP_UU_H, H4, H2, float16_to_uint32)
+THCALL(TH_OPFVV1, th_vfwcvt_xu_f_v_w, WOP_UU_W, H8, H4, float32_to_uint64)
+GEN_TH_V_ENV(th_vfwcvt_xu_f_v_h, 2, 4, clearl_th)
+GEN_TH_V_ENV(th_vfwcvt_xu_f_v_w, 4, 8, clearq_th)
+
+/* vfwcvt.x.f.v vd, vs2, vm # Convert float to double-width signed integer. */
+THCALL(TH_OPFVV1, th_vfwcvt_x_f_v_h, WOP_UU_H, H4, H2, float16_to_int32)
+THCALL(TH_OPFVV1, th_vfwcvt_x_f_v_w, WOP_UU_W, H8, H4, float32_to_int64)
+GEN_TH_V_ENV(th_vfwcvt_x_f_v_h, 2, 4, clearl_th)
+GEN_TH_V_ENV(th_vfwcvt_x_f_v_w, 4, 8, clearq_th)
+
+/* vfwcvt.f.xu.v vd, vs2, vm # Convert unsigned integer to double-width float */
+THCALL(TH_OPFVV1, th_vfwcvt_f_xu_v_b, WOP_UU_B, H2, H1, uint8_to_float16)
+THCALL(TH_OPFVV1, th_vfwcvt_f_xu_v_h, WOP_UU_H, H4, H2, uint16_to_float32)
+THCALL(TH_OPFVV1, th_vfwcvt_f_xu_v_w, WOP_UU_W, H8, H4, uint32_to_float64)
+GEN_TH_V_ENV(th_vfwcvt_f_xu_v_b, 1, 2, clearh_th)
+GEN_TH_V_ENV(th_vfwcvt_f_xu_v_h, 2, 4, clearl_th)
+GEN_TH_V_ENV(th_vfwcvt_f_xu_v_w, 4, 8, clearq_th)
+
+/* vfwcvt.f.x.v vd, vs2, vm # Convert integer to double-width float. */
+THCALL(TH_OPFVV1, th_vfwcvt_f_x_v_b, WOP_UU_B, H2, H1, int8_to_float16)
+THCALL(TH_OPFVV1, th_vfwcvt_f_x_v_h, WOP_UU_H, H4, H2, int16_to_float32)
+THCALL(TH_OPFVV1, th_vfwcvt_f_x_v_w, WOP_UU_W, H8, H4, int32_to_float64)
+GEN_TH_V_ENV(th_vfwcvt_f_x_v_b, 1, 2, clearh_th)
+GEN_TH_V_ENV(th_vfwcvt_f_x_v_h, 2, 4, clearl_th)
+GEN_TH_V_ENV(th_vfwcvt_f_x_v_w, 4, 8, clearq_th)
+
+/*
+ * vfwcvt.f.f.v vd, vs2, vm #
+ * Convert single-width float to double-width float.
+ */
+static uint32_t vfwcvtffv16(uint16_t a, float_status *s)
+{
+    return float16_to_float32(a, true, s);
+}
+
+THCALL(TH_OPFVV1, th_vfwcvt_f_f_v_h, WOP_UU_H, H4, H2, vfwcvtffv16)
+THCALL(TH_OPFVV1, th_vfwcvt_f_f_v_w, WOP_UU_W, H8, H4, float32_to_float64)
+GEN_TH_V_ENV(th_vfwcvt_f_f_v_h, 2, 4, clearl_th)
+GEN_TH_V_ENV(th_vfwcvt_f_f_v_w, 4, 8, clearq_th)