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); \ 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); \ 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); \ 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); 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); 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