1e13c7d3bSLawrence Hunter/* 2e13c7d3bSLawrence Hunter * RISC-V translation routines for the vector crypto extension. 3e13c7d3bSLawrence Hunter * 4e13c7d3bSLawrence Hunter * Copyright (C) 2023 SiFive, Inc. 5e13c7d3bSLawrence Hunter * Written by Codethink Ltd and SiFive. 6e13c7d3bSLawrence Hunter * 7e13c7d3bSLawrence Hunter * This program is free software; you can redistribute it and/or modify it 8e13c7d3bSLawrence Hunter * under the terms and conditions of the GNU General Public License, 9e13c7d3bSLawrence Hunter * version 2 or later, as published by the Free Software Foundation. 10e13c7d3bSLawrence Hunter * 11e13c7d3bSLawrence Hunter * This program is distributed in the hope it will be useful, but WITHOUT 12e13c7d3bSLawrence Hunter * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13e13c7d3bSLawrence Hunter * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14e13c7d3bSLawrence Hunter * more details. 15e13c7d3bSLawrence Hunter * 16e13c7d3bSLawrence Hunter * You should have received a copy of the GNU General Public License along with 17e13c7d3bSLawrence Hunter * this program. If not, see <http://www.gnu.org/licenses/>. 18e13c7d3bSLawrence Hunter */ 19e13c7d3bSLawrence Hunter 20e13c7d3bSLawrence Hunter/* 21e13c7d3bSLawrence Hunter * Zvbc 22e13c7d3bSLawrence Hunter */ 23e13c7d3bSLawrence Hunter 24e13c7d3bSLawrence Hunter#define GEN_VV_MASKED_TRANS(NAME, CHECK) \ 25e13c7d3bSLawrence Hunter static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ 26e13c7d3bSLawrence Hunter { \ 27e13c7d3bSLawrence Hunter if (CHECK(s, a)) { \ 28e13c7d3bSLawrence Hunter return opivv_trans(a->rd, a->rs1, a->rs2, a->vm, \ 29e13c7d3bSLawrence Hunter gen_helper_##NAME, s); \ 30e13c7d3bSLawrence Hunter } \ 31e13c7d3bSLawrence Hunter return false; \ 32e13c7d3bSLawrence Hunter } 33e13c7d3bSLawrence Hunter 34e13c7d3bSLawrence Hunterstatic bool vclmul_vv_check(DisasContext *s, arg_rmrr *a) 35e13c7d3bSLawrence Hunter{ 36e13c7d3bSLawrence Hunter return opivv_check(s, a) && 37e13c7d3bSLawrence Hunter s->cfg_ptr->ext_zvbc == true && 38e13c7d3bSLawrence Hunter s->sew == MO_64; 39e13c7d3bSLawrence Hunter} 40e13c7d3bSLawrence Hunter 41e13c7d3bSLawrence HunterGEN_VV_MASKED_TRANS(vclmul_vv, vclmul_vv_check) 42e13c7d3bSLawrence HunterGEN_VV_MASKED_TRANS(vclmulh_vv, vclmul_vv_check) 43e13c7d3bSLawrence Hunter 44e13c7d3bSLawrence Hunter#define GEN_VX_MASKED_TRANS(NAME, CHECK) \ 45e13c7d3bSLawrence Hunter static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ 46e13c7d3bSLawrence Hunter { \ 47e13c7d3bSLawrence Hunter if (CHECK(s, a)) { \ 48e13c7d3bSLawrence Hunter return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, \ 49e13c7d3bSLawrence Hunter gen_helper_##NAME, s); \ 50e13c7d3bSLawrence Hunter } \ 51e13c7d3bSLawrence Hunter return false; \ 52e13c7d3bSLawrence Hunter } 53e13c7d3bSLawrence Hunter 54e13c7d3bSLawrence Hunterstatic bool vclmul_vx_check(DisasContext *s, arg_rmrr *a) 55e13c7d3bSLawrence Hunter{ 56e13c7d3bSLawrence Hunter return opivx_check(s, a) && 57e13c7d3bSLawrence Hunter s->cfg_ptr->ext_zvbc == true && 58e13c7d3bSLawrence Hunter s->sew == MO_64; 59e13c7d3bSLawrence Hunter} 60e13c7d3bSLawrence Hunter 61e13c7d3bSLawrence HunterGEN_VX_MASKED_TRANS(vclmul_vx, vclmul_vx_check) 62e13c7d3bSLawrence HunterGEN_VX_MASKED_TRANS(vclmulh_vx, vclmul_vx_check) 6306028472SDickon Hood 6406028472SDickon Hood/* 6506028472SDickon Hood * Zvbb 6606028472SDickon Hood */ 6706028472SDickon Hood 6806028472SDickon Hood#define GEN_OPIVI_GVEC_TRANS_CHECK(NAME, IMM_MODE, OPIVX, SUF, CHECK) \ 6906028472SDickon Hood static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ 7006028472SDickon Hood { \ 7106028472SDickon Hood if (CHECK(s, a)) { \ 7206028472SDickon Hood static gen_helper_opivx *const fns[4] = { \ 7306028472SDickon Hood gen_helper_##OPIVX##_b, \ 7406028472SDickon Hood gen_helper_##OPIVX##_h, \ 7506028472SDickon Hood gen_helper_##OPIVX##_w, \ 7606028472SDickon Hood gen_helper_##OPIVX##_d, \ 7706028472SDickon Hood }; \ 7806028472SDickon Hood return do_opivi_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew], \ 7906028472SDickon Hood IMM_MODE); \ 8006028472SDickon Hood } \ 8106028472SDickon Hood return false; \ 8206028472SDickon Hood } 8306028472SDickon Hood 8406028472SDickon Hood#define GEN_OPIVV_GVEC_TRANS_CHECK(NAME, SUF, CHECK) \ 8506028472SDickon Hood static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ 8606028472SDickon Hood { \ 8706028472SDickon Hood if (CHECK(s, a)) { \ 8806028472SDickon Hood static gen_helper_gvec_4_ptr *const fns[4] = { \ 8906028472SDickon Hood gen_helper_##NAME##_b, \ 9006028472SDickon Hood gen_helper_##NAME##_h, \ 9106028472SDickon Hood gen_helper_##NAME##_w, \ 9206028472SDickon Hood gen_helper_##NAME##_d, \ 9306028472SDickon Hood }; \ 9406028472SDickon Hood return do_opivv_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]); \ 9506028472SDickon Hood } \ 9606028472SDickon Hood return false; \ 9706028472SDickon Hood } 9806028472SDickon Hood 9906028472SDickon Hood#define GEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(NAME, SUF, CHECK) \ 10006028472SDickon Hood static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ 10106028472SDickon Hood { \ 10206028472SDickon Hood if (CHECK(s, a)) { \ 10306028472SDickon Hood static gen_helper_opivx *const fns[4] = { \ 10406028472SDickon Hood gen_helper_##NAME##_b, \ 10506028472SDickon Hood gen_helper_##NAME##_h, \ 10606028472SDickon Hood gen_helper_##NAME##_w, \ 10706028472SDickon Hood gen_helper_##NAME##_d, \ 10806028472SDickon Hood }; \ 10906028472SDickon Hood return do_opivx_gvec_shift(s, a, tcg_gen_gvec_##SUF, \ 11006028472SDickon Hood fns[s->sew]); \ 11106028472SDickon Hood } \ 11206028472SDickon Hood return false; \ 11306028472SDickon Hood } 11406028472SDickon Hood 1151db699f8SMax Choustatic bool zvkb_vv_check(DisasContext *s, arg_rmrr *a) 11606028472SDickon Hood{ 1171db699f8SMax Chou return opivv_check(s, a) && 1181db699f8SMax Chou (s->cfg_ptr->ext_zvbb == true || s->cfg_ptr->ext_zvkb == true); 11906028472SDickon Hood} 12006028472SDickon Hood 1211db699f8SMax Choustatic bool zvkb_vx_check(DisasContext *s, arg_rmrr *a) 12206028472SDickon Hood{ 1231db699f8SMax Chou return opivx_check(s, a) && 1241db699f8SMax Chou (s->cfg_ptr->ext_zvbb == true || s->cfg_ptr->ext_zvkb == true); 12506028472SDickon Hood} 12606028472SDickon Hood 12706028472SDickon Hood/* vrol.v[vx] */ 1281db699f8SMax ChouGEN_OPIVV_GVEC_TRANS_CHECK(vrol_vv, rotlv, zvkb_vv_check) 1291db699f8SMax ChouGEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(vrol_vx, rotls, zvkb_vx_check) 13006028472SDickon Hood 13106028472SDickon Hood/* vror.v[vxi] */ 1321db699f8SMax ChouGEN_OPIVV_GVEC_TRANS_CHECK(vror_vv, rotrv, zvkb_vv_check) 1331db699f8SMax ChouGEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(vror_vx, rotrs, zvkb_vx_check) 1341db699f8SMax ChouGEN_OPIVI_GVEC_TRANS_CHECK(vror_vi, IMM_TRUNC_SEW, vror_vx, rotri, 1351db699f8SMax Chou zvkb_vx_check) 13606028472SDickon Hood 13706028472SDickon Hood#define GEN_OPIVX_GVEC_TRANS_CHECK(NAME, SUF, CHECK) \ 13806028472SDickon Hood static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ 13906028472SDickon Hood { \ 14006028472SDickon Hood if (CHECK(s, a)) { \ 14106028472SDickon Hood static gen_helper_opivx *const fns[4] = { \ 14206028472SDickon Hood gen_helper_##NAME##_b, \ 14306028472SDickon Hood gen_helper_##NAME##_h, \ 14406028472SDickon Hood gen_helper_##NAME##_w, \ 14506028472SDickon Hood gen_helper_##NAME##_d, \ 14606028472SDickon Hood }; \ 14706028472SDickon Hood return do_opivx_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]); \ 14806028472SDickon Hood } \ 14906028472SDickon Hood return false; \ 15006028472SDickon Hood } 15106028472SDickon Hood 15206028472SDickon Hood/* vandn.v[vx] */ 1531db699f8SMax ChouGEN_OPIVV_GVEC_TRANS_CHECK(vandn_vv, andc, zvkb_vv_check) 1541db699f8SMax ChouGEN_OPIVX_GVEC_TRANS_CHECK(vandn_vx, andcs, zvkb_vx_check) 15506028472SDickon Hood 15606028472SDickon Hood#define GEN_OPIV_TRANS(NAME, CHECK) \ 15706028472SDickon Hood static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ 15806028472SDickon Hood { \ 15906028472SDickon Hood if (CHECK(s, a)) { \ 16006028472SDickon Hood uint32_t data = 0; \ 16106028472SDickon Hood static gen_helper_gvec_3_ptr *const fns[4] = { \ 16206028472SDickon Hood gen_helper_##NAME##_b, \ 16306028472SDickon Hood gen_helper_##NAME##_h, \ 16406028472SDickon Hood gen_helper_##NAME##_w, \ 16506028472SDickon Hood gen_helper_##NAME##_d, \ 16606028472SDickon Hood }; \ 16706028472SDickon Hood \ 16806028472SDickon Hood data = FIELD_DP32(data, VDATA, VM, a->vm); \ 16906028472SDickon Hood data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ 17006028472SDickon Hood data = FIELD_DP32(data, VDATA, VTA, s->vta); \ 17106028472SDickon Hood data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s); \ 17206028472SDickon Hood data = FIELD_DP32(data, VDATA, VMA, s->vma); \ 17306028472SDickon Hood tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ 174ad75a51eSRichard Henderson vreg_ofs(s, a->rs2), tcg_env, \ 175f5a5e71eSDaniel Henrique Barboza s->cfg_ptr->vlenb, s->cfg_ptr->vlenb, \ 17606028472SDickon Hood data, fns[s->sew]); \ 177*bac802adSIvan Klokov finalize_rvv_inst(s); \ 17806028472SDickon Hood return true; \ 17906028472SDickon Hood } \ 18006028472SDickon Hood return false; \ 18106028472SDickon Hood } 18206028472SDickon Hood 18306028472SDickon Hoodstatic bool zvbb_opiv_check(DisasContext *s, arg_rmr *a) 18406028472SDickon Hood{ 18506028472SDickon Hood return s->cfg_ptr->ext_zvbb == true && 18606028472SDickon Hood require_rvv(s) && 18706028472SDickon Hood vext_check_isa_ill(s) && 18806028472SDickon Hood vext_check_ss(s, a->rd, a->rs2, a->vm); 18906028472SDickon Hood} 19006028472SDickon Hood 1911db699f8SMax Choustatic bool zvkb_opiv_check(DisasContext *s, arg_rmr *a) 1921db699f8SMax Chou{ 1931db699f8SMax Chou return (s->cfg_ptr->ext_zvbb == true || s->cfg_ptr->ext_zvkb == true) && 1941db699f8SMax Chou require_rvv(s) && 1951db699f8SMax Chou vext_check_isa_ill(s) && 1961db699f8SMax Chou vext_check_ss(s, a->rd, a->rs2, a->vm); 1971db699f8SMax Chou} 1981db699f8SMax Chou 1991db699f8SMax ChouGEN_OPIV_TRANS(vbrev8_v, zvkb_opiv_check) 2001db699f8SMax ChouGEN_OPIV_TRANS(vrev8_v, zvkb_opiv_check) 20106028472SDickon HoodGEN_OPIV_TRANS(vbrev_v, zvbb_opiv_check) 20206028472SDickon HoodGEN_OPIV_TRANS(vclz_v, zvbb_opiv_check) 20306028472SDickon HoodGEN_OPIV_TRANS(vctz_v, zvbb_opiv_check) 20406028472SDickon HoodGEN_OPIV_TRANS(vcpop_v, zvbb_opiv_check) 20506028472SDickon Hood 20606028472SDickon Hoodstatic bool vwsll_vv_check(DisasContext *s, arg_rmrr *a) 20706028472SDickon Hood{ 20806028472SDickon Hood return s->cfg_ptr->ext_zvbb && opivv_widen_check(s, a); 20906028472SDickon Hood} 21006028472SDickon Hood 21106028472SDickon Hoodstatic bool vwsll_vx_check(DisasContext *s, arg_rmrr *a) 21206028472SDickon Hood{ 21306028472SDickon Hood return s->cfg_ptr->ext_zvbb && opivx_widen_check(s, a); 21406028472SDickon Hood} 21506028472SDickon Hood 21606028472SDickon Hood/* OPIVI without GVEC IR */ 21706028472SDickon Hood#define GEN_OPIVI_WIDEN_TRANS(NAME, IMM_MODE, OPIVX, CHECK) \ 21806028472SDickon Hood static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ 21906028472SDickon Hood { \ 22006028472SDickon Hood if (CHECK(s, a)) { \ 22106028472SDickon Hood static gen_helper_opivx *const fns[3] = { \ 22206028472SDickon Hood gen_helper_##OPIVX##_b, \ 22306028472SDickon Hood gen_helper_##OPIVX##_h, \ 22406028472SDickon Hood gen_helper_##OPIVX##_w, \ 22506028472SDickon Hood }; \ 22606028472SDickon Hood return opivi_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s, \ 22706028472SDickon Hood IMM_MODE); \ 22806028472SDickon Hood } \ 22906028472SDickon Hood return false; \ 23006028472SDickon Hood } 23106028472SDickon Hood 23206028472SDickon HoodGEN_OPIVV_WIDEN_TRANS(vwsll_vv, vwsll_vv_check) 23306028472SDickon HoodGEN_OPIVX_WIDEN_TRANS(vwsll_vx, vwsll_vx_check) 23406028472SDickon HoodGEN_OPIVI_WIDEN_TRANS(vwsll_vi, IMM_ZX, vwsll_vx, vwsll_vx_check) 235e972bf22SNazar Kazakov 236e972bf22SNazar Kazakov/* 237e972bf22SNazar Kazakov * Zvkned 238e972bf22SNazar Kazakov */ 239e972bf22SNazar Kazakov 240e972bf22SNazar Kazakov#define ZVKNED_EGS 4 241e972bf22SNazar Kazakov 242e972bf22SNazar Kazakov#define GEN_V_UNMASKED_TRANS(NAME, CHECK, EGS) \ 243e972bf22SNazar Kazakov static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \ 244e972bf22SNazar Kazakov { \ 245e972bf22SNazar Kazakov if (CHECK(s, a)) { \ 246e972bf22SNazar Kazakov TCGv_ptr rd_v, rs2_v; \ 247e972bf22SNazar Kazakov TCGv_i32 desc, egs; \ 248e972bf22SNazar Kazakov uint32_t data = 0; \ 249e972bf22SNazar Kazakov \ 250e972bf22SNazar Kazakov if (!s->vstart_eq_zero || !s->vl_eq_vlmax) { \ 251e972bf22SNazar Kazakov /* save opcode for unwinding in case we throw an exception */ \ 252e972bf22SNazar Kazakov decode_save_opc(s); \ 253e972bf22SNazar Kazakov egs = tcg_constant_i32(EGS); \ 254ad75a51eSRichard Henderson gen_helper_egs_check(egs, tcg_env); \ 255e972bf22SNazar Kazakov } \ 256e972bf22SNazar Kazakov \ 257e972bf22SNazar Kazakov data = FIELD_DP32(data, VDATA, VM, a->vm); \ 258e972bf22SNazar Kazakov data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ 259e972bf22SNazar Kazakov data = FIELD_DP32(data, VDATA, VTA, s->vta); \ 260e972bf22SNazar Kazakov data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s); \ 261e972bf22SNazar Kazakov data = FIELD_DP32(data, VDATA, VMA, s->vma); \ 262e972bf22SNazar Kazakov rd_v = tcg_temp_new_ptr(); \ 263e972bf22SNazar Kazakov rs2_v = tcg_temp_new_ptr(); \ 264e972bf22SNazar Kazakov desc = tcg_constant_i32( \ 265f5a5e71eSDaniel Henrique Barboza simd_desc(s->cfg_ptr->vlenb, s->cfg_ptr->vlenb, data)); \ 266ad75a51eSRichard Henderson tcg_gen_addi_ptr(rd_v, tcg_env, vreg_ofs(s, a->rd)); \ 267ad75a51eSRichard Henderson tcg_gen_addi_ptr(rs2_v, tcg_env, vreg_ofs(s, a->rs2)); \ 268ad75a51eSRichard Henderson gen_helper_##NAME(rd_v, rs2_v, tcg_env, desc); \ 269*bac802adSIvan Klokov finalize_rvv_inst(s); \ 270e972bf22SNazar Kazakov return true; \ 271e972bf22SNazar Kazakov } \ 272e972bf22SNazar Kazakov return false; \ 273e972bf22SNazar Kazakov } 274e972bf22SNazar Kazakov 275e972bf22SNazar Kazakovstatic bool vaes_check_vv(DisasContext *s, arg_rmr *a) 276e972bf22SNazar Kazakov{ 277e972bf22SNazar Kazakov int egw_bytes = ZVKNED_EGS << s->sew; 278e972bf22SNazar Kazakov return s->cfg_ptr->ext_zvkned == true && 279e972bf22SNazar Kazakov require_rvv(s) && 280e972bf22SNazar Kazakov vext_check_isa_ill(s) && 281e972bf22SNazar Kazakov MAXSZ(s) >= egw_bytes && 282e972bf22SNazar Kazakov require_align(a->rd, s->lmul) && 283e972bf22SNazar Kazakov require_align(a->rs2, s->lmul) && 284e972bf22SNazar Kazakov s->sew == MO_32; 285e972bf22SNazar Kazakov} 286e972bf22SNazar Kazakov 287e972bf22SNazar Kazakovstatic bool vaes_check_overlap(DisasContext *s, int vd, int vs2) 288e972bf22SNazar Kazakov{ 289e972bf22SNazar Kazakov int8_t op_size = s->lmul <= 0 ? 1 : 1 << s->lmul; 290e972bf22SNazar Kazakov return !is_overlapped(vd, op_size, vs2, 1); 291e972bf22SNazar Kazakov} 292e972bf22SNazar Kazakov 293e972bf22SNazar Kazakovstatic bool vaes_check_vs(DisasContext *s, arg_rmr *a) 294e972bf22SNazar Kazakov{ 295e972bf22SNazar Kazakov int egw_bytes = ZVKNED_EGS << s->sew; 296e972bf22SNazar Kazakov return vaes_check_overlap(s, a->rd, a->rs2) && 297e972bf22SNazar Kazakov MAXSZ(s) >= egw_bytes && 298e972bf22SNazar Kazakov s->cfg_ptr->ext_zvkned == true && 299e972bf22SNazar Kazakov require_rvv(s) && 300e972bf22SNazar Kazakov vext_check_isa_ill(s) && 301e972bf22SNazar Kazakov require_align(a->rd, s->lmul) && 302e972bf22SNazar Kazakov s->sew == MO_32; 303e972bf22SNazar Kazakov} 304e972bf22SNazar Kazakov 305e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesef_vv, vaes_check_vv, ZVKNED_EGS) 306e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesef_vs, vaes_check_vs, ZVKNED_EGS) 307e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesdf_vv, vaes_check_vv, ZVKNED_EGS) 308e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesdf_vs, vaes_check_vs, ZVKNED_EGS) 309e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesdm_vv, vaes_check_vv, ZVKNED_EGS) 310e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesdm_vs, vaes_check_vs, ZVKNED_EGS) 311e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesz_vs, vaes_check_vs, ZVKNED_EGS) 312e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesem_vv, vaes_check_vv, ZVKNED_EGS) 313e972bf22SNazar KazakovGEN_V_UNMASKED_TRANS(vaesem_vs, vaes_check_vs, ZVKNED_EGS) 314e972bf22SNazar Kazakov 315e972bf22SNazar Kazakov#define GEN_VI_UNMASKED_TRANS(NAME, CHECK, EGS) \ 316e972bf22SNazar Kazakov static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \ 317e972bf22SNazar Kazakov { \ 318e972bf22SNazar Kazakov if (CHECK(s, a)) { \ 319e972bf22SNazar Kazakov TCGv_ptr rd_v, rs2_v; \ 320e972bf22SNazar Kazakov TCGv_i32 uimm_v, desc, egs; \ 321e972bf22SNazar Kazakov uint32_t data = 0; \ 322e972bf22SNazar Kazakov \ 323e972bf22SNazar Kazakov if (!s->vstart_eq_zero || !s->vl_eq_vlmax) { \ 324e972bf22SNazar Kazakov /* save opcode for unwinding in case we throw an exception */ \ 325e972bf22SNazar Kazakov decode_save_opc(s); \ 326e972bf22SNazar Kazakov egs = tcg_constant_i32(EGS); \ 327ad75a51eSRichard Henderson gen_helper_egs_check(egs, tcg_env); \ 328e972bf22SNazar Kazakov } \ 329e972bf22SNazar Kazakov \ 330e972bf22SNazar Kazakov data = FIELD_DP32(data, VDATA, VM, a->vm); \ 331e972bf22SNazar Kazakov data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ 332e972bf22SNazar Kazakov data = FIELD_DP32(data, VDATA, VTA, s->vta); \ 333e972bf22SNazar Kazakov data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s); \ 334e972bf22SNazar Kazakov data = FIELD_DP32(data, VDATA, VMA, s->vma); \ 335e972bf22SNazar Kazakov \ 336e972bf22SNazar Kazakov rd_v = tcg_temp_new_ptr(); \ 337e972bf22SNazar Kazakov rs2_v = tcg_temp_new_ptr(); \ 338e972bf22SNazar Kazakov uimm_v = tcg_constant_i32(a->rs1); \ 339e972bf22SNazar Kazakov desc = tcg_constant_i32( \ 340f5a5e71eSDaniel Henrique Barboza simd_desc(s->cfg_ptr->vlenb, s->cfg_ptr->vlenb, data)); \ 341ad75a51eSRichard Henderson tcg_gen_addi_ptr(rd_v, tcg_env, vreg_ofs(s, a->rd)); \ 342ad75a51eSRichard Henderson tcg_gen_addi_ptr(rs2_v, tcg_env, vreg_ofs(s, a->rs2)); \ 343ad75a51eSRichard Henderson gen_helper_##NAME(rd_v, rs2_v, uimm_v, tcg_env, desc); \ 344*bac802adSIvan Klokov finalize_rvv_inst(s); \ 345e972bf22SNazar Kazakov return true; \ 346e972bf22SNazar Kazakov } \ 347e972bf22SNazar Kazakov return false; \ 348e972bf22SNazar Kazakov } 349e972bf22SNazar Kazakov 350e972bf22SNazar Kazakovstatic bool vaeskf1_check(DisasContext *s, arg_vaeskf1_vi *a) 351e972bf22SNazar Kazakov{ 352e972bf22SNazar Kazakov int egw_bytes = ZVKNED_EGS << s->sew; 353e972bf22SNazar Kazakov return s->cfg_ptr->ext_zvkned == true && 354e972bf22SNazar Kazakov require_rvv(s) && 355e972bf22SNazar Kazakov vext_check_isa_ill(s) && 356e972bf22SNazar Kazakov MAXSZ(s) >= egw_bytes && 357e972bf22SNazar Kazakov s->sew == MO_32 && 358e972bf22SNazar Kazakov require_align(a->rd, s->lmul) && 359e972bf22SNazar Kazakov require_align(a->rs2, s->lmul); 360e972bf22SNazar Kazakov} 361e972bf22SNazar Kazakov 362e972bf22SNazar Kazakovstatic bool vaeskf2_check(DisasContext *s, arg_vaeskf2_vi *a) 363e972bf22SNazar Kazakov{ 364e972bf22SNazar Kazakov int egw_bytes = ZVKNED_EGS << s->sew; 365e972bf22SNazar Kazakov return s->cfg_ptr->ext_zvkned == true && 366e972bf22SNazar Kazakov require_rvv(s) && 367e972bf22SNazar Kazakov vext_check_isa_ill(s) && 368e972bf22SNazar Kazakov MAXSZ(s) >= egw_bytes && 369e972bf22SNazar Kazakov s->sew == MO_32 && 370e972bf22SNazar Kazakov require_align(a->rd, s->lmul) && 371e972bf22SNazar Kazakov require_align(a->rs2, s->lmul); 372e972bf22SNazar Kazakov} 373e972bf22SNazar Kazakov 374e972bf22SNazar KazakovGEN_VI_UNMASKED_TRANS(vaeskf1_vi, vaeskf1_check, ZVKNED_EGS) 375e972bf22SNazar KazakovGEN_VI_UNMASKED_TRANS(vaeskf2_vi, vaeskf2_check, ZVKNED_EGS) 376fcf19433SKiran Ostrolenk 377fcf19433SKiran Ostrolenk/* 378fcf19433SKiran Ostrolenk * Zvknh 379fcf19433SKiran Ostrolenk */ 380fcf19433SKiran Ostrolenk 381fcf19433SKiran Ostrolenk#define ZVKNH_EGS 4 382fcf19433SKiran Ostrolenk 383fcf19433SKiran Ostrolenk#define GEN_VV_UNMASKED_TRANS(NAME, CHECK, EGS) \ 384fcf19433SKiran Ostrolenk static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ 385fcf19433SKiran Ostrolenk { \ 386fcf19433SKiran Ostrolenk if (CHECK(s, a)) { \ 387fcf19433SKiran Ostrolenk uint32_t data = 0; \ 388fcf19433SKiran Ostrolenk TCGv_i32 egs; \ 389fcf19433SKiran Ostrolenk \ 390fcf19433SKiran Ostrolenk if (!s->vstart_eq_zero || !s->vl_eq_vlmax) { \ 391fcf19433SKiran Ostrolenk /* save opcode for unwinding in case we throw an exception */ \ 392fcf19433SKiran Ostrolenk decode_save_opc(s); \ 393fcf19433SKiran Ostrolenk egs = tcg_constant_i32(EGS); \ 394ad75a51eSRichard Henderson gen_helper_egs_check(egs, tcg_env); \ 395fcf19433SKiran Ostrolenk } \ 396fcf19433SKiran Ostrolenk \ 397fcf19433SKiran Ostrolenk data = FIELD_DP32(data, VDATA, VM, a->vm); \ 398fcf19433SKiran Ostrolenk data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ 399fcf19433SKiran Ostrolenk data = FIELD_DP32(data, VDATA, VTA, s->vta); \ 400fcf19433SKiran Ostrolenk data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s); \ 401fcf19433SKiran Ostrolenk data = FIELD_DP32(data, VDATA, VMA, s->vma); \ 402fcf19433SKiran Ostrolenk \ 403fcf19433SKiran Ostrolenk tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1), \ 404ad75a51eSRichard Henderson vreg_ofs(s, a->rs2), tcg_env, \ 405f5a5e71eSDaniel Henrique Barboza s->cfg_ptr->vlenb, s->cfg_ptr->vlenb, \ 406fcf19433SKiran Ostrolenk data, gen_helper_##NAME); \ 407fcf19433SKiran Ostrolenk \ 408*bac802adSIvan Klokov finalize_rvv_inst(s); \ 409fcf19433SKiran Ostrolenk return true; \ 410fcf19433SKiran Ostrolenk } \ 411fcf19433SKiran Ostrolenk return false; \ 412fcf19433SKiran Ostrolenk } 413fcf19433SKiran Ostrolenk 414fcf19433SKiran Ostrolenkstatic bool vsha_check_sew(DisasContext *s) 415fcf19433SKiran Ostrolenk{ 416fcf19433SKiran Ostrolenk return (s->cfg_ptr->ext_zvknha == true && s->sew == MO_32) || 417fcf19433SKiran Ostrolenk (s->cfg_ptr->ext_zvknhb == true && 418fcf19433SKiran Ostrolenk (s->sew == MO_32 || s->sew == MO_64)); 419fcf19433SKiran Ostrolenk} 420fcf19433SKiran Ostrolenk 421fcf19433SKiran Ostrolenkstatic bool vsha_check(DisasContext *s, arg_rmrr *a) 422fcf19433SKiran Ostrolenk{ 423fcf19433SKiran Ostrolenk int egw_bytes = ZVKNH_EGS << s->sew; 424fcf19433SKiran Ostrolenk int mult = 1 << MAX(s->lmul, 0); 425fcf19433SKiran Ostrolenk return opivv_check(s, a) && 426fcf19433SKiran Ostrolenk vsha_check_sew(s) && 427fcf19433SKiran Ostrolenk MAXSZ(s) >= egw_bytes && 428fcf19433SKiran Ostrolenk !is_overlapped(a->rd, mult, a->rs1, mult) && 429fcf19433SKiran Ostrolenk !is_overlapped(a->rd, mult, a->rs2, mult) && 430fcf19433SKiran Ostrolenk s->lmul >= 0; 431fcf19433SKiran Ostrolenk} 432fcf19433SKiran Ostrolenk 433fcf19433SKiran OstrolenkGEN_VV_UNMASKED_TRANS(vsha2ms_vv, vsha_check, ZVKNH_EGS) 434fcf19433SKiran Ostrolenk 435fcf19433SKiran Ostrolenkstatic bool trans_vsha2cl_vv(DisasContext *s, arg_rmrr *a) 436fcf19433SKiran Ostrolenk{ 437fcf19433SKiran Ostrolenk if (vsha_check(s, a)) { 438fcf19433SKiran Ostrolenk uint32_t data = 0; 439fcf19433SKiran Ostrolenk TCGv_i32 egs; 440fcf19433SKiran Ostrolenk 441fcf19433SKiran Ostrolenk if (!s->vstart_eq_zero || !s->vl_eq_vlmax) { 442fcf19433SKiran Ostrolenk /* save opcode for unwinding in case we throw an exception */ 443fcf19433SKiran Ostrolenk decode_save_opc(s); 444fcf19433SKiran Ostrolenk egs = tcg_constant_i32(ZVKNH_EGS); 445ad75a51eSRichard Henderson gen_helper_egs_check(egs, tcg_env); 446fcf19433SKiran Ostrolenk } 447fcf19433SKiran Ostrolenk 448fcf19433SKiran Ostrolenk data = FIELD_DP32(data, VDATA, VM, a->vm); 449fcf19433SKiran Ostrolenk data = FIELD_DP32(data, VDATA, LMUL, s->lmul); 450fcf19433SKiran Ostrolenk data = FIELD_DP32(data, VDATA, VTA, s->vta); 451fcf19433SKiran Ostrolenk data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s); 452fcf19433SKiran Ostrolenk data = FIELD_DP32(data, VDATA, VMA, s->vma); 453fcf19433SKiran Ostrolenk 454fcf19433SKiran Ostrolenk tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1), 455f5a5e71eSDaniel Henrique Barboza vreg_ofs(s, a->rs2), tcg_env, s->cfg_ptr->vlenb, 456f5a5e71eSDaniel Henrique Barboza s->cfg_ptr->vlenb, data, 457fcf19433SKiran Ostrolenk s->sew == MO_32 ? 458fcf19433SKiran Ostrolenk gen_helper_vsha2cl32_vv : gen_helper_vsha2cl64_vv); 459fcf19433SKiran Ostrolenk 460*bac802adSIvan Klokov finalize_rvv_inst(s); 461fcf19433SKiran Ostrolenk return true; 462fcf19433SKiran Ostrolenk } 463fcf19433SKiran Ostrolenk return false; 464fcf19433SKiran Ostrolenk} 465fcf19433SKiran Ostrolenk 466fcf19433SKiran Ostrolenkstatic bool trans_vsha2ch_vv(DisasContext *s, arg_rmrr *a) 467fcf19433SKiran Ostrolenk{ 468fcf19433SKiran Ostrolenk if (vsha_check(s, a)) { 469fcf19433SKiran Ostrolenk uint32_t data = 0; 470fcf19433SKiran Ostrolenk TCGv_i32 egs; 471fcf19433SKiran Ostrolenk 472fcf19433SKiran Ostrolenk if (!s->vstart_eq_zero || !s->vl_eq_vlmax) { 473fcf19433SKiran Ostrolenk /* save opcode for unwinding in case we throw an exception */ 474fcf19433SKiran Ostrolenk decode_save_opc(s); 475fcf19433SKiran Ostrolenk egs = tcg_constant_i32(ZVKNH_EGS); 476ad75a51eSRichard Henderson gen_helper_egs_check(egs, tcg_env); 477fcf19433SKiran Ostrolenk } 478fcf19433SKiran Ostrolenk 479fcf19433SKiran Ostrolenk data = FIELD_DP32(data, VDATA, VM, a->vm); 480fcf19433SKiran Ostrolenk data = FIELD_DP32(data, VDATA, LMUL, s->lmul); 481fcf19433SKiran Ostrolenk data = FIELD_DP32(data, VDATA, VTA, s->vta); 482fcf19433SKiran Ostrolenk data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s); 483fcf19433SKiran Ostrolenk data = FIELD_DP32(data, VDATA, VMA, s->vma); 484fcf19433SKiran Ostrolenk 485fcf19433SKiran Ostrolenk tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1), 486f5a5e71eSDaniel Henrique Barboza vreg_ofs(s, a->rs2), tcg_env, s->cfg_ptr->vlenb, 487f5a5e71eSDaniel Henrique Barboza s->cfg_ptr->vlenb, data, 488fcf19433SKiran Ostrolenk s->sew == MO_32 ? 489fcf19433SKiran Ostrolenk gen_helper_vsha2ch32_vv : gen_helper_vsha2ch64_vv); 490fcf19433SKiran Ostrolenk 491*bac802adSIvan Klokov finalize_rvv_inst(s); 492fcf19433SKiran Ostrolenk return true; 493fcf19433SKiran Ostrolenk } 494fcf19433SKiran Ostrolenk return false; 495fcf19433SKiran Ostrolenk} 4962350881cSLawrence Hunter 4972350881cSLawrence Hunter/* 4982350881cSLawrence Hunter * Zvksh 4992350881cSLawrence Hunter */ 5002350881cSLawrence Hunter 5012350881cSLawrence Hunter#define ZVKSH_EGS 8 5022350881cSLawrence Hunter 5032350881cSLawrence Hunterstatic inline bool vsm3_check(DisasContext *s, arg_rmrr *a) 5042350881cSLawrence Hunter{ 5052350881cSLawrence Hunter int egw_bytes = ZVKSH_EGS << s->sew; 5062350881cSLawrence Hunter int mult = 1 << MAX(s->lmul, 0); 5072350881cSLawrence Hunter return s->cfg_ptr->ext_zvksh == true && 5082350881cSLawrence Hunter require_rvv(s) && 5092350881cSLawrence Hunter vext_check_isa_ill(s) && 5102350881cSLawrence Hunter !is_overlapped(a->rd, mult, a->rs2, mult) && 5112350881cSLawrence Hunter MAXSZ(s) >= egw_bytes && 5122350881cSLawrence Hunter s->sew == MO_32; 5132350881cSLawrence Hunter} 5142350881cSLawrence Hunter 5152350881cSLawrence Hunterstatic inline bool vsm3me_check(DisasContext *s, arg_rmrr *a) 5162350881cSLawrence Hunter{ 5172350881cSLawrence Hunter return vsm3_check(s, a) && vext_check_sss(s, a->rd, a->rs1, a->rs2, a->vm); 5182350881cSLawrence Hunter} 5192350881cSLawrence Hunter 5202350881cSLawrence Hunterstatic inline bool vsm3c_check(DisasContext *s, arg_rmrr *a) 5212350881cSLawrence Hunter{ 5222350881cSLawrence Hunter return vsm3_check(s, a) && vext_check_ss(s, a->rd, a->rs2, a->vm); 5232350881cSLawrence Hunter} 5242350881cSLawrence Hunter 5252350881cSLawrence HunterGEN_VV_UNMASKED_TRANS(vsm3me_vv, vsm3me_check, ZVKSH_EGS) 5262350881cSLawrence HunterGEN_VI_UNMASKED_TRANS(vsm3c_vi, vsm3c_check, ZVKSH_EGS) 527767eb035SNazar Kazakov 528767eb035SNazar Kazakov/* 529767eb035SNazar Kazakov * Zvkg 530767eb035SNazar Kazakov */ 531767eb035SNazar Kazakov 532767eb035SNazar Kazakov#define ZVKG_EGS 4 533767eb035SNazar Kazakov 534767eb035SNazar Kazakovstatic bool vgmul_check(DisasContext *s, arg_rmr *a) 535767eb035SNazar Kazakov{ 536767eb035SNazar Kazakov int egw_bytes = ZVKG_EGS << s->sew; 537767eb035SNazar Kazakov return s->cfg_ptr->ext_zvkg == true && 538767eb035SNazar Kazakov vext_check_isa_ill(s) && 539767eb035SNazar Kazakov require_rvv(s) && 540767eb035SNazar Kazakov MAXSZ(s) >= egw_bytes && 541767eb035SNazar Kazakov vext_check_ss(s, a->rd, a->rs2, a->vm) && 542767eb035SNazar Kazakov s->sew == MO_32; 543767eb035SNazar Kazakov} 544767eb035SNazar Kazakov 545767eb035SNazar KazakovGEN_V_UNMASKED_TRANS(vgmul_vv, vgmul_check, ZVKG_EGS) 546767eb035SNazar Kazakov 547767eb035SNazar Kazakovstatic bool vghsh_check(DisasContext *s, arg_rmrr *a) 548767eb035SNazar Kazakov{ 549767eb035SNazar Kazakov int egw_bytes = ZVKG_EGS << s->sew; 550767eb035SNazar Kazakov return s->cfg_ptr->ext_zvkg == true && 551767eb035SNazar Kazakov opivv_check(s, a) && 552767eb035SNazar Kazakov MAXSZ(s) >= egw_bytes && 553767eb035SNazar Kazakov s->sew == MO_32; 554767eb035SNazar Kazakov} 555767eb035SNazar Kazakov 556767eb035SNazar KazakovGEN_VV_UNMASKED_TRANS(vghsh_vv, vghsh_check, ZVKG_EGS) 5578b045ff4SMax Chou 5588b045ff4SMax Chou/* 5598b045ff4SMax Chou * Zvksed 5608b045ff4SMax Chou */ 5618b045ff4SMax Chou 5628b045ff4SMax Chou#define ZVKSED_EGS 4 5638b045ff4SMax Chou 5648b045ff4SMax Choustatic bool zvksed_check(DisasContext *s) 5658b045ff4SMax Chou{ 5668b045ff4SMax Chou int egw_bytes = ZVKSED_EGS << s->sew; 5678b045ff4SMax Chou return s->cfg_ptr->ext_zvksed == true && 5688b045ff4SMax Chou require_rvv(s) && 5698b045ff4SMax Chou vext_check_isa_ill(s) && 5708b045ff4SMax Chou MAXSZ(s) >= egw_bytes && 5718b045ff4SMax Chou s->sew == MO_32; 5728b045ff4SMax Chou} 5738b045ff4SMax Chou 5748b045ff4SMax Choustatic bool vsm4k_vi_check(DisasContext *s, arg_rmrr *a) 5758b045ff4SMax Chou{ 5768b045ff4SMax Chou return zvksed_check(s) && 5778b045ff4SMax Chou require_align(a->rd, s->lmul) && 5788b045ff4SMax Chou require_align(a->rs2, s->lmul); 5798b045ff4SMax Chou} 5808b045ff4SMax Chou 5818b045ff4SMax ChouGEN_VI_UNMASKED_TRANS(vsm4k_vi, vsm4k_vi_check, ZVKSED_EGS) 5828b045ff4SMax Chou 5838b045ff4SMax Choustatic bool vsm4r_vv_check(DisasContext *s, arg_rmr *a) 5848b045ff4SMax Chou{ 5858b045ff4SMax Chou return zvksed_check(s) && 5868b045ff4SMax Chou require_align(a->rd, s->lmul) && 5878b045ff4SMax Chou require_align(a->rs2, s->lmul); 5888b045ff4SMax Chou} 5898b045ff4SMax Chou 5908b045ff4SMax ChouGEN_V_UNMASKED_TRANS(vsm4r_vv, vsm4r_vv_check, ZVKSED_EGS) 5918b045ff4SMax Chou 5928b045ff4SMax Choustatic bool vsm4r_vs_check(DisasContext *s, arg_rmr *a) 5938b045ff4SMax Chou{ 5948b045ff4SMax Chou return zvksed_check(s) && 5958b045ff4SMax Chou !is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs2, 1) && 5968b045ff4SMax Chou require_align(a->rd, s->lmul); 5978b045ff4SMax Chou} 5988b045ff4SMax Chou 5998b045ff4SMax ChouGEN_V_UNMASKED_TRANS(vsm4r_vs, vsm4r_vs_check, ZVKSED_EGS) 600