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