1e13c7d3bSLawrence Hunter/*
2e13c7d3bSLawrence Hunter * RISC-V translation routines for the vector crypto extension.
3e13c7d3bSLawrence Hunter *
4e13c7d3bSLawrence Hunter * Copyright (C) 2023 SiFive, Inc.
5e13c7d3bSLawrence Hunter * Written by Codethink Ltd and SiFive.
6e13c7d3bSLawrence Hunter *
7e13c7d3bSLawrence Hunter * This program is free software; you can redistribute it and/or modify it
8e13c7d3bSLawrence Hunter * under the terms and conditions of the GNU General Public License,
9e13c7d3bSLawrence Hunter * version 2 or later, as published by the Free Software Foundation.
10e13c7d3bSLawrence Hunter *
11e13c7d3bSLawrence Hunter * This program is distributed in the hope it will be useful, but WITHOUT
12e13c7d3bSLawrence Hunter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13e13c7d3bSLawrence Hunter * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14e13c7d3bSLawrence Hunter * more details.
15e13c7d3bSLawrence Hunter *
16e13c7d3bSLawrence Hunter * You should have received a copy of the GNU General Public License along with
17e13c7d3bSLawrence Hunter * this program.  If not, see <http://www.gnu.org/licenses/>.
18e13c7d3bSLawrence Hunter */
19e13c7d3bSLawrence Hunter
20e13c7d3bSLawrence Hunter/*
21e13c7d3bSLawrence Hunter * Zvbc
22e13c7d3bSLawrence Hunter */
23e13c7d3bSLawrence Hunter
24e13c7d3bSLawrence Hunter#define GEN_VV_MASKED_TRANS(NAME, CHECK)                     \
25e13c7d3bSLawrence Hunter    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)   \
26e13c7d3bSLawrence Hunter    {                                                        \
27e13c7d3bSLawrence Hunter        if (CHECK(s, a)) {                                   \
28e13c7d3bSLawrence Hunter            return opivv_trans(a->rd, a->rs1, a->rs2, a->vm, \
29e13c7d3bSLawrence Hunter                               gen_helper_##NAME, s);        \
30e13c7d3bSLawrence Hunter        }                                                    \
31e13c7d3bSLawrence Hunter        return false;                                        \
32e13c7d3bSLawrence Hunter    }
33e13c7d3bSLawrence Hunter
34e13c7d3bSLawrence Hunterstatic bool vclmul_vv_check(DisasContext *s, arg_rmrr *a)
35e13c7d3bSLawrence Hunter{
36e13c7d3bSLawrence Hunter    return opivv_check(s, a) &&
37e13c7d3bSLawrence Hunter           s->cfg_ptr->ext_zvbc == true &&
38e13c7d3bSLawrence Hunter           s->sew == MO_64;
39e13c7d3bSLawrence Hunter}
40e13c7d3bSLawrence Hunter
41e13c7d3bSLawrence HunterGEN_VV_MASKED_TRANS(vclmul_vv, vclmul_vv_check)
42e13c7d3bSLawrence HunterGEN_VV_MASKED_TRANS(vclmulh_vv, vclmul_vv_check)
43e13c7d3bSLawrence Hunter
44e13c7d3bSLawrence Hunter#define GEN_VX_MASKED_TRANS(NAME, CHECK)                     \
45e13c7d3bSLawrence Hunter    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)   \
46e13c7d3bSLawrence Hunter    {                                                        \
47e13c7d3bSLawrence Hunter        if (CHECK(s, a)) {                                   \
48e13c7d3bSLawrence Hunter            return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, \
49e13c7d3bSLawrence Hunter                               gen_helper_##NAME, s);        \
50e13c7d3bSLawrence Hunter        }                                                    \
51e13c7d3bSLawrence Hunter        return false;                                        \
52e13c7d3bSLawrence Hunter    }
53e13c7d3bSLawrence Hunter
54e13c7d3bSLawrence Hunterstatic bool vclmul_vx_check(DisasContext *s, arg_rmrr *a)
55e13c7d3bSLawrence Hunter{
56e13c7d3bSLawrence Hunter    return opivx_check(s, a) &&
57e13c7d3bSLawrence Hunter           s->cfg_ptr->ext_zvbc == true &&
58e13c7d3bSLawrence Hunter           s->sew == MO_64;
59e13c7d3bSLawrence Hunter}
60e13c7d3bSLawrence Hunter
61e13c7d3bSLawrence HunterGEN_VX_MASKED_TRANS(vclmul_vx, vclmul_vx_check)
62e13c7d3bSLawrence HunterGEN_VX_MASKED_TRANS(vclmulh_vx, vclmul_vx_check)
6306028472SDickon Hood
6406028472SDickon Hood/*
6506028472SDickon Hood * Zvbb
6606028472SDickon Hood */
6706028472SDickon Hood
6806028472SDickon Hood#define GEN_OPIVI_GVEC_TRANS_CHECK(NAME, IMM_MODE, OPIVX, SUF, CHECK)   \
6906028472SDickon Hood    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)              \
7006028472SDickon Hood    {                                                                   \
7106028472SDickon Hood        if (CHECK(s, a)) {                                              \
7206028472SDickon Hood            static gen_helper_opivx *const fns[4] = {                   \
7306028472SDickon Hood                gen_helper_##OPIVX##_b,                                 \
7406028472SDickon Hood                gen_helper_##OPIVX##_h,                                 \
7506028472SDickon Hood                gen_helper_##OPIVX##_w,                                 \
7606028472SDickon Hood                gen_helper_##OPIVX##_d,                                 \
7706028472SDickon Hood            };                                                          \
7806028472SDickon Hood            return do_opivi_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew], \
7906028472SDickon Hood                                 IMM_MODE);                             \
8006028472SDickon Hood        }                                                               \
8106028472SDickon Hood        return false;                                                   \
8206028472SDickon Hood    }
8306028472SDickon Hood
8406028472SDickon Hood#define GEN_OPIVV_GVEC_TRANS_CHECK(NAME, SUF, CHECK)                     \
8506028472SDickon Hood    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)               \
8606028472SDickon Hood    {                                                                    \
8706028472SDickon Hood        if (CHECK(s, a)) {                                               \
8806028472SDickon Hood            static gen_helper_gvec_4_ptr *const fns[4] = {               \
8906028472SDickon Hood                gen_helper_##NAME##_b,                                   \
9006028472SDickon Hood                gen_helper_##NAME##_h,                                   \
9106028472SDickon Hood                gen_helper_##NAME##_w,                                   \
9206028472SDickon Hood                gen_helper_##NAME##_d,                                   \
9306028472SDickon Hood            };                                                           \
9406028472SDickon Hood            return do_opivv_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]); \
9506028472SDickon Hood        }                                                                \
9606028472SDickon Hood        return false;                                                    \
9706028472SDickon Hood    }
9806028472SDickon Hood
9906028472SDickon Hood#define GEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(NAME, SUF, CHECK)       \
10006028472SDickon Hood    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)       \
10106028472SDickon Hood    {                                                            \
10206028472SDickon Hood        if (CHECK(s, a)) {                                       \
10306028472SDickon Hood            static gen_helper_opivx *const fns[4] = {            \
10406028472SDickon Hood                gen_helper_##NAME##_b,                           \
10506028472SDickon Hood                gen_helper_##NAME##_h,                           \
10606028472SDickon Hood                gen_helper_##NAME##_w,                           \
10706028472SDickon Hood                gen_helper_##NAME##_d,                           \
10806028472SDickon Hood            };                                                   \
10906028472SDickon Hood            return do_opivx_gvec_shift(s, a, tcg_gen_gvec_##SUF, \
11006028472SDickon Hood                                       fns[s->sew]);             \
11106028472SDickon Hood        }                                                        \
11206028472SDickon Hood        return false;                                            \
11306028472SDickon Hood    }
11406028472SDickon Hood
1151db699f8SMax Choustatic bool zvkb_vv_check(DisasContext *s, arg_rmrr *a)
11606028472SDickon Hood{
1171db699f8SMax Chou    return opivv_check(s, a) &&
1181db699f8SMax Chou           (s->cfg_ptr->ext_zvbb == true || s->cfg_ptr->ext_zvkb == true);
11906028472SDickon Hood}
12006028472SDickon Hood
1211db699f8SMax Choustatic bool zvkb_vx_check(DisasContext *s, arg_rmrr *a)
12206028472SDickon Hood{
1231db699f8SMax Chou    return opivx_check(s, a) &&
1241db699f8SMax Chou           (s->cfg_ptr->ext_zvbb == true || s->cfg_ptr->ext_zvkb == true);
12506028472SDickon Hood}
12606028472SDickon Hood
12706028472SDickon Hood/* vrol.v[vx] */
1281db699f8SMax ChouGEN_OPIVV_GVEC_TRANS_CHECK(vrol_vv, rotlv, zvkb_vv_check)
1291db699f8SMax ChouGEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(vrol_vx, rotls, zvkb_vx_check)
13006028472SDickon Hood
13106028472SDickon Hood/* vror.v[vxi] */
1321db699f8SMax ChouGEN_OPIVV_GVEC_TRANS_CHECK(vror_vv, rotrv, zvkb_vv_check)
1331db699f8SMax ChouGEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(vror_vx, rotrs, zvkb_vx_check)
1341db699f8SMax ChouGEN_OPIVI_GVEC_TRANS_CHECK(vror_vi, IMM_TRUNC_SEW, vror_vx, rotri,
1351db699f8SMax Chou                           zvkb_vx_check)
13606028472SDickon Hood
13706028472SDickon Hood#define GEN_OPIVX_GVEC_TRANS_CHECK(NAME, SUF, CHECK)                     \
13806028472SDickon Hood    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)               \
13906028472SDickon Hood    {                                                                    \
14006028472SDickon Hood        if (CHECK(s, a)) {                                               \
14106028472SDickon Hood            static gen_helper_opivx *const fns[4] = {                    \
14206028472SDickon Hood                gen_helper_##NAME##_b,                                   \
14306028472SDickon Hood                gen_helper_##NAME##_h,                                   \
14406028472SDickon Hood                gen_helper_##NAME##_w,                                   \
14506028472SDickon Hood                gen_helper_##NAME##_d,                                   \
14606028472SDickon Hood            };                                                           \
14706028472SDickon Hood            return do_opivx_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]); \
14806028472SDickon Hood        }                                                                \
14906028472SDickon Hood        return false;                                                    \
15006028472SDickon Hood    }
15106028472SDickon Hood
15206028472SDickon Hood/* vandn.v[vx] */
1531db699f8SMax ChouGEN_OPIVV_GVEC_TRANS_CHECK(vandn_vv, andc, zvkb_vv_check)
1541db699f8SMax ChouGEN_OPIVX_GVEC_TRANS_CHECK(vandn_vx, andcs, zvkb_vx_check)
15506028472SDickon Hood
15606028472SDickon Hood#define GEN_OPIV_TRANS(NAME, CHECK)                                        \
15706028472SDickon Hood    static bool trans_##NAME(DisasContext *s, arg_rmr *a)                  \
15806028472SDickon Hood    {                                                                      \
15906028472SDickon Hood        if (CHECK(s, a)) {                                                 \
16006028472SDickon Hood            uint32_t data = 0;                                             \
16106028472SDickon Hood            static gen_helper_gvec_3_ptr *const fns[4] = {                 \
16206028472SDickon Hood                gen_helper_##NAME##_b,                                     \
16306028472SDickon Hood                gen_helper_##NAME##_h,                                     \
16406028472SDickon Hood                gen_helper_##NAME##_w,                                     \
16506028472SDickon Hood                gen_helper_##NAME##_d,                                     \
16606028472SDickon Hood            };                                                             \
16706028472SDickon Hood                                                                           \
16806028472SDickon Hood            data = FIELD_DP32(data, VDATA, VM, a->vm);                     \
16906028472SDickon Hood            data = FIELD_DP32(data, VDATA, LMUL, s->lmul);                 \
17006028472SDickon Hood            data = FIELD_DP32(data, VDATA, VTA, s->vta);                   \
17106028472SDickon Hood            data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s); \
17206028472SDickon Hood            data = FIELD_DP32(data, VDATA, VMA, s->vma);                   \
17306028472SDickon Hood            tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),         \
174ad75a51eSRichard Henderson                               vreg_ofs(s, a->rs2), tcg_env,               \
175f5a5e71eSDaniel Henrique Barboza                               s->cfg_ptr->vlenb, s->cfg_ptr->vlenb,       \
17606028472SDickon Hood                               data, fns[s->sew]);                         \
177*bac802adSIvan Klokov            finalize_rvv_inst(s);                                          \
17806028472SDickon Hood            return true;                                                   \
17906028472SDickon Hood        }                                                                  \
18006028472SDickon Hood        return false;                                                      \
18106028472SDickon Hood    }
18206028472SDickon Hood
18306028472SDickon Hoodstatic bool zvbb_opiv_check(DisasContext *s, arg_rmr *a)
18406028472SDickon Hood{
18506028472SDickon Hood    return s->cfg_ptr->ext_zvbb == true &&
18606028472SDickon Hood           require_rvv(s) &&
18706028472SDickon Hood           vext_check_isa_ill(s) &&
18806028472SDickon Hood           vext_check_ss(s, a->rd, a->rs2, a->vm);
18906028472SDickon Hood}
19006028472SDickon Hood
1911db699f8SMax Choustatic bool zvkb_opiv_check(DisasContext *s, arg_rmr *a)
1921db699f8SMax Chou{
1931db699f8SMax Chou    return (s->cfg_ptr->ext_zvbb == true || s->cfg_ptr->ext_zvkb == true) &&
1941db699f8SMax Chou           require_rvv(s) &&
1951db699f8SMax Chou           vext_check_isa_ill(s) &&
1961db699f8SMax Chou           vext_check_ss(s, a->rd, a->rs2, a->vm);
1971db699f8SMax Chou}
1981db699f8SMax Chou
1991db699f8SMax ChouGEN_OPIV_TRANS(vbrev8_v, zvkb_opiv_check)
2001db699f8SMax ChouGEN_OPIV_TRANS(vrev8_v, zvkb_opiv_check)
20106028472SDickon HoodGEN_OPIV_TRANS(vbrev_v, zvbb_opiv_check)
20206028472SDickon HoodGEN_OPIV_TRANS(vclz_v, zvbb_opiv_check)
20306028472SDickon HoodGEN_OPIV_TRANS(vctz_v, zvbb_opiv_check)
20406028472SDickon HoodGEN_OPIV_TRANS(vcpop_v, zvbb_opiv_check)
20506028472SDickon Hood
20606028472SDickon Hoodstatic bool vwsll_vv_check(DisasContext *s, arg_rmrr *a)
20706028472SDickon Hood{
20806028472SDickon Hood    return s->cfg_ptr->ext_zvbb && opivv_widen_check(s, a);
20906028472SDickon Hood}
21006028472SDickon Hood
21106028472SDickon Hoodstatic bool vwsll_vx_check(DisasContext *s, arg_rmrr *a)
21206028472SDickon Hood{
21306028472SDickon Hood    return s->cfg_ptr->ext_zvbb && opivx_widen_check(s, a);
21406028472SDickon Hood}
21506028472SDickon Hood
21606028472SDickon Hood/* OPIVI without GVEC IR */
21706028472SDickon Hood#define GEN_OPIVI_WIDEN_TRANS(NAME, IMM_MODE, OPIVX, CHECK)                  \
21806028472SDickon Hood    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)                   \
21906028472SDickon Hood    {                                                                        \
22006028472SDickon Hood        if (CHECK(s, a)) {                                                   \
22106028472SDickon Hood            static gen_helper_opivx *const fns[3] = {                        \
22206028472SDickon Hood                gen_helper_##OPIVX##_b,                                      \
22306028472SDickon Hood                gen_helper_##OPIVX##_h,                                      \
22406028472SDickon Hood                gen_helper_##OPIVX##_w,                                      \
22506028472SDickon Hood            };                                                               \
22606028472SDickon Hood            return opivi_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s, \
22706028472SDickon Hood                               IMM_MODE);                                    \
22806028472SDickon Hood        }                                                                    \
22906028472SDickon Hood        return false;                                                        \
23006028472SDickon Hood    }
23106028472SDickon Hood
23206028472SDickon HoodGEN_OPIVV_WIDEN_TRANS(vwsll_vv, vwsll_vv_check)
23306028472SDickon HoodGEN_OPIVX_WIDEN_TRANS(vwsll_vx, vwsll_vx_check)
23406028472SDickon HoodGEN_OPIVI_WIDEN_TRANS(vwsll_vi, IMM_ZX, vwsll_vx, vwsll_vx_check)
235e972bf22SNazar Kazakov
236e972bf22SNazar Kazakov/*
237e972bf22SNazar Kazakov * Zvkned
238e972bf22SNazar Kazakov */
239e972bf22SNazar Kazakov
240e972bf22SNazar Kazakov#define ZVKNED_EGS 4
241e972bf22SNazar Kazakov
242e972bf22SNazar Kazakov#define GEN_V_UNMASKED_TRANS(NAME, CHECK, EGS)                                \
243e972bf22SNazar Kazakov    static bool trans_##NAME(DisasContext *s, arg_##NAME *a)                  \
244e972bf22SNazar Kazakov    {                                                                         \
245e972bf22SNazar Kazakov        if (CHECK(s, a)) {                                                    \
246e972bf22SNazar Kazakov            TCGv_ptr rd_v, rs2_v;                                             \
247e972bf22SNazar Kazakov            TCGv_i32 desc, egs;                                               \
248e972bf22SNazar Kazakov            uint32_t data = 0;                                                \
249e972bf22SNazar Kazakov                                                                              \
250e972bf22SNazar Kazakov            if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {                      \
251e972bf22SNazar Kazakov                /* save opcode for unwinding in case we throw an exception */ \
252e972bf22SNazar Kazakov                decode_save_opc(s);                                           \
253e972bf22SNazar Kazakov                egs = tcg_constant_i32(EGS);                                  \
254ad75a51eSRichard Henderson                gen_helper_egs_check(egs, tcg_env);                           \
255e972bf22SNazar Kazakov            }                                                                 \
256e972bf22SNazar Kazakov                                                                              \
257e972bf22SNazar Kazakov            data = FIELD_DP32(data, VDATA, VM, a->vm);                        \
258e972bf22SNazar Kazakov            data = FIELD_DP32(data, VDATA, LMUL, s->lmul);                    \
259e972bf22SNazar Kazakov            data = FIELD_DP32(data, VDATA, VTA, s->vta);                      \
260e972bf22SNazar Kazakov            data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);    \
261e972bf22SNazar Kazakov            data = FIELD_DP32(data, VDATA, VMA, s->vma);                      \
262e972bf22SNazar Kazakov            rd_v = tcg_temp_new_ptr();                                        \
263e972bf22SNazar Kazakov            rs2_v = tcg_temp_new_ptr();                                       \
264e972bf22SNazar Kazakov            desc = tcg_constant_i32(                                          \
265f5a5e71eSDaniel Henrique Barboza                simd_desc(s->cfg_ptr->vlenb, s->cfg_ptr->vlenb, data));       \
266ad75a51eSRichard Henderson            tcg_gen_addi_ptr(rd_v, tcg_env, vreg_ofs(s, a->rd));              \
267ad75a51eSRichard Henderson            tcg_gen_addi_ptr(rs2_v, tcg_env, vreg_ofs(s, a->rs2));            \
268ad75a51eSRichard Henderson            gen_helper_##NAME(rd_v, rs2_v, tcg_env, desc);                    \
269*bac802adSIvan Klokov            finalize_rvv_inst(s);                                             \
270e972bf22SNazar Kazakov            return true;                                                      \
271e972bf22SNazar Kazakov        }                                                                     \
272e972bf22SNazar Kazakov        return false;                                                         \
273e972bf22SNazar Kazakov    }
274e972bf22SNazar Kazakov
275e972bf22SNazar Kazakovstatic bool vaes_check_vv(DisasContext *s, arg_rmr *a)
276e972bf22SNazar Kazakov{
277e972bf22SNazar Kazakov    int egw_bytes = ZVKNED_EGS << s->sew;
278e972bf22SNazar Kazakov    return s->cfg_ptr->ext_zvkned == true &&
279e972bf22SNazar Kazakov           require_rvv(s) &&
280e972bf22SNazar Kazakov           vext_check_isa_ill(s) &&
281e972bf22SNazar Kazakov           MAXSZ(s) >= egw_bytes &&
282e972bf22SNazar Kazakov           require_align(a->rd, s->lmul) &&
283e972bf22SNazar Kazakov           require_align(a->rs2, s->lmul) &&
284e972bf22SNazar Kazakov           s->sew == MO_32;
285e972bf22SNazar Kazakov}
286e972bf22SNazar Kazakov
287e972bf22SNazar Kazakovstatic bool vaes_check_overlap(DisasContext *s, int vd, int vs2)
288e972bf22SNazar Kazakov{
289e972bf22SNazar Kazakov    int8_t op_size = s->lmul <= 0 ? 1 : 1 << s->lmul;
290e972bf22SNazar Kazakov    return !is_overlapped(vd, op_size, vs2, 1);
291e972bf22SNazar Kazakov}
292e972bf22SNazar Kazakov
293e972bf22SNazar Kazakovstatic bool vaes_check_vs(DisasContext *s, arg_rmr *a)
294e972bf22SNazar Kazakov{
295e972bf22SNazar Kazakov    int egw_bytes = ZVKNED_EGS << s->sew;
296e972bf22SNazar Kazakov    return vaes_check_overlap(s, a->rd, a->rs2) &&
297e972bf22SNazar Kazakov           MAXSZ(s) >= egw_bytes &&
298e972bf22SNazar Kazakov           s->cfg_ptr->ext_zvkned == true &&
299e972bf22SNazar Kazakov           require_rvv(s) &&
300e972bf22SNazar Kazakov           vext_check_isa_ill(s) &&
301e972bf22SNazar Kazakov           require_align(a->rd, s->lmul) &&
302e972bf22SNazar Kazakov           s->sew == MO_32;
303e972bf22SNazar Kazakov}
304e972bf22SNazar Kazakov
305e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesef_vv, vaes_check_vv, ZVKNED_EGS)
306e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesef_vs, vaes_check_vs, ZVKNED_EGS)
307e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesdf_vv, vaes_check_vv, ZVKNED_EGS)
308e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesdf_vs, vaes_check_vs, ZVKNED_EGS)
309e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesdm_vv, vaes_check_vv, ZVKNED_EGS)
310e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesdm_vs, vaes_check_vs, ZVKNED_EGS)
311e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesz_vs, vaes_check_vs, ZVKNED_EGS)
312e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesem_vv, vaes_check_vv, ZVKNED_EGS)
313e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesem_vs, vaes_check_vs, ZVKNED_EGS)
314e972bf22SNazar Kazakov
315e972bf22SNazar Kazakov#define GEN_VI_UNMASKED_TRANS(NAME, CHECK, EGS)                               \
316e972bf22SNazar Kazakov    static bool trans_##NAME(DisasContext *s, arg_##NAME *a)                  \
317e972bf22SNazar Kazakov    {                                                                         \
318e972bf22SNazar Kazakov        if (CHECK(s, a)) {                                                    \
319e972bf22SNazar Kazakov            TCGv_ptr rd_v, rs2_v;                                             \
320e972bf22SNazar Kazakov            TCGv_i32 uimm_v, desc, egs;                                       \
321e972bf22SNazar Kazakov            uint32_t data = 0;                                                \
322e972bf22SNazar Kazakov                                                                              \
323e972bf22SNazar Kazakov            if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {                      \
324e972bf22SNazar Kazakov                /* save opcode for unwinding in case we throw an exception */ \
325e972bf22SNazar Kazakov                decode_save_opc(s);                                           \
326e972bf22SNazar Kazakov                egs = tcg_constant_i32(EGS);                                  \
327ad75a51eSRichard Henderson                gen_helper_egs_check(egs, tcg_env);                           \
328e972bf22SNazar Kazakov            }                                                                 \
329e972bf22SNazar Kazakov                                                                              \
330e972bf22SNazar Kazakov            data = FIELD_DP32(data, VDATA, VM, a->vm);                        \
331e972bf22SNazar Kazakov            data = FIELD_DP32(data, VDATA, LMUL, s->lmul);                    \
332e972bf22SNazar Kazakov            data = FIELD_DP32(data, VDATA, VTA, s->vta);                      \
333e972bf22SNazar Kazakov            data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);    \
334e972bf22SNazar Kazakov            data = FIELD_DP32(data, VDATA, VMA, s->vma);                      \
335e972bf22SNazar Kazakov                                                                              \
336e972bf22SNazar Kazakov            rd_v = tcg_temp_new_ptr();                                        \
337e972bf22SNazar Kazakov            rs2_v = tcg_temp_new_ptr();                                       \
338e972bf22SNazar Kazakov            uimm_v = tcg_constant_i32(a->rs1);                                \
339e972bf22SNazar Kazakov            desc = tcg_constant_i32(                                          \
340f5a5e71eSDaniel Henrique Barboza                simd_desc(s->cfg_ptr->vlenb, s->cfg_ptr->vlenb, data));       \
341ad75a51eSRichard Henderson            tcg_gen_addi_ptr(rd_v, tcg_env, vreg_ofs(s, a->rd));              \
342ad75a51eSRichard Henderson            tcg_gen_addi_ptr(rs2_v, tcg_env, vreg_ofs(s, a->rs2));            \
343ad75a51eSRichard Henderson            gen_helper_##NAME(rd_v, rs2_v, uimm_v, tcg_env, desc);            \
344*bac802adSIvan Klokov            finalize_rvv_inst(s);                                             \
345e972bf22SNazar Kazakov            return true;                                                      \
346e972bf22SNazar Kazakov        }                                                                     \
347e972bf22SNazar Kazakov        return false;                                                         \
348e972bf22SNazar Kazakov    }
349e972bf22SNazar Kazakov
350e972bf22SNazar Kazakovstatic bool vaeskf1_check(DisasContext *s, arg_vaeskf1_vi *a)
351e972bf22SNazar Kazakov{
352e972bf22SNazar Kazakov    int egw_bytes = ZVKNED_EGS << s->sew;
353e972bf22SNazar Kazakov    return s->cfg_ptr->ext_zvkned == true &&
354e972bf22SNazar Kazakov           require_rvv(s) &&
355e972bf22SNazar Kazakov           vext_check_isa_ill(s) &&
356e972bf22SNazar Kazakov           MAXSZ(s) >= egw_bytes &&
357e972bf22SNazar Kazakov           s->sew == MO_32 &&
358e972bf22SNazar Kazakov           require_align(a->rd, s->lmul) &&
359e972bf22SNazar Kazakov           require_align(a->rs2, s->lmul);
360e972bf22SNazar Kazakov}
361e972bf22SNazar Kazakov
362e972bf22SNazar Kazakovstatic bool vaeskf2_check(DisasContext *s, arg_vaeskf2_vi *a)
363e972bf22SNazar Kazakov{
364e972bf22SNazar Kazakov    int egw_bytes = ZVKNED_EGS << s->sew;
365e972bf22SNazar Kazakov    return s->cfg_ptr->ext_zvkned == true &&
366e972bf22SNazar Kazakov           require_rvv(s) &&
367e972bf22SNazar Kazakov           vext_check_isa_ill(s) &&
368e972bf22SNazar Kazakov           MAXSZ(s) >= egw_bytes &&
369e972bf22SNazar Kazakov           s->sew == MO_32 &&
370e972bf22SNazar Kazakov           require_align(a->rd, s->lmul) &&
371e972bf22SNazar Kazakov           require_align(a->rs2, s->lmul);
372e972bf22SNazar Kazakov}
373e972bf22SNazar Kazakov
374e972bf22SNazar KazakovGEN_VI_UNMASKED_TRANS(vaeskf1_vi, vaeskf1_check, ZVKNED_EGS)
375e972bf22SNazar KazakovGEN_VI_UNMASKED_TRANS(vaeskf2_vi, vaeskf2_check, ZVKNED_EGS)
376fcf19433SKiran Ostrolenk
377fcf19433SKiran Ostrolenk/*
378fcf19433SKiran Ostrolenk * Zvknh
379fcf19433SKiran Ostrolenk */
380fcf19433SKiran Ostrolenk
381fcf19433SKiran Ostrolenk#define ZVKNH_EGS 4
382fcf19433SKiran Ostrolenk
383fcf19433SKiran Ostrolenk#define GEN_VV_UNMASKED_TRANS(NAME, CHECK, EGS)                               \
384fcf19433SKiran Ostrolenk    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)                    \
385fcf19433SKiran Ostrolenk    {                                                                         \
386fcf19433SKiran Ostrolenk        if (CHECK(s, a)) {                                                    \
387fcf19433SKiran Ostrolenk            uint32_t data = 0;                                                \
388fcf19433SKiran Ostrolenk            TCGv_i32 egs;                                                     \
389fcf19433SKiran Ostrolenk                                                                              \
390fcf19433SKiran Ostrolenk            if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {                      \
391fcf19433SKiran Ostrolenk                /* save opcode for unwinding in case we throw an exception */ \
392fcf19433SKiran Ostrolenk                decode_save_opc(s);                                           \
393fcf19433SKiran Ostrolenk                egs = tcg_constant_i32(EGS);                                  \
394ad75a51eSRichard Henderson                gen_helper_egs_check(egs, tcg_env);                           \
395fcf19433SKiran Ostrolenk            }                                                                 \
396fcf19433SKiran Ostrolenk                                                                              \
397fcf19433SKiran Ostrolenk            data = FIELD_DP32(data, VDATA, VM, a->vm);                        \
398fcf19433SKiran Ostrolenk            data = FIELD_DP32(data, VDATA, LMUL, s->lmul);                    \
399fcf19433SKiran Ostrolenk            data = FIELD_DP32(data, VDATA, VTA, s->vta);                      \
400fcf19433SKiran Ostrolenk            data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);    \
401fcf19433SKiran Ostrolenk            data = FIELD_DP32(data, VDATA, VMA, s->vma);                      \
402fcf19433SKiran Ostrolenk                                                                              \
403fcf19433SKiran Ostrolenk            tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),       \
404ad75a51eSRichard Henderson                               vreg_ofs(s, a->rs2), tcg_env,                  \
405f5a5e71eSDaniel Henrique Barboza                               s->cfg_ptr->vlenb, s->cfg_ptr->vlenb,          \
406fcf19433SKiran Ostrolenk                               data, gen_helper_##NAME);                      \
407fcf19433SKiran Ostrolenk                                                                              \
408*bac802adSIvan Klokov            finalize_rvv_inst(s);                                             \
409fcf19433SKiran Ostrolenk            return true;                                                      \
410fcf19433SKiran Ostrolenk        }                                                                     \
411fcf19433SKiran Ostrolenk        return false;                                                         \
412fcf19433SKiran Ostrolenk    }
413fcf19433SKiran Ostrolenk
414fcf19433SKiran Ostrolenkstatic bool vsha_check_sew(DisasContext *s)
415fcf19433SKiran Ostrolenk{
416fcf19433SKiran Ostrolenk    return (s->cfg_ptr->ext_zvknha == true && s->sew == MO_32) ||
417fcf19433SKiran Ostrolenk           (s->cfg_ptr->ext_zvknhb == true &&
418fcf19433SKiran Ostrolenk            (s->sew == MO_32 || s->sew == MO_64));
419fcf19433SKiran Ostrolenk}
420fcf19433SKiran Ostrolenk
421fcf19433SKiran Ostrolenkstatic bool vsha_check(DisasContext *s, arg_rmrr *a)
422fcf19433SKiran Ostrolenk{
423fcf19433SKiran Ostrolenk    int egw_bytes = ZVKNH_EGS << s->sew;
424fcf19433SKiran Ostrolenk    int mult = 1 << MAX(s->lmul, 0);
425fcf19433SKiran Ostrolenk    return opivv_check(s, a) &&
426fcf19433SKiran Ostrolenk           vsha_check_sew(s) &&
427fcf19433SKiran Ostrolenk           MAXSZ(s) >= egw_bytes &&
428fcf19433SKiran Ostrolenk           !is_overlapped(a->rd, mult, a->rs1, mult) &&
429fcf19433SKiran Ostrolenk           !is_overlapped(a->rd, mult, a->rs2, mult) &&
430fcf19433SKiran Ostrolenk           s->lmul >= 0;
431fcf19433SKiran Ostrolenk}
432fcf19433SKiran Ostrolenk
433fcf19433SKiran OstrolenkGEN_VV_UNMASKED_TRANS(vsha2ms_vv, vsha_check, ZVKNH_EGS)
434fcf19433SKiran Ostrolenk
435fcf19433SKiran Ostrolenkstatic bool trans_vsha2cl_vv(DisasContext *s, arg_rmrr *a)
436fcf19433SKiran Ostrolenk{
437fcf19433SKiran Ostrolenk    if (vsha_check(s, a)) {
438fcf19433SKiran Ostrolenk        uint32_t data = 0;
439fcf19433SKiran Ostrolenk        TCGv_i32 egs;
440fcf19433SKiran Ostrolenk
441fcf19433SKiran Ostrolenk        if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {
442fcf19433SKiran Ostrolenk            /* save opcode for unwinding in case we throw an exception */
443fcf19433SKiran Ostrolenk            decode_save_opc(s);
444fcf19433SKiran Ostrolenk            egs = tcg_constant_i32(ZVKNH_EGS);
445ad75a51eSRichard Henderson            gen_helper_egs_check(egs, tcg_env);
446fcf19433SKiran Ostrolenk        }
447fcf19433SKiran Ostrolenk
448fcf19433SKiran Ostrolenk        data = FIELD_DP32(data, VDATA, VM, a->vm);
449fcf19433SKiran Ostrolenk        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
450fcf19433SKiran Ostrolenk        data = FIELD_DP32(data, VDATA, VTA, s->vta);
451fcf19433SKiran Ostrolenk        data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
452fcf19433SKiran Ostrolenk        data = FIELD_DP32(data, VDATA, VMA, s->vma);
453fcf19433SKiran Ostrolenk
454fcf19433SKiran Ostrolenk        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),
455f5a5e71eSDaniel Henrique Barboza            vreg_ofs(s, a->rs2), tcg_env, s->cfg_ptr->vlenb,
456f5a5e71eSDaniel Henrique Barboza            s->cfg_ptr->vlenb, data,
457fcf19433SKiran Ostrolenk            s->sew == MO_32 ?
458fcf19433SKiran Ostrolenk                gen_helper_vsha2cl32_vv : gen_helper_vsha2cl64_vv);
459fcf19433SKiran Ostrolenk
460*bac802adSIvan Klokov        finalize_rvv_inst(s);
461fcf19433SKiran Ostrolenk        return true;
462fcf19433SKiran Ostrolenk    }
463fcf19433SKiran Ostrolenk    return false;
464fcf19433SKiran Ostrolenk}
465fcf19433SKiran Ostrolenk
466fcf19433SKiran Ostrolenkstatic bool trans_vsha2ch_vv(DisasContext *s, arg_rmrr *a)
467fcf19433SKiran Ostrolenk{
468fcf19433SKiran Ostrolenk    if (vsha_check(s, a)) {
469fcf19433SKiran Ostrolenk        uint32_t data = 0;
470fcf19433SKiran Ostrolenk        TCGv_i32 egs;
471fcf19433SKiran Ostrolenk
472fcf19433SKiran Ostrolenk        if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {
473fcf19433SKiran Ostrolenk            /* save opcode for unwinding in case we throw an exception */
474fcf19433SKiran Ostrolenk            decode_save_opc(s);
475fcf19433SKiran Ostrolenk            egs = tcg_constant_i32(ZVKNH_EGS);
476ad75a51eSRichard Henderson            gen_helper_egs_check(egs, tcg_env);
477fcf19433SKiran Ostrolenk        }
478fcf19433SKiran Ostrolenk
479fcf19433SKiran Ostrolenk        data = FIELD_DP32(data, VDATA, VM, a->vm);
480fcf19433SKiran Ostrolenk        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
481fcf19433SKiran Ostrolenk        data = FIELD_DP32(data, VDATA, VTA, s->vta);
482fcf19433SKiran Ostrolenk        data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
483fcf19433SKiran Ostrolenk        data = FIELD_DP32(data, VDATA, VMA, s->vma);
484fcf19433SKiran Ostrolenk
485fcf19433SKiran Ostrolenk        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),
486f5a5e71eSDaniel Henrique Barboza            vreg_ofs(s, a->rs2), tcg_env, s->cfg_ptr->vlenb,
487f5a5e71eSDaniel Henrique Barboza            s->cfg_ptr->vlenb, data,
488fcf19433SKiran Ostrolenk            s->sew == MO_32 ?
489fcf19433SKiran Ostrolenk                gen_helper_vsha2ch32_vv : gen_helper_vsha2ch64_vv);
490fcf19433SKiran Ostrolenk
491*bac802adSIvan Klokov        finalize_rvv_inst(s);
492fcf19433SKiran Ostrolenk        return true;
493fcf19433SKiran Ostrolenk    }
494fcf19433SKiran Ostrolenk    return false;
495fcf19433SKiran Ostrolenk}
4962350881cSLawrence Hunter
4972350881cSLawrence Hunter/*
4982350881cSLawrence Hunter * Zvksh
4992350881cSLawrence Hunter */
5002350881cSLawrence Hunter
5012350881cSLawrence Hunter#define ZVKSH_EGS 8
5022350881cSLawrence Hunter
5032350881cSLawrence Hunterstatic inline bool vsm3_check(DisasContext *s, arg_rmrr *a)
5042350881cSLawrence Hunter{
5052350881cSLawrence Hunter    int egw_bytes = ZVKSH_EGS << s->sew;
5062350881cSLawrence Hunter    int mult = 1 << MAX(s->lmul, 0);
5072350881cSLawrence Hunter    return s->cfg_ptr->ext_zvksh == true &&
5082350881cSLawrence Hunter           require_rvv(s) &&
5092350881cSLawrence Hunter           vext_check_isa_ill(s) &&
5102350881cSLawrence Hunter           !is_overlapped(a->rd, mult, a->rs2, mult) &&
5112350881cSLawrence Hunter           MAXSZ(s) >= egw_bytes &&
5122350881cSLawrence Hunter           s->sew == MO_32;
5132350881cSLawrence Hunter}
5142350881cSLawrence Hunter
5152350881cSLawrence Hunterstatic inline bool vsm3me_check(DisasContext *s, arg_rmrr *a)
5162350881cSLawrence Hunter{
5172350881cSLawrence Hunter    return vsm3_check(s, a) && vext_check_sss(s, a->rd, a->rs1, a->rs2, a->vm);
5182350881cSLawrence Hunter}
5192350881cSLawrence Hunter
5202350881cSLawrence Hunterstatic inline bool vsm3c_check(DisasContext *s, arg_rmrr *a)
5212350881cSLawrence Hunter{
5222350881cSLawrence Hunter    return vsm3_check(s, a) && vext_check_ss(s, a->rd, a->rs2, a->vm);
5232350881cSLawrence Hunter}
5242350881cSLawrence Hunter
5252350881cSLawrence HunterGEN_VV_UNMASKED_TRANS(vsm3me_vv, vsm3me_check, ZVKSH_EGS)
5262350881cSLawrence HunterGEN_VI_UNMASKED_TRANS(vsm3c_vi, vsm3c_check, ZVKSH_EGS)
527767eb035SNazar Kazakov
528767eb035SNazar Kazakov/*
529767eb035SNazar Kazakov * Zvkg
530767eb035SNazar Kazakov */
531767eb035SNazar Kazakov
532767eb035SNazar Kazakov#define ZVKG_EGS 4
533767eb035SNazar Kazakov
534767eb035SNazar Kazakovstatic bool vgmul_check(DisasContext *s, arg_rmr *a)
535767eb035SNazar Kazakov{
536767eb035SNazar Kazakov    int egw_bytes = ZVKG_EGS << s->sew;
537767eb035SNazar Kazakov    return s->cfg_ptr->ext_zvkg == true &&
538767eb035SNazar Kazakov           vext_check_isa_ill(s) &&
539767eb035SNazar Kazakov           require_rvv(s) &&
540767eb035SNazar Kazakov           MAXSZ(s) >= egw_bytes &&
541767eb035SNazar Kazakov           vext_check_ss(s, a->rd, a->rs2, a->vm) &&
542767eb035SNazar Kazakov           s->sew == MO_32;
543767eb035SNazar Kazakov}
544767eb035SNazar Kazakov
545767eb035SNazar KazakovGEN_V_UNMASKED_TRANS(vgmul_vv, vgmul_check, ZVKG_EGS)
546767eb035SNazar Kazakov
547767eb035SNazar Kazakovstatic bool vghsh_check(DisasContext *s, arg_rmrr *a)
548767eb035SNazar Kazakov{
549767eb035SNazar Kazakov    int egw_bytes = ZVKG_EGS << s->sew;
550767eb035SNazar Kazakov    return s->cfg_ptr->ext_zvkg == true &&
551767eb035SNazar Kazakov           opivv_check(s, a) &&
552767eb035SNazar Kazakov           MAXSZ(s) >= egw_bytes &&
553767eb035SNazar Kazakov           s->sew == MO_32;
554767eb035SNazar Kazakov}
555767eb035SNazar Kazakov
556767eb035SNazar KazakovGEN_VV_UNMASKED_TRANS(vghsh_vv, vghsh_check, ZVKG_EGS)
5578b045ff4SMax Chou
5588b045ff4SMax Chou/*
5598b045ff4SMax Chou * Zvksed
5608b045ff4SMax Chou */
5618b045ff4SMax Chou
5628b045ff4SMax Chou#define ZVKSED_EGS 4
5638b045ff4SMax Chou
5648b045ff4SMax Choustatic bool zvksed_check(DisasContext *s)
5658b045ff4SMax Chou{
5668b045ff4SMax Chou    int egw_bytes = ZVKSED_EGS << s->sew;
5678b045ff4SMax Chou    return s->cfg_ptr->ext_zvksed == true &&
5688b045ff4SMax Chou           require_rvv(s) &&
5698b045ff4SMax Chou           vext_check_isa_ill(s) &&
5708b045ff4SMax Chou           MAXSZ(s) >= egw_bytes &&
5718b045ff4SMax Chou           s->sew == MO_32;
5728b045ff4SMax Chou}
5738b045ff4SMax Chou
5748b045ff4SMax Choustatic bool vsm4k_vi_check(DisasContext *s, arg_rmrr *a)
5758b045ff4SMax Chou{
5768b045ff4SMax Chou    return zvksed_check(s) &&
5778b045ff4SMax Chou           require_align(a->rd, s->lmul) &&
5788b045ff4SMax Chou           require_align(a->rs2, s->lmul);
5798b045ff4SMax Chou}
5808b045ff4SMax Chou
5818b045ff4SMax ChouGEN_VI_UNMASKED_TRANS(vsm4k_vi, vsm4k_vi_check, ZVKSED_EGS)
5828b045ff4SMax Chou
5838b045ff4SMax Choustatic bool vsm4r_vv_check(DisasContext *s, arg_rmr *a)
5848b045ff4SMax Chou{
5858b045ff4SMax Chou    return zvksed_check(s) &&
5868b045ff4SMax Chou           require_align(a->rd, s->lmul) &&
5878b045ff4SMax Chou           require_align(a->rs2, s->lmul);
5888b045ff4SMax Chou}
5898b045ff4SMax Chou
5908b045ff4SMax ChouGEN_V_UNMASKED_TRANS(vsm4r_vv, vsm4r_vv_check, ZVKSED_EGS)
5918b045ff4SMax Chou
5928b045ff4SMax Choustatic bool vsm4r_vs_check(DisasContext *s, arg_rmr *a)
5938b045ff4SMax Chou{
5948b045ff4SMax Chou    return zvksed_check(s) &&
5958b045ff4SMax Chou           !is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs2, 1) &&
5968b045ff4SMax Chou           require_align(a->rd, s->lmul);
5978b045ff4SMax Chou}
5988b045ff4SMax Chou
5998b045ff4SMax ChouGEN_V_UNMASKED_TRANS(vsm4r_vs, vsm4r_vs_check, ZVKSED_EGS)
600