From: Marco Liebel <[email protected]> Add gvec helpers for halfword absolute difference and sign fill.
Signed-off-by: Marco Liebel <[email protected]> Reviewed-by: Brian Cain <[email protected]> Signed-off-by: Brian Cain <[email protected]> --- target/hexagon/helper.h | 9 +++++ target/hexagon/hlx_gvec_tables.h | 5 +++ target/hexagon/hlx_gvec_tables.c | 68 ++++++++++++++++++++++++++++++++ target/hexagon/hlx_helper.c | 39 ++++++++++++++++++ target/hexagon/hex_common.py | 10 +++++ 5 files changed, 131 insertions(+) diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h index f42cb8d9b6a..1ced8c56513 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/hlx_gvec_tables.h b/target/hexagon/hlx_gvec_tables.h index e01c853eb18..4375bf3ff84 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_gvec_tables.c b/target/hexagon/hlx_gvec_tables.c index a5d40e149c3..f1e36bd20b7 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_helper.c b/target/hexagon/hlx_helper.c index c624b66f83c..c063706cfac 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); + } +} diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py index 0e38f630ae7..adf739f8f53 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): -- 2.34.1
