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            TCGLabel *over = gen_new_label();                              \
168            tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);     \
169                                                                           \
170            data = FIELD_DP32(data, VDATA, VM, a->vm);                     \
171            data = FIELD_DP32(data, VDATA, LMUL, s->lmul);                 \
172            data = FIELD_DP32(data, VDATA, VTA, s->vta);                   \
173            data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s); \
174            data = FIELD_DP32(data, VDATA, VMA, s->vma);                   \
175            tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),         \
176                               vreg_ofs(s, a->rs2), tcg_env,               \
177                               s->cfg_ptr->vlen / 8, s->cfg_ptr->vlen / 8, \
178                               data, fns[s->sew]);                         \
179            mark_vs_dirty(s);                                              \
180            gen_set_label(over);                                           \
181            return true;                                                   \
182        }                                                                  \
183        return false;                                                      \
184    }
185
186static bool zvbb_opiv_check(DisasContext *s, arg_rmr *a)
187{
188    return s->cfg_ptr->ext_zvbb == true &&
189           require_rvv(s) &&
190           vext_check_isa_ill(s) &&
191           vext_check_ss(s, a->rd, a->rs2, a->vm);
192}
193
194static bool zvkb_opiv_check(DisasContext *s, arg_rmr *a)
195{
196    return (s->cfg_ptr->ext_zvbb == true || s->cfg_ptr->ext_zvkb == true) &&
197           require_rvv(s) &&
198           vext_check_isa_ill(s) &&
199           vext_check_ss(s, a->rd, a->rs2, a->vm);
200}
201
202GEN_OPIV_TRANS(vbrev8_v, zvkb_opiv_check)
203GEN_OPIV_TRANS(vrev8_v, zvkb_opiv_check)
204GEN_OPIV_TRANS(vbrev_v, zvbb_opiv_check)
205GEN_OPIV_TRANS(vclz_v, zvbb_opiv_check)
206GEN_OPIV_TRANS(vctz_v, zvbb_opiv_check)
207GEN_OPIV_TRANS(vcpop_v, zvbb_opiv_check)
208
209static bool vwsll_vv_check(DisasContext *s, arg_rmrr *a)
210{
211    return s->cfg_ptr->ext_zvbb && opivv_widen_check(s, a);
212}
213
214static bool vwsll_vx_check(DisasContext *s, arg_rmrr *a)
215{
216    return s->cfg_ptr->ext_zvbb && opivx_widen_check(s, a);
217}
218
219/* OPIVI without GVEC IR */
220#define GEN_OPIVI_WIDEN_TRANS(NAME, IMM_MODE, OPIVX, CHECK)                  \
221    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)                   \
222    {                                                                        \
223        if (CHECK(s, a)) {                                                   \
224            static gen_helper_opivx *const fns[3] = {                        \
225                gen_helper_##OPIVX##_b,                                      \
226                gen_helper_##OPIVX##_h,                                      \
227                gen_helper_##OPIVX##_w,                                      \
228            };                                                               \
229            return opivi_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s, \
230                               IMM_MODE);                                    \
231        }                                                                    \
232        return false;                                                        \
233    }
234
235GEN_OPIVV_WIDEN_TRANS(vwsll_vv, vwsll_vv_check)
236GEN_OPIVX_WIDEN_TRANS(vwsll_vx, vwsll_vx_check)
237GEN_OPIVI_WIDEN_TRANS(vwsll_vi, IMM_ZX, vwsll_vx, vwsll_vx_check)
238
239/*
240 * Zvkned
241 */
242
243#define ZVKNED_EGS 4
244
245#define GEN_V_UNMASKED_TRANS(NAME, CHECK, EGS)                                \
246    static bool trans_##NAME(DisasContext *s, arg_##NAME *a)                  \
247    {                                                                         \
248        if (CHECK(s, a)) {                                                    \
249            TCGv_ptr rd_v, rs2_v;                                             \
250            TCGv_i32 desc, egs;                                               \
251            uint32_t data = 0;                                                \
252            TCGLabel *over = gen_new_label();                                 \
253                                                                              \
254            if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {                      \
255                /* save opcode for unwinding in case we throw an exception */ \
256                decode_save_opc(s);                                           \
257                egs = tcg_constant_i32(EGS);                                  \
258                gen_helper_egs_check(egs, tcg_env);                           \
259                tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);    \
260            }                                                                 \
261                                                                              \
262            data = FIELD_DP32(data, VDATA, VM, a->vm);                        \
263            data = FIELD_DP32(data, VDATA, LMUL, s->lmul);                    \
264            data = FIELD_DP32(data, VDATA, VTA, s->vta);                      \
265            data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);    \
266            data = FIELD_DP32(data, VDATA, VMA, s->vma);                      \
267            rd_v = tcg_temp_new_ptr();                                        \
268            rs2_v = tcg_temp_new_ptr();                                       \
269            desc = tcg_constant_i32(                                          \
270                simd_desc(s->cfg_ptr->vlen / 8, s->cfg_ptr->vlen / 8, data)); \
271            tcg_gen_addi_ptr(rd_v, tcg_env, vreg_ofs(s, a->rd));              \
272            tcg_gen_addi_ptr(rs2_v, tcg_env, vreg_ofs(s, a->rs2));            \
273            gen_helper_##NAME(rd_v, rs2_v, tcg_env, desc);                    \
274            mark_vs_dirty(s);                                                 \
275            gen_set_label(over);                                              \
276            return true;                                                      \
277        }                                                                     \
278        return false;                                                         \
279    }
280
281static bool vaes_check_vv(DisasContext *s, arg_rmr *a)
282{
283    int egw_bytes = ZVKNED_EGS << s->sew;
284    return s->cfg_ptr->ext_zvkned == true &&
285           require_rvv(s) &&
286           vext_check_isa_ill(s) &&
287           MAXSZ(s) >= egw_bytes &&
288           require_align(a->rd, s->lmul) &&
289           require_align(a->rs2, s->lmul) &&
290           s->sew == MO_32;
291}
292
293static bool vaes_check_overlap(DisasContext *s, int vd, int vs2)
294{
295    int8_t op_size = s->lmul <= 0 ? 1 : 1 << s->lmul;
296    return !is_overlapped(vd, op_size, vs2, 1);
297}
298
299static bool vaes_check_vs(DisasContext *s, arg_rmr *a)
300{
301    int egw_bytes = ZVKNED_EGS << s->sew;
302    return vaes_check_overlap(s, a->rd, a->rs2) &&
303           MAXSZ(s) >= egw_bytes &&
304           s->cfg_ptr->ext_zvkned == true &&
305           require_rvv(s) &&
306           vext_check_isa_ill(s) &&
307           require_align(a->rd, s->lmul) &&
308           s->sew == MO_32;
309}
310
311GEN_V_UNMASKED_TRANS(vaesef_vv, vaes_check_vv, ZVKNED_EGS)
312GEN_V_UNMASKED_TRANS(vaesef_vs, vaes_check_vs, ZVKNED_EGS)
313GEN_V_UNMASKED_TRANS(vaesdf_vv, vaes_check_vv, ZVKNED_EGS)
314GEN_V_UNMASKED_TRANS(vaesdf_vs, vaes_check_vs, ZVKNED_EGS)
315GEN_V_UNMASKED_TRANS(vaesdm_vv, vaes_check_vv, ZVKNED_EGS)
316GEN_V_UNMASKED_TRANS(vaesdm_vs, vaes_check_vs, ZVKNED_EGS)
317GEN_V_UNMASKED_TRANS(vaesz_vs, vaes_check_vs, ZVKNED_EGS)
318GEN_V_UNMASKED_TRANS(vaesem_vv, vaes_check_vv, ZVKNED_EGS)
319GEN_V_UNMASKED_TRANS(vaesem_vs, vaes_check_vs, ZVKNED_EGS)
320
321#define GEN_VI_UNMASKED_TRANS(NAME, CHECK, EGS)                               \
322    static bool trans_##NAME(DisasContext *s, arg_##NAME *a)                  \
323    {                                                                         \
324        if (CHECK(s, a)) {                                                    \
325            TCGv_ptr rd_v, rs2_v;                                             \
326            TCGv_i32 uimm_v, desc, egs;                                       \
327            uint32_t data = 0;                                                \
328            TCGLabel *over = gen_new_label();                                 \
329                                                                              \
330            if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {                      \
331                /* save opcode for unwinding in case we throw an exception */ \
332                decode_save_opc(s);                                           \
333                egs = tcg_constant_i32(EGS);                                  \
334                gen_helper_egs_check(egs, tcg_env);                           \
335                tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);    \
336            }                                                                 \
337                                                                              \
338            data = FIELD_DP32(data, VDATA, VM, a->vm);                        \
339            data = FIELD_DP32(data, VDATA, LMUL, s->lmul);                    \
340            data = FIELD_DP32(data, VDATA, VTA, s->vta);                      \
341            data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);    \
342            data = FIELD_DP32(data, VDATA, VMA, s->vma);                      \
343                                                                              \
344            rd_v = tcg_temp_new_ptr();                                        \
345            rs2_v = tcg_temp_new_ptr();                                       \
346            uimm_v = tcg_constant_i32(a->rs1);                                \
347            desc = tcg_constant_i32(                                          \
348                simd_desc(s->cfg_ptr->vlen / 8, s->cfg_ptr->vlen / 8, data)); \
349            tcg_gen_addi_ptr(rd_v, tcg_env, vreg_ofs(s, a->rd));              \
350            tcg_gen_addi_ptr(rs2_v, tcg_env, vreg_ofs(s, a->rs2));            \
351            gen_helper_##NAME(rd_v, rs2_v, uimm_v, tcg_env, desc);            \
352            mark_vs_dirty(s);                                                 \
353            gen_set_label(over);                                              \
354            return true;                                                      \
355        }                                                                     \
356        return false;                                                         \
357    }
358
359static bool vaeskf1_check(DisasContext *s, arg_vaeskf1_vi *a)
360{
361    int egw_bytes = ZVKNED_EGS << s->sew;
362    return s->cfg_ptr->ext_zvkned == true &&
363           require_rvv(s) &&
364           vext_check_isa_ill(s) &&
365           MAXSZ(s) >= egw_bytes &&
366           s->sew == MO_32 &&
367           require_align(a->rd, s->lmul) &&
368           require_align(a->rs2, s->lmul);
369}
370
371static bool vaeskf2_check(DisasContext *s, arg_vaeskf2_vi *a)
372{
373    int egw_bytes = ZVKNED_EGS << s->sew;
374    return s->cfg_ptr->ext_zvkned == true &&
375           require_rvv(s) &&
376           vext_check_isa_ill(s) &&
377           MAXSZ(s) >= egw_bytes &&
378           s->sew == MO_32 &&
379           require_align(a->rd, s->lmul) &&
380           require_align(a->rs2, s->lmul);
381}
382
383GEN_VI_UNMASKED_TRANS(vaeskf1_vi, vaeskf1_check, ZVKNED_EGS)
384GEN_VI_UNMASKED_TRANS(vaeskf2_vi, vaeskf2_check, ZVKNED_EGS)
385
386/*
387 * Zvknh
388 */
389
390#define ZVKNH_EGS 4
391
392#define GEN_VV_UNMASKED_TRANS(NAME, CHECK, EGS)                               \
393    static bool trans_##NAME(DisasContext *s, arg_rmrr *a)                    \
394    {                                                                         \
395        if (CHECK(s, a)) {                                                    \
396            uint32_t data = 0;                                                \
397            TCGLabel *over = gen_new_label();                                 \
398            TCGv_i32 egs;                                                     \
399                                                                              \
400            if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {                      \
401                /* save opcode for unwinding in case we throw an exception */ \
402                decode_save_opc(s);                                           \
403                egs = tcg_constant_i32(EGS);                                  \
404                gen_helper_egs_check(egs, tcg_env);                           \
405                tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);    \
406            }                                                                 \
407                                                                              \
408            data = FIELD_DP32(data, VDATA, VM, a->vm);                        \
409            data = FIELD_DP32(data, VDATA, LMUL, s->lmul);                    \
410            data = FIELD_DP32(data, VDATA, VTA, s->vta);                      \
411            data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);    \
412            data = FIELD_DP32(data, VDATA, VMA, s->vma);                      \
413                                                                              \
414            tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),       \
415                               vreg_ofs(s, a->rs2), tcg_env,                  \
416                               s->cfg_ptr->vlen / 8, s->cfg_ptr->vlen / 8,    \
417                               data, gen_helper_##NAME);                      \
418                                                                              \
419            mark_vs_dirty(s);                                                 \
420            gen_set_label(over);                                              \
421            return true;                                                      \
422        }                                                                     \
423        return false;                                                         \
424    }
425
426static bool vsha_check_sew(DisasContext *s)
427{
428    return (s->cfg_ptr->ext_zvknha == true && s->sew == MO_32) ||
429           (s->cfg_ptr->ext_zvknhb == true &&
430            (s->sew == MO_32 || s->sew == MO_64));
431}
432
433static bool vsha_check(DisasContext *s, arg_rmrr *a)
434{
435    int egw_bytes = ZVKNH_EGS << s->sew;
436    int mult = 1 << MAX(s->lmul, 0);
437    return opivv_check(s, a) &&
438           vsha_check_sew(s) &&
439           MAXSZ(s) >= egw_bytes &&
440           !is_overlapped(a->rd, mult, a->rs1, mult) &&
441           !is_overlapped(a->rd, mult, a->rs2, mult) &&
442           s->lmul >= 0;
443}
444
445GEN_VV_UNMASKED_TRANS(vsha2ms_vv, vsha_check, ZVKNH_EGS)
446
447static bool trans_vsha2cl_vv(DisasContext *s, arg_rmrr *a)
448{
449    if (vsha_check(s, a)) {
450        uint32_t data = 0;
451        TCGLabel *over = gen_new_label();
452        TCGv_i32 egs;
453
454        if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {
455            /* save opcode for unwinding in case we throw an exception */
456            decode_save_opc(s);
457            egs = tcg_constant_i32(ZVKNH_EGS);
458            gen_helper_egs_check(egs, tcg_env);
459            tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
460        }
461
462        data = FIELD_DP32(data, VDATA, VM, a->vm);
463        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
464        data = FIELD_DP32(data, VDATA, VTA, s->vta);
465        data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
466        data = FIELD_DP32(data, VDATA, VMA, s->vma);
467
468        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),
469            vreg_ofs(s, a->rs2), tcg_env, s->cfg_ptr->vlen / 8,
470            s->cfg_ptr->vlen / 8, data,
471            s->sew == MO_32 ?
472                gen_helper_vsha2cl32_vv : gen_helper_vsha2cl64_vv);
473
474        mark_vs_dirty(s);
475        gen_set_label(over);
476        return true;
477    }
478    return false;
479}
480
481static bool trans_vsha2ch_vv(DisasContext *s, arg_rmrr *a)
482{
483    if (vsha_check(s, a)) {
484        uint32_t data = 0;
485        TCGLabel *over = gen_new_label();
486        TCGv_i32 egs;
487
488        if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {
489            /* save opcode for unwinding in case we throw an exception */
490            decode_save_opc(s);
491            egs = tcg_constant_i32(ZVKNH_EGS);
492            gen_helper_egs_check(egs, tcg_env);
493            tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
494        }
495
496        data = FIELD_DP32(data, VDATA, VM, a->vm);
497        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
498        data = FIELD_DP32(data, VDATA, VTA, s->vta);
499        data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
500        data = FIELD_DP32(data, VDATA, VMA, s->vma);
501
502        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),
503            vreg_ofs(s, a->rs2), tcg_env, s->cfg_ptr->vlen / 8,
504            s->cfg_ptr->vlen / 8, data,
505            s->sew == MO_32 ?
506                gen_helper_vsha2ch32_vv : gen_helper_vsha2ch64_vv);
507
508        mark_vs_dirty(s);
509        gen_set_label(over);
510        return true;
511    }
512    return false;
513}
514
515/*
516 * Zvksh
517 */
518
519#define ZVKSH_EGS 8
520
521static inline bool vsm3_check(DisasContext *s, arg_rmrr *a)
522{
523    int egw_bytes = ZVKSH_EGS << s->sew;
524    int mult = 1 << MAX(s->lmul, 0);
525    return s->cfg_ptr->ext_zvksh == true &&
526           require_rvv(s) &&
527           vext_check_isa_ill(s) &&
528           !is_overlapped(a->rd, mult, a->rs2, mult) &&
529           MAXSZ(s) >= egw_bytes &&
530           s->sew == MO_32;
531}
532
533static inline bool vsm3me_check(DisasContext *s, arg_rmrr *a)
534{
535    return vsm3_check(s, a) && vext_check_sss(s, a->rd, a->rs1, a->rs2, a->vm);
536}
537
538static inline bool vsm3c_check(DisasContext *s, arg_rmrr *a)
539{
540    return vsm3_check(s, a) && vext_check_ss(s, a->rd, a->rs2, a->vm);
541}
542
543GEN_VV_UNMASKED_TRANS(vsm3me_vv, vsm3me_check, ZVKSH_EGS)
544GEN_VI_UNMASKED_TRANS(vsm3c_vi, vsm3c_check, ZVKSH_EGS)
545
546/*
547 * Zvkg
548 */
549
550#define ZVKG_EGS 4
551
552static bool vgmul_check(DisasContext *s, arg_rmr *a)
553{
554    int egw_bytes = ZVKG_EGS << s->sew;
555    return s->cfg_ptr->ext_zvkg == true &&
556           vext_check_isa_ill(s) &&
557           require_rvv(s) &&
558           MAXSZ(s) >= egw_bytes &&
559           vext_check_ss(s, a->rd, a->rs2, a->vm) &&
560           s->sew == MO_32;
561}
562
563GEN_V_UNMASKED_TRANS(vgmul_vv, vgmul_check, ZVKG_EGS)
564
565static bool vghsh_check(DisasContext *s, arg_rmrr *a)
566{
567    int egw_bytes = ZVKG_EGS << s->sew;
568    return s->cfg_ptr->ext_zvkg == true &&
569           opivv_check(s, a) &&
570           MAXSZ(s) >= egw_bytes &&
571           s->sew == MO_32;
572}
573
574GEN_VV_UNMASKED_TRANS(vghsh_vv, vghsh_check, ZVKG_EGS)
575
576/*
577 * Zvksed
578 */
579
580#define ZVKSED_EGS 4
581
582static bool zvksed_check(DisasContext *s)
583{
584    int egw_bytes = ZVKSED_EGS << s->sew;
585    return s->cfg_ptr->ext_zvksed == true &&
586           require_rvv(s) &&
587           vext_check_isa_ill(s) &&
588           MAXSZ(s) >= egw_bytes &&
589           s->sew == MO_32;
590}
591
592static bool vsm4k_vi_check(DisasContext *s, arg_rmrr *a)
593{
594    return zvksed_check(s) &&
595           require_align(a->rd, s->lmul) &&
596           require_align(a->rs2, s->lmul);
597}
598
599GEN_VI_UNMASKED_TRANS(vsm4k_vi, vsm4k_vi_check, ZVKSED_EGS)
600
601static bool vsm4r_vv_check(DisasContext *s, arg_rmr *a)
602{
603    return zvksed_check(s) &&
604           require_align(a->rd, s->lmul) &&
605           require_align(a->rs2, s->lmul);
606}
607
608GEN_V_UNMASKED_TRANS(vsm4r_vv, vsm4r_vv_check, ZVKSED_EGS)
609
610static bool vsm4r_vs_check(DisasContext *s, arg_rmr *a)
611{
612    return zvksed_check(s) &&
613           !is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs2, 1) &&
614           require_align(a->rd, s->lmul);
615}
616
617GEN_V_UNMASKED_TRANS(vsm4r_vs, vsm4r_vs_check, ZVKSED_EGS)
618