Add gvec helpers for halfword absolute difference and sign fill.

Signed-off-by: Marco Liebel <[email protected]>
Signed-off-by: Brian Cain <[email protected]>
---
 target/hexagon/helper.h          |  9 +++++
 target/hexagon/hex_common.py     | 10 +++++
 target/hexagon/hlx_gvec_tables.c | 68 ++++++++++++++++++++++++++++++++
 target/hexagon/hlx_gvec_tables.h |  5 +++
 target/hexagon/hlx_helper.c      | 39 ++++++++++++++++++
 5 files changed, 131 insertions(+)

diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h
index f42cb8d9b6..1ced8c5651 100644
--- a/target/hexagon/helper.h
+++ b/target/hexagon/helper.h
@@ -54,6 +54,15 @@ DEF_HELPER_FLAGS_4(hlx_gvec_avg_uh16, TCG_CALL_NO_RWG,
 DEF_HELPER_FLAGS_4(hlx_gvec_avg_uh16_rnd, TCG_CALL_NO_RWG,
                    void, ptr, ptr, ptr, i32)
 
+/* GVec helpers for MO_16 absolute differences. */
+DEF_HELPER_FLAGS_4(hlx_gvec_absdiff_sh16, TCG_CALL_NO_RWG,
+                   void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(hlx_gvec_absdiff_uh16, TCG_CALL_NO_RWG,
+                   void, ptr, ptr, ptr, i32)
+
+/* GVec helper for a halfword arithmetic shift by 15. */
+DEF_HELPER_FLAGS_3(hlx_gvec_sari15_h16, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+
 /* Floating point */
 DEF_HELPER_3(conv_sf2df, f64, env, f32, i32)
 DEF_HELPER_3(conv_df2sf, f32, env, f64, i32)
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index d0b36b8e06..fc6f69b411 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -404,6 +404,16 @@ def skip_qemu_helper(tag):
                          "vece": "MO_16"},
     "LX_avg_uh_rnd":    {"op": "gvec3", "table": "hlx_avg_uh_rnd_op",
                          "vece": "MO_16"},
+    "LX_absdiff_h":     {"op": "gvec3", "table": "hlx_absdiff_sh_op",
+                         "vece": "MO_16"},
+    "LX_absdiff_uh":    {"op": "gvec3", "table": "hlx_absdiff_uh_op",
+                         "vece": "MO_16"},
+
+    # These use one source register, not a pair destination.
+    "LX_conv_uw_uh":    {"op": "conv_h_to_w_pair", "sign_extend": False,
+                         "vece": "MO_16"},
+    "LX_conv_w_h":      {"op": "conv_h_to_w_pair", "sign_extend": True,
+                         "vece": "MO_16", "table": "hlx_sari15_h_op"},
 }
 
 def is_hlx_inline_tag(tag):
diff --git a/target/hexagon/hlx_gvec_tables.c b/target/hexagon/hlx_gvec_tables.c
index a5d40e149c..f1e36bd20b 100644
--- a/target/hexagon/hlx_gvec_tables.c
+++ b/target/hexagon/hlx_gvec_tables.c
@@ -216,3 +216,71 @@ const GVecGen3 hlx_avg_uh_rnd_op = {
     .fno     = gen_helper_hlx_gvec_avg_uh16_rnd,
     .vece    = MO_16,
 };
+
+/* Halfword absolute difference as uint16_t. */
+static void hlx_fniv_absdiff_sh(unsigned vece, TCGv_vec r,
+                                 TCGv_vec a, TCGv_vec b)
+{
+    TCGv_vec mx = tcg_temp_new_vec_matching(r);
+    TCGv_vec mn = tcg_temp_new_vec_matching(r);
+    tcg_gen_smax_vec(vece, mx, a, b);
+    tcg_gen_smin_vec(vece, mn, a, b);
+    tcg_gen_sub_vec(vece, r, mx, mn);
+}
+
+static void hlx_fniv_absdiff_uh(unsigned vece, TCGv_vec r,
+                                 TCGv_vec a, TCGv_vec b)
+{
+    TCGv_vec mx = tcg_temp_new_vec_matching(r);
+    TCGv_vec mn = tcg_temp_new_vec_matching(r);
+    tcg_gen_umax_vec(vece, mx, a, b);
+    tcg_gen_umin_vec(vece, mn, a, b);
+    tcg_gen_sub_vec(vece, r, mx, mn);
+}
+
+static const TCGOpcode hlx_vecop_absdiff_sh[] = {
+    INDEX_op_smax_vec,
+    INDEX_op_smin_vec,
+    INDEX_op_sub_vec,
+    0
+};
+
+static const TCGOpcode hlx_vecop_absdiff_uh[] = {
+    INDEX_op_umax_vec,
+    INDEX_op_umin_vec,
+    INDEX_op_sub_vec,
+    0
+};
+
+const GVecGen3 hlx_absdiff_sh_op = {
+    .fniv    = hlx_fniv_absdiff_sh,
+    .opt_opc = hlx_vecop_absdiff_sh,
+    .fno     = gen_helper_hlx_gvec_absdiff_sh16,
+    .vece    = MO_16,
+};
+
+const GVecGen3 hlx_absdiff_uh_op = {
+    .fniv    = hlx_fniv_absdiff_uh,
+    .opt_opc = hlx_vecop_absdiff_uh,
+    .fno     = gen_helper_hlx_gvec_absdiff_uh16,
+    .vece    = MO_16,
+};
+
+/* Fill LX_conv_w_h's high register with sign bits. */
+
+static void hlx_fniv_sari15_h(unsigned vece, TCGv_vec r, TCGv_vec a)
+{
+    tcg_gen_sari_vec(vece, r, a, 15);
+}
+
+static const TCGOpcode hlx_vecop_sari15_h[] = {
+    INDEX_op_sari_vec,
+    0
+};
+
+const GVecGen2 hlx_sari15_h_op = {
+    .fniv    = hlx_fniv_sari15_h,
+    .opt_opc = hlx_vecop_sari15_h,
+    .fno     = gen_helper_hlx_gvec_sari15_h16,
+    .vece    = MO_16,
+};
diff --git a/target/hexagon/hlx_gvec_tables.h b/target/hexagon/hlx_gvec_tables.h
index e01c853eb1..4375bf3ff8 100644
--- a/target/hexagon/hlx_gvec_tables.h
+++ b/target/hexagon/hlx_gvec_tables.h
@@ -17,4 +17,9 @@ extern const GVecGen3 hlx_avg_sh_rnd_op;
 extern const GVecGen3 hlx_avg_uh_op;
 extern const GVecGen3 hlx_avg_uh_rnd_op;
 
+extern const GVecGen3 hlx_absdiff_sh_op;
+extern const GVecGen3 hlx_absdiff_uh_op;
+
+extern const GVecGen2 hlx_sari15_h_op;
+
 #endif /* HLX_GVEC_TABLES_H */
diff --git a/target/hexagon/hlx_helper.c b/target/hexagon/hlx_helper.c
index c624b66f83..c063706cfa 100644
--- a/target/hexagon/hlx_helper.c
+++ b/target/hexagon/hlx_helper.c
@@ -195,3 +195,42 @@ void HELPER(hlx_gvec_avg_uh16_rnd)(void *d, void *a, void 
*b, uint32_t desc)
         *(uint16_t *)((char *)d + i) = r;
     }
 }
+
+void HELPER(hlx_gvec_absdiff_sh16)(void *d, void *a, void *b, uint32_t desc)
+{
+    intptr_t oprsz = simd_oprsz(desc);
+    intptr_t i;
+
+    for (i = 0; i < oprsz; i += sizeof(int16_t)) {
+        int16_t av = *(int16_t *)((char *)a + i);
+        int16_t bv = *(int16_t *)((char *)b + i);
+        int16_t mx = (av > bv) ? av : bv;
+        int16_t mn = (av > bv) ? bv : av;
+        *(uint16_t *)((char *)d + i) = (uint16_t)(mx - mn);
+    }
+}
+
+void HELPER(hlx_gvec_absdiff_uh16)(void *d, void *a, void *b, uint32_t desc)
+{
+    intptr_t oprsz = simd_oprsz(desc);
+    intptr_t i;
+
+    for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
+        uint16_t av = *(uint16_t *)((char *)a + i);
+        uint16_t bv = *(uint16_t *)((char *)b + i);
+        uint16_t mx = (av > bv) ? av : bv;
+        uint16_t mn = (av > bv) ? bv : av;
+        *(uint16_t *)((char *)d + i) = mx - mn;
+    }
+}
+
+void HELPER(hlx_gvec_sari15_h16)(void *d, void *a, uint32_t desc)
+{
+    intptr_t oprsz = simd_oprsz(desc);
+    intptr_t i;
+
+    for (i = 0; i < oprsz; i += sizeof(int16_t)) {
+        int16_t av = *(int16_t *)((char *)a + i);
+        *(uint16_t *)((char *)d + i) = (uint16_t)(av >> 15);
+    }
+}
-- 
2.43.0


Reply via email to