From nobody Mon Feb 9 23:11:49 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518892207925635.6210469015367; Sat, 17 Feb 2018 10:30:07 -0800 (PST) Received: from localhost ([::1]:48090 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en7FM-0005Sd-VV for importer@patchew.org; Sat, 17 Feb 2018 13:30:05 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39623) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en79C-0000GF-7v for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:23:45 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1en799-0001We-NK for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:23:42 -0500 Received: from mail-pg0-x244.google.com ([2607:f8b0:400e:c05::244]:43776) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1en799-0001WB-EU for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:23:39 -0500 Received: by mail-pg0-x244.google.com with SMTP id f6so4342749pgs.10 for ; Sat, 17 Feb 2018 10:23:39 -0800 (PST) Received: from cloudburst.twiddle.net ([50.0.192.64]) by smtp.gmail.com with ESMTPSA id h15sm13466712pfi.56.2018.02.17.10.23.36 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 17 Feb 2018 10:23:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6uhmGKy5nLmfDGSIQVraRklHXj0OvYQ5hNxaPRxQJrw=; b=DMFUbaz6cwZJthSX6wD4LrR8bAVHTO2CF348HaX0jJAiwN8KLlrpbB1A2etO1Pgx5L PMGUZIAVQdb/oCwuq59Ha/x3QDj1yzF87M5SM8ipL/F+WZMxRhYuqTtwEEFybiUrcZs2 Ao2NwnmrRjdBicpkn5zbdHzHb6E1TAy8L0qzg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6uhmGKy5nLmfDGSIQVraRklHXj0OvYQ5hNxaPRxQJrw=; b=VMzln/IxFE+kcQuUPWBovzPu1RCxXUB3k/Ugm+zKdjIFR8Z38WbcEyexgMNG8ieiUa YxofGXINx+OqV6mbKZsSFhHw5gndyQPNal4o524DAh0IqwUJrNn5Duxy/sgElgjxsHt+ kjGVJAYjiGQdpaXsWzh0AzNYRIXNS4ASz+w4GfjQ/93xJiacwqt/quY4lyRdMYbX2dpP 3e1FGG4eP5ZJBi7iIzjnRY/wbuu3bQCNqHN3vg0uwFOJ4AXVwNCAiBrWi48KZ78aYvwv mRsCey1/X09fGGcOuMRUOPT/lskVh+N+W8WdXc9EFFdXh5aRoOhnTis53aAsSr7RnBS2 rTbA== X-Gm-Message-State: APf1xPCRwTSQOnCi4mP3yLPJyh051O/zcVHvMqMY1Py7XQld4o/vvwEi 1X7a2//C6CfhN2P0KPwXJ8tMhg2lqI8= X-Google-Smtp-Source: AH8x224bWQkBz8JNgRZ5U5Xjn0aF/YcvlDKBuswgjzfhAIEuLKE17bXVKeR4MV6/Y6Q4CcEJmr64/A== X-Received: by 10.99.125.13 with SMTP id y13mr8121205pgc.282.1518891817849; Sat, 17 Feb 2018 10:23:37 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Sat, 17 Feb 2018 10:22:23 -0800 Message-Id: <20180217182323.25885-8-richard.henderson@linaro.org> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180217182323.25885-1-richard.henderson@linaro.org> References: <20180217182323.25885-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::244 Subject: [Qemu-devel] [PATCH v2 07/67] target/arm: Implement SVE Predicate Logical Operations Group X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-arm@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Richard Henderson Reviewed-by: Peter Maydell --- target/arm/cpu.h | 4 +- target/arm/helper-sve.h | 10 ++ target/arm/sve_helper.c | 39 ++++++ target/arm/translate-sve.c | 338 +++++++++++++++++++++++++++++++++++++++++= +++- target/arm/sve.decode | 16 +++ 5 files changed, 405 insertions(+), 2 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 70e05f00fe..8befe43a01 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -527,6 +527,8 @@ typedef struct CPUARMState { #ifdef TARGET_AARCH64 /* Store FFR as pregs[16] to make it easier to treat as any other.= */ ARMPredicateReg pregs[17]; + /* Scratch space for aa64 sve predicate temporary. */ + ARMPredicateReg preg_tmp; #endif =20 uint32_t xregs[16]; @@ -534,7 +536,7 @@ typedef struct CPUARMState { int vec_len; int vec_stride; =20 - /* scratch space when Tn are not sufficient. */ + /* Scratch space for aa32 neon expansion. */ uint32_t scratch[8]; =20 /* There are a number of distinct float control structures: diff --git a/target/arm/helper-sve.h b/target/arm/helper-sve.h index b6e91539ae..57adc4d912 100644 --- a/target/arm/helper-sve.h +++ b/target/arm/helper-sve.h @@ -19,3 +19,13 @@ =20 DEF_HELPER_FLAGS_2(sve_predtest1, TCG_CALL_NO_WG, i32, i64, i64) DEF_HELPER_FLAGS_3(sve_predtest, TCG_CALL_NO_WG, i32, ptr, ptr, i32) + +DEF_HELPER_FLAGS_5(sve_and_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr= , i32) +DEF_HELPER_FLAGS_5(sve_bic_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr= , i32) +DEF_HELPER_FLAGS_5(sve_eor_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr= , i32) +DEF_HELPER_FLAGS_5(sve_sel_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr= , i32) +DEF_HELPER_FLAGS_5(sve_orr_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr= , i32) +DEF_HELPER_FLAGS_5(sve_orn_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr= , i32) +DEF_HELPER_FLAGS_5(sve_nor_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr= , i32) +DEF_HELPER_FLAGS_5(sve_nand_pppp, TCG_CALL_NO_RWG, + void, ptr, ptr, ptr, ptr, i32) diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c index 7d13fd40ed..b63e7cc90e 100644 --- a/target/arm/sve_helper.c +++ b/target/arm/sve_helper.c @@ -75,3 +75,42 @@ uint32_t HELPER(sve_predtest)(void *vd, void *vg, uint32= _t words) =20 return flags; } + +#define LOGICAL_PPPP(NAME, FUNC) \ +void HELPER(NAME)(void *vd, void *vn, void *vm, void *vg, uint32_t desc) \ +{ \ + uintptr_t opr_sz =3D simd_oprsz(desc); = \ + uint64_t *d =3D vd, *n =3D vn, *m =3D vm, *g =3D vg; = \ + uintptr_t i; \ + for (i =3D 0; i < opr_sz / 8; ++i) { = \ + d[i] =3D FUNC(n[i], m[i], g[i]); = \ + } \ +} + +#define DO_AND(N, M, G) (((N) & (M)) & (G)) +#define DO_BIC(N, M, G) (((N) & ~(M)) & (G)) +#define DO_EOR(N, M, G) (((N) ^ (M)) & (G)) +#define DO_ORR(N, M, G) (((N) | (M)) & (G)) +#define DO_ORN(N, M, G) (((N) | ~(M)) & (G)) +#define DO_NOR(N, M, G) (~((N) | (M)) & (G)) +#define DO_NAND(N, M, G) (~((N) & (M)) & (G)) +#define DO_SEL(N, M, G) (((N) & (G)) | ((M) & ~(G))) + +LOGICAL_PPPP(sve_and_pppp, DO_AND) +LOGICAL_PPPP(sve_bic_pppp, DO_BIC) +LOGICAL_PPPP(sve_eor_pppp, DO_EOR) +LOGICAL_PPPP(sve_sel_pppp, DO_SEL) +LOGICAL_PPPP(sve_orr_pppp, DO_ORR) +LOGICAL_PPPP(sve_orn_pppp, DO_ORN) +LOGICAL_PPPP(sve_nor_pppp, DO_NOR) +LOGICAL_PPPP(sve_nand_pppp, DO_NAND) + +#undef DO_ADD +#undef DO_BIC +#undef DO_EOR +#undef DO_ORR +#undef DO_ORN +#undef DO_NOR +#undef DO_NAND +#undef DO_SEL +#undef LOGICAL_PPPP diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c index c2e7fac938..405f9397a1 100644 --- a/target/arm/translate-sve.c +++ b/target/arm/translate-sve.c @@ -59,6 +59,24 @@ static inline int pred_full_reg_size(DisasContext *s) return s->sve_len >> 3; } =20 +/* Round up the size of a predicate register to a size allowed by + * the tcg vector infrastructure. Any operation which uses this + * size may assume that the bits above pred_full_reg_size are zero, + * and must leave them the same way. + * + * Note that this is not needed for the vector registers as they + * are always properly sized for tcg vectors. + */ +static int pred_gvec_reg_size(DisasContext *s) +{ + int size =3D pred_full_reg_size(s); + if (size <=3D 8) { + return 8; + } else { + return QEMU_ALIGN_UP(size, 16); + } +} + /* Invoke a vector expander on two Zregs. */ static void do_vector2_z(DisasContext *s, GVecGen2Fn *gvec_fn, int esz, int rd, int rn) @@ -83,6 +101,40 @@ static void do_mov_z(DisasContext *s, int rd, int rn) do_vector2_z(s, tcg_gen_gvec_mov, 0, rd, rn); } =20 +/* Invoke a vector expander on two Pregs. */ +static void do_vector2_p(DisasContext *s, GVecGen2Fn *gvec_fn, + int esz, int rd, int rn) +{ + unsigned psz =3D pred_gvec_reg_size(s); + gvec_fn(esz, pred_full_reg_offset(s, rd), + pred_full_reg_offset(s, rn), psz, psz); +} + +/* Invoke a vector expander on three Pregs. */ +static void do_vector3_p(DisasContext *s, GVecGen3Fn *gvec_fn, + int esz, int rd, int rn, int rm) +{ + unsigned psz =3D pred_gvec_reg_size(s); + gvec_fn(esz, pred_full_reg_offset(s, rd), pred_full_reg_offset(s, rn), + pred_full_reg_offset(s, rm), psz, psz); +} + +/* Invoke a vector operation on four Pregs. */ +static void do_vecop4_p(DisasContext *s, const GVecGen4 *gvec_op, + int rd, int rn, int rm, int rg) +{ + unsigned psz =3D pred_gvec_reg_size(s); + tcg_gen_gvec_4(pred_full_reg_offset(s, rd), pred_full_reg_offset(s, rn= ), + pred_full_reg_offset(s, rm), pred_full_reg_offset(s, rg= ), + psz, psz, gvec_op); +} + +/* Invoke a vector move on two Pregs. */ +static void do_mov_p(DisasContext *s, int rd, int rn) +{ + do_vector2_p(s, tcg_gen_gvec_mov, 0, rd, rn); +} + /* Set the cpu flags as per a return from an SVE helper. */ static void do_pred_flags(TCGv_i32 t) { @@ -148,11 +200,295 @@ static void trans_BIC_zzz(DisasContext *s, arg_BIC_z= zz *a, uint32_t insn) do_vector3_z(s, tcg_gen_gvec_andc, 0, a->rd, a->rn, a->rm); } =20 +/* + *** SVE Predicate Logical Operations Group + */ + +static void do_pppp_flags(DisasContext *s, arg_rprr_s *a, + const GVecGen4 *gvec_op) +{ + unsigned psz =3D pred_gvec_reg_size(s); + int dofs =3D pred_full_reg_offset(s, a->rd); + int nofs =3D pred_full_reg_offset(s, a->rn); + int mofs =3D pred_full_reg_offset(s, a->rm); + int gofs =3D pred_full_reg_offset(s, a->pg); + + if (psz =3D=3D 8) { + /* Do the operation and the flags generation in temps. */ + TCGv_i64 pd =3D tcg_temp_new_i64(); + TCGv_i64 pn =3D tcg_temp_new_i64(); + TCGv_i64 pm =3D tcg_temp_new_i64(); + TCGv_i64 pg =3D tcg_temp_new_i64(); + + tcg_gen_ld_i64(pn, cpu_env, nofs); + tcg_gen_ld_i64(pm, cpu_env, mofs); + tcg_gen_ld_i64(pg, cpu_env, gofs); + + gvec_op->fni8(pd, pn, pm, pg); + tcg_gen_st_i64(pd, cpu_env, dofs); + + do_predtest1(pd, pg); + + tcg_temp_free_i64(pd); + tcg_temp_free_i64(pn); + tcg_temp_free_i64(pm); + tcg_temp_free_i64(pg); + } else { + /* The operation and flags generation is large. The computation + * of the flags depends on the original contents of the guarding + * predicate. If the destination overwrites the guarding predicat= e, + * then the easiest way to get this right is to save a copy. + */ + int tofs =3D gofs; + if (a->rd =3D=3D a->pg) { + tofs =3D offsetof(CPUARMState, vfp.preg_tmp); + tcg_gen_gvec_mov(0, tofs, gofs, psz, psz); + } + + tcg_gen_gvec_4(dofs, nofs, mofs, gofs, psz, psz, gvec_op); + do_predtest(s, dofs, tofs, psz / 8); + } +} + +static void gen_and_pg_i64(TCGv_i64 pd, TCGv_i64 pn, TCGv_i64 pm, TCGv_i64= pg) +{ + tcg_gen_and_i64(pd, pn, pm); + tcg_gen_and_i64(pd, pd, pg); +} + +static void gen_and_pg_vec(unsigned vece, TCGv_vec pd, TCGv_vec pn, + TCGv_vec pm, TCGv_vec pg) +{ + tcg_gen_and_vec(vece, pd, pn, pm); + tcg_gen_and_vec(vece, pd, pd, pg); +} + +static void trans_AND_pppp(DisasContext *s, arg_rprr_s *a, uint32_t insn) +{ + static const GVecGen4 op =3D { + .fni8 =3D gen_and_pg_i64, + .fniv =3D gen_and_pg_vec, + .fno =3D gen_helper_sve_and_pppp, + .prefer_i64 =3D TCG_TARGET_REG_BITS =3D=3D 64, + }; + if (a->s) { + do_pppp_flags(s, a, &op); + } else if (a->pg =3D=3D a->rn && a->rn =3D=3D a->rm) { + do_mov_p(s, a->rd, a->rn); + } else if (a->pg =3D=3D a->rn || a->pg =3D=3D a->rm) { + do_vector3_p(s, tcg_gen_gvec_and, 0, a->rd, a->rn, a->rm); + } else { + do_vecop4_p(s, &op, a->rd, a->rn, a->rm, a->pg); + } +} + +static void gen_bic_pg_i64(TCGv_i64 pd, TCGv_i64 pn, TCGv_i64 pm, TCGv_i64= pg) +{ + tcg_gen_andc_i64(pd, pn, pm); + tcg_gen_and_i64(pd, pd, pg); +} + +static void gen_bic_pg_vec(unsigned vece, TCGv_vec pd, TCGv_vec pn, + TCGv_vec pm, TCGv_vec pg) +{ + tcg_gen_andc_vec(vece, pd, pn, pm); + tcg_gen_and_vec(vece, pd, pd, pg); +} + +static void trans_BIC_pppp(DisasContext *s, arg_rprr_s *a, uint32_t insn) +{ + static const GVecGen4 op =3D { + .fni8 =3D gen_bic_pg_i64, + .fniv =3D gen_bic_pg_vec, + .fno =3D gen_helper_sve_bic_pppp, + .prefer_i64 =3D TCG_TARGET_REG_BITS =3D=3D 64, + }; + if (a->s) { + do_pppp_flags(s, a, &op); + } else if (a->pg =3D=3D a->rn) { + do_vector3_p(s, tcg_gen_gvec_andc, 0, a->rd, a->rn, a->rm); + } else { + do_vecop4_p(s, &op, a->rd, a->rn, a->rm, a->pg); + } +} + +static void gen_eor_pg_i64(TCGv_i64 pd, TCGv_i64 pn, TCGv_i64 pm, TCGv_i64= pg) +{ + tcg_gen_xor_i64(pd, pn, pm); + tcg_gen_and_i64(pd, pd, pg); +} + +static void gen_eor_pg_vec(unsigned vece, TCGv_vec pd, TCGv_vec pn, + TCGv_vec pm, TCGv_vec pg) +{ + tcg_gen_xor_vec(vece, pd, pn, pm); + tcg_gen_and_vec(vece, pd, pd, pg); +} + +static void trans_EOR_pppp(DisasContext *s, arg_rprr_s *a, uint32_t insn) +{ + static const GVecGen4 op =3D { + .fni8 =3D gen_eor_pg_i64, + .fniv =3D gen_eor_pg_vec, + .fno =3D gen_helper_sve_eor_pppp, + .prefer_i64 =3D TCG_TARGET_REG_BITS =3D=3D 64, + }; + if (a->s) { + do_pppp_flags(s, a, &op); + } else { + do_vecop4_p(s, &op, a->rd, a->rn, a->rm, a->pg); + } +} + +static void gen_sel_pg_i64(TCGv_i64 pd, TCGv_i64 pn, TCGv_i64 pm, TCGv_i64= pg) +{ + tcg_gen_and_i64(pn, pn, pg); + tcg_gen_andc_i64(pm, pm, pg); + tcg_gen_or_i64(pd, pn, pm); +} + +static void gen_sel_pg_vec(unsigned vece, TCGv_vec pd, TCGv_vec pn, + TCGv_vec pm, TCGv_vec pg) +{ + tcg_gen_and_vec(vece, pn, pn, pg); + tcg_gen_andc_vec(vece, pm, pm, pg); + tcg_gen_or_vec(vece, pd, pn, pm); +} + +static void trans_SEL_pppp(DisasContext *s, arg_rprr_s *a, uint32_t insn) +{ + static const GVecGen4 op =3D { + .fni8 =3D gen_sel_pg_i64, + .fniv =3D gen_sel_pg_vec, + .fno =3D gen_helper_sve_sel_pppp, + .prefer_i64 =3D TCG_TARGET_REG_BITS =3D=3D 64, + }; + if (a->s) { + unallocated_encoding(s); + } else { + do_vecop4_p(s, &op, a->rd, a->rn, a->rm, a->pg); + } +} + +static void gen_orr_pg_i64(TCGv_i64 pd, TCGv_i64 pn, TCGv_i64 pm, TCGv_i64= pg) +{ + tcg_gen_or_i64(pd, pn, pm); + tcg_gen_and_i64(pd, pd, pg); +} + +static void gen_orr_pg_vec(unsigned vece, TCGv_vec pd, TCGv_vec pn, + TCGv_vec pm, TCGv_vec pg) +{ + tcg_gen_or_vec(vece, pd, pn, pm); + tcg_gen_and_vec(vece, pd, pd, pg); +} + +static void trans_ORR_pppp(DisasContext *s, arg_rprr_s *a, uint32_t insn) +{ + static const GVecGen4 op =3D { + .fni8 =3D gen_orr_pg_i64, + .fniv =3D gen_orr_pg_vec, + .fno =3D gen_helper_sve_orr_pppp, + .prefer_i64 =3D TCG_TARGET_REG_BITS =3D=3D 64, + }; + if (a->s) { + do_pppp_flags(s, a, &op); + } else if (a->pg =3D=3D a->rn && a->rn =3D=3D a->rm) { + do_mov_p(s, a->rd, a->rn); + } else { + do_vecop4_p(s, &op, a->rd, a->rn, a->rm, a->pg); + } +} + +static void gen_orn_pg_i64(TCGv_i64 pd, TCGv_i64 pn, TCGv_i64 pm, TCGv_i64= pg) +{ + tcg_gen_orc_i64(pd, pn, pm); + tcg_gen_and_i64(pd, pd, pg); +} + +static void gen_orn_pg_vec(unsigned vece, TCGv_vec pd, TCGv_vec pn, + TCGv_vec pm, TCGv_vec pg) +{ + tcg_gen_orc_vec(vece, pd, pn, pm); + tcg_gen_and_vec(vece, pd, pd, pg); +} + +static void trans_ORN_pppp(DisasContext *s, arg_rprr_s *a, uint32_t insn) +{ + static const GVecGen4 op =3D { + .fni8 =3D gen_orn_pg_i64, + .fniv =3D gen_orn_pg_vec, + .fno =3D gen_helper_sve_orn_pppp, + .prefer_i64 =3D TCG_TARGET_REG_BITS =3D=3D 64, + }; + if (a->s) { + do_pppp_flags(s, a, &op); + } else { + do_vecop4_p(s, &op, a->rd, a->rn, a->rm, a->pg); + } +} + +static void gen_nor_pg_i64(TCGv_i64 pd, TCGv_i64 pn, TCGv_i64 pm, TCGv_i64= pg) +{ + tcg_gen_or_i64(pd, pn, pm); + tcg_gen_andc_i64(pd, pg, pd); +} + +static void gen_nor_pg_vec(unsigned vece, TCGv_vec pd, TCGv_vec pn, + TCGv_vec pm, TCGv_vec pg) +{ + tcg_gen_or_vec(vece, pd, pn, pm); + tcg_gen_andc_vec(vece, pd, pg, pd); +} + +static void trans_NOR_pppp(DisasContext *s, arg_rprr_s *a, uint32_t insn) +{ + static const GVecGen4 op =3D { + .fni8 =3D gen_nor_pg_i64, + .fniv =3D gen_nor_pg_vec, + .fno =3D gen_helper_sve_nor_pppp, + .prefer_i64 =3D TCG_TARGET_REG_BITS =3D=3D 64, + }; + if (a->s) { + do_pppp_flags(s, a, &op); + } else { + do_vecop4_p(s, &op, a->rd, a->rn, a->rm, a->pg); + } +} + +static void gen_nand_pg_i64(TCGv_i64 pd, TCGv_i64 pn, TCGv_i64 pm, TCGv_i6= 4 pg) +{ + tcg_gen_and_i64(pd, pn, pm); + tcg_gen_andc_i64(pd, pg, pd); +} + +static void gen_nand_pg_vec(unsigned vece, TCGv_vec pd, TCGv_vec pn, + TCGv_vec pm, TCGv_vec pg) +{ + tcg_gen_and_vec(vece, pd, pn, pm); + tcg_gen_andc_vec(vece, pd, pg, pd); +} + +static void trans_NAND_pppp(DisasContext *s, arg_rprr_s *a, uint32_t insn) +{ + static const GVecGen4 op =3D { + .fni8 =3D gen_nand_pg_i64, + .fniv =3D gen_nand_pg_vec, + .fno =3D gen_helper_sve_nand_pppp, + .prefer_i64 =3D TCG_TARGET_REG_BITS =3D=3D 64, + }; + if (a->s) { + do_pppp_flags(s, a, &op); + } else { + do_vecop4_p(s, &op, a->rd, a->rn, a->rm, a->pg); + } +} + /* *** SVE Predicate Misc Group */ =20 -void trans_PTEST(DisasContext *s, arg_PTEST *a, uint32_t insn) +static void trans_PTEST(DisasContext *s, arg_PTEST *a, uint32_t insn) { int nofs =3D pred_full_reg_offset(s, a->rn); int gofs =3D pred_full_reg_offset(s, a->pg); diff --git a/target/arm/sve.decode b/target/arm/sve.decode index 7efaa8fe8e..d92886127a 100644 --- a/target/arm/sve.decode +++ b/target/arm/sve.decode @@ -31,6 +31,7 @@ =20 &rri rd rn imm &rrr_esz rd rn rm esz +&rprr_s rd pg rn rm s =20 ########################################################################### # Named instruction formats. These are generally used to @@ -39,6 +40,9 @@ # Three operand with unused vector element size @rd_rn_rm_e0 ........ ... rm:5 ... ... rn:5 rd:5 &rrr_esz esz=3D0 =20 +# Three prediate operand, with governing predicate, flag setting +@pd_pg_pn_pm_s ........ . s:1 .. rm:4 .. pg:4 . rn:4 . rd:4 &rprr_s + # Basic Load/Store with 9-bit immediate offset @pd_rn_i9 ........ ........ ...... rn:5 . rd:4 \ &rri imm=3D%imm9_16_10 @@ -56,6 +60,18 @@ ORR_zzz 00000100 01 1 ..... 001 100 ..... ..... @rd_rn= _rm_e0 EOR_zzz 00000100 10 1 ..... 001 100 ..... ..... @rd_rn_rm_e0 BIC_zzz 00000100 11 1 ..... 001 100 ..... ..... @rd_rn_rm_e0 =20 +### SVE Predicate Logical Operations Group + +# SVE predicate logical operations +AND_pppp 00100101 0. 00 .... 01 .... 0 .... 0 .... @pd_pg_pn_pm_s +BIC_pppp 00100101 0. 00 .... 01 .... 0 .... 1 .... @pd_pg_pn_pm_s +EOR_pppp 00100101 0. 00 .... 01 .... 1 .... 0 .... @pd_pg_pn_pm_s +SEL_pppp 00100101 0. 00 .... 01 .... 1 .... 1 .... @pd_pg_pn_pm_s +ORR_pppp 00100101 1. 00 .... 01 .... 0 .... 0 .... @pd_pg_pn_pm_s +ORN_pppp 00100101 1. 00 .... 01 .... 0 .... 1 .... @pd_pg_pn_pm_s +NOR_pppp 00100101 1. 00 .... 01 .... 1 .... 0 .... @pd_pg_pn_pm_s +NAND_pppp 00100101 1. 00 .... 01 .... 1 .... 1 .... @pd_pg_pn_pm_s + ### SVE Predicate Misc Group =20 # SVE predicate test --=20 2.14.3