[PATCH v3 4/7] target/hexagon: add GVec overrides for HVX absolute difference

Brian Cain <[email protected]>
Newsgroups gmane.comp.emulators.qemu
Message-ID <[email protected]>
Reviewed-by: Marco Liebel <[email protected]>
Signed-off-by: Brian Cain <[email protected]>
---
 target/hexagon/gen_tcg_hvx.h | 16 +++++++++
 target/hexagon/genptr.h      |  4 +++
 target/hexagon/helper.h      |  5 +++
 target/hexagon/genptr.c      | 70 ++++++++++++++++++++++++++++++++++++
 target/hexagon/op_helper.c   | 21 +++++++++++
 5 files changed, 116 insertions(+)

diff --git a/target/hexagon/gen_tcg_hvx.h b/target/hexagon/gen_tcg_hvx.h
index 7e5372a7642..cbf84a8caee 100644
--- a/target/hexagon/gen_tcg_hvx.h
+++ b/target/hexagon/gen_tcg_hvx.h
@@ -326,6 +326,22 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
     tcg_gen_gvec_mul(MO_16, VdV_off, VuV_off, VvV_off, \
                      VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
 
+#define fGEN_TCG_V6_vabsdiffub(SHORTCODE) \
+    gen_gvec_uabsdiff(MO_8, VdV_off, VuV_off, VvV_off, \
+                     VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+
+#define fGEN_TCG_V6_vabsdiffuh(SHORTCODE) \
+    gen_gvec_uabsdiff(MO_16, VdV_off, VuV_off, VvV_off, \
+                     VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+
+#define fGEN_TCG_V6_vabsdiffh(SHORTCODE) \
+    gen_gvec_sabsdiff(MO_16, VdV_off, VuV_off, VvV_off, \
+                     VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+
+#define fGEN_TCG_V6_vabsdiffw(SHORTCODE) \
+    gen_gvec_sabsdiff(MO_32, VdV_off, VuV_off, VvV_off, \
+                     VECTOR_SIZE_BYTE, VECTOR_SIZE_BYTE)
+
 /* Vector shift right - various forms */
 #define fGEN_TCG_V6_vasrh(SHORTCODE) \
     do { \
diff --git a/target/hexagon/genptr.h b/target/hexagon/genptr.h
index 45ee038ca94..172d5cff3af 100644
--- a/target/hexagon/genptr.h
+++ b/target/hexagon/genptr.h
@@ -58,6 +58,10 @@ TCGv gen_get_half(TCGv result, int N, TCGv src, bool sign);
 void gen_set_half(int N, TCGv result, TCGv src);
 void gen_set_half_i64(int N, TCGv_i64 result, TCGv src);
 void probe_noshuf_load(TCGv va, int s, int mi);
+void gen_gvec_sabsdiff(unsigned vece, uint32_t dofs, uint32_t aofs,
+                       uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
+void gen_gvec_uabsdiff(unsigned vece, uint32_t dofs, uint32_t aofs,
+                       uint32_t bofs, uint32_t oprsz, uint32_t maxsz);
 
 extern const target_ulong reg_immut_masks[TOTAL_PER_THREAD_REGS];
 
diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h
index 033e5619d6b..78dc28ca9e5 100644
--- a/target/hexagon/helper.h
+++ b/target/hexagon/helper.h
@@ -108,6 +108,11 @@ DEF_HELPER_2(probe_pkt_scalar_store_s0, void, env, int)
 DEF_HELPER_2(probe_hvx_stores, void, env, int)
 DEF_HELPER_2(probe_pkt_scalar_hvx_stores, void, env, int)
 
+DEF_HELPER_FLAGS_4(gvec_sabsdiff_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(gvec_sabsdiff_w, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(gvec_uabsdiff_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(gvec_uabsdiff_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
 #if !defined(CONFIG_USER_ONLY)
 DEF_HELPER_3(raise_stack_overflow, void, env, i32, i32)
 DEF_HELPER_2(swi, void, env, i32)
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 3f310377097..849c8b7c403 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -37,6 +37,76 @@
 
 #include "genptr.h"
 
+static void gen_sabsdiff_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
+{
+    TCGv_i32 t = tcg_temp_new_i32();
+
+    tcg_gen_sub_i32(t, a, b);
+    tcg_gen_sub_i32(d, b, a);
+    tcg_gen_movcond_i32(TCG_COND_LT, d, a, b, d, t);
+}
+
+static void gen_sabsdiff_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
+{
+    TCGv_vec t = tcg_temp_new_vec_matching(d);
+
+    tcg_gen_smin_vec(vece, t, a, b);
+    tcg_gen_smax_vec(vece, d, a, b);
+    tcg_gen_sub_vec(vece, d, d, t);
+}
+
+void gen_gvec_sabsdiff(unsigned vece, uint32_t dofs, uint32_t aofs,
+                       uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+    static const TCGOpcode vecop_list[] = {
+        INDEX_op_sub_vec, INDEX_op_smin_vec, INDEX_op_smax_vec, 0
+    };
+    static const GVecGen3 ops[4] = {
+        [MO_16] = { .fniv = gen_sabsdiff_vec,
+                    .fno = gen_helper_gvec_sabsdiff_h,
+                    .opt_opc = vecop_list,
+                    .vece = MO_16 },
+        [MO_32] = { .fni4 = gen_sabsdiff_i32,
+                    .fniv = gen_sabsdiff_vec,
+                    .fno = gen_helper_gvec_sabsdiff_w,
+                    .opt_opc = vecop_list,
+                    .vece = MO_32 },
+    };
+
+    tcg_debug_assert(vece == MO_16 || vece == MO_32);
+    tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &ops[vece]);
+}
+
+static void gen_uabsdiff_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
+{
+    TCGv_vec t = tcg_temp_new_vec_matching(d);
+
+    tcg_gen_umin_vec(vece, t, a, b);
+    tcg_gen_umax_vec(vece, d, a, b);
+    tcg_gen_sub_vec(vece, d, d, t);
+}
+
+void gen_gvec_uabsdiff(unsigned vece, uint32_t dofs, uint32_t aofs,
+                       uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
+{
+    static const TCGOpcode vecop_list[] = {
+        INDEX_op_sub_vec, INDEX_op_umin_vec, INDEX_op_umax_vec, 0
+    };
+    static const GVecGen3 ops[4] = {
+        [MO_8] = { .fniv = gen_uabsdiff_vec,
+                   .fno = gen_helper_gvec_uabsdiff_b,
+                   .opt_opc = vecop_list,
+                   .vece = MO_8 },
+        [MO_16] = { .fniv = gen_uabsdiff_vec,
+                    .fno = gen_helper_gvec_uabsdiff_h,
+                    .opt_opc = vecop_list,
+                    .vece = MO_16 },
+    };
+
+    tcg_debug_assert(vece == MO_8 || vece == MO_16);
+    tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &ops[vece]);
+}
+
 TCGv gen_read_reg(TCGv result, int num)
 {
     tcg_gen_mov_tl(result, hex_gpr[num]);
diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c
index 3ce223caba3..f0574dae5ad 100644
--- a/target/hexagon/op_helper.c
+++ b/target/hexagon/op_helper.c
@@ -35,6 +35,7 @@
 #include "mmvec/macros.h"
 #include "op_helper.h"
 #include "cpu_helper.h"
+#include "tcg/tcg-gvec-desc.h"
 #include "translate.h"
 #ifndef CONFIG_USER_ONLY
 #include "hw/hexagon/hexagon_globalreg.h"
@@ -1947,3 +1948,23 @@ void HELPER(pending_interrupt)(CPUHexagonState *env)
     printf("ERROR: bogus helper: " #tag "\n")
 
 #include "helper_funcs_generated.c.inc"
+
+#define DO_ABSDIFF(NAME, TYPE, UTYPE) \
+void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
+{ \
+    intptr_t i, oprsz = simd_oprsz(desc); \
+    UTYPE *d = vd; \
+    TYPE *n = vn, *m = vm; \
+    \
+    for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
+        d[i] = n[i] < m[i] ? (UTYPE)m[i] - (UTYPE)n[i] \
+                           : (UTYPE)n[i] - (UTYPE)m[i]; \
+    } \
+}
+
+DO_ABSDIFF(gvec_sabsdiff_h, int16_t, uint16_t)
+DO_ABSDIFF(gvec_sabsdiff_w, int32_t, uint32_t)
+DO_ABSDIFF(gvec_uabsdiff_b, uint8_t, uint8_t)
+DO_ABSDIFF(gvec_uabsdiff_h, uint16_t, uint16_t)
+
+#undef DO_ABSDIFF
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.