master
inc 598 lines 25.7 KB
Raw
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
34 static 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
41 GEN_VV_MASKED_TRANS(vclmul_vv, vclmul_vv_check)
42 GEN_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
54 static 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
61 GEN_VX_MASKED_TRANS(vclmul_vx, vclmul_vx_check)
62 GEN_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
115 static 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
121 static 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] */
128 GEN_OPIVV_GVEC_TRANS_CHECK(vrol_vv, rotlv, zvkb_vv_check)
129 GEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(vrol_vx, rotls, zvkb_vx_check)
130
131 /* vror.v[vxi] */
132 GEN_OPIVV_GVEC_TRANS_CHECK(vror_vv, rotrv, zvkb_vv_check)
133 GEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(vror_vx, rotrs, zvkb_vx_check)
134 GEN_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] */
153 GEN_OPIVV_GVEC_TRANS_CHECK(vandn_vv, andc, zvkb_vv_check)
154 GEN_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
183 static 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
191 static 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
199 GEN_OPIV_TRANS(vbrev8_v, zvkb_opiv_check)
200 GEN_OPIV_TRANS(vrev8_v, zvkb_opiv_check)
201 GEN_OPIV_TRANS(vbrev_v, zvbb_opiv_check)
202 GEN_OPIV_TRANS(vclz_v, zvbb_opiv_check)
203 GEN_OPIV_TRANS(vctz_v, zvbb_opiv_check)
204 GEN_OPIV_TRANS(vcpop_v, zvbb_opiv_check)
205
206 static bool vwsll_vv_check(DisasContext *s, arg_rmrr *a)
207 {
208 return s->cfg_ptr->ext_zvbb && opivv_widen_check(s, a);
209 }
210
211 static 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
232 GEN_OPIVV_WIDEN_TRANS(vwsll_vv, vwsll_vv_check)
233 GEN_OPIVX_WIDEN_TRANS(vwsll_vx, vwsll_vx_check)
234 GEN_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
275 static 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
287 static 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
293 static 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
305 GEN_V_UNMASKED_TRANS(vaesef_vv, vaes_check_vv, ZVKNED_EGS)
306 GEN_V_UNMASKED_TRANS(vaesef_vs, vaes_check_vs, ZVKNED_EGS)
307 GEN_V_UNMASKED_TRANS(vaesdf_vv, vaes_check_vv, ZVKNED_EGS)
308 GEN_V_UNMASKED_TRANS(vaesdf_vs, vaes_check_vs, ZVKNED_EGS)
309 GEN_V_UNMASKED_TRANS(vaesdm_vv, vaes_check_vv, ZVKNED_EGS)
310 GEN_V_UNMASKED_TRANS(vaesdm_vs, vaes_check_vs, ZVKNED_EGS)
311 GEN_V_UNMASKED_TRANS(vaesz_vs, vaes_check_vs, ZVKNED_EGS)
312 GEN_V_UNMASKED_TRANS(vaesem_vv, vaes_check_vv, ZVKNED_EGS)
313 GEN_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
350 static 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
362 static 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
374 GEN_VI_UNMASKED_TRANS(vaeskf1_vi, vaeskf1_check, ZVKNED_EGS)
375 GEN_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
414 static 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
421 static 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 }
431
432 GEN_VV_UNMASKED_TRANS(vsha2ms_vv, vsha_check, ZVKNH_EGS)
433
434 static bool trans_vsha2cl_vv(DisasContext *s, arg_rmrr *a)
435 {
436 if (vsha_check(s, a)) {
437 uint32_t data = 0;
438 TCGv_i32 egs;
439
440 if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {
441 /* save opcode for unwinding in case we throw an exception */
442 decode_save_opc(s, 0);
443 egs = tcg_constant_i32(ZVKNH_EGS);
444 gen_helper_egs_check(egs, tcg_env);
445 }
446
447 data = FIELD_DP32(data, VDATA, VM, a->vm);
448 data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
449 data = FIELD_DP32(data, VDATA, VTA, s->vta);
450 data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
451 data = FIELD_DP32(data, VDATA, VMA, s->vma);
452
453 tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),
454 vreg_ofs(s, a->rs2), tcg_env, s->cfg_ptr->vlenb,
455 s->cfg_ptr->vlenb, data,
456 s->sew == MO_32 ?
457 gen_helper_vsha2cl32_vv : gen_helper_vsha2cl64_vv);
458
459 finalize_rvv_inst(s);
460 return true;
461 }
462 return false;
463 }
464
465 static bool trans_vsha2ch_vv(DisasContext *s, arg_rmrr *a)
466 {
467 if (vsha_check(s, a)) {
468 uint32_t data = 0;
469 TCGv_i32 egs;
470
471 if (!s->vstart_eq_zero || !s->vl_eq_vlmax) {
472 /* save opcode for unwinding in case we throw an exception */
473 decode_save_opc(s, 0);
474 egs = tcg_constant_i32(ZVKNH_EGS);
475 gen_helper_egs_check(egs, tcg_env);
476 }
477
478 data = FIELD_DP32(data, VDATA, VM, a->vm);
479 data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
480 data = FIELD_DP32(data, VDATA, VTA, s->vta);
481 data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
482 data = FIELD_DP32(data, VDATA, VMA, s->vma);
483
484 tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),
485 vreg_ofs(s, a->rs2), tcg_env, s->cfg_ptr->vlenb,
486 s->cfg_ptr->vlenb, data,
487 s->sew == MO_32 ?
488 gen_helper_vsha2ch32_vv : gen_helper_vsha2ch64_vv);
489
490 finalize_rvv_inst(s);
491 return true;
492 }
493 return false;
494 }
495
496 /*
497 * Zvksh
498 */
499
500 #define ZVKSH_EGS 8
501
502 static inline bool vsm3_check(DisasContext *s, arg_rmrr *a)
503 {
504 int egw_bytes = ZVKSH_EGS << s->sew;
505 int mult = 1 << MAX(s->lmul, 0);
506 return s->cfg_ptr->ext_zvksh == true &&
507 require_rvv(s) &&
508 vext_check_isa_ill(s) &&
509 !is_overlapped(a->rd, mult, a->rs2, mult) &&
510 MAXSZ(s) >= egw_bytes &&
511 s->sew == MO_32;
512 }
513
514 static inline bool vsm3me_check(DisasContext *s, arg_rmrr *a)
515 {
516 return vsm3_check(s, a) && vext_check_sss(s, a->rd, a->rs1, a->rs2, a->vm);
517 }
518
519 static inline bool vsm3c_check(DisasContext *s, arg_rmrr *a)
520 {
521 return vsm3_check(s, a) && vext_check_ss(s, a->rd, a->rs2, a->vm);
522 }
523
524 GEN_VV_UNMASKED_TRANS(vsm3me_vv, vsm3me_check, ZVKSH_EGS)
525 GEN_VI_UNMASKED_TRANS(vsm3c_vi, vsm3c_check, ZVKSH_EGS)
526
527 /*
528 * Zvkg
529 */
530
531 #define ZVKG_EGS 4
532
533 static bool vgmul_check(DisasContext *s, arg_rmr *a)
534 {
535 int egw_bytes = ZVKG_EGS << s->sew;
536 return s->cfg_ptr->ext_zvkg == true &&
537 vext_check_isa_ill(s) &&
538 require_rvv(s) &&
539 MAXSZ(s) >= egw_bytes &&
540 vext_check_ss(s, a->rd, a->rs2, a->vm) &&
541 s->sew == MO_32;
542 }
543
544 GEN_V_UNMASKED_TRANS(vgmul_vv, vgmul_check, ZVKG_EGS)
545
546 static bool vghsh_check(DisasContext *s, arg_rmrr *a)
547 {
548 int egw_bytes = ZVKG_EGS << s->sew;
549 return s->cfg_ptr->ext_zvkg == true &&
550 opivv_check(s, a) &&
551 MAXSZ(s) >= egw_bytes &&
552 s->sew == MO_32;
553 }
554
555 GEN_VV_UNMASKED_TRANS(vghsh_vv, vghsh_check, ZVKG_EGS)
556
557 /*
558 * Zvksed
559 */
560
561 #define ZVKSED_EGS 4
562
563 static bool zvksed_check(DisasContext *s)
564 {
565 int egw_bytes = ZVKSED_EGS << s->sew;
566 return s->cfg_ptr->ext_zvksed == true &&
567 require_rvv(s) &&
568 vext_check_isa_ill(s) &&
569 MAXSZ(s) >= egw_bytes &&
570 s->sew == MO_32;
571 }
572
573 static bool vsm4k_vi_check(DisasContext *s, arg_rmrr *a)
574 {
575 return zvksed_check(s) &&
576 require_align(a->rd, s->lmul) &&
577 require_align(a->rs2, s->lmul);
578 }
579
580 GEN_VI_UNMASKED_TRANS(vsm4k_vi, vsm4k_vi_check, ZVKSED_EGS)
581
582 static bool vsm4r_vv_check(DisasContext *s, arg_rmr *a)
583 {
584 return zvksed_check(s) &&
585 require_align(a->rd, s->lmul) &&
586 require_align(a->rs2, s->lmul);
587 }
588
589 GEN_V_UNMASKED_TRANS(vsm4r_vv, vsm4r_vv_check, ZVKSED_EGS)
590
591 static bool vsm4r_vs_check(DisasContext *s, arg_rmr *a)
592 {
593 return zvksed_check(s) &&
594 !is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs2, 1) &&
595 require_align(a->rd, s->lmul);
596 }
597
598 GEN_V_UNMASKED_TRANS(vsm4r_vs, vsm4r_vs_check, ZVKSED_EGS)