diff --git a/qemu/aarch64.h b/qemu/aarch64.h index b1fc0bcf..35d7bc62 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -3247,20 +3247,6 @@ #define helper_advsimd_rinth_exact helper_advsimd_rinth_exact_aarch64 #define helper_advsimd_sub2h helper_advsimd_sub2h_aarch64 #define helper_advsimd_subh helper_advsimd_subh_aarch64 -#define helper_sve_brka_m helper_sve_brka_m_aarch64 -#define helper_sve_brkas_m helper_sve_brkas_m_aarch64 -#define helper_sve_brka_z helper_sve_brka_z_aarch64 -#define helper_sve_brkas_z helper_sve_brkas_z_aarch64 -#define helper_sve_brkb_m helper_sve_brkb_m_aarch64 -#define helper_sve_brkbs_m helper_sve_brkbs_m_aarch64 -#define helper_sve_brkb_z helper_sve_brkb_z_aarch64 -#define helper_sve_brkbs_z helper_sve_brkbs_z_aarch64 -#define helper_sve_brkn helper_sve_brkn_aarch64 -#define helper_sve_brkns helper_sve_brkns_aarch64 -#define helper_sve_brkpa helper_sve_brkpa_aarch64 -#define helper_sve_brkpas helper_sve_brkpas_aarch64 -#define helper_sve_brkpb helper_sve_brkpb_aarch64 -#define helper_sve_brkpbs helper_sve_brkpbs_aarch64 #define helper_casp_be_parallel helper_casp_be_parallel_aarch64 #define helper_casp_le_parallel helper_casp_le_parallel_aarch64 #define helper_crc32_64 helper_crc32_64_aarch64 @@ -3332,6 +3318,20 @@ #define helper_sve_bic_zpzz_d helper_sve_bic_zpzz_d_aarch64 #define helper_sve_bic_zpzz_h helper_sve_bic_zpzz_h_aarch64 #define helper_sve_bic_zpzz_s helper_sve_bic_zpzz_s_aarch64 +#define helper_sve_brka_m helper_sve_brka_m_aarch64 +#define helper_sve_brkas_m helper_sve_brkas_m_aarch64 +#define helper_sve_brka_z helper_sve_brka_z_aarch64 +#define helper_sve_brkas_z helper_sve_brkas_z_aarch64 +#define helper_sve_brkb_m helper_sve_brkb_m_aarch64 +#define helper_sve_brkbs_m helper_sve_brkbs_m_aarch64 +#define helper_sve_brkb_z helper_sve_brkb_z_aarch64 +#define helper_sve_brkbs_z helper_sve_brkbs_z_aarch64 +#define helper_sve_brkn helper_sve_brkn_aarch64 +#define helper_sve_brkns helper_sve_brkns_aarch64 +#define helper_sve_brkpa helper_sve_brkpa_aarch64 +#define helper_sve_brkpas helper_sve_brkpas_aarch64 +#define helper_sve_brkpb helper_sve_brkpb_aarch64 +#define helper_sve_brkpbs helper_sve_brkpbs_aarch64 #define helper_sve_clr_b helper_sve_clr_b_aarch64 #define helper_sve_clr_d helper_sve_clr_d_aarch64 #define helper_sve_clr_h helper_sve_clr_h_aarch64 @@ -3456,6 +3456,7 @@ #define helper_sve_cnt_zpz_d helper_sve_cnt_zpz_d_aarch64 #define helper_sve_cnt_zpz_h helper_sve_cnt_zpz_h_aarch64 #define helper_sve_cnt_zpz_s helper_sve_cnt_zpz_s_aarch64 +#define helper_sve_cntp helper_sve_cntp_aarch64 #define helper_sve_compact_d helper_sve_compact_d_aarch64 #define helper_sve_compact_s helper_sve_compact_s_aarch64 #define helper_sve_cpy_m_b helper_sve_cpy_m_b_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index abc39ae6..f49b8dc4 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -3247,20 +3247,6 @@ #define helper_advsimd_rinth_exact helper_advsimd_rinth_exact_aarch64eb #define helper_advsimd_sub2h helper_advsimd_sub2h_aarch64eb #define helper_advsimd_subh helper_advsimd_subh_aarch64eb -#define helper_sve_brka_m helper_sve_brka_m_aarch64eb -#define helper_sve_brkas_m helper_sve_brkas_m_aarch64eb -#define helper_sve_brka_z helper_sve_brka_z_aarch64eb -#define helper_sve_brkas_z helper_sve_brkas_z_aarch64eb -#define helper_sve_brkb_m helper_sve_brkb_m_aarch64eb -#define helper_sve_brkbs_m helper_sve_brkbs_m_aarch64eb -#define helper_sve_brkb_z helper_sve_brkb_z_aarch64eb -#define helper_sve_brkbs_z helper_sve_brkbs_z_aarch64eb -#define helper_sve_brkn helper_sve_brkn_aarch64eb -#define helper_sve_brkns helper_sve_brkns_aarch64eb -#define helper_sve_brkpa helper_sve_brkpa_aarch64eb -#define helper_sve_brkpas helper_sve_brkpas_aarch64eb -#define helper_sve_brkpb helper_sve_brkpb_aarch64eb -#define helper_sve_brkpbs helper_sve_brkpbs_aarch64eb #define helper_casp_be_parallel helper_casp_be_parallel_aarch64eb #define helper_casp_le_parallel helper_casp_le_parallel_aarch64eb #define helper_crc32_64 helper_crc32_64_aarch64eb @@ -3332,6 +3318,20 @@ #define helper_sve_bic_zpzz_d helper_sve_bic_zpzz_d_aarch64eb #define helper_sve_bic_zpzz_h helper_sve_bic_zpzz_h_aarch64eb #define helper_sve_bic_zpzz_s helper_sve_bic_zpzz_s_aarch64eb +#define helper_sve_brka_m helper_sve_brka_m_aarch64eb +#define helper_sve_brkas_m helper_sve_brkas_m_aarch64eb +#define helper_sve_brka_z helper_sve_brka_z_aarch64eb +#define helper_sve_brkas_z helper_sve_brkas_z_aarch64eb +#define helper_sve_brkb_m helper_sve_brkb_m_aarch64eb +#define helper_sve_brkbs_m helper_sve_brkbs_m_aarch64eb +#define helper_sve_brkb_z helper_sve_brkb_z_aarch64eb +#define helper_sve_brkbs_z helper_sve_brkbs_z_aarch64eb +#define helper_sve_brkn helper_sve_brkn_aarch64eb +#define helper_sve_brkns helper_sve_brkns_aarch64eb +#define helper_sve_brkpa helper_sve_brkpa_aarch64eb +#define helper_sve_brkpas helper_sve_brkpas_aarch64eb +#define helper_sve_brkpb helper_sve_brkpb_aarch64eb +#define helper_sve_brkpbs helper_sve_brkpbs_aarch64eb #define helper_sve_clr_b helper_sve_clr_b_aarch64eb #define helper_sve_clr_d helper_sve_clr_d_aarch64eb #define helper_sve_clr_h helper_sve_clr_h_aarch64eb @@ -3456,6 +3456,7 @@ #define helper_sve_cnt_zpz_d helper_sve_cnt_zpz_d_aarch64eb #define helper_sve_cnt_zpz_h helper_sve_cnt_zpz_h_aarch64eb #define helper_sve_cnt_zpz_s helper_sve_cnt_zpz_s_aarch64eb +#define helper_sve_cntp helper_sve_cntp_aarch64eb #define helper_sve_compact_d helper_sve_compact_d_aarch64eb #define helper_sve_compact_s helper_sve_compact_s_aarch64eb #define helper_sve_cpy_m_b helper_sve_cpy_m_b_aarch64eb diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 2c62b4b1..5d1cc9b6 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -3268,20 +3268,6 @@ aarch64_symbols = ( 'helper_advsimd_rinth_exact', 'helper_advsimd_sub2h', 'helper_advsimd_subh', - 'helper_sve_brka_m', - 'helper_sve_brkas_m', - 'helper_sve_brka_z', - 'helper_sve_brkas_z', - 'helper_sve_brkb_m', - 'helper_sve_brkbs_m', - 'helper_sve_brkb_z', - 'helper_sve_brkbs_z', - 'helper_sve_brkn', - 'helper_sve_brkns', - 'helper_sve_brkpa', - 'helper_sve_brkpas', - 'helper_sve_brkpb', - 'helper_sve_brkpbs', 'helper_casp_be_parallel', 'helper_casp_le_parallel', 'helper_crc32_64', @@ -3353,6 +3339,20 @@ aarch64_symbols = ( 'helper_sve_bic_zpzz_d', 'helper_sve_bic_zpzz_h', 'helper_sve_bic_zpzz_s', + 'helper_sve_brka_m', + 'helper_sve_brkas_m', + 'helper_sve_brka_z', + 'helper_sve_brkas_z', + 'helper_sve_brkb_m', + 'helper_sve_brkbs_m', + 'helper_sve_brkb_z', + 'helper_sve_brkbs_z', + 'helper_sve_brkn', + 'helper_sve_brkns', + 'helper_sve_brkpa', + 'helper_sve_brkpas', + 'helper_sve_brkpb', + 'helper_sve_brkpbs', 'helper_sve_clr_b', 'helper_sve_clr_d', 'helper_sve_clr_h', @@ -3477,6 +3477,7 @@ aarch64_symbols = ( 'helper_sve_cnt_zpz_d', 'helper_sve_cnt_zpz_h', 'helper_sve_cnt_zpz_s', + 'helper_sve_cntp', 'helper_sve_compact_d', 'helper_sve_compact_s', 'helper_sve_cpy_m_b', diff --git a/qemu/target/arm/helper-sve.h b/qemu/target/arm/helper-sve.h index f0a3ed34..dd4f8f75 100644 --- a/qemu/target/arm/helper-sve.h +++ b/qemu/target/arm/helper-sve.h @@ -676,3 +676,5 @@ DEF_HELPER_FLAGS_4(sve_brkbs_m, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(sve_brkn, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(sve_brkns, TCG_CALL_NO_RWG, i32, ptr, ptr, ptr, i32) + +DEF_HELPER_FLAGS_3(sve_cntp, TCG_CALL_NO_RWG, i64, ptr, ptr, i32) diff --git a/qemu/target/arm/sve.decode b/qemu/target/arm/sve.decode index 5e836251..b4e20b24 100644 --- a/qemu/target/arm/sve.decode +++ b/qemu/target/arm/sve.decode @@ -67,6 +67,8 @@ &ptrue rd esz pat s &incdec_cnt rd pat esz imm d u &incdec2_cnt rd rn pat esz imm d u +&incdec_pred rd pg esz d u +&incdec2_pred rd rn pg esz d u ########################################################################### # Named instruction formats. These are generally used to @@ -107,6 +109,7 @@ # One register operand, with governing predicate, vector element size @rd_pg_rn ........ esz:2 ... ... ... pg:3 rn:5 rd:5 &rpr_esz +@rd_pg4_pn ........ esz:2 ... ... .. pg:4 . rn:4 rd:5 &rpr_esz # Three register operand, with governing predicate, vector element size @rda_pg_rn_rm ........ esz:2 . rm:5 ... pg:3 rn:5 rd:5 \ @@ -153,6 +156,12 @@ @incdec2_cnt ........ esz:2 .. .... ...... pat:5 rd:5 \ &incdec2_cnt imm=%imm4_16_p1 rn=%reg_movprfx +# One register, predicate. +# User must fill in U and D. +@incdec_pred ........ esz:2 .... .. ..... .. pg:4 rd:5 &incdec_pred +@incdec2_pred ........ esz:2 .... .. ..... .. pg:4 rd:5 \ + &incdec2_pred rn=%reg_movprfx + ########################################################################### # Instruction patterns. Grouped according to the SVE encodingindex.xhtml. @@ -579,6 +588,24 @@ BRKB_m 00100101 1. 01000001 .... 0 .... 1 .... @pd_pg_pn_s # SVE propagate break to next partition BRKN 00100101 0. 01100001 .... 0 .... 0 .... @pd_pg_pn_s +### SVE Predicate Count Group + +# SVE predicate count +CNTP 00100101 .. 100 000 10 .... 0 .... ..... @rd_pg4_pn + +# SVE inc/dec register by predicate count +INCDECP_r 00100101 .. 10110 d:1 10001 00 .... ..... @incdec_pred u=1 + +# SVE inc/dec vector by predicate count +INCDECP_z 00100101 .. 10110 d:1 10000 00 .... ..... @incdec2_pred u=1 + +# SVE saturating inc/dec register by predicate count +SINCDECP_r_32 00100101 .. 1010 d:1 u:1 10001 00 .... ..... @incdec_pred +SINCDECP_r_64 00100101 .. 1010 d:1 u:1 10001 10 .... ..... @incdec_pred + +# SVE saturating inc/dec vector by predicate count +SINCDECP_z 00100101 .. 1010 d:1 u:1 10000 00 .... ..... @incdec2_pred + ### SVE Memory - 32-bit Gather and Unsized Contiguous Group # SVE load predicate register diff --git a/qemu/target/arm/sve_helper.c b/qemu/target/arm/sve_helper.c index 098a9bd3..ce4f7e6b 100644 --- a/qemu/target/arm/sve_helper.c +++ b/qemu/target/arm/sve_helper.c @@ -2723,3 +2723,17 @@ uint32_t HELPER(sve_brkns)(void *vd, void *vn, void *vg, uint32_t pred_desc) return do_zero(vd, oprsz); } } + +uint64_t HELPER(sve_cntp)(void *vn, void *vg, uint32_t pred_desc) +{ + intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2; + intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2); + uint64_t *n = vn, *g = vg, sum = 0, mask = pred_esz_masks[esz]; + intptr_t i; + + for (i = 0; i < DIV_ROUND_UP(oprsz, 8); ++i) { + uint64_t t = n[i] & g[i] & mask; + sum += ctpop64(t); + } + return sum; +} diff --git a/qemu/target/arm/translate-sve.c b/qemu/target/arm/translate-sve.c index a9238b9f..cb6ba6fd 100644 --- a/qemu/target/arm/translate-sve.c +++ b/qemu/target/arm/translate-sve.c @@ -30,6 +30,9 @@ #include "exec/helper-gen.h" #include "translate-a64.h" +typedef void GVecGen2sFn(TCGContext *, unsigned, uint32_t, uint32_t, + TCGv_i64, uint32_t, uint32_t); + typedef void gen_helper_gvec_flags_3(TCGContext *, TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32); typedef void gen_helper_gvec_flags_4(TCGContext *, TCGv_i32, TCGv_ptr, TCGv_ptr, @@ -3066,6 +3069,142 @@ static bool trans_BRKN(DisasContext *s, arg_rpr_s *a, uint32_t insn) return do_brk2(s, a, gen_helper_sve_brkn, gen_helper_sve_brkns); } +/* + *** SVE Predicate Count Group + */ + +static void do_cntp(DisasContext *s, TCGv_i64 val, int esz, int pn, int pg) +{ + TCGContext *tcg_ctx = s->uc->tcg_ctx; + unsigned psz = pred_full_reg_size(s); + + if (psz <= 8) { + uint64_t psz_mask; + + tcg_gen_ld_i64(tcg_ctx, val, tcg_ctx->cpu_env, pred_full_reg_offset(s, pn)); + if (pn != pg) { + TCGv_i64 g = tcg_temp_new_i64(tcg_ctx); + tcg_gen_ld_i64(tcg_ctx, g, tcg_ctx->cpu_env, pred_full_reg_offset(s, pg)); + tcg_gen_and_i64(tcg_ctx, val, val, g); + tcg_temp_free_i64(tcg_ctx, g); + } + + /* Reduce the pred_esz_masks value simply to reduce the + * size of the code generated here. + */ + psz_mask = MAKE_64BIT_MASK(0, psz * 8); + tcg_gen_andi_i64(tcg_ctx, val, val, pred_esz_masks[esz] & psz_mask); + + tcg_gen_ctpop_i64(tcg_ctx, val, val); + } else { + TCGv_ptr t_pn = tcg_temp_new_ptr(tcg_ctx); + TCGv_ptr t_pg = tcg_temp_new_ptr(tcg_ctx); + unsigned desc; + TCGv_i32 t_desc; + + desc = psz - 2; + desc = deposit32(desc, SIMD_DATA_SHIFT, 2, esz); + + tcg_gen_addi_ptr(tcg_ctx, t_pn, tcg_ctx->cpu_env, pred_full_reg_offset(s, pn)); + tcg_gen_addi_ptr(tcg_ctx, t_pg, tcg_ctx->cpu_env, pred_full_reg_offset(s, pg)); + t_desc = tcg_const_i32(tcg_ctx, desc); + + gen_helper_sve_cntp(tcg_ctx, val, t_pn, t_pg, t_desc); + tcg_temp_free_ptr(tcg_ctx, t_pn); + tcg_temp_free_ptr(tcg_ctx, t_pg); + tcg_temp_free_i32(tcg_ctx, t_desc); + } +} + +static bool trans_CNTP(DisasContext *s, arg_CNTP *a, uint32_t insn) +{ + if (sve_access_check(s)) { + do_cntp(s, cpu_reg(s, a->rd), a->esz, a->rn, a->pg); + } + return true; +} + +static bool trans_INCDECP_r(DisasContext *s, arg_incdec_pred *a, + uint32_t insn) +{ + if (sve_access_check(s)) { + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv_i64 reg = cpu_reg(s, a->rd); + TCGv_i64 val = tcg_temp_new_i64(tcg_ctx); + + do_cntp(s, val, a->esz, a->pg, a->pg); + if (a->d) { + tcg_gen_sub_i64(tcg_ctx, reg, reg, val); + } else { + tcg_gen_add_i64(tcg_ctx, reg, reg, val); + } + tcg_temp_free_i64(tcg_ctx, val); + } + return true; +} + +static bool trans_INCDECP_z(DisasContext *s, arg_incdec2_pred *a, + uint32_t insn) +{ + if (a->esz == 0) { + return false; + } + if (sve_access_check(s)) { + TCGContext *tcg_ctx = s->uc->tcg_ctx; + unsigned vsz = vec_full_reg_size(s); + TCGv_i64 val = tcg_temp_new_i64(tcg_ctx); + GVecGen2sFn *gvec_fn = a->d ? tcg_gen_gvec_subs : tcg_gen_gvec_adds; + + do_cntp(s, val, a->esz, a->pg, a->pg); + gvec_fn(tcg_ctx, a->esz, vec_full_reg_offset(s, a->rd), + vec_full_reg_offset(s, a->rn), val, vsz, vsz); + } + return true; +} + +static bool trans_SINCDECP_r_32(DisasContext *s, arg_incdec_pred *a, + uint32_t insn) +{ + if (sve_access_check(s)) { + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv_i64 reg = cpu_reg(s, a->rd); + TCGv_i64 val = tcg_temp_new_i64(tcg_ctx); + + do_cntp(s, val, a->esz, a->pg, a->pg); + do_sat_addsub_32(s, reg, val, a->u, a->d); + } + return true; +} + +static bool trans_SINCDECP_r_64(DisasContext *s, arg_incdec_pred *a, + uint32_t insn) +{ + if (sve_access_check(s)) { + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv_i64 reg = cpu_reg(s, a->rd); + TCGv_i64 val = tcg_temp_new_i64(tcg_ctx); + + do_cntp(s, val, a->esz, a->pg, a->pg); + do_sat_addsub_64(s, reg, val, a->u, a->d); + } + return true; +} + +static bool trans_SINCDECP_z(DisasContext *s, arg_incdec2_pred *a, + uint32_t insn) +{ + if (a->esz == 0) { + return false; + } + if (sve_access_check(s)) { + TCGContext *tcg_ctx = s->uc->tcg_ctx; + TCGv_i64 val = tcg_temp_new_i64(tcg_ctx); + do_cntp(s, val, a->esz, a->pg, a->pg); + do_sat_addsub_vec(s, a->esz, a->rd, a->rn, val, a->u, a->d); + } + return true; +} + /* *** SVE Memory - 32-bit Gather and Unsized Contiguous Group */