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