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