Add halfword greater-than compares and out-of-line helpers for truncating and rounding halfword averages.
Signed-off-by: Marco Liebel <[email protected]> Signed-off-by: Brian Cain <[email protected]> --- target/hexagon/helper.h | 10 +++ target/hexagon/hex_common.py | 16 +++++ target/hexagon/hlx_gvec_tables.c | 105 +++++++++++++++++++++++++++++++ target/hexagon/hlx_gvec_tables.h | 5 ++ target/hexagon/hlx_helper.c | 52 +++++++++++++++ 5 files changed, 188 insertions(+) diff --git a/target/hexagon/helper.h b/target/hexagon/helper.h index 471ef0903b..f42cb8d9b6 100644 --- a/target/hexagon/helper.h +++ b/target/hexagon/helper.h @@ -44,6 +44,16 @@ DEF_HELPER_FLAGS_4(hlx_gvec_ushsat_sub16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_3(hlx_gvec_abs_uh_sat16, TCG_CALL_NO_RWG, void, ptr, ptr, i32) +/* GVec helpers for MO_16 averages. */ +DEF_HELPER_FLAGS_4(hlx_gvec_avg_sh16, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(hlx_gvec_avg_sh16_rnd, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(hlx_gvec_avg_uh16, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(hlx_gvec_avg_uh16_rnd, TCG_CALL_NO_RWG, + void, ptr, 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 3f4d796a98..d0b36b8e06 100755 --- a/target/hexagon/hex_common.py +++ b/target/hexagon/hex_common.py @@ -388,6 +388,22 @@ def skip_qemu_helper(tag): "vece": "MO_16", "size": "2 * sizeof(HLXVector)"}, "LX_abs_uh_sat": {"op": "gvec2", "table": "hlx_abs_uh_sat_op", "vece": "MO_16"}, + "LX_cmp_gt_h": {"op": "cmp", "cond": "TCG_COND_GT", + "vece": "MO_16"}, + "LX_cmp_gt_uh": {"op": "cmp", "cond": "TCG_COND_GTU", + "vece": "MO_16"}, + "LX_cmp_gt_hp": {"op": "cmp", "cond": "TCG_COND_GT", + "vece": "MO_16", "size": "2 * sizeof(HLXVector)"}, + "LX_cmp_gt_uhp": {"op": "cmp", "cond": "TCG_COND_GTU", + "vece": "MO_16", "size": "2 * sizeof(HLXVector)"}, + "LX_avg_h": {"op": "gvec3", "table": "hlx_avg_sh_op", + "vece": "MO_16"}, + "LX_avg_h_rnd": {"op": "gvec3", "table": "hlx_avg_sh_rnd_op", + "vece": "MO_16"}, + "LX_avg_uh": {"op": "gvec3", "table": "hlx_avg_uh_op", + "vece": "MO_16"}, + "LX_avg_uh_rnd": {"op": "gvec3", "table": "hlx_avg_uh_rnd_op", + "vece": "MO_16"}, } def is_hlx_inline_tag(tag): diff --git a/target/hexagon/hlx_gvec_tables.c b/target/hexagon/hlx_gvec_tables.c index dd5aa788e0..a5d40e149c 100644 --- a/target/hexagon/hlx_gvec_tables.c +++ b/target/hexagon/hlx_gvec_tables.c @@ -111,3 +111,108 @@ const GVecGen2 hlx_abs_uh_sat_op = { .fno = gen_helper_hlx_gvec_abs_uh_sat16, .vece = MO_16, }; + +/* Halfword averages. The shift is arithmetic or logical by signedness. */ +static void hlx_fniv_avg_sh(unsigned vece, TCGv_vec r, + TCGv_vec a, TCGv_vec b) +{ + TCGv_vec ta = tcg_temp_new_vec_matching(r); + TCGv_vec tb = tcg_temp_new_vec_matching(r); + tcg_gen_and_vec(vece, ta, a, b); + tcg_gen_xor_vec(vece, tb, a, b); + tcg_gen_sari_vec(vece, tb, tb, 1); + tcg_gen_add_vec(vece, r, ta, tb); +} + +static void hlx_fniv_avg_sh_rnd(unsigned vece, TCGv_vec r, + TCGv_vec a, TCGv_vec b) +{ + TCGv_vec ta = tcg_temp_new_vec_matching(r); + TCGv_vec tb = tcg_temp_new_vec_matching(r); + tcg_gen_or_vec(vece, ta, a, b); + tcg_gen_xor_vec(vece, tb, a, b); + tcg_gen_sari_vec(vece, tb, tb, 1); + tcg_gen_sub_vec(vece, r, ta, tb); +} + +static void hlx_fniv_avg_uh(unsigned vece, TCGv_vec r, + TCGv_vec a, TCGv_vec b) +{ + TCGv_vec ta = tcg_temp_new_vec_matching(r); + TCGv_vec tb = tcg_temp_new_vec_matching(r); + tcg_gen_and_vec(vece, ta, a, b); + tcg_gen_xor_vec(vece, tb, a, b); + tcg_gen_shri_vec(vece, tb, tb, 1); + tcg_gen_add_vec(vece, r, ta, tb); +} + +static void hlx_fniv_avg_uh_rnd(unsigned vece, TCGv_vec r, + TCGv_vec a, TCGv_vec b) +{ + TCGv_vec ta = tcg_temp_new_vec_matching(r); + TCGv_vec tb = tcg_temp_new_vec_matching(r); + tcg_gen_or_vec(vece, ta, a, b); + tcg_gen_xor_vec(vece, tb, a, b); + tcg_gen_shri_vec(vece, tb, tb, 1); + tcg_gen_sub_vec(vece, r, ta, tb); +} + +static const TCGOpcode hlx_vecop_avg_sh[] = { + INDEX_op_and_vec, + INDEX_op_xor_vec, + INDEX_op_sari_vec, + INDEX_op_add_vec, + 0 +}; + +static const TCGOpcode hlx_vecop_avg_sh_rnd[] = { + INDEX_op_or_vec, + INDEX_op_xor_vec, + INDEX_op_sari_vec, + INDEX_op_sub_vec, + 0 +}; + +static const TCGOpcode hlx_vecop_avg_uh[] = { + INDEX_op_and_vec, + INDEX_op_xor_vec, + INDEX_op_shri_vec, + INDEX_op_add_vec, + 0 +}; + +static const TCGOpcode hlx_vecop_avg_uh_rnd[] = { + INDEX_op_or_vec, + INDEX_op_xor_vec, + INDEX_op_shri_vec, + INDEX_op_sub_vec, + 0 +}; + +const GVecGen3 hlx_avg_sh_op = { + .fniv = hlx_fniv_avg_sh, + .opt_opc = hlx_vecop_avg_sh, + .fno = gen_helper_hlx_gvec_avg_sh16, + .vece = MO_16, +}; + +const GVecGen3 hlx_avg_sh_rnd_op = { + .fniv = hlx_fniv_avg_sh_rnd, + .opt_opc = hlx_vecop_avg_sh_rnd, + .fno = gen_helper_hlx_gvec_avg_sh16_rnd, + .vece = MO_16, +}; + +const GVecGen3 hlx_avg_uh_op = { + .fniv = hlx_fniv_avg_uh, + .opt_opc = hlx_vecop_avg_uh, + .fno = gen_helper_hlx_gvec_avg_uh16, + .vece = MO_16, +}; + +const GVecGen3 hlx_avg_uh_rnd_op = { + .fniv = hlx_fniv_avg_uh_rnd, + .opt_opc = hlx_vecop_avg_uh_rnd, + .fno = gen_helper_hlx_gvec_avg_uh16_rnd, + .vece = MO_16, +}; diff --git a/target/hexagon/hlx_gvec_tables.h b/target/hexagon/hlx_gvec_tables.h index 55ab6bb63f..e01c853eb1 100644 --- a/target/hexagon/hlx_gvec_tables.h +++ b/target/hexagon/hlx_gvec_tables.h @@ -12,4 +12,9 @@ extern const GVecGen3 hlx_ushsat_add_op; extern const GVecGen3 hlx_ushsat_sub_op; extern const GVecGen2 hlx_abs_uh_sat_op; +extern const GVecGen3 hlx_avg_sh_op; +extern const GVecGen3 hlx_avg_sh_rnd_op; +extern const GVecGen3 hlx_avg_uh_op; +extern const GVecGen3 hlx_avg_uh_rnd_op; + #endif /* HLX_GVEC_TABLES_H */ diff --git a/target/hexagon/hlx_helper.c b/target/hexagon/hlx_helper.c index 906f31ba17..c624b66f83 100644 --- a/target/hexagon/hlx_helper.c +++ b/target/hexagon/hlx_helper.c @@ -143,3 +143,55 @@ void HELPER(hlx_gvec_abs_uh_sat16)(void *d, void *a, uint32_t desc) *(int16_t *)((char *)d + i) = (int16_t)r; } } + +void HELPER(hlx_gvec_avg_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 r = (int16_t)((av & bv) + ((av ^ bv) >> 1)); + *(int16_t *)((char *)d + i) = r; + } +} + +void HELPER(hlx_gvec_avg_sh16_rnd)(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 r = (int16_t)((av | bv) - ((av ^ bv) >> 1)); + *(int16_t *)((char *)d + i) = r; + } +} + +void HELPER(hlx_gvec_avg_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 r = (uint16_t)((av & bv) + ((av ^ bv) >> 1)); + *(uint16_t *)((char *)d + i) = r; + } +} + +void HELPER(hlx_gvec_avg_uh16_rnd)(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 r = (uint16_t)((av | bv) - ((av ^ bv) >> 1)); + *(uint16_t *)((char *)d + i) = r; + } +} -- 2.43.0
