1/*
2 * RISC-V translation routines for the vector crypto extension.
3 *
4 * Copyright (C) 2023 SiFive, Inc.
5 * Written by Codethink Ltd and SiFive.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2 or later, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20/*
21 * Zvbc
22 */
23
24#define GEN_VV_MASKED_TRANS(NAME, CHECK)                     \
25    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)   \
26    {                                                        \
27        if (CHECK(s, a)) {                                   \
28            return opivv_trans(a->rd, a->rs1, a->rs2, a->vm, \
29                               gen_helper_##NAME, s);        \
30        }                                                    \
31        return false;                                        \
32    }
33
34static bool vclmul_vv_check(DisasContext *s, arg_rmrr *a)
35{
36    return opivv_check(s, a) &&
37           s->cfg_ptr->ext_zvbc == true &&
38           s->sew == MO_64;
39}
40
41GEN_VV_MASKED_TRANS(vclmul_vv, vclmul_vv_check)
42GEN_VV_MASKED_TRANS(vclmulh_vv, vclmul_vv_check)
43
44#define GEN_VX_MASKED_TRANS(NAME, CHECK)                     \
45    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)   \
46    {                                                        \
47        if (CHECK(s, a)) {                                   \
48            return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, \
49                               gen_helper_##NAME, s);        \
50        }                                                    \
51        return false;                                        \
52    }
53
54static bool vclmul_vx_check(DisasContext *s, arg_rmrr *a)
55{
56    return opivx_check(s, a) &&
57           s->cfg_ptr->ext_zvbc == true &&
58           s->sew == MO_64;
59}
60
61GEN_VX_MASKED_TRANS(vclmul_vx, vclmul_vx_check)
62GEN_VX_MASKED_TRANS(vclmulh_vx, vclmul_vx_check)
63
64/*
65 * Zvbb
66 */
67
68#define GEN_OPIVI_GVEC_TRANS_CHECK(NAME, IMM_MODE, OPIVX, SUF, CHECK)   \
69    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)              \
70    {                                                                   \
71        if (CHECK(s, a)) {                                              \
72            static gen_helper_opivx *const fns[4] = {                   \
73                gen_helper_##OPIVX##_b,                                 \
74                gen_helper_##OPIVX##_h,                                 \
75                gen_helper_##OPIVX##_w,                                 \
76                gen_helper_##OPIVX##_d,                                 \
77            };                                                          \
78            return do_opivi_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew], \
79                                 IMM_MODE);                             \
80        }                                                               \
81        return false;                                                   \
82    }
83
84#define GEN_OPIVV_GVEC_TRANS_CHECK(NAME, SUF, CHECK)                     \
85    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)               \
86    {                                                                    \
87        if (CHECK(s, a)) {                                               \
88            static gen_helper_gvec_4_ptr *const fns[4] = {               \
89                gen_helper_##NAME##_b,                                   \
90                gen_helper_##NAME##_h,                                   \
91                gen_helper_##NAME##_w,                                   \
92                gen_helper_##NAME##_d,                                   \
93            };                                                           \
94            return do_opivv_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]); \
95        }                                                                \
96        return false;                                                    \
97    }
98
99#define GEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(NAME, SUF, CHECK)       \
100    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)       \
101    {                                                            \
102        if (CHECK(s, a)) {                                       \
103            static gen_helper_opivx *const fns[4] = {            \
104                gen_helper_##NAME##_b,                           \
105                gen_helper_##NAME##_h,                           \
106                gen_helper_##NAME##_w,                           \
107                gen_helper_##NAME##_d,                           \
108            };                                                   \
109            return do_opivx_gvec_shift(s, a, tcg_gen_gvec_##SUF, \
110                                       fns[s->sew]);             \
111        }                                                        \
112        return false;                                            \
113    }
114
115static bool zvkb_vv_check(DisasContext *s, arg_rmrr *a)
116{
117    return opivv_check(s, a) &&
118           (s->cfg_ptr->ext_zvbb == true || s->cfg_ptr->ext_zvkb == true);
119}
120
121static bool zvkb_vx_check(DisasContext *s, arg_rmrr *a)
122{
123    return opivx_check(s, a) &&
124           (s->cfg_ptr->ext_zvbb == true || s->cfg_ptr->ext_zvkb == true);
125}
126
127/* vrol.v[vx] */
128GEN_OPIVV_GVEC_TRANS_CHECK(vrol_vv, rotlv, zvkb_vv_check)
129GEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(vrol_vx, rotls, zvkb_vx_check)
130
131/* vror.v[vxi] */
132GEN_OPIVV_GVEC_TRANS_CHECK(vror_vv, rotrv, zvkb_vv_check)
133GEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(vror_vx, rotrs, zvkb_vx_check)
134GEN_OPIVI_GVEC_TRANS_CHECK(vror_vi, IMM_TRUNC_SEW, vror_vx, rotri,
135                           zvkb_vx_check)
136
137#define GEN_OPIVX_GVEC_TRANS_CHECK(NAME, SUF, CHECK)                     \
138    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)               \
139    {                                                                    \
140        if (CHECK(s, a)) {                                               \
141            static gen_helper_opivx *const fns[4] = {                    \
142                gen_helper_##NAME##_b,                                   \
143                gen_helper_##NAME##_h,                                   \
144                gen_helper_##NAME##_w,                                   \
145                gen_helper_##NAME##_d,                                   \
146            };                                                           \
147            return do_opivx_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]); \
148        }                                                                \
149        return false;                                                    \
150    }
151
152/* vandn.v[vx] */
153GEN_OPIVV_GVEC_TRANS_CHECK(vandn_vv, andc, zvkb_vv_check)
154GEN_OPIVX_GVEC_TRANS_CHECK(vandn_vx, andcs, zvkb_vx_check)
155
156#define GEN_OPIV_TRANS(NAME, CHECK)                                        \
157    static bool trans_##NAME(DisasContext *s, arg_rmr *a)                  \
158    {                                                                      \
159        if (CHECK(s, a)) {                                                 \
160            uint32_t data = 0;                                             \
161            static gen_helper_gvec_3_ptr *const fns[4] = {                 \
162                gen_helper_##NAME##_b,                                     \
163                gen_helper_##NAME##_h,                                     \
164                gen_helper_##NAME##_w,                                     \
165                gen_helper_##NAME##_d,                                     \
166            };                                                             \
167                                                                           \
168            data = FIELD_DP32(data, VDATA, VM, a->vm);                     \
169            data = FIELD_DP32(data, VDATA, LMUL, s->lmul);                 \
170            data = FIELD_DP32(data, VDATA, VTA, s->vta);                   \
171            data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s); \
172            data = FIELD_DP32(data, VDATA, VMA, s->vma);                   \
173            tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),         \
174                               vreg_ofs(s, a->rs2), tcg_env,               \
175                               s->cfg_ptr->vlenb, s->cfg_ptr->vlenb,       \
176                               data, fns[s->sew]);                         \
177            finalize_rvv_inst(s);                                          \
178            return true;                                                   \
179        }                                                                  \
180        return false;                                                      \
181    }
182
183static bool zvbb_opiv_check(DisasContext *s, arg_rmr *a)
184{
185    return s->cfg_ptr->ext_zvbb == true &&
186           require_rvv(s) &&
187           vext_check_isa_ill(s) &&
188           vext_check_ss(s, a->rd, a->rs2, a->vm);
189}
190
191static bool zvkb_opiv_check(DisasContext *s, arg_rmr *a)
192{
193    return (s->cfg_ptr->ext_zvbb == true || s->cfg_ptr->ext_zvkb == true) &&
194           require_rvv(s) &&
195           vext_check_isa_ill(s) &&
196           vext_check_ss(s, a->rd, a->rs2, a->vm);
197}
198
199GEN_OPIV_TRANS(vbrev8_v, zvkb_opiv_check)
200GEN_OPIV_TRANS(vrev8_v, zvkb_opiv_check)
201GEN_OPIV_TRANS(vbrev_v, zvbb_opiv_check)
202GEN_OPIV_TRANS(vclz_v, zvbb_opiv_check)
203GEN_OPIV_TRANS(vctz_v, zvbb_opiv_check)
204GEN_OPIV_TRANS(vcpop_v, zvbb_opiv_check)
205
206static bool vwsll_vv_check(DisasContext *s, arg_rmrr *a)
207{
208    return s->cfg_ptr->ext_zvbb && opivv_widen_check(s, a);
209}
210
211static bool vwsll_vx_check(DisasContext *s, arg_rmrr *a)
212{
213    return s->cfg_ptr->ext_zvbb && opivx_widen_check(s, a);
214}
215
216/* OPIVI without GVEC IR */
217#define GEN_OPIVI_WIDEN_TRANS(NAME, IMM_MODE, OPIVX, CHECK)                  \
218    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)                   \
219    {                                                                        \
220        if (CHECK(s, a)) {                                                   \
221            static gen_helper_opivx *const fns[3] = {                        \
222                gen_helper_##OPIVX##_b,                                      \
223                gen_helper_##OPIVX##_h,                                      \
224                gen_helper_##OPIVX##_w,                                      \
225            };                                                               \
226            return opivi_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s, \
227                               IMM_MODE);                                    \
228        }                                                                    \
229        return false;                                                        \
230    }
231
232GEN_OPIVV_WIDEN_TRANS(vwsll_vv, vwsll_vv_check)
233GEN_OPIVX_WIDEN_TRANS(vwsll_vx, vwsll_vx_check)
234GEN_OPIVI_WIDEN_TRANS(vwsll_vi, IMM_ZX, vwsll_vx, vwsll_vx_check)
235
236/*
237 * Zvkned
238 */
239
240#define ZVKNED_EGS 4
241
242#define GEN_V_UNMASKED_TRANS(NAME, CHECK, EGS)                                \
243    static bool trans_##NAME(DisasContext *s, arg_##NAME *a)                  \
244    {                                                                         \
245        if (CHECK(s, a)) {                                                    \
246            TCGv_ptr rd_v, rs2_v;                                             \
247            TCGv_i32 desc, egs;                                               \
248            uint32_t data = 0;                                                \
249                                                                              \
250            if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {                      \
251                /* save opcode for unwinding in case we throw an exception */ \
252                decode_save_opc(s, 0);                                        \
253                egs = tcg_constant_i32(EGS);                                  \
254                gen_helper_egs_check(egs, tcg_env);                           \
255            }                                                                 \
256                                                                              \
257            data = FIELD_DP32(data, VDATA, VM, a->vm);                        \
258            data = FIELD_DP32(data, VDATA, LMUL, s->lmul);                    \
259            data = FIELD_DP32(data, VDATA, VTA, s->vta);                      \
260            data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);    \
261            data = FIELD_DP32(data, VDATA, VMA, s->vma);                      \
262            rd_v = tcg_temp_new_ptr();                                        \
263            rs2_v = tcg_temp_new_ptr();                                       \
264            desc = tcg_constant_i32(                                          \
265                simd_desc(s->cfg_ptr->vlenb, s->cfg_ptr->vlenb, data));       \
266            tcg_gen_addi_ptr(rd_v, tcg_env, vreg_ofs(s, a->rd));              \
267            tcg_gen_addi_ptr(rs2_v, tcg_env, vreg_ofs(s, a->rs2));            \
268            gen_helper_##NAME(rd_v, rs2_v, tcg_env, desc);                    \
269            finalize_rvv_inst(s);                                             \
270            return true;                                                      \
271        }                                                                     \
272        return false;                                                         \
273    }
274
275static bool vaes_check_vv(DisasContext *s, arg_rmr *a)
276{
277    int egw_bytes = ZVKNED_EGS << s->sew;
278    return s->cfg_ptr->ext_zvkned == true &&
279           require_rvv(s) &&
280           vext_check_isa_ill(s) &&
281           MAXSZ(s) >= egw_bytes &&
282           require_align(a->rd, s->lmul) &&
283           require_align(a->rs2, s->lmul) &&
284           s->sew == MO_32;
285}
286
287static bool vaes_check_overlap(DisasContext *s, int vd, int vs2)
288{
289    int8_t op_size = s->lmul <= 0 ? 1 : 1 << s->lmul;
290    return !is_overlapped(vd, op_size, vs2, 1);
291}
292
293static bool vaes_check_vs(DisasContext *s, arg_rmr *a)
294{
295    int egw_bytes = ZVKNED_EGS << s->sew;
296    return vaes_check_overlap(s, a->rd, a->rs2) &&
297           MAXSZ(s) >= egw_bytes &&
298           s->cfg_ptr->ext_zvkned == true &&
299           require_rvv(s) &&
300           vext_check_isa_ill(s) &&
301           require_align(a->rd, s->lmul) &&
302           s->sew == MO_32;
303}
304
305GEN_V_UNMASKED_TRANS(vaesef_vv, vaes_check_vv, ZVKNED_EGS)
306GEN_V_UNMASKED_TRANS(vaesef_vs, vaes_check_vs, ZVKNED_EGS)
307GEN_V_UNMASKED_TRANS(vaesdf_vv, vaes_check_vv, ZVKNED_EGS)
308GEN_V_UNMASKED_TRANS(vaesdf_vs, vaes_check_vs, ZVKNED_EGS)
309GEN_V_UNMASKED_TRANS(vaesdm_vv, vaes_check_vv, ZVKNED_EGS)
310GEN_V_UNMASKED_TRANS(vaesdm_vs, vaes_check_vs, ZVKNED_EGS)
311GEN_V_UNMASKED_TRANS(vaesz_vs, vaes_check_vs, ZVKNED_EGS)
312GEN_V_UNMASKED_TRANS(vaesem_vv, vaes_check_vv, ZVKNED_EGS)
313GEN_V_UNMASKED_TRANS(vaesem_vs, vaes_check_vs, ZVKNED_EGS)
314
315#define GEN_VI_UNMASKED_TRANS(NAME, CHECK, EGS)                               \
316    static bool trans_##NAME(DisasContext *s, arg_##NAME *a)                  \
317    {                                                                         \
318        if (CHECK(s, a)) {                                                    \
319            TCGv_ptr rd_v, rs2_v;                                             \
320            TCGv_i32 uimm_v, desc, egs;                                       \
321            uint32_t data = 0;                                                \
322                                                                              \
323            if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {                      \
324                /* save opcode for unwinding in case we throw an exception */ \
325                decode_save_opc(s, 0);                                        \
326                egs = tcg_constant_i32(EGS);                                  \
327                gen_helper_egs_check(egs, tcg_env);                           \
328            }                                                                 \
329                                                                              \
330            data = FIELD_DP32(data, VDATA, VM, a->vm);                        \
331            data = FIELD_DP32(data, VDATA, LMUL, s->lmul);                    \
332            data = FIELD_DP32(data, VDATA, VTA, s->vta);                      \
333            data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);    \
334            data = FIELD_DP32(data, VDATA, VMA, s->vma);                      \
335                                                                              \
336            rd_v = tcg_temp_new_ptr();                                        \
337            rs2_v = tcg_temp_new_ptr();                                       \
338            uimm_v = tcg_constant_i32(a->rs1);                                \
339            desc = tcg_constant_i32(                                          \
340                simd_desc(s->cfg_ptr->vlenb, s->cfg_ptr->vlenb, data));       \
341            tcg_gen_addi_ptr(rd_v, tcg_env, vreg_ofs(s, a->rd));              \
342            tcg_gen_addi_ptr(rs2_v, tcg_env, vreg_ofs(s, a->rs2));            \
343            gen_helper_##NAME(rd_v, rs2_v, uimm_v, tcg_env, desc);            \
344            finalize_rvv_inst(s);                                             \
345            return true;                                                      \
346        }                                                                     \
347        return false;                                                         \
348    }
349
350static bool vaeskf1_check(DisasContext *s, arg_vaeskf1_vi *a)
351{
352    int egw_bytes = ZVKNED_EGS << s->sew;
353    return s->cfg_ptr->ext_zvkned == true &&
354           require_rvv(s) &&
355           vext_check_isa_ill(s) &&
356           MAXSZ(s) >= egw_bytes &&
357           s->sew == MO_32 &&
358           require_align(a->rd, s->lmul) &&
359           require_align(a->rs2, s->lmul);
360}
361
362static bool vaeskf2_check(DisasContext *s, arg_vaeskf2_vi *a)
363{
364    int egw_bytes = ZVKNED_EGS << s->sew;
365    return s->cfg_ptr->ext_zvkned == true &&
366           require_rvv(s) &&
367           vext_check_isa_ill(s) &&
368           MAXSZ(s) >= egw_bytes &&
369           s->sew == MO_32 &&
370           require_align(a->rd, s->lmul) &&
371           require_align(a->rs2, s->lmul);
372}
373
374GEN_VI_UNMASKED_TRANS(vaeskf1_vi, vaeskf1_check, ZVKNED_EGS)
375GEN_VI_UNMASKED_TRANS(vaeskf2_vi, vaeskf2_check, ZVKNED_EGS)
376
377/*
378 * Zvknh
379 */
380
381#define ZVKNH_EGS 4
382
383#define GEN_VV_UNMASKED_TRANS(NAME, CHECK, EGS)                               \
384    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)                    \
385    {                                                                         \
386        if (CHECK(s, a)) {                                                    \
387            uint32_t data = 0;                                                \
388            TCGv_i32 egs;                                                     \
389                                                                              \
390            if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {                      \
391                /* save opcode for unwinding in case we throw an exception */ \
392                decode_save_opc(s, 0);                                        \
393                egs = tcg_constant_i32(EGS);                                  \
394                gen_helper_egs_check(egs, tcg_env);                           \
395            }                                                                 \
396                                                                              \
397            data = FIELD_DP32(data, VDATA, VM, a->vm);                        \
398            data = FIELD_DP32(data, VDATA, LMUL, s->lmul);                    \
399            data = FIELD_DP32(data, VDATA, VTA, s->vta);                      \
400            data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);    \
401            data = FIELD_DP32(data, VDATA, VMA, s->vma);                      \
402                                                                              \
403            tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),       \
404                               vreg_ofs(s, a->rs2), tcg_env,                  \
405                               s->cfg_ptr->vlenb, s->cfg_ptr->vlenb,          \
406                               data, gen_helper_##NAME);                      \
407                                                                              \
408            finalize_rvv_inst(s);                                             \
409            return true;                                                      \
410        }                                                                     \
411        return false;                                                         \
412    }
413
414static bool vsha_check_sew(DisasContext *s)
415{
416    return (s->cfg_ptr->ext_zvknha == true && s->sew == MO_32) ||
417           (s->cfg_ptr->ext_zvknhb == true &&
418            (s->sew == MO_32 || s->sew == MO_64));
419}
420
421static bool vsha_check(DisasContext *s, arg_rmrr *a)
422{
423    int egw_bytes = ZVKNH_EGS << s->sew;
424    int mult = 1 << MAX(s->lmul, 0);
425    return opivv_check(s, a) &&
426           vsha_check_sew(s) &&
427           MAXSZ(s) >= egw_bytes &&
428           !is_overlapped(a->rd, mult, a->rs1, mult) &&
429           !is_overlapped(a->rd, mult, a->rs2, mult) &&
430           s->lmul >= 0;
431}
432
433GEN_VV_UNMASKED_TRANS(vsha2ms_vv, vsha_check, ZVKNH_EGS)
434
435static bool trans_vsha2cl_vv(DisasContext *s, arg_rmrr *a)
436{
437    if (vsha_check(s, a)) {
438        uint32_t data = 0;
439        TCGv_i32 egs;
440
441        if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {
442            /* save opcode for unwinding in case we throw an exception */
443            decode_save_opc(s, 0);
444            egs = tcg_constant_i32(ZVKNH_EGS);
445            gen_helper_egs_check(egs, tcg_env);
446        }
447
448        data = FIELD_DP32(data, VDATA, VM, a->vm);
449        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
450        data = FIELD_DP32(data, VDATA, VTA, s->vta);
451        data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
452        data = FIELD_DP32(data, VDATA, VMA, s->vma);
453
454        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),
455            vreg_ofs(s, a->rs2), tcg_env, s->cfg_ptr->vlenb,
456            s->cfg_ptr->vlenb, data,
457            s->sew == MO_32 ?
458                gen_helper_vsha2cl32_vv : gen_helper_vsha2cl64_vv);
459
460        finalize_rvv_inst(s);
461        return true;
462    }
463    return false;
464}
465
466static bool trans_vsha2ch_vv(DisasContext *s, arg_rmrr *a)
467{
468    if (vsha_check(s, a)) {
469        uint32_t data = 0;
470        TCGv_i32 egs;
471
472        if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {
473            /* save opcode for unwinding in case we throw an exception */
474            decode_save_opc(s, 0);
475            egs = tcg_constant_i32(ZVKNH_EGS);
476            gen_helper_egs_check(egs, tcg_env);
477        }
478
479        data = FIELD_DP32(data, VDATA, VM, a->vm);
480        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
481        data = FIELD_DP32(data, VDATA, VTA, s->vta);
482        data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
483        data = FIELD_DP32(data, VDATA, VMA, s->vma);
484
485        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),
486            vreg_ofs(s, a->rs2), tcg_env, s->cfg_ptr->vlenb,
487            s->cfg_ptr->vlenb, data,
488            s->sew == MO_32 ?
489                gen_helper_vsha2ch32_vv : gen_helper_vsha2ch64_vv);
490
491        finalize_rvv_inst(s);
492        return true;
493    }
494    return false;
495}
496
497/*
498 * Zvksh
499 */
500
501#define ZVKSH_EGS 8
502
503static inline bool vsm3_check(DisasContext *s, arg_rmrr *a)
504{
505    int egw_bytes = ZVKSH_EGS << s->sew;
506    int mult = 1 << MAX(s->lmul, 0);
507    return s->cfg_ptr->ext_zvksh == true &&
508           require_rvv(s) &&
509           vext_check_isa_ill(s) &&
510           !is_overlapped(a->rd, mult, a->rs2, mult) &&
511           MAXSZ(s) >= egw_bytes &&
512           s->sew == MO_32;
513}
514
515static inline bool vsm3me_check(DisasContext *s, arg_rmrr *a)
516{
517    return vsm3_check(s, a) && vext_check_sss(s, a->rd, a->rs1, a->rs2, a->vm);
518}
519
520static inline bool vsm3c_check(DisasContext *s, arg_rmrr *a)
521{
522    return vsm3_check(s, a) && vext_check_ss(s, a->rd, a->rs2, a->vm);
523}
524
525GEN_VV_UNMASKED_TRANS(vsm3me_vv, vsm3me_check, ZVKSH_EGS)
526GEN_VI_UNMASKED_TRANS(vsm3c_vi, vsm3c_check, ZVKSH_EGS)
527
528/*
529 * Zvkg
530 */
531
532#define ZVKG_EGS 4
533
534static bool vgmul_check(DisasContext *s, arg_rmr *a)
535{
536    int egw_bytes = ZVKG_EGS << s->sew;
537    return s->cfg_ptr->ext_zvkg == true &&
538           vext_check_isa_ill(s) &&
539           require_rvv(s) &&
540           MAXSZ(s) >= egw_bytes &&
541           vext_check_ss(s, a->rd, a->rs2, a->vm) &&
542           s->sew == MO_32;
543}
544
545GEN_V_UNMASKED_TRANS(vgmul_vv, vgmul_check, ZVKG_EGS)
546
547static bool vghsh_check(DisasContext *s, arg_rmrr *a)
548{
549    int egw_bytes = ZVKG_EGS << s->sew;
550    return s->cfg_ptr->ext_zvkg == true &&
551           opivv_check(s, a) &&
552           MAXSZ(s) >= egw_bytes &&
553           s->sew == MO_32;
554}
555
556GEN_VV_UNMASKED_TRANS(vghsh_vv, vghsh_check, ZVKG_EGS)
557
558/*
559 * Zvksed
560 */
561
562#define ZVKSED_EGS 4
563
564static bool zvksed_check(DisasContext *s)
565{
566    int egw_bytes = ZVKSED_EGS << s->sew;
567    return s->cfg_ptr->ext_zvksed == true &&
568           require_rvv(s) &&
569           vext_check_isa_ill(s) &&
570           MAXSZ(s) >= egw_bytes &&
571           s->sew == MO_32;
572}
573
574static bool vsm4k_vi_check(DisasContext *s, arg_rmrr *a)
575{
576    return zvksed_check(s) &&
577           require_align(a->rd, s->lmul) &&
578           require_align(a->rs2, s->lmul);
579}
580
581GEN_VI_UNMASKED_TRANS(vsm4k_vi, vsm4k_vi_check, ZVKSED_EGS)
582
583static bool vsm4r_vv_check(DisasContext *s, arg_rmr *a)
584{
585    return zvksed_check(s) &&
586           require_align(a->rd, s->lmul) &&
587           require_align(a->rs2, s->lmul);
588}
589
590GEN_V_UNMASKED_TRANS(vsm4r_vv, vsm4r_vv_check, ZVKSED_EGS)
591
592static bool vsm4r_vs_check(DisasContext *s, arg_rmr *a)
593{
594    return zvksed_check(s) &&
595           !is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs2, 1) &&
596           require_align(a->rd, s->lmul);
597}
598
599GEN_V_UNMASKED_TRANS(vsm4r_vs, vsm4r_vs_check, ZVKSED_EGS)
600