cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

trans_rvv.c.inc (108344B)


      1/*
      2 * RISC-V translation routines for the RVV Standard Extension.
      3 *
      4 * Copyright (c) 2020 T-Head Semiconductor Co., Ltd. All rights reserved.
      5 *
      6 * This program is free software; you can redistribute it and/or modify it
      7 * under the terms and conditions of the GNU General Public License,
      8 * version 2 or later, as published by the Free Software Foundation.
      9 *
     10 * This program is distributed in the hope it will be useful, but WITHOUT
     11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     13 * more details.
     14 *
     15 * You should have received a copy of the GNU General Public License along with
     16 * this program.  If not, see <http://www.gnu.org/licenses/>.
     17 */
     18#include "tcg/tcg-op-gvec.h"
     19#include "tcg/tcg-gvec-desc.h"
     20#include "internals.h"
     21
     22static bool trans_vsetvl(DisasContext *ctx, arg_vsetvl *a)
     23{
     24    TCGv s1, s2, dst;
     25
     26    if (!has_ext(ctx, RVV)) {
     27        return false;
     28    }
     29
     30    s2 = get_gpr(ctx, a->rs2, EXT_ZERO);
     31    dst = dest_gpr(ctx, a->rd);
     32
     33    /* Using x0 as the rs1 register specifier, encodes an infinite AVL */
     34    if (a->rs1 == 0) {
     35        /* As the mask is at least one bit, RV_VLEN_MAX is >= VLMAX */
     36        s1 = tcg_constant_tl(RV_VLEN_MAX);
     37    } else {
     38        s1 = get_gpr(ctx, a->rs1, EXT_ZERO);
     39    }
     40    gen_helper_vsetvl(dst, cpu_env, s1, s2);
     41    gen_set_gpr(ctx, a->rd, dst);
     42
     43    tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn);
     44    lookup_and_goto_ptr(ctx);
     45    ctx->base.is_jmp = DISAS_NORETURN;
     46    return true;
     47}
     48
     49static bool trans_vsetvli(DisasContext *ctx, arg_vsetvli *a)
     50{
     51    TCGv s1, s2, dst;
     52
     53    if (!has_ext(ctx, RVV)) {
     54        return false;
     55    }
     56
     57    s2 = tcg_constant_tl(a->zimm);
     58    dst = dest_gpr(ctx, a->rd);
     59
     60    /* Using x0 as the rs1 register specifier, encodes an infinite AVL */
     61    if (a->rs1 == 0) {
     62        /* As the mask is at least one bit, RV_VLEN_MAX is >= VLMAX */
     63        s1 = tcg_constant_tl(RV_VLEN_MAX);
     64    } else {
     65        s1 = get_gpr(ctx, a->rs1, EXT_ZERO);
     66    }
     67    gen_helper_vsetvl(dst, cpu_env, s1, s2);
     68    gen_set_gpr(ctx, a->rd, dst);
     69
     70    gen_goto_tb(ctx, 0, ctx->pc_succ_insn);
     71    ctx->base.is_jmp = DISAS_NORETURN;
     72    return true;
     73}
     74
     75/* vector register offset from env */
     76static uint32_t vreg_ofs(DisasContext *s, int reg)
     77{
     78    return offsetof(CPURISCVState, vreg) + reg * s->vlen / 8;
     79}
     80
     81/* check functions */
     82
     83/*
     84 * In cpu_get_tb_cpu_state(), set VILL if RVV was not present.
     85 * So RVV is also be checked in this function.
     86 */
     87static bool vext_check_isa_ill(DisasContext *s)
     88{
     89    return !s->vill;
     90}
     91
     92/*
     93 * There are two rules check here.
     94 *
     95 * 1. Vector register numbers are multiples of LMUL. (Section 3.2)
     96 *
     97 * 2. For all widening instructions, the destination LMUL value must also be
     98 *    a supported LMUL value. (Section 11.2)
     99 */
    100static bool vext_check_reg(DisasContext *s, uint32_t reg, bool widen)
    101{
    102    /*
    103     * The destination vector register group results are arranged as if both
    104     * SEW and LMUL were at twice their current settings. (Section 11.2).
    105     */
    106    int legal = widen ? 2 << s->lmul : 1 << s->lmul;
    107
    108    return !((s->lmul == 0x3 && widen) || (reg % legal));
    109}
    110
    111/*
    112 * There are two rules check here.
    113 *
    114 * 1. The destination vector register group for a masked vector instruction can
    115 *    only overlap the source mask register (v0) when LMUL=1. (Section 5.3)
    116 *
    117 * 2. In widen instructions and some other insturctions, like vslideup.vx,
    118 *    there is no need to check whether LMUL=1.
    119 */
    120static bool vext_check_overlap_mask(DisasContext *s, uint32_t vd, bool vm,
    121    bool force)
    122{
    123    return (vm != 0 || vd != 0) || (!force && (s->lmul == 0));
    124}
    125
    126/* The LMUL setting must be such that LMUL * NFIELDS <= 8. (Section 7.8) */
    127static bool vext_check_nf(DisasContext *s, uint32_t nf)
    128{
    129    return (1 << s->lmul) * nf <= 8;
    130}
    131
    132/*
    133 * The destination vector register group cannot overlap a source vector register
    134 * group of a different element width. (Section 11.2)
    135 */
    136static inline bool vext_check_overlap_group(int rd, int dlen, int rs, int slen)
    137{
    138    return ((rd >= rs + slen) || (rs >= rd + dlen));
    139}
    140/* common translation macro */
    141#define GEN_VEXT_TRANS(NAME, SEQ, ARGTYPE, OP, CHECK)      \
    142static bool trans_##NAME(DisasContext *s, arg_##ARGTYPE *a)\
    143{                                                          \
    144    if (CHECK(s, a)) {                                     \
    145        return OP(s, a, SEQ);                              \
    146    }                                                      \
    147    return false;                                          \
    148}
    149
    150/*
    151 *** unit stride load and store
    152 */
    153typedef void gen_helper_ldst_us(TCGv_ptr, TCGv_ptr, TCGv,
    154                                TCGv_env, TCGv_i32);
    155
    156static bool ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data,
    157                          gen_helper_ldst_us *fn, DisasContext *s)
    158{
    159    TCGv_ptr dest, mask;
    160    TCGv base;
    161    TCGv_i32 desc;
    162
    163    TCGLabel *over = gen_new_label();
    164    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
    165
    166    dest = tcg_temp_new_ptr();
    167    mask = tcg_temp_new_ptr();
    168    base = get_gpr(s, rs1, EXT_NONE);
    169
    170    /*
    171     * As simd_desc supports at most 256 bytes, and in this implementation,
    172     * the max vector group length is 2048 bytes. So split it into two parts.
    173     *
    174     * The first part is vlen in bytes, encoded in maxsz of simd_desc.
    175     * The second part is lmul, encoded in data of simd_desc.
    176     */
    177    desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
    178
    179    tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
    180    tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
    181
    182    fn(dest, mask, base, cpu_env, desc);
    183
    184    tcg_temp_free_ptr(dest);
    185    tcg_temp_free_ptr(mask);
    186    gen_set_label(over);
    187    return true;
    188}
    189
    190static bool ld_us_op(DisasContext *s, arg_r2nfvm *a, uint8_t seq)
    191{
    192    uint32_t data = 0;
    193    gen_helper_ldst_us *fn;
    194    static gen_helper_ldst_us * const fns[2][7][4] = {
    195        /* masked unit stride load */
    196        { { gen_helper_vlb_v_b_mask,  gen_helper_vlb_v_h_mask,
    197            gen_helper_vlb_v_w_mask,  gen_helper_vlb_v_d_mask },
    198          { NULL,                     gen_helper_vlh_v_h_mask,
    199            gen_helper_vlh_v_w_mask,  gen_helper_vlh_v_d_mask },
    200          { NULL,                     NULL,
    201            gen_helper_vlw_v_w_mask,  gen_helper_vlw_v_d_mask },
    202          { gen_helper_vle_v_b_mask,  gen_helper_vle_v_h_mask,
    203            gen_helper_vle_v_w_mask,  gen_helper_vle_v_d_mask },
    204          { gen_helper_vlbu_v_b_mask, gen_helper_vlbu_v_h_mask,
    205            gen_helper_vlbu_v_w_mask, gen_helper_vlbu_v_d_mask },
    206          { NULL,                     gen_helper_vlhu_v_h_mask,
    207            gen_helper_vlhu_v_w_mask, gen_helper_vlhu_v_d_mask },
    208          { NULL,                     NULL,
    209            gen_helper_vlwu_v_w_mask, gen_helper_vlwu_v_d_mask } },
    210        /* unmasked unit stride load */
    211        { { gen_helper_vlb_v_b,  gen_helper_vlb_v_h,
    212            gen_helper_vlb_v_w,  gen_helper_vlb_v_d },
    213          { NULL,                gen_helper_vlh_v_h,
    214            gen_helper_vlh_v_w,  gen_helper_vlh_v_d },
    215          { NULL,                NULL,
    216            gen_helper_vlw_v_w,  gen_helper_vlw_v_d },
    217          { gen_helper_vle_v_b,  gen_helper_vle_v_h,
    218            gen_helper_vle_v_w,  gen_helper_vle_v_d },
    219          { gen_helper_vlbu_v_b, gen_helper_vlbu_v_h,
    220            gen_helper_vlbu_v_w, gen_helper_vlbu_v_d },
    221          { NULL,                gen_helper_vlhu_v_h,
    222            gen_helper_vlhu_v_w, gen_helper_vlhu_v_d },
    223          { NULL,                NULL,
    224            gen_helper_vlwu_v_w, gen_helper_vlwu_v_d } }
    225    };
    226
    227    fn =  fns[a->vm][seq][s->sew];
    228    if (fn == NULL) {
    229        return false;
    230    }
    231
    232    data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
    233    data = FIELD_DP32(data, VDATA, VM, a->vm);
    234    data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
    235    data = FIELD_DP32(data, VDATA, NF, a->nf);
    236    return ldst_us_trans(a->rd, a->rs1, data, fn, s);
    237}
    238
    239static bool ld_us_check(DisasContext *s, arg_r2nfvm* a)
    240{
    241    return (vext_check_isa_ill(s) &&
    242            vext_check_overlap_mask(s, a->rd, a->vm, false) &&
    243            vext_check_reg(s, a->rd, false) &&
    244            vext_check_nf(s, a->nf));
    245}
    246
    247GEN_VEXT_TRANS(vlb_v, 0, r2nfvm, ld_us_op, ld_us_check)
    248GEN_VEXT_TRANS(vlh_v, 1, r2nfvm, ld_us_op, ld_us_check)
    249GEN_VEXT_TRANS(vlw_v, 2, r2nfvm, ld_us_op, ld_us_check)
    250GEN_VEXT_TRANS(vle_v, 3, r2nfvm, ld_us_op, ld_us_check)
    251GEN_VEXT_TRANS(vlbu_v, 4, r2nfvm, ld_us_op, ld_us_check)
    252GEN_VEXT_TRANS(vlhu_v, 5, r2nfvm, ld_us_op, ld_us_check)
    253GEN_VEXT_TRANS(vlwu_v, 6, r2nfvm, ld_us_op, ld_us_check)
    254
    255static bool st_us_op(DisasContext *s, arg_r2nfvm *a, uint8_t seq)
    256{
    257    uint32_t data = 0;
    258    gen_helper_ldst_us *fn;
    259    static gen_helper_ldst_us * const fns[2][4][4] = {
    260        /* masked unit stride load and store */
    261        { { gen_helper_vsb_v_b_mask,  gen_helper_vsb_v_h_mask,
    262            gen_helper_vsb_v_w_mask,  gen_helper_vsb_v_d_mask },
    263          { NULL,                     gen_helper_vsh_v_h_mask,
    264            gen_helper_vsh_v_w_mask,  gen_helper_vsh_v_d_mask },
    265          { NULL,                     NULL,
    266            gen_helper_vsw_v_w_mask,  gen_helper_vsw_v_d_mask },
    267          { gen_helper_vse_v_b_mask,  gen_helper_vse_v_h_mask,
    268            gen_helper_vse_v_w_mask,  gen_helper_vse_v_d_mask } },
    269        /* unmasked unit stride store */
    270        { { gen_helper_vsb_v_b,  gen_helper_vsb_v_h,
    271            gen_helper_vsb_v_w,  gen_helper_vsb_v_d },
    272          { NULL,                gen_helper_vsh_v_h,
    273            gen_helper_vsh_v_w,  gen_helper_vsh_v_d },
    274          { NULL,                NULL,
    275            gen_helper_vsw_v_w,  gen_helper_vsw_v_d },
    276          { gen_helper_vse_v_b,  gen_helper_vse_v_h,
    277            gen_helper_vse_v_w,  gen_helper_vse_v_d } }
    278    };
    279
    280    fn =  fns[a->vm][seq][s->sew];
    281    if (fn == NULL) {
    282        return false;
    283    }
    284
    285    data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
    286    data = FIELD_DP32(data, VDATA, VM, a->vm);
    287    data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
    288    data = FIELD_DP32(data, VDATA, NF, a->nf);
    289    return ldst_us_trans(a->rd, a->rs1, data, fn, s);
    290}
    291
    292static bool st_us_check(DisasContext *s, arg_r2nfvm* a)
    293{
    294    return (vext_check_isa_ill(s) &&
    295            vext_check_reg(s, a->rd, false) &&
    296            vext_check_nf(s, a->nf));
    297}
    298
    299GEN_VEXT_TRANS(vsb_v, 0, r2nfvm, st_us_op, st_us_check)
    300GEN_VEXT_TRANS(vsh_v, 1, r2nfvm, st_us_op, st_us_check)
    301GEN_VEXT_TRANS(vsw_v, 2, r2nfvm, st_us_op, st_us_check)
    302GEN_VEXT_TRANS(vse_v, 3, r2nfvm, st_us_op, st_us_check)
    303
    304/*
    305 *** stride load and store
    306 */
    307typedef void gen_helper_ldst_stride(TCGv_ptr, TCGv_ptr, TCGv,
    308                                    TCGv, TCGv_env, TCGv_i32);
    309
    310static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, uint32_t rs2,
    311                              uint32_t data, gen_helper_ldst_stride *fn,
    312                              DisasContext *s)
    313{
    314    TCGv_ptr dest, mask;
    315    TCGv base, stride;
    316    TCGv_i32 desc;
    317
    318    TCGLabel *over = gen_new_label();
    319    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
    320
    321    dest = tcg_temp_new_ptr();
    322    mask = tcg_temp_new_ptr();
    323    base = get_gpr(s, rs1, EXT_NONE);
    324    stride = get_gpr(s, rs2, EXT_NONE);
    325    desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
    326
    327    tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
    328    tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
    329
    330    fn(dest, mask, base, stride, cpu_env, desc);
    331
    332    tcg_temp_free_ptr(dest);
    333    tcg_temp_free_ptr(mask);
    334    gen_set_label(over);
    335    return true;
    336}
    337
    338static bool ld_stride_op(DisasContext *s, arg_rnfvm *a, uint8_t seq)
    339{
    340    uint32_t data = 0;
    341    gen_helper_ldst_stride *fn;
    342    static gen_helper_ldst_stride * const fns[7][4] = {
    343        { gen_helper_vlsb_v_b,  gen_helper_vlsb_v_h,
    344          gen_helper_vlsb_v_w,  gen_helper_vlsb_v_d },
    345        { NULL,                 gen_helper_vlsh_v_h,
    346          gen_helper_vlsh_v_w,  gen_helper_vlsh_v_d },
    347        { NULL,                 NULL,
    348          gen_helper_vlsw_v_w,  gen_helper_vlsw_v_d },
    349        { gen_helper_vlse_v_b,  gen_helper_vlse_v_h,
    350          gen_helper_vlse_v_w,  gen_helper_vlse_v_d },
    351        { gen_helper_vlsbu_v_b, gen_helper_vlsbu_v_h,
    352          gen_helper_vlsbu_v_w, gen_helper_vlsbu_v_d },
    353        { NULL,                 gen_helper_vlshu_v_h,
    354          gen_helper_vlshu_v_w, gen_helper_vlshu_v_d },
    355        { NULL,                 NULL,
    356          gen_helper_vlswu_v_w, gen_helper_vlswu_v_d },
    357    };
    358
    359    fn =  fns[seq][s->sew];
    360    if (fn == NULL) {
    361        return false;
    362    }
    363
    364    data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
    365    data = FIELD_DP32(data, VDATA, VM, a->vm);
    366    data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
    367    data = FIELD_DP32(data, VDATA, NF, a->nf);
    368    return ldst_stride_trans(a->rd, a->rs1, a->rs2, data, fn, s);
    369}
    370
    371static bool ld_stride_check(DisasContext *s, arg_rnfvm* a)
    372{
    373    return (vext_check_isa_ill(s) &&
    374            vext_check_overlap_mask(s, a->rd, a->vm, false) &&
    375            vext_check_reg(s, a->rd, false) &&
    376            vext_check_nf(s, a->nf));
    377}
    378
    379GEN_VEXT_TRANS(vlsb_v, 0, rnfvm, ld_stride_op, ld_stride_check)
    380GEN_VEXT_TRANS(vlsh_v, 1, rnfvm, ld_stride_op, ld_stride_check)
    381GEN_VEXT_TRANS(vlsw_v, 2, rnfvm, ld_stride_op, ld_stride_check)
    382GEN_VEXT_TRANS(vlse_v, 3, rnfvm, ld_stride_op, ld_stride_check)
    383GEN_VEXT_TRANS(vlsbu_v, 4, rnfvm, ld_stride_op, ld_stride_check)
    384GEN_VEXT_TRANS(vlshu_v, 5, rnfvm, ld_stride_op, ld_stride_check)
    385GEN_VEXT_TRANS(vlswu_v, 6, rnfvm, ld_stride_op, ld_stride_check)
    386
    387static bool st_stride_op(DisasContext *s, arg_rnfvm *a, uint8_t seq)
    388{
    389    uint32_t data = 0;
    390    gen_helper_ldst_stride *fn;
    391    static gen_helper_ldst_stride * const fns[4][4] = {
    392        /* masked stride store */
    393        { gen_helper_vssb_v_b,  gen_helper_vssb_v_h,
    394          gen_helper_vssb_v_w,  gen_helper_vssb_v_d },
    395        { NULL,                 gen_helper_vssh_v_h,
    396          gen_helper_vssh_v_w,  gen_helper_vssh_v_d },
    397        { NULL,                 NULL,
    398          gen_helper_vssw_v_w,  gen_helper_vssw_v_d },
    399        { gen_helper_vsse_v_b,  gen_helper_vsse_v_h,
    400          gen_helper_vsse_v_w,  gen_helper_vsse_v_d }
    401    };
    402
    403    data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
    404    data = FIELD_DP32(data, VDATA, VM, a->vm);
    405    data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
    406    data = FIELD_DP32(data, VDATA, NF, a->nf);
    407    fn =  fns[seq][s->sew];
    408    if (fn == NULL) {
    409        return false;
    410    }
    411
    412    return ldst_stride_trans(a->rd, a->rs1, a->rs2, data, fn, s);
    413}
    414
    415static bool st_stride_check(DisasContext *s, arg_rnfvm* a)
    416{
    417    return (vext_check_isa_ill(s) &&
    418            vext_check_reg(s, a->rd, false) &&
    419            vext_check_nf(s, a->nf));
    420}
    421
    422GEN_VEXT_TRANS(vssb_v, 0, rnfvm, st_stride_op, st_stride_check)
    423GEN_VEXT_TRANS(vssh_v, 1, rnfvm, st_stride_op, st_stride_check)
    424GEN_VEXT_TRANS(vssw_v, 2, rnfvm, st_stride_op, st_stride_check)
    425GEN_VEXT_TRANS(vsse_v, 3, rnfvm, st_stride_op, st_stride_check)
    426
    427/*
    428 *** index load and store
    429 */
    430typedef void gen_helper_ldst_index(TCGv_ptr, TCGv_ptr, TCGv,
    431                                   TCGv_ptr, TCGv_env, TCGv_i32);
    432
    433static bool ldst_index_trans(uint32_t vd, uint32_t rs1, uint32_t vs2,
    434                             uint32_t data, gen_helper_ldst_index *fn,
    435                             DisasContext *s)
    436{
    437    TCGv_ptr dest, mask, index;
    438    TCGv base;
    439    TCGv_i32 desc;
    440
    441    TCGLabel *over = gen_new_label();
    442    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
    443
    444    dest = tcg_temp_new_ptr();
    445    mask = tcg_temp_new_ptr();
    446    index = tcg_temp_new_ptr();
    447    base = get_gpr(s, rs1, EXT_NONE);
    448    desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
    449
    450    tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
    451    tcg_gen_addi_ptr(index, cpu_env, vreg_ofs(s, vs2));
    452    tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
    453
    454    fn(dest, mask, base, index, cpu_env, desc);
    455
    456    tcg_temp_free_ptr(dest);
    457    tcg_temp_free_ptr(mask);
    458    tcg_temp_free_ptr(index);
    459    gen_set_label(over);
    460    return true;
    461}
    462
    463static bool ld_index_op(DisasContext *s, arg_rnfvm *a, uint8_t seq)
    464{
    465    uint32_t data = 0;
    466    gen_helper_ldst_index *fn;
    467    static gen_helper_ldst_index * const fns[7][4] = {
    468        { gen_helper_vlxb_v_b,  gen_helper_vlxb_v_h,
    469          gen_helper_vlxb_v_w,  gen_helper_vlxb_v_d },
    470        { NULL,                 gen_helper_vlxh_v_h,
    471          gen_helper_vlxh_v_w,  gen_helper_vlxh_v_d },
    472        { NULL,                 NULL,
    473          gen_helper_vlxw_v_w,  gen_helper_vlxw_v_d },
    474        { gen_helper_vlxe_v_b,  gen_helper_vlxe_v_h,
    475          gen_helper_vlxe_v_w,  gen_helper_vlxe_v_d },
    476        { gen_helper_vlxbu_v_b, gen_helper_vlxbu_v_h,
    477          gen_helper_vlxbu_v_w, gen_helper_vlxbu_v_d },
    478        { NULL,                 gen_helper_vlxhu_v_h,
    479          gen_helper_vlxhu_v_w, gen_helper_vlxhu_v_d },
    480        { NULL,                 NULL,
    481          gen_helper_vlxwu_v_w, gen_helper_vlxwu_v_d },
    482    };
    483
    484    fn =  fns[seq][s->sew];
    485    if (fn == NULL) {
    486        return false;
    487    }
    488
    489    data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
    490    data = FIELD_DP32(data, VDATA, VM, a->vm);
    491    data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
    492    data = FIELD_DP32(data, VDATA, NF, a->nf);
    493    return ldst_index_trans(a->rd, a->rs1, a->rs2, data, fn, s);
    494}
    495
    496/*
    497 * For vector indexed segment loads, the destination vector register
    498 * groups cannot overlap the source vector register group (specified by
    499 * `vs2`), else an illegal instruction exception is raised.
    500 */
    501static bool ld_index_check(DisasContext *s, arg_rnfvm* a)
    502{
    503    return (vext_check_isa_ill(s) &&
    504            vext_check_overlap_mask(s, a->rd, a->vm, false) &&
    505            vext_check_reg(s, a->rd, false) &&
    506            vext_check_reg(s, a->rs2, false) &&
    507            vext_check_nf(s, a->nf) &&
    508            ((a->nf == 1) ||
    509             vext_check_overlap_group(a->rd, a->nf << s->lmul,
    510                                      a->rs2, 1 << s->lmul)));
    511}
    512
    513GEN_VEXT_TRANS(vlxb_v, 0, rnfvm, ld_index_op, ld_index_check)
    514GEN_VEXT_TRANS(vlxh_v, 1, rnfvm, ld_index_op, ld_index_check)
    515GEN_VEXT_TRANS(vlxw_v, 2, rnfvm, ld_index_op, ld_index_check)
    516GEN_VEXT_TRANS(vlxe_v, 3, rnfvm, ld_index_op, ld_index_check)
    517GEN_VEXT_TRANS(vlxbu_v, 4, rnfvm, ld_index_op, ld_index_check)
    518GEN_VEXT_TRANS(vlxhu_v, 5, rnfvm, ld_index_op, ld_index_check)
    519GEN_VEXT_TRANS(vlxwu_v, 6, rnfvm, ld_index_op, ld_index_check)
    520
    521static bool st_index_op(DisasContext *s, arg_rnfvm *a, uint8_t seq)
    522{
    523    uint32_t data = 0;
    524    gen_helper_ldst_index *fn;
    525    static gen_helper_ldst_index * const fns[4][4] = {
    526        { gen_helper_vsxb_v_b,  gen_helper_vsxb_v_h,
    527          gen_helper_vsxb_v_w,  gen_helper_vsxb_v_d },
    528        { NULL,                 gen_helper_vsxh_v_h,
    529          gen_helper_vsxh_v_w,  gen_helper_vsxh_v_d },
    530        { NULL,                 NULL,
    531          gen_helper_vsxw_v_w,  gen_helper_vsxw_v_d },
    532        { gen_helper_vsxe_v_b,  gen_helper_vsxe_v_h,
    533          gen_helper_vsxe_v_w,  gen_helper_vsxe_v_d }
    534    };
    535
    536    fn =  fns[seq][s->sew];
    537    if (fn == NULL) {
    538        return false;
    539    }
    540
    541    data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
    542    data = FIELD_DP32(data, VDATA, VM, a->vm);
    543    data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
    544    data = FIELD_DP32(data, VDATA, NF, a->nf);
    545    return ldst_index_trans(a->rd, a->rs1, a->rs2, data, fn, s);
    546}
    547
    548static bool st_index_check(DisasContext *s, arg_rnfvm* a)
    549{
    550    return (vext_check_isa_ill(s) &&
    551            vext_check_reg(s, a->rd, false) &&
    552            vext_check_reg(s, a->rs2, false) &&
    553            vext_check_nf(s, a->nf));
    554}
    555
    556GEN_VEXT_TRANS(vsxb_v, 0, rnfvm, st_index_op, st_index_check)
    557GEN_VEXT_TRANS(vsxh_v, 1, rnfvm, st_index_op, st_index_check)
    558GEN_VEXT_TRANS(vsxw_v, 2, rnfvm, st_index_op, st_index_check)
    559GEN_VEXT_TRANS(vsxe_v, 3, rnfvm, st_index_op, st_index_check)
    560
    561/*
    562 *** unit stride fault-only-first load
    563 */
    564static bool ldff_trans(uint32_t vd, uint32_t rs1, uint32_t data,
    565                       gen_helper_ldst_us *fn, DisasContext *s)
    566{
    567    TCGv_ptr dest, mask;
    568    TCGv base;
    569    TCGv_i32 desc;
    570
    571    TCGLabel *over = gen_new_label();
    572    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
    573
    574    dest = tcg_temp_new_ptr();
    575    mask = tcg_temp_new_ptr();
    576    base = get_gpr(s, rs1, EXT_NONE);
    577    desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
    578
    579    tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
    580    tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
    581
    582    fn(dest, mask, base, cpu_env, desc);
    583
    584    tcg_temp_free_ptr(dest);
    585    tcg_temp_free_ptr(mask);
    586    gen_set_label(over);
    587    return true;
    588}
    589
    590static bool ldff_op(DisasContext *s, arg_r2nfvm *a, uint8_t seq)
    591{
    592    uint32_t data = 0;
    593    gen_helper_ldst_us *fn;
    594    static gen_helper_ldst_us * const fns[7][4] = {
    595        { gen_helper_vlbff_v_b,  gen_helper_vlbff_v_h,
    596          gen_helper_vlbff_v_w,  gen_helper_vlbff_v_d },
    597        { NULL,                  gen_helper_vlhff_v_h,
    598          gen_helper_vlhff_v_w,  gen_helper_vlhff_v_d },
    599        { NULL,                  NULL,
    600          gen_helper_vlwff_v_w,  gen_helper_vlwff_v_d },
    601        { gen_helper_vleff_v_b,  gen_helper_vleff_v_h,
    602          gen_helper_vleff_v_w,  gen_helper_vleff_v_d },
    603        { gen_helper_vlbuff_v_b, gen_helper_vlbuff_v_h,
    604          gen_helper_vlbuff_v_w, gen_helper_vlbuff_v_d },
    605        { NULL,                  gen_helper_vlhuff_v_h,
    606          gen_helper_vlhuff_v_w, gen_helper_vlhuff_v_d },
    607        { NULL,                  NULL,
    608          gen_helper_vlwuff_v_w, gen_helper_vlwuff_v_d }
    609    };
    610
    611    fn =  fns[seq][s->sew];
    612    if (fn == NULL) {
    613        return false;
    614    }
    615
    616    data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
    617    data = FIELD_DP32(data, VDATA, VM, a->vm);
    618    data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
    619    data = FIELD_DP32(data, VDATA, NF, a->nf);
    620    return ldff_trans(a->rd, a->rs1, data, fn, s);
    621}
    622
    623GEN_VEXT_TRANS(vlbff_v, 0, r2nfvm, ldff_op, ld_us_check)
    624GEN_VEXT_TRANS(vlhff_v, 1, r2nfvm, ldff_op, ld_us_check)
    625GEN_VEXT_TRANS(vlwff_v, 2, r2nfvm, ldff_op, ld_us_check)
    626GEN_VEXT_TRANS(vleff_v, 3, r2nfvm, ldff_op, ld_us_check)
    627GEN_VEXT_TRANS(vlbuff_v, 4, r2nfvm, ldff_op, ld_us_check)
    628GEN_VEXT_TRANS(vlhuff_v, 5, r2nfvm, ldff_op, ld_us_check)
    629GEN_VEXT_TRANS(vlwuff_v, 6, r2nfvm, ldff_op, ld_us_check)
    630
    631/*
    632 *** vector atomic operation
    633 */
    634typedef void gen_helper_amo(TCGv_ptr, TCGv_ptr, TCGv, TCGv_ptr,
    635                            TCGv_env, TCGv_i32);
    636
    637static bool amo_trans(uint32_t vd, uint32_t rs1, uint32_t vs2,
    638                      uint32_t data, gen_helper_amo *fn, DisasContext *s)
    639{
    640    TCGv_ptr dest, mask, index;
    641    TCGv base;
    642    TCGv_i32 desc;
    643
    644    TCGLabel *over = gen_new_label();
    645    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
    646
    647    dest = tcg_temp_new_ptr();
    648    mask = tcg_temp_new_ptr();
    649    index = tcg_temp_new_ptr();
    650    base = get_gpr(s, rs1, EXT_NONE);
    651    desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
    652
    653    tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
    654    tcg_gen_addi_ptr(index, cpu_env, vreg_ofs(s, vs2));
    655    tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
    656
    657    fn(dest, mask, base, index, cpu_env, desc);
    658
    659    tcg_temp_free_ptr(dest);
    660    tcg_temp_free_ptr(mask);
    661    tcg_temp_free_ptr(index);
    662    gen_set_label(over);
    663    return true;
    664}
    665
    666static bool amo_op(DisasContext *s, arg_rwdvm *a, uint8_t seq)
    667{
    668    uint32_t data = 0;
    669    gen_helper_amo *fn;
    670    static gen_helper_amo *const fnsw[9] = {
    671        /* no atomic operation */
    672        gen_helper_vamoswapw_v_w,
    673        gen_helper_vamoaddw_v_w,
    674        gen_helper_vamoxorw_v_w,
    675        gen_helper_vamoandw_v_w,
    676        gen_helper_vamoorw_v_w,
    677        gen_helper_vamominw_v_w,
    678        gen_helper_vamomaxw_v_w,
    679        gen_helper_vamominuw_v_w,
    680        gen_helper_vamomaxuw_v_w
    681    };
    682    static gen_helper_amo *const fnsd[18] = {
    683        gen_helper_vamoswapw_v_d,
    684        gen_helper_vamoaddw_v_d,
    685        gen_helper_vamoxorw_v_d,
    686        gen_helper_vamoandw_v_d,
    687        gen_helper_vamoorw_v_d,
    688        gen_helper_vamominw_v_d,
    689        gen_helper_vamomaxw_v_d,
    690        gen_helper_vamominuw_v_d,
    691        gen_helper_vamomaxuw_v_d,
    692        gen_helper_vamoswapd_v_d,
    693        gen_helper_vamoaddd_v_d,
    694        gen_helper_vamoxord_v_d,
    695        gen_helper_vamoandd_v_d,
    696        gen_helper_vamoord_v_d,
    697        gen_helper_vamomind_v_d,
    698        gen_helper_vamomaxd_v_d,
    699        gen_helper_vamominud_v_d,
    700        gen_helper_vamomaxud_v_d
    701    };
    702
    703    if (tb_cflags(s->base.tb) & CF_PARALLEL) {
    704        gen_helper_exit_atomic(cpu_env);
    705        s->base.is_jmp = DISAS_NORETURN;
    706        return true;
    707    } else {
    708        if (s->sew == 3) {
    709            if (!is_32bit(s)) {
    710                fn = fnsd[seq];
    711            } else {
    712                /* Check done in amo_check(). */
    713                g_assert_not_reached();
    714            }
    715        } else {
    716            assert(seq < ARRAY_SIZE(fnsw));
    717            fn = fnsw[seq];
    718        }
    719    }
    720
    721    data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
    722    data = FIELD_DP32(data, VDATA, VM, a->vm);
    723    data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
    724    data = FIELD_DP32(data, VDATA, WD, a->wd);
    725    return amo_trans(a->rd, a->rs1, a->rs2, data, fn, s);
    726}
    727/*
    728 * There are two rules check here.
    729 *
    730 * 1. SEW must be at least as wide as the AMO memory element size.
    731 *
    732 * 2. If SEW is greater than XLEN, an illegal instruction exception is raised.
    733 */
    734static bool amo_check(DisasContext *s, arg_rwdvm* a)
    735{
    736    return (!s->vill && has_ext(s, RVA) &&
    737            (!a->wd || vext_check_overlap_mask(s, a->rd, a->vm, false)) &&
    738            vext_check_reg(s, a->rd, false) &&
    739            vext_check_reg(s, a->rs2, false) &&
    740            ((1 << s->sew) <= sizeof(target_ulong)) &&
    741            ((1 << s->sew) >= 4));
    742}
    743
    744static bool amo_check64(DisasContext *s, arg_rwdvm* a)
    745{
    746    return !is_32bit(s) && amo_check(s, a);
    747}
    748
    749GEN_VEXT_TRANS(vamoswapw_v, 0, rwdvm, amo_op, amo_check)
    750GEN_VEXT_TRANS(vamoaddw_v, 1, rwdvm, amo_op, amo_check)
    751GEN_VEXT_TRANS(vamoxorw_v, 2, rwdvm, amo_op, amo_check)
    752GEN_VEXT_TRANS(vamoandw_v, 3, rwdvm, amo_op, amo_check)
    753GEN_VEXT_TRANS(vamoorw_v, 4, rwdvm, amo_op, amo_check)
    754GEN_VEXT_TRANS(vamominw_v, 5, rwdvm, amo_op, amo_check)
    755GEN_VEXT_TRANS(vamomaxw_v, 6, rwdvm, amo_op, amo_check)
    756GEN_VEXT_TRANS(vamominuw_v, 7, rwdvm, amo_op, amo_check)
    757GEN_VEXT_TRANS(vamomaxuw_v, 8, rwdvm, amo_op, amo_check)
    758GEN_VEXT_TRANS(vamoswapd_v, 9, rwdvm, amo_op, amo_check64)
    759GEN_VEXT_TRANS(vamoaddd_v, 10, rwdvm, amo_op, amo_check64)
    760GEN_VEXT_TRANS(vamoxord_v, 11, rwdvm, amo_op, amo_check64)
    761GEN_VEXT_TRANS(vamoandd_v, 12, rwdvm, amo_op, amo_check64)
    762GEN_VEXT_TRANS(vamoord_v, 13, rwdvm, amo_op, amo_check64)
    763GEN_VEXT_TRANS(vamomind_v, 14, rwdvm, amo_op, amo_check64)
    764GEN_VEXT_TRANS(vamomaxd_v, 15, rwdvm, amo_op, amo_check64)
    765GEN_VEXT_TRANS(vamominud_v, 16, rwdvm, amo_op, amo_check64)
    766GEN_VEXT_TRANS(vamomaxud_v, 17, rwdvm, amo_op, amo_check64)
    767
    768/*
    769 *** Vector Integer Arithmetic Instructions
    770 */
    771#define MAXSZ(s) (s->vlen >> (3 - s->lmul))
    772
    773static bool opivv_check(DisasContext *s, arg_rmrr *a)
    774{
    775    return (vext_check_isa_ill(s) &&
    776            vext_check_overlap_mask(s, a->rd, a->vm, false) &&
    777            vext_check_reg(s, a->rd, false) &&
    778            vext_check_reg(s, a->rs2, false) &&
    779            vext_check_reg(s, a->rs1, false));
    780}
    781
    782typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t,
    783                        uint32_t, uint32_t, uint32_t);
    784
    785static inline bool
    786do_opivv_gvec(DisasContext *s, arg_rmrr *a, GVecGen3Fn *gvec_fn,
    787              gen_helper_gvec_4_ptr *fn)
    788{
    789    TCGLabel *over = gen_new_label();
    790    if (!opivv_check(s, a)) {
    791        return false;
    792    }
    793
    794    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
    795
    796    if (a->vm && s->vl_eq_vlmax) {
    797        gvec_fn(s->sew, vreg_ofs(s, a->rd),
    798                vreg_ofs(s, a->rs2), vreg_ofs(s, a->rs1),
    799                MAXSZ(s), MAXSZ(s));
    800    } else {
    801        uint32_t data = 0;
    802
    803        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
    804        data = FIELD_DP32(data, VDATA, VM, a->vm);
    805        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
    806        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
    807                           vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2),
    808                           cpu_env, s->vlen / 8, s->vlen / 8, data, fn);
    809    }
    810    gen_set_label(over);
    811    return true;
    812}
    813
    814/* OPIVV with GVEC IR */
    815#define GEN_OPIVV_GVEC_TRANS(NAME, SUF) \
    816static bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
    817{                                                                  \
    818    static gen_helper_gvec_4_ptr * const fns[4] = {                \
    819        gen_helper_##NAME##_b, gen_helper_##NAME##_h,              \
    820        gen_helper_##NAME##_w, gen_helper_##NAME##_d,              \
    821    };                                                             \
    822    return do_opivv_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]);   \
    823}
    824
    825GEN_OPIVV_GVEC_TRANS(vadd_vv, add)
    826GEN_OPIVV_GVEC_TRANS(vsub_vv, sub)
    827
    828typedef void gen_helper_opivx(TCGv_ptr, TCGv_ptr, TCGv, TCGv_ptr,
    829                              TCGv_env, TCGv_i32);
    830
    831static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm,
    832                        gen_helper_opivx *fn, DisasContext *s)
    833{
    834    TCGv_ptr dest, src2, mask;
    835    TCGv src1;
    836    TCGv_i32 desc;
    837    uint32_t data = 0;
    838
    839    TCGLabel *over = gen_new_label();
    840    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
    841
    842    dest = tcg_temp_new_ptr();
    843    mask = tcg_temp_new_ptr();
    844    src2 = tcg_temp_new_ptr();
    845    src1 = get_gpr(s, rs1, EXT_NONE);
    846
    847    data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
    848    data = FIELD_DP32(data, VDATA, VM, vm);
    849    data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
    850    desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
    851
    852    tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
    853    tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2));
    854    tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
    855
    856    fn(dest, mask, src1, src2, cpu_env, desc);
    857
    858    tcg_temp_free_ptr(dest);
    859    tcg_temp_free_ptr(mask);
    860    tcg_temp_free_ptr(src2);
    861    gen_set_label(over);
    862    return true;
    863}
    864
    865static bool opivx_check(DisasContext *s, arg_rmrr *a)
    866{
    867    return (vext_check_isa_ill(s) &&
    868            vext_check_overlap_mask(s, a->rd, a->vm, false) &&
    869            vext_check_reg(s, a->rd, false) &&
    870            vext_check_reg(s, a->rs2, false));
    871}
    872
    873typedef void GVecGen2sFn(unsigned, uint32_t, uint32_t, TCGv_i64,
    874                         uint32_t, uint32_t);
    875
    876static inline bool
    877do_opivx_gvec(DisasContext *s, arg_rmrr *a, GVecGen2sFn *gvec_fn,
    878              gen_helper_opivx *fn)
    879{
    880    if (!opivx_check(s, a)) {
    881        return false;
    882    }
    883
    884    if (a->vm && s->vl_eq_vlmax) {
    885        TCGv_i64 src1 = tcg_temp_new_i64();
    886
    887        tcg_gen_ext_tl_i64(src1, get_gpr(s, a->rs1, EXT_SIGN));
    888        gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2),
    889                src1, MAXSZ(s), MAXSZ(s));
    890
    891        tcg_temp_free_i64(src1);
    892        return true;
    893    }
    894    return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s);
    895}
    896
    897/* OPIVX with GVEC IR */
    898#define GEN_OPIVX_GVEC_TRANS(NAME, SUF) \
    899static bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
    900{                                                                  \
    901    static gen_helper_opivx * const fns[4] = {                     \
    902        gen_helper_##NAME##_b, gen_helper_##NAME##_h,              \
    903        gen_helper_##NAME##_w, gen_helper_##NAME##_d,              \
    904    };                                                             \
    905    return do_opivx_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]);   \
    906}
    907
    908GEN_OPIVX_GVEC_TRANS(vadd_vx, adds)
    909GEN_OPIVX_GVEC_TRANS(vsub_vx, subs)
    910
    911static void gen_vec_rsub8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
    912{
    913    tcg_gen_vec_sub8_i64(d, b, a);
    914}
    915
    916static void gen_vec_rsub16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
    917{
    918    tcg_gen_vec_sub16_i64(d, b, a);
    919}
    920
    921static void gen_rsub_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
    922{
    923    tcg_gen_sub_i32(ret, arg2, arg1);
    924}
    925
    926static void gen_rsub_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
    927{
    928    tcg_gen_sub_i64(ret, arg2, arg1);
    929}
    930
    931static void gen_rsub_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
    932{
    933    tcg_gen_sub_vec(vece, r, b, a);
    934}
    935
    936static void tcg_gen_gvec_rsubs(unsigned vece, uint32_t dofs, uint32_t aofs,
    937                               TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
    938{
    939    static const TCGOpcode vecop_list[] = { INDEX_op_sub_vec, 0 };
    940    static const GVecGen2s rsub_op[4] = {
    941        { .fni8 = gen_vec_rsub8_i64,
    942          .fniv = gen_rsub_vec,
    943          .fno = gen_helper_vec_rsubs8,
    944          .opt_opc = vecop_list,
    945          .vece = MO_8 },
    946        { .fni8 = gen_vec_rsub16_i64,
    947          .fniv = gen_rsub_vec,
    948          .fno = gen_helper_vec_rsubs16,
    949          .opt_opc = vecop_list,
    950          .vece = MO_16 },
    951        { .fni4 = gen_rsub_i32,
    952          .fniv = gen_rsub_vec,
    953          .fno = gen_helper_vec_rsubs32,
    954          .opt_opc = vecop_list,
    955          .vece = MO_32 },
    956        { .fni8 = gen_rsub_i64,
    957          .fniv = gen_rsub_vec,
    958          .fno = gen_helper_vec_rsubs64,
    959          .opt_opc = vecop_list,
    960          .prefer_i64 = TCG_TARGET_REG_BITS == 64,
    961          .vece = MO_64 },
    962    };
    963
    964    tcg_debug_assert(vece <= MO_64);
    965    tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, c, &rsub_op[vece]);
    966}
    967
    968GEN_OPIVX_GVEC_TRANS(vrsub_vx, rsubs)
    969
    970static bool opivi_trans(uint32_t vd, uint32_t imm, uint32_t vs2, uint32_t vm,
    971                        gen_helper_opivx *fn, DisasContext *s, int zx)
    972{
    973    TCGv_ptr dest, src2, mask;
    974    TCGv src1;
    975    TCGv_i32 desc;
    976    uint32_t data = 0;
    977
    978    TCGLabel *over = gen_new_label();
    979    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
    980
    981    dest = tcg_temp_new_ptr();
    982    mask = tcg_temp_new_ptr();
    983    src2 = tcg_temp_new_ptr();
    984    if (zx) {
    985        src1 = tcg_constant_tl(imm);
    986    } else {
    987        src1 = tcg_constant_tl(sextract64(imm, 0, 5));
    988    }
    989    data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
    990    data = FIELD_DP32(data, VDATA, VM, vm);
    991    data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
    992    desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
    993
    994    tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
    995    tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2));
    996    tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
    997
    998    fn(dest, mask, src1, src2, cpu_env, desc);
    999
   1000    tcg_temp_free_ptr(dest);
   1001    tcg_temp_free_ptr(mask);
   1002    tcg_temp_free_ptr(src2);
   1003    gen_set_label(over);
   1004    return true;
   1005}
   1006
   1007typedef void GVecGen2iFn(unsigned, uint32_t, uint32_t, int64_t,
   1008                         uint32_t, uint32_t);
   1009
   1010static inline bool
   1011do_opivi_gvec(DisasContext *s, arg_rmrr *a, GVecGen2iFn *gvec_fn,
   1012              gen_helper_opivx *fn, int zx)
   1013{
   1014    if (!opivx_check(s, a)) {
   1015        return false;
   1016    }
   1017
   1018    if (a->vm && s->vl_eq_vlmax) {
   1019        if (zx) {
   1020            gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2),
   1021                    extract64(a->rs1, 0, 5), MAXSZ(s), MAXSZ(s));
   1022        } else {
   1023            gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2),
   1024                    sextract64(a->rs1, 0, 5), MAXSZ(s), MAXSZ(s));
   1025        }
   1026    } else {
   1027        return opivi_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s, zx);
   1028    }
   1029    return true;
   1030}
   1031
   1032/* OPIVI with GVEC IR */
   1033#define GEN_OPIVI_GVEC_TRANS(NAME, ZX, OPIVX, SUF) \
   1034static bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
   1035{                                                                  \
   1036    static gen_helper_opivx * const fns[4] = {                     \
   1037        gen_helper_##OPIVX##_b, gen_helper_##OPIVX##_h,            \
   1038        gen_helper_##OPIVX##_w, gen_helper_##OPIVX##_d,            \
   1039    };                                                             \
   1040    return do_opivi_gvec(s, a, tcg_gen_gvec_##SUF,                 \
   1041                         fns[s->sew], ZX);                         \
   1042}
   1043
   1044GEN_OPIVI_GVEC_TRANS(vadd_vi, 0, vadd_vx, addi)
   1045
   1046static void tcg_gen_gvec_rsubi(unsigned vece, uint32_t dofs, uint32_t aofs,
   1047                               int64_t c, uint32_t oprsz, uint32_t maxsz)
   1048{
   1049    TCGv_i64 tmp = tcg_constant_i64(c);
   1050    tcg_gen_gvec_rsubs(vece, dofs, aofs, tmp, oprsz, maxsz);
   1051}
   1052
   1053GEN_OPIVI_GVEC_TRANS(vrsub_vi, 0, vrsub_vx, rsubi)
   1054
   1055/* Vector Widening Integer Add/Subtract */
   1056
   1057/* OPIVV with WIDEN */
   1058static bool opivv_widen_check(DisasContext *s, arg_rmrr *a)
   1059{
   1060    return (vext_check_isa_ill(s) &&
   1061            vext_check_overlap_mask(s, a->rd, a->vm, true) &&
   1062            vext_check_reg(s, a->rd, true) &&
   1063            vext_check_reg(s, a->rs2, false) &&
   1064            vext_check_reg(s, a->rs1, false) &&
   1065            vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs2,
   1066                                     1 << s->lmul) &&
   1067            vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs1,
   1068                                     1 << s->lmul) &&
   1069            (s->lmul < 0x3) && (s->sew < 0x3));
   1070}
   1071
   1072static bool do_opivv_widen(DisasContext *s, arg_rmrr *a,
   1073                           gen_helper_gvec_4_ptr *fn,
   1074                           bool (*checkfn)(DisasContext *, arg_rmrr *))
   1075{
   1076    if (checkfn(s, a)) {
   1077        uint32_t data = 0;
   1078        TCGLabel *over = gen_new_label();
   1079        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
   1080
   1081        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
   1082        data = FIELD_DP32(data, VDATA, VM, a->vm);
   1083        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
   1084        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
   1085                           vreg_ofs(s, a->rs1),
   1086                           vreg_ofs(s, a->rs2),
   1087                           cpu_env, s->vlen / 8, s->vlen / 8,
   1088                           data, fn);
   1089        gen_set_label(over);
   1090        return true;
   1091    }
   1092    return false;
   1093}
   1094
   1095#define GEN_OPIVV_WIDEN_TRANS(NAME, CHECK) \
   1096static bool trans_##NAME(DisasContext *s, arg_rmrr *a)       \
   1097{                                                            \
   1098    static gen_helper_gvec_4_ptr * const fns[3] = {          \
   1099        gen_helper_##NAME##_b,                               \
   1100        gen_helper_##NAME##_h,                               \
   1101        gen_helper_##NAME##_w                                \
   1102    };                                                       \
   1103    return do_opivv_widen(s, a, fns[s->sew], CHECK);         \
   1104}
   1105
   1106GEN_OPIVV_WIDEN_TRANS(vwaddu_vv, opivv_widen_check)
   1107GEN_OPIVV_WIDEN_TRANS(vwadd_vv, opivv_widen_check)
   1108GEN_OPIVV_WIDEN_TRANS(vwsubu_vv, opivv_widen_check)
   1109GEN_OPIVV_WIDEN_TRANS(vwsub_vv, opivv_widen_check)
   1110
   1111/* OPIVX with WIDEN */
   1112static bool opivx_widen_check(DisasContext *s, arg_rmrr *a)
   1113{
   1114    return (vext_check_isa_ill(s) &&
   1115            vext_check_overlap_mask(s, a->rd, a->vm, true) &&
   1116            vext_check_reg(s, a->rd, true) &&
   1117            vext_check_reg(s, a->rs2, false) &&
   1118            vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs2,
   1119                                     1 << s->lmul) &&
   1120            (s->lmul < 0x3) && (s->sew < 0x3));
   1121}
   1122
   1123static bool do_opivx_widen(DisasContext *s, arg_rmrr *a,
   1124                           gen_helper_opivx *fn)
   1125{
   1126    if (opivx_widen_check(s, a)) {
   1127        return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s);
   1128    }
   1129    return false;
   1130}
   1131
   1132#define GEN_OPIVX_WIDEN_TRANS(NAME) \
   1133static bool trans_##NAME(DisasContext *s, arg_rmrr *a)       \
   1134{                                                            \
   1135    static gen_helper_opivx * const fns[3] = {               \
   1136        gen_helper_##NAME##_b,                               \
   1137        gen_helper_##NAME##_h,                               \
   1138        gen_helper_##NAME##_w                                \
   1139    };                                                       \
   1140    return do_opivx_widen(s, a, fns[s->sew]);                \
   1141}
   1142
   1143GEN_OPIVX_WIDEN_TRANS(vwaddu_vx)
   1144GEN_OPIVX_WIDEN_TRANS(vwadd_vx)
   1145GEN_OPIVX_WIDEN_TRANS(vwsubu_vx)
   1146GEN_OPIVX_WIDEN_TRANS(vwsub_vx)
   1147
   1148/* WIDEN OPIVV with WIDEN */
   1149static bool opiwv_widen_check(DisasContext *s, arg_rmrr *a)
   1150{
   1151    return (vext_check_isa_ill(s) &&
   1152            vext_check_overlap_mask(s, a->rd, a->vm, true) &&
   1153            vext_check_reg(s, a->rd, true) &&
   1154            vext_check_reg(s, a->rs2, true) &&
   1155            vext_check_reg(s, a->rs1, false) &&
   1156            vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs1,
   1157                                     1 << s->lmul) &&
   1158            (s->lmul < 0x3) && (s->sew < 0x3));
   1159}
   1160
   1161static bool do_opiwv_widen(DisasContext *s, arg_rmrr *a,
   1162                           gen_helper_gvec_4_ptr *fn)
   1163{
   1164    if (opiwv_widen_check(s, a)) {
   1165        uint32_t data = 0;
   1166        TCGLabel *over = gen_new_label();
   1167        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
   1168
   1169        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
   1170        data = FIELD_DP32(data, VDATA, VM, a->vm);
   1171        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
   1172        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
   1173                           vreg_ofs(s, a->rs1),
   1174                           vreg_ofs(s, a->rs2),
   1175                           cpu_env, s->vlen / 8, s->vlen / 8, data, fn);
   1176        gen_set_label(over);
   1177        return true;
   1178    }
   1179    return false;
   1180}
   1181
   1182#define GEN_OPIWV_WIDEN_TRANS(NAME) \
   1183static bool trans_##NAME(DisasContext *s, arg_rmrr *a)       \
   1184{                                                            \
   1185    static gen_helper_gvec_4_ptr * const fns[3] = {          \
   1186        gen_helper_##NAME##_b,                               \
   1187        gen_helper_##NAME##_h,                               \
   1188        gen_helper_##NAME##_w                                \
   1189    };                                                       \
   1190    return do_opiwv_widen(s, a, fns[s->sew]);                \
   1191}
   1192
   1193GEN_OPIWV_WIDEN_TRANS(vwaddu_wv)
   1194GEN_OPIWV_WIDEN_TRANS(vwadd_wv)
   1195GEN_OPIWV_WIDEN_TRANS(vwsubu_wv)
   1196GEN_OPIWV_WIDEN_TRANS(vwsub_wv)
   1197
   1198/* WIDEN OPIVX with WIDEN */
   1199static bool opiwx_widen_check(DisasContext *s, arg_rmrr *a)
   1200{
   1201    return (vext_check_isa_ill(s) &&
   1202            vext_check_overlap_mask(s, a->rd, a->vm, true) &&
   1203            vext_check_reg(s, a->rd, true) &&
   1204            vext_check_reg(s, a->rs2, true) &&
   1205            (s->lmul < 0x3) && (s->sew < 0x3));
   1206}
   1207
   1208static bool do_opiwx_widen(DisasContext *s, arg_rmrr *a,
   1209                           gen_helper_opivx *fn)
   1210{
   1211    if (opiwx_widen_check(s, a)) {
   1212        return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s);
   1213    }
   1214    return false;
   1215}
   1216
   1217#define GEN_OPIWX_WIDEN_TRANS(NAME) \
   1218static bool trans_##NAME(DisasContext *s, arg_rmrr *a)       \
   1219{                                                            \
   1220    static gen_helper_opivx * const fns[3] = {               \
   1221        gen_helper_##NAME##_b,                               \
   1222        gen_helper_##NAME##_h,                               \
   1223        gen_helper_##NAME##_w                                \
   1224    };                                                       \
   1225    return do_opiwx_widen(s, a, fns[s->sew]);                \
   1226}
   1227
   1228GEN_OPIWX_WIDEN_TRANS(vwaddu_wx)
   1229GEN_OPIWX_WIDEN_TRANS(vwadd_wx)
   1230GEN_OPIWX_WIDEN_TRANS(vwsubu_wx)
   1231GEN_OPIWX_WIDEN_TRANS(vwsub_wx)
   1232
   1233/* Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions */
   1234/* OPIVV without GVEC IR */
   1235#define GEN_OPIVV_TRANS(NAME, CHECK)                               \
   1236static bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
   1237{                                                                  \
   1238    if (CHECK(s, a)) {                                             \
   1239        uint32_t data = 0;                                         \
   1240        static gen_helper_gvec_4_ptr * const fns[4] = {            \
   1241            gen_helper_##NAME##_b, gen_helper_##NAME##_h,          \
   1242            gen_helper_##NAME##_w, gen_helper_##NAME##_d,          \
   1243        };                                                         \
   1244        TCGLabel *over = gen_new_label();                          \
   1245        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
   1246                                                                   \
   1247        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);             \
   1248        data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
   1249        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
   1250        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
   1251                           vreg_ofs(s, a->rs1),                    \
   1252                           vreg_ofs(s, a->rs2), cpu_env,           \
   1253                           s->vlen / 8, s->vlen / 8, data,         \
   1254                           fns[s->sew]);                           \
   1255        gen_set_label(over);                                       \
   1256        return true;                                               \
   1257    }                                                              \
   1258    return false;                                                  \
   1259}
   1260
   1261/*
   1262 * For vadc and vsbc, an illegal instruction exception is raised if the
   1263 * destination vector register is v0 and LMUL > 1. (Section 12.3)
   1264 */
   1265static bool opivv_vadc_check(DisasContext *s, arg_rmrr *a)
   1266{
   1267    return (vext_check_isa_ill(s) &&
   1268            vext_check_reg(s, a->rd, false) &&
   1269            vext_check_reg(s, a->rs2, false) &&
   1270            vext_check_reg(s, a->rs1, false) &&
   1271            ((a->rd != 0) || (s->lmul == 0)));
   1272}
   1273
   1274GEN_OPIVV_TRANS(vadc_vvm, opivv_vadc_check)
   1275GEN_OPIVV_TRANS(vsbc_vvm, opivv_vadc_check)
   1276
   1277/*
   1278 * For vmadc and vmsbc, an illegal instruction exception is raised if the
   1279 * destination vector register overlaps a source vector register group.
   1280 */
   1281static bool opivv_vmadc_check(DisasContext *s, arg_rmrr *a)
   1282{
   1283    return (vext_check_isa_ill(s) &&
   1284            vext_check_reg(s, a->rs2, false) &&
   1285            vext_check_reg(s, a->rs1, false) &&
   1286            vext_check_overlap_group(a->rd, 1, a->rs1, 1 << s->lmul) &&
   1287            vext_check_overlap_group(a->rd, 1, a->rs2, 1 << s->lmul));
   1288}
   1289
   1290GEN_OPIVV_TRANS(vmadc_vvm, opivv_vmadc_check)
   1291GEN_OPIVV_TRANS(vmsbc_vvm, opivv_vmadc_check)
   1292
   1293static bool opivx_vadc_check(DisasContext *s, arg_rmrr *a)
   1294{
   1295    return (vext_check_isa_ill(s) &&
   1296            vext_check_reg(s, a->rd, false) &&
   1297            vext_check_reg(s, a->rs2, false) &&
   1298            ((a->rd != 0) || (s->lmul == 0)));
   1299}
   1300
   1301/* OPIVX without GVEC IR */
   1302#define GEN_OPIVX_TRANS(NAME, CHECK)                                     \
   1303static bool trans_##NAME(DisasContext *s, arg_rmrr *a)                   \
   1304{                                                                        \
   1305    if (CHECK(s, a)) {                                                   \
   1306        static gen_helper_opivx * const fns[4] = {                       \
   1307            gen_helper_##NAME##_b, gen_helper_##NAME##_h,                \
   1308            gen_helper_##NAME##_w, gen_helper_##NAME##_d,                \
   1309        };                                                               \
   1310                                                                         \
   1311        return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s);\
   1312    }                                                                    \
   1313    return false;                                                        \
   1314}
   1315
   1316GEN_OPIVX_TRANS(vadc_vxm, opivx_vadc_check)
   1317GEN_OPIVX_TRANS(vsbc_vxm, opivx_vadc_check)
   1318
   1319static bool opivx_vmadc_check(DisasContext *s, arg_rmrr *a)
   1320{
   1321    return (vext_check_isa_ill(s) &&
   1322            vext_check_reg(s, a->rs2, false) &&
   1323            vext_check_overlap_group(a->rd, 1, a->rs2, 1 << s->lmul));
   1324}
   1325
   1326GEN_OPIVX_TRANS(vmadc_vxm, opivx_vmadc_check)
   1327GEN_OPIVX_TRANS(vmsbc_vxm, opivx_vmadc_check)
   1328
   1329/* OPIVI without GVEC IR */
   1330#define GEN_OPIVI_TRANS(NAME, ZX, OPIVX, CHECK)                          \
   1331static bool trans_##NAME(DisasContext *s, arg_rmrr *a)                   \
   1332{                                                                        \
   1333    if (CHECK(s, a)) {                                                   \
   1334        static gen_helper_opivx * const fns[4] = {                       \
   1335            gen_helper_##OPIVX##_b, gen_helper_##OPIVX##_h,              \
   1336            gen_helper_##OPIVX##_w, gen_helper_##OPIVX##_d,              \
   1337        };                                                               \
   1338        return opivi_trans(a->rd, a->rs1, a->rs2, a->vm,                 \
   1339                           fns[s->sew], s, ZX);                          \
   1340    }                                                                    \
   1341    return false;                                                        \
   1342}
   1343
   1344GEN_OPIVI_TRANS(vadc_vim, 0, vadc_vxm, opivx_vadc_check)
   1345GEN_OPIVI_TRANS(vmadc_vim, 0, vmadc_vxm, opivx_vmadc_check)
   1346
   1347/* Vector Bitwise Logical Instructions */
   1348GEN_OPIVV_GVEC_TRANS(vand_vv, and)
   1349GEN_OPIVV_GVEC_TRANS(vor_vv,  or)
   1350GEN_OPIVV_GVEC_TRANS(vxor_vv, xor)
   1351GEN_OPIVX_GVEC_TRANS(vand_vx, ands)
   1352GEN_OPIVX_GVEC_TRANS(vor_vx,  ors)
   1353GEN_OPIVX_GVEC_TRANS(vxor_vx, xors)
   1354GEN_OPIVI_GVEC_TRANS(vand_vi, 0, vand_vx, andi)
   1355GEN_OPIVI_GVEC_TRANS(vor_vi, 0, vor_vx,  ori)
   1356GEN_OPIVI_GVEC_TRANS(vxor_vi, 0, vxor_vx, xori)
   1357
   1358/* Vector Single-Width Bit Shift Instructions */
   1359GEN_OPIVV_GVEC_TRANS(vsll_vv,  shlv)
   1360GEN_OPIVV_GVEC_TRANS(vsrl_vv,  shrv)
   1361GEN_OPIVV_GVEC_TRANS(vsra_vv,  sarv)
   1362
   1363typedef void GVecGen2sFn32(unsigned, uint32_t, uint32_t, TCGv_i32,
   1364                           uint32_t, uint32_t);
   1365
   1366static inline bool
   1367do_opivx_gvec_shift(DisasContext *s, arg_rmrr *a, GVecGen2sFn32 *gvec_fn,
   1368                    gen_helper_opivx *fn)
   1369{
   1370    if (!opivx_check(s, a)) {
   1371        return false;
   1372    }
   1373
   1374    if (a->vm && s->vl_eq_vlmax) {
   1375        TCGv_i32 src1 = tcg_temp_new_i32();
   1376
   1377        tcg_gen_trunc_tl_i32(src1, get_gpr(s, a->rs1, EXT_NONE));
   1378        tcg_gen_extract_i32(src1, src1, 0, s->sew + 3);
   1379        gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2),
   1380                src1, MAXSZ(s), MAXSZ(s));
   1381
   1382        tcg_temp_free_i32(src1);
   1383        return true;
   1384    }
   1385    return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s);
   1386}
   1387
   1388#define GEN_OPIVX_GVEC_SHIFT_TRANS(NAME, SUF) \
   1389static bool trans_##NAME(DisasContext *s, arg_rmrr *a)                    \
   1390{                                                                         \
   1391    static gen_helper_opivx * const fns[4] = {                            \
   1392        gen_helper_##NAME##_b, gen_helper_##NAME##_h,                     \
   1393        gen_helper_##NAME##_w, gen_helper_##NAME##_d,                     \
   1394    };                                                                    \
   1395                                                                          \
   1396    return do_opivx_gvec_shift(s, a, tcg_gen_gvec_##SUF, fns[s->sew]);    \
   1397}
   1398
   1399GEN_OPIVX_GVEC_SHIFT_TRANS(vsll_vx,  shls)
   1400GEN_OPIVX_GVEC_SHIFT_TRANS(vsrl_vx,  shrs)
   1401GEN_OPIVX_GVEC_SHIFT_TRANS(vsra_vx,  sars)
   1402
   1403GEN_OPIVI_GVEC_TRANS(vsll_vi, 1, vsll_vx,  shli)
   1404GEN_OPIVI_GVEC_TRANS(vsrl_vi, 1, vsrl_vx,  shri)
   1405GEN_OPIVI_GVEC_TRANS(vsra_vi, 1, vsra_vx,  sari)
   1406
   1407/* Vector Narrowing Integer Right Shift Instructions */
   1408static bool opivv_narrow_check(DisasContext *s, arg_rmrr *a)
   1409{
   1410    return (vext_check_isa_ill(s) &&
   1411            vext_check_overlap_mask(s, a->rd, a->vm, false) &&
   1412            vext_check_reg(s, a->rd, false) &&
   1413            vext_check_reg(s, a->rs2, true) &&
   1414            vext_check_reg(s, a->rs1, false) &&
   1415            vext_check_overlap_group(a->rd, 1 << s->lmul, a->rs2,
   1416                2 << s->lmul) &&
   1417            (s->lmul < 0x3) && (s->sew < 0x3));
   1418}
   1419
   1420/* OPIVV with NARROW */
   1421#define GEN_OPIVV_NARROW_TRANS(NAME)                               \
   1422static bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
   1423{                                                                  \
   1424    if (opivv_narrow_check(s, a)) {                                \
   1425        uint32_t data = 0;                                         \
   1426        static gen_helper_gvec_4_ptr * const fns[3] = {            \
   1427            gen_helper_##NAME##_b,                                 \
   1428            gen_helper_##NAME##_h,                                 \
   1429            gen_helper_##NAME##_w,                                 \
   1430        };                                                         \
   1431        TCGLabel *over = gen_new_label();                          \
   1432        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
   1433                                                                   \
   1434        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);             \
   1435        data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
   1436        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
   1437        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
   1438                           vreg_ofs(s, a->rs1),                    \
   1439                           vreg_ofs(s, a->rs2), cpu_env,           \
   1440                           s->vlen / 8, s->vlen / 8, data,         \
   1441                           fns[s->sew]);                           \
   1442        gen_set_label(over);                                       \
   1443        return true;                                               \
   1444    }                                                              \
   1445    return false;                                                  \
   1446}
   1447GEN_OPIVV_NARROW_TRANS(vnsra_vv)
   1448GEN_OPIVV_NARROW_TRANS(vnsrl_vv)
   1449
   1450static bool opivx_narrow_check(DisasContext *s, arg_rmrr *a)
   1451{
   1452    return (vext_check_isa_ill(s) &&
   1453            vext_check_overlap_mask(s, a->rd, a->vm, false) &&
   1454            vext_check_reg(s, a->rd, false) &&
   1455            vext_check_reg(s, a->rs2, true) &&
   1456            vext_check_overlap_group(a->rd, 1 << s->lmul, a->rs2,
   1457                2 << s->lmul) &&
   1458            (s->lmul < 0x3) && (s->sew < 0x3));
   1459}
   1460
   1461/* OPIVX with NARROW */
   1462#define GEN_OPIVX_NARROW_TRANS(NAME)                                     \
   1463static bool trans_##NAME(DisasContext *s, arg_rmrr *a)                   \
   1464{                                                                        \
   1465    if (opivx_narrow_check(s, a)) {                                      \
   1466        static gen_helper_opivx * const fns[3] = {                       \
   1467            gen_helper_##NAME##_b,                                       \
   1468            gen_helper_##NAME##_h,                                       \
   1469            gen_helper_##NAME##_w,                                       \
   1470        };                                                               \
   1471        return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s);\
   1472    }                                                                    \
   1473    return false;                                                        \
   1474}
   1475
   1476GEN_OPIVX_NARROW_TRANS(vnsra_vx)
   1477GEN_OPIVX_NARROW_TRANS(vnsrl_vx)
   1478
   1479/* OPIVI with NARROW */
   1480#define GEN_OPIVI_NARROW_TRANS(NAME, ZX, OPIVX)                          \
   1481static bool trans_##NAME(DisasContext *s, arg_rmrr *a)                   \
   1482{                                                                        \
   1483    if (opivx_narrow_check(s, a)) {                                      \
   1484        static gen_helper_opivx * const fns[3] = {                       \
   1485            gen_helper_##OPIVX##_b,                                      \
   1486            gen_helper_##OPIVX##_h,                                      \
   1487            gen_helper_##OPIVX##_w,                                      \
   1488        };                                                               \
   1489        return opivi_trans(a->rd, a->rs1, a->rs2, a->vm,                 \
   1490                           fns[s->sew], s, ZX);                          \
   1491    }                                                                    \
   1492    return false;                                                        \
   1493}
   1494
   1495GEN_OPIVI_NARROW_TRANS(vnsra_vi, 1, vnsra_vx)
   1496GEN_OPIVI_NARROW_TRANS(vnsrl_vi, 1, vnsrl_vx)
   1497
   1498/* Vector Integer Comparison Instructions */
   1499/*
   1500 * For all comparison instructions, an illegal instruction exception is raised
   1501 * if the destination vector register overlaps a source vector register group
   1502 * and LMUL > 1.
   1503 */
   1504static bool opivv_cmp_check(DisasContext *s, arg_rmrr *a)
   1505{
   1506    return (vext_check_isa_ill(s) &&
   1507            vext_check_reg(s, a->rs2, false) &&
   1508            vext_check_reg(s, a->rs1, false) &&
   1509            ((vext_check_overlap_group(a->rd, 1, a->rs1, 1 << s->lmul) &&
   1510              vext_check_overlap_group(a->rd, 1, a->rs2, 1 << s->lmul)) ||
   1511             (s->lmul == 0)));
   1512}
   1513GEN_OPIVV_TRANS(vmseq_vv, opivv_cmp_check)
   1514GEN_OPIVV_TRANS(vmsne_vv, opivv_cmp_check)
   1515GEN_OPIVV_TRANS(vmsltu_vv, opivv_cmp_check)
   1516GEN_OPIVV_TRANS(vmslt_vv, opivv_cmp_check)
   1517GEN_OPIVV_TRANS(vmsleu_vv, opivv_cmp_check)
   1518GEN_OPIVV_TRANS(vmsle_vv, opivv_cmp_check)
   1519
   1520static bool opivx_cmp_check(DisasContext *s, arg_rmrr *a)
   1521{
   1522    return (vext_check_isa_ill(s) &&
   1523            vext_check_reg(s, a->rs2, false) &&
   1524            (vext_check_overlap_group(a->rd, 1, a->rs2, 1 << s->lmul) ||
   1525             (s->lmul == 0)));
   1526}
   1527
   1528GEN_OPIVX_TRANS(vmseq_vx, opivx_cmp_check)
   1529GEN_OPIVX_TRANS(vmsne_vx, opivx_cmp_check)
   1530GEN_OPIVX_TRANS(vmsltu_vx, opivx_cmp_check)
   1531GEN_OPIVX_TRANS(vmslt_vx, opivx_cmp_check)
   1532GEN_OPIVX_TRANS(vmsleu_vx, opivx_cmp_check)
   1533GEN_OPIVX_TRANS(vmsle_vx, opivx_cmp_check)
   1534GEN_OPIVX_TRANS(vmsgtu_vx, opivx_cmp_check)
   1535GEN_OPIVX_TRANS(vmsgt_vx, opivx_cmp_check)
   1536
   1537GEN_OPIVI_TRANS(vmseq_vi, 0, vmseq_vx, opivx_cmp_check)
   1538GEN_OPIVI_TRANS(vmsne_vi, 0, vmsne_vx, opivx_cmp_check)
   1539GEN_OPIVI_TRANS(vmsleu_vi, 1, vmsleu_vx, opivx_cmp_check)
   1540GEN_OPIVI_TRANS(vmsle_vi, 0, vmsle_vx, opivx_cmp_check)
   1541GEN_OPIVI_TRANS(vmsgtu_vi, 1, vmsgtu_vx, opivx_cmp_check)
   1542GEN_OPIVI_TRANS(vmsgt_vi, 0, vmsgt_vx, opivx_cmp_check)
   1543
   1544/* Vector Integer Min/Max Instructions */
   1545GEN_OPIVV_GVEC_TRANS(vminu_vv, umin)
   1546GEN_OPIVV_GVEC_TRANS(vmin_vv,  smin)
   1547GEN_OPIVV_GVEC_TRANS(vmaxu_vv, umax)
   1548GEN_OPIVV_GVEC_TRANS(vmax_vv,  smax)
   1549GEN_OPIVX_TRANS(vminu_vx, opivx_check)
   1550GEN_OPIVX_TRANS(vmin_vx,  opivx_check)
   1551GEN_OPIVX_TRANS(vmaxu_vx, opivx_check)
   1552GEN_OPIVX_TRANS(vmax_vx,  opivx_check)
   1553
   1554/* Vector Single-Width Integer Multiply Instructions */
   1555GEN_OPIVV_GVEC_TRANS(vmul_vv,  mul)
   1556GEN_OPIVV_TRANS(vmulh_vv, opivv_check)
   1557GEN_OPIVV_TRANS(vmulhu_vv, opivv_check)
   1558GEN_OPIVV_TRANS(vmulhsu_vv, opivv_check)
   1559GEN_OPIVX_GVEC_TRANS(vmul_vx,  muls)
   1560GEN_OPIVX_TRANS(vmulh_vx, opivx_check)
   1561GEN_OPIVX_TRANS(vmulhu_vx, opivx_check)
   1562GEN_OPIVX_TRANS(vmulhsu_vx, opivx_check)
   1563
   1564/* Vector Integer Divide Instructions */
   1565GEN_OPIVV_TRANS(vdivu_vv, opivv_check)
   1566GEN_OPIVV_TRANS(vdiv_vv, opivv_check)
   1567GEN_OPIVV_TRANS(vremu_vv, opivv_check)
   1568GEN_OPIVV_TRANS(vrem_vv, opivv_check)
   1569GEN_OPIVX_TRANS(vdivu_vx, opivx_check)
   1570GEN_OPIVX_TRANS(vdiv_vx, opivx_check)
   1571GEN_OPIVX_TRANS(vremu_vx, opivx_check)
   1572GEN_OPIVX_TRANS(vrem_vx, opivx_check)
   1573
   1574/* Vector Widening Integer Multiply Instructions */
   1575GEN_OPIVV_WIDEN_TRANS(vwmul_vv, opivv_widen_check)
   1576GEN_OPIVV_WIDEN_TRANS(vwmulu_vv, opivv_widen_check)
   1577GEN_OPIVV_WIDEN_TRANS(vwmulsu_vv, opivv_widen_check)
   1578GEN_OPIVX_WIDEN_TRANS(vwmul_vx)
   1579GEN_OPIVX_WIDEN_TRANS(vwmulu_vx)
   1580GEN_OPIVX_WIDEN_TRANS(vwmulsu_vx)
   1581
   1582/* Vector Single-Width Integer Multiply-Add Instructions */
   1583GEN_OPIVV_TRANS(vmacc_vv, opivv_check)
   1584GEN_OPIVV_TRANS(vnmsac_vv, opivv_check)
   1585GEN_OPIVV_TRANS(vmadd_vv, opivv_check)
   1586GEN_OPIVV_TRANS(vnmsub_vv, opivv_check)
   1587GEN_OPIVX_TRANS(vmacc_vx, opivx_check)
   1588GEN_OPIVX_TRANS(vnmsac_vx, opivx_check)
   1589GEN_OPIVX_TRANS(vmadd_vx, opivx_check)
   1590GEN_OPIVX_TRANS(vnmsub_vx, opivx_check)
   1591
   1592/* Vector Widening Integer Multiply-Add Instructions */
   1593GEN_OPIVV_WIDEN_TRANS(vwmaccu_vv, opivv_widen_check)
   1594GEN_OPIVV_WIDEN_TRANS(vwmacc_vv, opivv_widen_check)
   1595GEN_OPIVV_WIDEN_TRANS(vwmaccsu_vv, opivv_widen_check)
   1596GEN_OPIVX_WIDEN_TRANS(vwmaccu_vx)
   1597GEN_OPIVX_WIDEN_TRANS(vwmacc_vx)
   1598GEN_OPIVX_WIDEN_TRANS(vwmaccsu_vx)
   1599GEN_OPIVX_WIDEN_TRANS(vwmaccus_vx)
   1600
   1601/* Vector Integer Merge and Move Instructions */
   1602static bool trans_vmv_v_v(DisasContext *s, arg_vmv_v_v *a)
   1603{
   1604    if (vext_check_isa_ill(s) &&
   1605        vext_check_reg(s, a->rd, false) &&
   1606        vext_check_reg(s, a->rs1, false)) {
   1607
   1608        if (s->vl_eq_vlmax) {
   1609            tcg_gen_gvec_mov(s->sew, vreg_ofs(s, a->rd),
   1610                             vreg_ofs(s, a->rs1),
   1611                             MAXSZ(s), MAXSZ(s));
   1612        } else {
   1613            uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul);
   1614            static gen_helper_gvec_2_ptr * const fns[4] = {
   1615                gen_helper_vmv_v_v_b, gen_helper_vmv_v_v_h,
   1616                gen_helper_vmv_v_v_w, gen_helper_vmv_v_v_d,
   1617            };
   1618            TCGLabel *over = gen_new_label();
   1619            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
   1620
   1621            tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),
   1622                               cpu_env, 0, s->vlen / 8, data, fns[s->sew]);
   1623            gen_set_label(over);
   1624        }
   1625        return true;
   1626    }
   1627    return false;
   1628}
   1629
   1630typedef void gen_helper_vmv_vx(TCGv_ptr, TCGv_i64, TCGv_env, TCGv_i32);
   1631static bool trans_vmv_v_x(DisasContext *s, arg_vmv_v_x *a)
   1632{
   1633    if (vext_check_isa_ill(s) &&
   1634        vext_check_reg(s, a->rd, false)) {
   1635
   1636        TCGv s1;
   1637        TCGLabel *over = gen_new_label();
   1638        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
   1639
   1640        s1 = get_gpr(s, a->rs1, EXT_SIGN);
   1641
   1642        if (s->vl_eq_vlmax) {
   1643            tcg_gen_gvec_dup_tl(s->sew, vreg_ofs(s, a->rd),
   1644                                MAXSZ(s), MAXSZ(s), s1);
   1645        } else {
   1646            TCGv_i32 desc;
   1647            TCGv_i64 s1_i64 = tcg_temp_new_i64();
   1648            TCGv_ptr dest = tcg_temp_new_ptr();
   1649            uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul);
   1650            static gen_helper_vmv_vx * const fns[4] = {
   1651                gen_helper_vmv_v_x_b, gen_helper_vmv_v_x_h,
   1652                gen_helper_vmv_v_x_w, gen_helper_vmv_v_x_d,
   1653            };
   1654
   1655            tcg_gen_ext_tl_i64(s1_i64, s1);
   1656            desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
   1657            tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd));
   1658            fns[s->sew](dest, s1_i64, cpu_env, desc);
   1659
   1660            tcg_temp_free_ptr(dest);
   1661            tcg_temp_free_i64(s1_i64);
   1662        }
   1663
   1664        gen_set_label(over);
   1665        return true;
   1666    }
   1667    return false;
   1668}
   1669
   1670static bool trans_vmv_v_i(DisasContext *s, arg_vmv_v_i *a)
   1671{
   1672    if (vext_check_isa_ill(s) &&
   1673        vext_check_reg(s, a->rd, false)) {
   1674
   1675        int64_t simm = sextract64(a->rs1, 0, 5);
   1676        if (s->vl_eq_vlmax) {
   1677            tcg_gen_gvec_dup_imm(s->sew, vreg_ofs(s, a->rd),
   1678                                 MAXSZ(s), MAXSZ(s), simm);
   1679        } else {
   1680            TCGv_i32 desc;
   1681            TCGv_i64 s1;
   1682            TCGv_ptr dest;
   1683            uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul);
   1684            static gen_helper_vmv_vx * const fns[4] = {
   1685                gen_helper_vmv_v_x_b, gen_helper_vmv_v_x_h,
   1686                gen_helper_vmv_v_x_w, gen_helper_vmv_v_x_d,
   1687            };
   1688            TCGLabel *over = gen_new_label();
   1689            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
   1690
   1691            s1 = tcg_constant_i64(simm);
   1692            dest = tcg_temp_new_ptr();
   1693            desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
   1694            tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd));
   1695            fns[s->sew](dest, s1, cpu_env, desc);
   1696
   1697            tcg_temp_free_ptr(dest);
   1698            gen_set_label(over);
   1699        }
   1700        return true;
   1701    }
   1702    return false;
   1703}
   1704
   1705GEN_OPIVV_TRANS(vmerge_vvm, opivv_vadc_check)
   1706GEN_OPIVX_TRANS(vmerge_vxm, opivx_vadc_check)
   1707GEN_OPIVI_TRANS(vmerge_vim, 0, vmerge_vxm, opivx_vadc_check)
   1708
   1709/*
   1710 *** Vector Fixed-Point Arithmetic Instructions
   1711 */
   1712
   1713/* Vector Single-Width Saturating Add and Subtract */
   1714GEN_OPIVV_TRANS(vsaddu_vv, opivv_check)
   1715GEN_OPIVV_TRANS(vsadd_vv,  opivv_check)
   1716GEN_OPIVV_TRANS(vssubu_vv, opivv_check)
   1717GEN_OPIVV_TRANS(vssub_vv,  opivv_check)
   1718GEN_OPIVX_TRANS(vsaddu_vx,  opivx_check)
   1719GEN_OPIVX_TRANS(vsadd_vx,  opivx_check)
   1720GEN_OPIVX_TRANS(vssubu_vx,  opivx_check)
   1721GEN_OPIVX_TRANS(vssub_vx,  opivx_check)
   1722GEN_OPIVI_TRANS(vsaddu_vi, 1, vsaddu_vx, opivx_check)
   1723GEN_OPIVI_TRANS(vsadd_vi, 0, vsadd_vx, opivx_check)
   1724
   1725/* Vector Single-Width Averaging Add and Subtract */
   1726GEN_OPIVV_TRANS(vaadd_vv, opivv_check)
   1727GEN_OPIVV_TRANS(vasub_vv, opivv_check)
   1728GEN_OPIVX_TRANS(vaadd_vx,  opivx_check)
   1729GEN_OPIVX_TRANS(vasub_vx,  opivx_check)
   1730GEN_OPIVI_TRANS(vaadd_vi, 0, vaadd_vx, opivx_check)
   1731
   1732/* Vector Single-Width Fractional Multiply with Rounding and Saturation */
   1733GEN_OPIVV_TRANS(vsmul_vv, opivv_check)
   1734GEN_OPIVX_TRANS(vsmul_vx,  opivx_check)
   1735
   1736/* Vector Widening Saturating Scaled Multiply-Add */
   1737GEN_OPIVV_WIDEN_TRANS(vwsmaccu_vv, opivv_widen_check)
   1738GEN_OPIVV_WIDEN_TRANS(vwsmacc_vv, opivv_widen_check)
   1739GEN_OPIVV_WIDEN_TRANS(vwsmaccsu_vv, opivv_widen_check)
   1740GEN_OPIVX_WIDEN_TRANS(vwsmaccu_vx)
   1741GEN_OPIVX_WIDEN_TRANS(vwsmacc_vx)
   1742GEN_OPIVX_WIDEN_TRANS(vwsmaccsu_vx)
   1743GEN_OPIVX_WIDEN_TRANS(vwsmaccus_vx)
   1744
   1745/* Vector Single-Width Scaling Shift Instructions */
   1746GEN_OPIVV_TRANS(vssrl_vv, opivv_check)
   1747GEN_OPIVV_TRANS(vssra_vv, opivv_check)
   1748GEN_OPIVX_TRANS(vssrl_vx,  opivx_check)
   1749GEN_OPIVX_TRANS(vssra_vx,  opivx_check)
   1750GEN_OPIVI_TRANS(vssrl_vi, 1, vssrl_vx, opivx_check)
   1751GEN_OPIVI_TRANS(vssra_vi, 0, vssra_vx, opivx_check)
   1752
   1753/* Vector Narrowing Fixed-Point Clip Instructions */
   1754GEN_OPIVV_NARROW_TRANS(vnclipu_vv)
   1755GEN_OPIVV_NARROW_TRANS(vnclip_vv)
   1756GEN_OPIVX_NARROW_TRANS(vnclipu_vx)
   1757GEN_OPIVX_NARROW_TRANS(vnclip_vx)
   1758GEN_OPIVI_NARROW_TRANS(vnclipu_vi, 1, vnclipu_vx)
   1759GEN_OPIVI_NARROW_TRANS(vnclip_vi, 1, vnclip_vx)
   1760
   1761/*
   1762 *** Vector Float Point Arithmetic Instructions
   1763 */
   1764/* Vector Single-Width Floating-Point Add/Subtract Instructions */
   1765
   1766/*
   1767 * If the current SEW does not correspond to a supported IEEE floating-point
   1768 * type, an illegal instruction exception is raised.
   1769 */
   1770static bool opfvv_check(DisasContext *s, arg_rmrr *a)
   1771{
   1772    return (vext_check_isa_ill(s) &&
   1773            vext_check_overlap_mask(s, a->rd, a->vm, false) &&
   1774            vext_check_reg(s, a->rd, false) &&
   1775            vext_check_reg(s, a->rs2, false) &&
   1776            vext_check_reg(s, a->rs1, false) &&
   1777            (s->sew != 0));
   1778}
   1779
   1780/* OPFVV without GVEC IR */
   1781#define GEN_OPFVV_TRANS(NAME, CHECK)                               \
   1782static bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
   1783{                                                                  \
   1784    if (CHECK(s, a)) {                                             \
   1785        uint32_t data = 0;                                         \
   1786        static gen_helper_gvec_4_ptr * const fns[3] = {            \
   1787            gen_helper_##NAME##_h,                                 \
   1788            gen_helper_##NAME##_w,                                 \
   1789            gen_helper_##NAME##_d,                                 \
   1790        };                                                         \
   1791        TCGLabel *over = gen_new_label();                          \
   1792        gen_set_rm(s, 7);                                          \
   1793        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
   1794                                                                   \
   1795        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);             \
   1796        data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
   1797        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
   1798        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
   1799                           vreg_ofs(s, a->rs1),                    \
   1800                           vreg_ofs(s, a->rs2), cpu_env,           \
   1801                           s->vlen / 8, s->vlen / 8, data,         \
   1802                           fns[s->sew - 1]);                       \
   1803        gen_set_label(over);                                       \
   1804        return true;                                               \
   1805    }                                                              \
   1806    return false;                                                  \
   1807}
   1808GEN_OPFVV_TRANS(vfadd_vv, opfvv_check)
   1809GEN_OPFVV_TRANS(vfsub_vv, opfvv_check)
   1810
   1811typedef void gen_helper_opfvf(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv_ptr,
   1812                              TCGv_env, TCGv_i32);
   1813
   1814static bool opfvf_trans(uint32_t vd, uint32_t rs1, uint32_t vs2,
   1815                        uint32_t data, gen_helper_opfvf *fn, DisasContext *s)
   1816{
   1817    TCGv_ptr dest, src2, mask;
   1818    TCGv_i32 desc;
   1819
   1820    TCGLabel *over = gen_new_label();
   1821    tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
   1822
   1823    dest = tcg_temp_new_ptr();
   1824    mask = tcg_temp_new_ptr();
   1825    src2 = tcg_temp_new_ptr();
   1826    desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
   1827
   1828    tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
   1829    tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2));
   1830    tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
   1831
   1832    fn(dest, mask, cpu_fpr[rs1], src2, cpu_env, desc);
   1833
   1834    tcg_temp_free_ptr(dest);
   1835    tcg_temp_free_ptr(mask);
   1836    tcg_temp_free_ptr(src2);
   1837    gen_set_label(over);
   1838    return true;
   1839}
   1840
   1841static bool opfvf_check(DisasContext *s, arg_rmrr *a)
   1842{
   1843/*
   1844 * If the current SEW does not correspond to a supported IEEE floating-point
   1845 * type, an illegal instruction exception is raised
   1846 */
   1847    return (vext_check_isa_ill(s) &&
   1848            vext_check_overlap_mask(s, a->rd, a->vm, false) &&
   1849            vext_check_reg(s, a->rd, false) &&
   1850            vext_check_reg(s, a->rs2, false) &&
   1851            (s->sew != 0));
   1852}
   1853
   1854/* OPFVF without GVEC IR */
   1855#define GEN_OPFVF_TRANS(NAME, CHECK)                              \
   1856static bool trans_##NAME(DisasContext *s, arg_rmrr *a)            \
   1857{                                                                 \
   1858    if (CHECK(s, a)) {                                            \
   1859        uint32_t data = 0;                                        \
   1860        static gen_helper_opfvf *const fns[3] = {                 \
   1861            gen_helper_##NAME##_h,                                \
   1862            gen_helper_##NAME##_w,                                \
   1863            gen_helper_##NAME##_d,                                \
   1864        };                                                        \
   1865        gen_set_rm(s, 7);                                         \
   1866        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);            \
   1867        data = FIELD_DP32(data, VDATA, VM, a->vm);                \
   1868        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);            \
   1869        return opfvf_trans(a->rd, a->rs1, a->rs2, data,           \
   1870                           fns[s->sew - 1], s);                   \
   1871    }                                                             \
   1872    return false;                                                 \
   1873}
   1874
   1875GEN_OPFVF_TRANS(vfadd_vf,  opfvf_check)
   1876GEN_OPFVF_TRANS(vfsub_vf,  opfvf_check)
   1877GEN_OPFVF_TRANS(vfrsub_vf,  opfvf_check)
   1878
   1879/* Vector Widening Floating-Point Add/Subtract Instructions */
   1880static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a)
   1881{
   1882    return (vext_check_isa_ill(s) &&
   1883            vext_check_overlap_mask(s, a->rd, a->vm, true) &&
   1884            vext_check_reg(s, a->rd, true) &&
   1885            vext_check_reg(s, a->rs2, false) &&
   1886            vext_check_reg(s, a->rs1, false) &&
   1887            vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs2,
   1888                                     1 << s->lmul) &&
   1889            vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs1,
   1890                                     1 << s->lmul) &&
   1891            (s->lmul < 0x3) && (s->sew < 0x3) && (s->sew != 0));
   1892}
   1893
   1894/* OPFVV with WIDEN */
   1895#define GEN_OPFVV_WIDEN_TRANS(NAME, CHECK)                       \
   1896static bool trans_##NAME(DisasContext *s, arg_rmrr *a)           \
   1897{                                                                \
   1898    if (CHECK(s, a)) {                                           \
   1899        uint32_t data = 0;                                       \
   1900        static gen_helper_gvec_4_ptr * const fns[2] = {          \
   1901            gen_helper_##NAME##_h, gen_helper_##NAME##_w,        \
   1902        };                                                       \
   1903        TCGLabel *over = gen_new_label();                        \
   1904        gen_set_rm(s, 7);                                        \
   1905        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);        \
   1906                                                                 \
   1907        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);           \
   1908        data = FIELD_DP32(data, VDATA, VM, a->vm);               \
   1909        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);           \
   1910        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),   \
   1911                           vreg_ofs(s, a->rs1),                  \
   1912                           vreg_ofs(s, a->rs2), cpu_env,         \
   1913                           s->vlen / 8, s->vlen / 8, data,       \
   1914                           fns[s->sew - 1]);                     \
   1915        gen_set_label(over);                                     \
   1916        return true;                                             \
   1917    }                                                            \
   1918    return false;                                                \
   1919}
   1920
   1921GEN_OPFVV_WIDEN_TRANS(vfwadd_vv, opfvv_widen_check)
   1922GEN_OPFVV_WIDEN_TRANS(vfwsub_vv, opfvv_widen_check)
   1923
   1924static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a)
   1925{
   1926    return (vext_check_isa_ill(s) &&
   1927            vext_check_overlap_mask(s, a->rd, a->vm, true) &&
   1928            vext_check_reg(s, a->rd, true) &&
   1929            vext_check_reg(s, a->rs2, false) &&
   1930            vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs2,
   1931                                     1 << s->lmul) &&
   1932            (s->lmul < 0x3) && (s->sew < 0x3) && (s->sew != 0));
   1933}
   1934
   1935/* OPFVF with WIDEN */
   1936#define GEN_OPFVF_WIDEN_TRANS(NAME)                              \
   1937static bool trans_##NAME(DisasContext *s, arg_rmrr *a)           \
   1938{                                                                \
   1939    if (opfvf_widen_check(s, a)) {                               \
   1940        uint32_t data = 0;                                       \
   1941        static gen_helper_opfvf *const fns[2] = {                \
   1942            gen_helper_##NAME##_h, gen_helper_##NAME##_w,        \
   1943        };                                                       \
   1944        gen_set_rm(s, 7);                                        \
   1945        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);           \
   1946        data = FIELD_DP32(data, VDATA, VM, a->vm);               \
   1947        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);           \
   1948        return opfvf_trans(a->rd, a->rs1, a->rs2, data,          \
   1949                           fns[s->sew - 1], s);                  \
   1950    }                                                            \
   1951    return false;                                                \
   1952}
   1953
   1954GEN_OPFVF_WIDEN_TRANS(vfwadd_vf)
   1955GEN_OPFVF_WIDEN_TRANS(vfwsub_vf)
   1956
   1957static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a)
   1958{
   1959    return (vext_check_isa_ill(s) &&
   1960            vext_check_overlap_mask(s, a->rd, a->vm, true) &&
   1961            vext_check_reg(s, a->rd, true) &&
   1962            vext_check_reg(s, a->rs2, true) &&
   1963            vext_check_reg(s, a->rs1, false) &&
   1964            vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs1,
   1965                                     1 << s->lmul) &&
   1966            (s->lmul < 0x3) && (s->sew < 0x3) && (s->sew != 0));
   1967}
   1968
   1969/* WIDEN OPFVV with WIDEN */
   1970#define GEN_OPFWV_WIDEN_TRANS(NAME)                                \
   1971static bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
   1972{                                                                  \
   1973    if (opfwv_widen_check(s, a)) {                                 \
   1974        uint32_t data = 0;                                         \
   1975        static gen_helper_gvec_4_ptr * const fns[2] = {            \
   1976            gen_helper_##NAME##_h, gen_helper_##NAME##_w,          \
   1977        };                                                         \
   1978        TCGLabel *over = gen_new_label();                          \
   1979        gen_set_rm(s, 7);                                          \
   1980        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
   1981                                                                   \
   1982        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);             \
   1983        data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
   1984        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
   1985        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
   1986                           vreg_ofs(s, a->rs1),                    \
   1987                           vreg_ofs(s, a->rs2), cpu_env,           \
   1988                           s->vlen / 8, s->vlen / 8, data,         \
   1989                           fns[s->sew - 1]);                       \
   1990        gen_set_label(over);                                       \
   1991        return true;                                               \
   1992    }                                                              \
   1993    return false;                                                  \
   1994}
   1995
   1996GEN_OPFWV_WIDEN_TRANS(vfwadd_wv)
   1997GEN_OPFWV_WIDEN_TRANS(vfwsub_wv)
   1998
   1999static bool opfwf_widen_check(DisasContext *s, arg_rmrr *a)
   2000{
   2001    return (vext_check_isa_ill(s) &&
   2002            vext_check_overlap_mask(s, a->rd, a->vm, true) &&
   2003            vext_check_reg(s, a->rd, true) &&
   2004            vext_check_reg(s, a->rs2, true) &&
   2005            (s->lmul < 0x3) && (s->sew < 0x3) && (s->sew != 0));
   2006}
   2007
   2008/* WIDEN OPFVF with WIDEN */
   2009#define GEN_OPFWF_WIDEN_TRANS(NAME)                              \
   2010static bool trans_##NAME(DisasContext *s, arg_rmrr *a)           \
   2011{                                                                \
   2012    if (opfwf_widen_check(s, a)) {                               \
   2013        uint32_t data = 0;                                       \
   2014        static gen_helper_opfvf *const fns[2] = {                \
   2015            gen_helper_##NAME##_h, gen_helper_##NAME##_w,        \
   2016        };                                                       \
   2017        gen_set_rm(s, 7);                                        \
   2018        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);           \
   2019        data = FIELD_DP32(data, VDATA, VM, a->vm);               \
   2020        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);           \
   2021        return opfvf_trans(a->rd, a->rs1, a->rs2, data,          \
   2022                           fns[s->sew - 1], s);                  \
   2023    }                                                            \
   2024    return false;                                                \
   2025}
   2026
   2027GEN_OPFWF_WIDEN_TRANS(vfwadd_wf)
   2028GEN_OPFWF_WIDEN_TRANS(vfwsub_wf)
   2029
   2030/* Vector Single-Width Floating-Point Multiply/Divide Instructions */
   2031GEN_OPFVV_TRANS(vfmul_vv, opfvv_check)
   2032GEN_OPFVV_TRANS(vfdiv_vv, opfvv_check)
   2033GEN_OPFVF_TRANS(vfmul_vf,  opfvf_check)
   2034GEN_OPFVF_TRANS(vfdiv_vf,  opfvf_check)
   2035GEN_OPFVF_TRANS(vfrdiv_vf,  opfvf_check)
   2036
   2037/* Vector Widening Floating-Point Multiply */
   2038GEN_OPFVV_WIDEN_TRANS(vfwmul_vv, opfvv_widen_check)
   2039GEN_OPFVF_WIDEN_TRANS(vfwmul_vf)
   2040
   2041/* Vector Single-Width Floating-Point Fused Multiply-Add Instructions */
   2042GEN_OPFVV_TRANS(vfmacc_vv, opfvv_check)
   2043GEN_OPFVV_TRANS(vfnmacc_vv, opfvv_check)
   2044GEN_OPFVV_TRANS(vfmsac_vv, opfvv_check)
   2045GEN_OPFVV_TRANS(vfnmsac_vv, opfvv_check)
   2046GEN_OPFVV_TRANS(vfmadd_vv, opfvv_check)
   2047GEN_OPFVV_TRANS(vfnmadd_vv, opfvv_check)
   2048GEN_OPFVV_TRANS(vfmsub_vv, opfvv_check)
   2049GEN_OPFVV_TRANS(vfnmsub_vv, opfvv_check)
   2050GEN_OPFVF_TRANS(vfmacc_vf, opfvf_check)
   2051GEN_OPFVF_TRANS(vfnmacc_vf, opfvf_check)
   2052GEN_OPFVF_TRANS(vfmsac_vf, opfvf_check)
   2053GEN_OPFVF_TRANS(vfnmsac_vf, opfvf_check)
   2054GEN_OPFVF_TRANS(vfmadd_vf, opfvf_check)
   2055GEN_OPFVF_TRANS(vfnmadd_vf, opfvf_check)
   2056GEN_OPFVF_TRANS(vfmsub_vf, opfvf_check)
   2057GEN_OPFVF_TRANS(vfnmsub_vf, opfvf_check)
   2058
   2059/* Vector Widening Floating-Point Fused Multiply-Add Instructions */
   2060GEN_OPFVV_WIDEN_TRANS(vfwmacc_vv, opfvv_widen_check)
   2061GEN_OPFVV_WIDEN_TRANS(vfwnmacc_vv, opfvv_widen_check)
   2062GEN_OPFVV_WIDEN_TRANS(vfwmsac_vv, opfvv_widen_check)
   2063GEN_OPFVV_WIDEN_TRANS(vfwnmsac_vv, opfvv_widen_check)
   2064GEN_OPFVF_WIDEN_TRANS(vfwmacc_vf)
   2065GEN_OPFVF_WIDEN_TRANS(vfwnmacc_vf)
   2066GEN_OPFVF_WIDEN_TRANS(vfwmsac_vf)
   2067GEN_OPFVF_WIDEN_TRANS(vfwnmsac_vf)
   2068
   2069/* Vector Floating-Point Square-Root Instruction */
   2070
   2071/*
   2072 * If the current SEW does not correspond to a supported IEEE floating-point
   2073 * type, an illegal instruction exception is raised
   2074 */
   2075static bool opfv_check(DisasContext *s, arg_rmr *a)
   2076{
   2077   return (vext_check_isa_ill(s) &&
   2078            vext_check_overlap_mask(s, a->rd, a->vm, false) &&
   2079            vext_check_reg(s, a->rd, false) &&
   2080            vext_check_reg(s, a->rs2, false) &&
   2081            (s->sew != 0));
   2082}
   2083
   2084#define GEN_OPFV_TRANS(NAME, CHECK)                                \
   2085static bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
   2086{                                                                  \
   2087    if (CHECK(s, a)) {                                             \
   2088        uint32_t data = 0;                                         \
   2089        static gen_helper_gvec_3_ptr * const fns[3] = {            \
   2090            gen_helper_##NAME##_h,                                 \
   2091            gen_helper_##NAME##_w,                                 \
   2092            gen_helper_##NAME##_d,                                 \
   2093        };                                                         \
   2094        TCGLabel *over = gen_new_label();                          \
   2095        gen_set_rm(s, 7);                                          \
   2096        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
   2097                                                                   \
   2098        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);             \
   2099        data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
   2100        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
   2101        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
   2102                           vreg_ofs(s, a->rs2), cpu_env,           \
   2103                           s->vlen / 8, s->vlen / 8, data,         \
   2104                           fns[s->sew - 1]);                       \
   2105        gen_set_label(over);                                       \
   2106        return true;                                               \
   2107    }                                                              \
   2108    return false;                                                  \
   2109}
   2110
   2111GEN_OPFV_TRANS(vfsqrt_v, opfv_check)
   2112
   2113/* Vector Floating-Point MIN/MAX Instructions */
   2114GEN_OPFVV_TRANS(vfmin_vv, opfvv_check)
   2115GEN_OPFVV_TRANS(vfmax_vv, opfvv_check)
   2116GEN_OPFVF_TRANS(vfmin_vf, opfvf_check)
   2117GEN_OPFVF_TRANS(vfmax_vf, opfvf_check)
   2118
   2119/* Vector Floating-Point Sign-Injection Instructions */
   2120GEN_OPFVV_TRANS(vfsgnj_vv, opfvv_check)
   2121GEN_OPFVV_TRANS(vfsgnjn_vv, opfvv_check)
   2122GEN_OPFVV_TRANS(vfsgnjx_vv, opfvv_check)
   2123GEN_OPFVF_TRANS(vfsgnj_vf, opfvf_check)
   2124GEN_OPFVF_TRANS(vfsgnjn_vf, opfvf_check)
   2125GEN_OPFVF_TRANS(vfsgnjx_vf, opfvf_check)
   2126
   2127/* Vector Floating-Point Compare Instructions */
   2128static bool opfvv_cmp_check(DisasContext *s, arg_rmrr *a)
   2129{
   2130    return (vext_check_isa_ill(s) &&
   2131            vext_check_reg(s, a->rs2, false) &&
   2132            vext_check_reg(s, a->rs1, false) &&
   2133            (s->sew != 0) &&
   2134            ((vext_check_overlap_group(a->rd, 1, a->rs1, 1 << s->lmul) &&
   2135              vext_check_overlap_group(a->rd, 1, a->rs2, 1 << s->lmul)) ||
   2136             (s->lmul == 0)));
   2137}
   2138
   2139GEN_OPFVV_TRANS(vmfeq_vv, opfvv_cmp_check)
   2140GEN_OPFVV_TRANS(vmfne_vv, opfvv_cmp_check)
   2141GEN_OPFVV_TRANS(vmflt_vv, opfvv_cmp_check)
   2142GEN_OPFVV_TRANS(vmfle_vv, opfvv_cmp_check)
   2143GEN_OPFVV_TRANS(vmford_vv, opfvv_cmp_check)
   2144
   2145static bool opfvf_cmp_check(DisasContext *s, arg_rmrr *a)
   2146{
   2147    return (vext_check_isa_ill(s) &&
   2148            vext_check_reg(s, a->rs2, false) &&
   2149            (s->sew != 0) &&
   2150            (vext_check_overlap_group(a->rd, 1, a->rs2, 1 << s->lmul) ||
   2151             (s->lmul == 0)));
   2152}
   2153
   2154GEN_OPFVF_TRANS(vmfeq_vf, opfvf_cmp_check)
   2155GEN_OPFVF_TRANS(vmfne_vf, opfvf_cmp_check)
   2156GEN_OPFVF_TRANS(vmflt_vf, opfvf_cmp_check)
   2157GEN_OPFVF_TRANS(vmfle_vf, opfvf_cmp_check)
   2158GEN_OPFVF_TRANS(vmfgt_vf, opfvf_cmp_check)
   2159GEN_OPFVF_TRANS(vmfge_vf, opfvf_cmp_check)
   2160GEN_OPFVF_TRANS(vmford_vf, opfvf_cmp_check)
   2161
   2162/* Vector Floating-Point Classify Instruction */
   2163GEN_OPFV_TRANS(vfclass_v, opfv_check)
   2164
   2165/* Vector Floating-Point Merge Instruction */
   2166GEN_OPFVF_TRANS(vfmerge_vfm,  opfvf_check)
   2167
   2168static bool trans_vfmv_v_f(DisasContext *s, arg_vfmv_v_f *a)
   2169{
   2170    if (vext_check_isa_ill(s) &&
   2171        vext_check_reg(s, a->rd, false) &&
   2172        (s->sew != 0)) {
   2173
   2174        if (s->vl_eq_vlmax) {
   2175            tcg_gen_gvec_dup_i64(s->sew, vreg_ofs(s, a->rd),
   2176                                 MAXSZ(s), MAXSZ(s), cpu_fpr[a->rs1]);
   2177        } else {
   2178            TCGv_ptr dest;
   2179            TCGv_i32 desc;
   2180            uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul);
   2181            static gen_helper_vmv_vx * const fns[3] = {
   2182                gen_helper_vmv_v_x_h,
   2183                gen_helper_vmv_v_x_w,
   2184                gen_helper_vmv_v_x_d,
   2185            };
   2186            TCGLabel *over = gen_new_label();
   2187            tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
   2188
   2189            dest = tcg_temp_new_ptr();
   2190            desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
   2191            tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd));
   2192            fns[s->sew - 1](dest, cpu_fpr[a->rs1], cpu_env, desc);
   2193
   2194            tcg_temp_free_ptr(dest);
   2195            gen_set_label(over);
   2196        }
   2197        return true;
   2198    }
   2199    return false;
   2200}
   2201
   2202/* Single-Width Floating-Point/Integer Type-Convert Instructions */
   2203GEN_OPFV_TRANS(vfcvt_xu_f_v, opfv_check)
   2204GEN_OPFV_TRANS(vfcvt_x_f_v, opfv_check)
   2205GEN_OPFV_TRANS(vfcvt_f_xu_v, opfv_check)
   2206GEN_OPFV_TRANS(vfcvt_f_x_v, opfv_check)
   2207
   2208/* Widening Floating-Point/Integer Type-Convert Instructions */
   2209
   2210/*
   2211 * If the current SEW does not correspond to a supported IEEE floating-point
   2212 * type, an illegal instruction exception is raised
   2213 */
   2214static bool opfv_widen_check(DisasContext *s, arg_rmr *a)
   2215{
   2216    return (vext_check_isa_ill(s) &&
   2217            vext_check_overlap_mask(s, a->rd, a->vm, true) &&
   2218            vext_check_reg(s, a->rd, true) &&
   2219            vext_check_reg(s, a->rs2, false) &&
   2220            vext_check_overlap_group(a->rd, 2 << s->lmul, a->rs2,
   2221                                     1 << s->lmul) &&
   2222            (s->lmul < 0x3) && (s->sew < 0x3) && (s->sew != 0));
   2223}
   2224
   2225#define GEN_OPFV_WIDEN_TRANS(NAME)                                 \
   2226static bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
   2227{                                                                  \
   2228    if (opfv_widen_check(s, a)) {                                  \
   2229        uint32_t data = 0;                                         \
   2230        static gen_helper_gvec_3_ptr * const fns[2] = {            \
   2231            gen_helper_##NAME##_h,                                 \
   2232            gen_helper_##NAME##_w,                                 \
   2233        };                                                         \
   2234        TCGLabel *over = gen_new_label();                          \
   2235        gen_set_rm(s, 7);                                          \
   2236        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
   2237                                                                   \
   2238        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);             \
   2239        data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
   2240        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
   2241        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
   2242                           vreg_ofs(s, a->rs2), cpu_env,           \
   2243                           s->vlen / 8, s->vlen / 8, data,         \
   2244                           fns[s->sew - 1]);                       \
   2245        gen_set_label(over);                                       \
   2246        return true;                                               \
   2247    }                                                              \
   2248    return false;                                                  \
   2249}
   2250
   2251GEN_OPFV_WIDEN_TRANS(vfwcvt_xu_f_v)
   2252GEN_OPFV_WIDEN_TRANS(vfwcvt_x_f_v)
   2253GEN_OPFV_WIDEN_TRANS(vfwcvt_f_xu_v)
   2254GEN_OPFV_WIDEN_TRANS(vfwcvt_f_x_v)
   2255GEN_OPFV_WIDEN_TRANS(vfwcvt_f_f_v)
   2256
   2257/* Narrowing Floating-Point/Integer Type-Convert Instructions */
   2258
   2259/*
   2260 * If the current SEW does not correspond to a supported IEEE floating-point
   2261 * type, an illegal instruction exception is raised
   2262 */
   2263static bool opfv_narrow_check(DisasContext *s, arg_rmr *a)
   2264{
   2265    return (vext_check_isa_ill(s) &&
   2266            vext_check_overlap_mask(s, a->rd, a->vm, false) &&
   2267            vext_check_reg(s, a->rd, false) &&
   2268            vext_check_reg(s, a->rs2, true) &&
   2269            vext_check_overlap_group(a->rd, 1 << s->lmul, a->rs2,
   2270                                     2 << s->lmul) &&
   2271            (s->lmul < 0x3) && (s->sew < 0x3) && (s->sew != 0));
   2272}
   2273
   2274#define GEN_OPFV_NARROW_TRANS(NAME)                                \
   2275static bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
   2276{                                                                  \
   2277    if (opfv_narrow_check(s, a)) {                                 \
   2278        uint32_t data = 0;                                         \
   2279        static gen_helper_gvec_3_ptr * const fns[2] = {            \
   2280            gen_helper_##NAME##_h,                                 \
   2281            gen_helper_##NAME##_w,                                 \
   2282        };                                                         \
   2283        TCGLabel *over = gen_new_label();                          \
   2284        gen_set_rm(s, 7);                                          \
   2285        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
   2286                                                                   \
   2287        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);             \
   2288        data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
   2289        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
   2290        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
   2291                           vreg_ofs(s, a->rs2), cpu_env,           \
   2292                           s->vlen / 8, s->vlen / 8, data,         \
   2293                           fns[s->sew - 1]);                       \
   2294        gen_set_label(over);                                       \
   2295        return true;                                               \
   2296    }                                                              \
   2297    return false;                                                  \
   2298}
   2299
   2300GEN_OPFV_NARROW_TRANS(vfncvt_xu_f_v)
   2301GEN_OPFV_NARROW_TRANS(vfncvt_x_f_v)
   2302GEN_OPFV_NARROW_TRANS(vfncvt_f_xu_v)
   2303GEN_OPFV_NARROW_TRANS(vfncvt_f_x_v)
   2304GEN_OPFV_NARROW_TRANS(vfncvt_f_f_v)
   2305
   2306/*
   2307 *** Vector Reduction Operations
   2308 */
   2309/* Vector Single-Width Integer Reduction Instructions */
   2310static bool reduction_check(DisasContext *s, arg_rmrr *a)
   2311{
   2312    return vext_check_isa_ill(s) && vext_check_reg(s, a->rs2, false);
   2313}
   2314
   2315GEN_OPIVV_TRANS(vredsum_vs, reduction_check)
   2316GEN_OPIVV_TRANS(vredmaxu_vs, reduction_check)
   2317GEN_OPIVV_TRANS(vredmax_vs, reduction_check)
   2318GEN_OPIVV_TRANS(vredminu_vs, reduction_check)
   2319GEN_OPIVV_TRANS(vredmin_vs, reduction_check)
   2320GEN_OPIVV_TRANS(vredand_vs, reduction_check)
   2321GEN_OPIVV_TRANS(vredor_vs, reduction_check)
   2322GEN_OPIVV_TRANS(vredxor_vs, reduction_check)
   2323
   2324/* Vector Widening Integer Reduction Instructions */
   2325GEN_OPIVV_WIDEN_TRANS(vwredsum_vs, reduction_check)
   2326GEN_OPIVV_WIDEN_TRANS(vwredsumu_vs, reduction_check)
   2327
   2328/* Vector Single-Width Floating-Point Reduction Instructions */
   2329GEN_OPFVV_TRANS(vfredsum_vs, reduction_check)
   2330GEN_OPFVV_TRANS(vfredmax_vs, reduction_check)
   2331GEN_OPFVV_TRANS(vfredmin_vs, reduction_check)
   2332
   2333/* Vector Widening Floating-Point Reduction Instructions */
   2334GEN_OPFVV_WIDEN_TRANS(vfwredsum_vs, reduction_check)
   2335
   2336/*
   2337 *** Vector Mask Operations
   2338 */
   2339
   2340/* Vector Mask-Register Logical Instructions */
   2341#define GEN_MM_TRANS(NAME)                                         \
   2342static bool trans_##NAME(DisasContext *s, arg_r *a)                \
   2343{                                                                  \
   2344    if (vext_check_isa_ill(s)) {                                   \
   2345        uint32_t data = 0;                                         \
   2346        gen_helper_gvec_4_ptr *fn = gen_helper_##NAME;             \
   2347        TCGLabel *over = gen_new_label();                          \
   2348        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
   2349                                                                   \
   2350        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);             \
   2351        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
   2352        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
   2353                           vreg_ofs(s, a->rs1),                    \
   2354                           vreg_ofs(s, a->rs2), cpu_env,           \
   2355                           s->vlen / 8, s->vlen / 8, data, fn);    \
   2356        gen_set_label(over);                                       \
   2357        return true;                                               \
   2358    }                                                              \
   2359    return false;                                                  \
   2360}
   2361
   2362GEN_MM_TRANS(vmand_mm)
   2363GEN_MM_TRANS(vmnand_mm)
   2364GEN_MM_TRANS(vmandnot_mm)
   2365GEN_MM_TRANS(vmxor_mm)
   2366GEN_MM_TRANS(vmor_mm)
   2367GEN_MM_TRANS(vmnor_mm)
   2368GEN_MM_TRANS(vmornot_mm)
   2369GEN_MM_TRANS(vmxnor_mm)
   2370
   2371/* Vector mask population count vmpopc */
   2372static bool trans_vmpopc_m(DisasContext *s, arg_rmr *a)
   2373{
   2374    if (vext_check_isa_ill(s)) {
   2375        TCGv_ptr src2, mask;
   2376        TCGv dst;
   2377        TCGv_i32 desc;
   2378        uint32_t data = 0;
   2379        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
   2380        data = FIELD_DP32(data, VDATA, VM, a->vm);
   2381        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
   2382
   2383        mask = tcg_temp_new_ptr();
   2384        src2 = tcg_temp_new_ptr();
   2385        dst = dest_gpr(s, a->rd);
   2386        desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
   2387
   2388        tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, a->rs2));
   2389        tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
   2390
   2391        gen_helper_vmpopc_m(dst, mask, src2, cpu_env, desc);
   2392        gen_set_gpr(s, a->rd, dst);
   2393
   2394        tcg_temp_free_ptr(mask);
   2395        tcg_temp_free_ptr(src2);
   2396        return true;
   2397    }
   2398    return false;
   2399}
   2400
   2401/* vmfirst find-first-set mask bit */
   2402static bool trans_vmfirst_m(DisasContext *s, arg_rmr *a)
   2403{
   2404    if (vext_check_isa_ill(s)) {
   2405        TCGv_ptr src2, mask;
   2406        TCGv dst;
   2407        TCGv_i32 desc;
   2408        uint32_t data = 0;
   2409        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
   2410        data = FIELD_DP32(data, VDATA, VM, a->vm);
   2411        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
   2412
   2413        mask = tcg_temp_new_ptr();
   2414        src2 = tcg_temp_new_ptr();
   2415        dst = dest_gpr(s, a->rd);
   2416        desc = tcg_constant_i32(simd_desc(s->vlen / 8, s->vlen / 8, data));
   2417
   2418        tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, a->rs2));
   2419        tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
   2420
   2421        gen_helper_vmfirst_m(dst, mask, src2, cpu_env, desc);
   2422        gen_set_gpr(s, a->rd, dst);
   2423
   2424        tcg_temp_free_ptr(mask);
   2425        tcg_temp_free_ptr(src2);
   2426        return true;
   2427    }
   2428    return false;
   2429}
   2430
   2431/* vmsbf.m set-before-first mask bit */
   2432/* vmsif.m set-includ-first mask bit */
   2433/* vmsof.m set-only-first mask bit */
   2434#define GEN_M_TRANS(NAME)                                          \
   2435static bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
   2436{                                                                  \
   2437    if (vext_check_isa_ill(s)) {                                   \
   2438        uint32_t data = 0;                                         \
   2439        gen_helper_gvec_3_ptr *fn = gen_helper_##NAME;             \
   2440        TCGLabel *over = gen_new_label();                          \
   2441        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
   2442                                                                   \
   2443        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);             \
   2444        data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
   2445        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
   2446        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd),                     \
   2447                           vreg_ofs(s, 0), vreg_ofs(s, a->rs2),    \
   2448                           cpu_env, s->vlen / 8, s->vlen / 8,      \
   2449                           data, fn);                              \
   2450        gen_set_label(over);                                       \
   2451        return true;                                               \
   2452    }                                                              \
   2453    return false;                                                  \
   2454}
   2455
   2456GEN_M_TRANS(vmsbf_m)
   2457GEN_M_TRANS(vmsif_m)
   2458GEN_M_TRANS(vmsof_m)
   2459
   2460/* Vector Iota Instruction */
   2461static bool trans_viota_m(DisasContext *s, arg_viota_m *a)
   2462{
   2463    if (vext_check_isa_ill(s) &&
   2464        vext_check_reg(s, a->rd, false) &&
   2465        vext_check_overlap_group(a->rd, 1 << s->lmul, a->rs2, 1) &&
   2466        (a->vm != 0 || a->rd != 0)) {
   2467        uint32_t data = 0;
   2468        TCGLabel *over = gen_new_label();
   2469        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
   2470
   2471        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
   2472        data = FIELD_DP32(data, VDATA, VM, a->vm);
   2473        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
   2474        static gen_helper_gvec_3_ptr * const fns[4] = {
   2475            gen_helper_viota_m_b, gen_helper_viota_m_h,
   2476            gen_helper_viota_m_w, gen_helper_viota_m_d,
   2477        };
   2478        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
   2479                           vreg_ofs(s, a->rs2), cpu_env,
   2480                           s->vlen / 8, s->vlen / 8, data, fns[s->sew]);
   2481        gen_set_label(over);
   2482        return true;
   2483    }
   2484    return false;
   2485}
   2486
   2487/* Vector Element Index Instruction */
   2488static bool trans_vid_v(DisasContext *s, arg_vid_v *a)
   2489{
   2490    if (vext_check_isa_ill(s) &&
   2491        vext_check_reg(s, a->rd, false) &&
   2492        vext_check_overlap_mask(s, a->rd, a->vm, false)) {
   2493        uint32_t data = 0;
   2494        TCGLabel *over = gen_new_label();
   2495        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
   2496
   2497        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
   2498        data = FIELD_DP32(data, VDATA, VM, a->vm);
   2499        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
   2500        static gen_helper_gvec_2_ptr * const fns[4] = {
   2501            gen_helper_vid_v_b, gen_helper_vid_v_h,
   2502            gen_helper_vid_v_w, gen_helper_vid_v_d,
   2503        };
   2504        tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
   2505                           cpu_env, s->vlen / 8, s->vlen / 8,
   2506                           data, fns[s->sew]);
   2507        gen_set_label(over);
   2508        return true;
   2509    }
   2510    return false;
   2511}
   2512
   2513/*
   2514 *** Vector Permutation Instructions
   2515 */
   2516
   2517/* Integer Extract Instruction */
   2518
   2519static void load_element(TCGv_i64 dest, TCGv_ptr base,
   2520                         int ofs, int sew)
   2521{
   2522    switch (sew) {
   2523    case MO_8:
   2524        tcg_gen_ld8u_i64(dest, base, ofs);
   2525        break;
   2526    case MO_16:
   2527        tcg_gen_ld16u_i64(dest, base, ofs);
   2528        break;
   2529    case MO_32:
   2530        tcg_gen_ld32u_i64(dest, base, ofs);
   2531        break;
   2532    case MO_64:
   2533        tcg_gen_ld_i64(dest, base, ofs);
   2534        break;
   2535    default:
   2536        g_assert_not_reached();
   2537        break;
   2538    }
   2539}
   2540
   2541/* offset of the idx element with base regsiter r */
   2542static uint32_t endian_ofs(DisasContext *s, int r, int idx)
   2543{
   2544#ifdef HOST_WORDS_BIGENDIAN
   2545    return vreg_ofs(s, r) + ((idx ^ (7 >> s->sew)) << s->sew);
   2546#else
   2547    return vreg_ofs(s, r) + (idx << s->sew);
   2548#endif
   2549}
   2550
   2551/* adjust the index according to the endian */
   2552static void endian_adjust(TCGv_i32 ofs, int sew)
   2553{
   2554#ifdef HOST_WORDS_BIGENDIAN
   2555    tcg_gen_xori_i32(ofs, ofs, 7 >> sew);
   2556#endif
   2557}
   2558
   2559/* Load idx >= VLMAX ? 0 : vreg[idx] */
   2560static void vec_element_loadx(DisasContext *s, TCGv_i64 dest,
   2561                              int vreg, TCGv idx, int vlmax)
   2562{
   2563    TCGv_i32 ofs = tcg_temp_new_i32();
   2564    TCGv_ptr base = tcg_temp_new_ptr();
   2565    TCGv_i64 t_idx = tcg_temp_new_i64();
   2566    TCGv_i64 t_vlmax, t_zero;
   2567
   2568    /*
   2569     * Mask the index to the length so that we do
   2570     * not produce an out-of-range load.
   2571     */
   2572    tcg_gen_trunc_tl_i32(ofs, idx);
   2573    tcg_gen_andi_i32(ofs, ofs, vlmax - 1);
   2574
   2575    /* Convert the index to an offset. */
   2576    endian_adjust(ofs, s->sew);
   2577    tcg_gen_shli_i32(ofs, ofs, s->sew);
   2578
   2579    /* Convert the index to a pointer. */
   2580    tcg_gen_ext_i32_ptr(base, ofs);
   2581    tcg_gen_add_ptr(base, base, cpu_env);
   2582
   2583    /* Perform the load. */
   2584    load_element(dest, base,
   2585                 vreg_ofs(s, vreg), s->sew);
   2586    tcg_temp_free_ptr(base);
   2587    tcg_temp_free_i32(ofs);
   2588
   2589    /* Flush out-of-range indexing to zero.  */
   2590    t_vlmax = tcg_constant_i64(vlmax);
   2591    t_zero = tcg_constant_i64(0);
   2592    tcg_gen_extu_tl_i64(t_idx, idx);
   2593
   2594    tcg_gen_movcond_i64(TCG_COND_LTU, dest, t_idx,
   2595                        t_vlmax, dest, t_zero);
   2596
   2597    tcg_temp_free_i64(t_idx);
   2598}
   2599
   2600static void vec_element_loadi(DisasContext *s, TCGv_i64 dest,
   2601                              int vreg, int idx)
   2602{
   2603    load_element(dest, cpu_env, endian_ofs(s, vreg, idx), s->sew);
   2604}
   2605
   2606static bool trans_vext_x_v(DisasContext *s, arg_r *a)
   2607{
   2608    TCGv_i64 tmp = tcg_temp_new_i64();
   2609    TCGv dest = dest_gpr(s, a->rd);
   2610
   2611    if (a->rs1 == 0) {
   2612        /* Special case vmv.x.s rd, vs2. */
   2613        vec_element_loadi(s, tmp, a->rs2, 0);
   2614    } else {
   2615        /* This instruction ignores LMUL and vector register groups */
   2616        int vlmax = s->vlen >> (3 + s->sew);
   2617        vec_element_loadx(s, tmp, a->rs2, cpu_gpr[a->rs1], vlmax);
   2618    }
   2619
   2620    tcg_gen_trunc_i64_tl(dest, tmp);
   2621    gen_set_gpr(s, a->rd, dest);
   2622
   2623    tcg_temp_free_i64(tmp);
   2624    return true;
   2625}
   2626
   2627/* Integer Scalar Move Instruction */
   2628
   2629static void store_element(TCGv_i64 val, TCGv_ptr base,
   2630                          int ofs, int sew)
   2631{
   2632    switch (sew) {
   2633    case MO_8:
   2634        tcg_gen_st8_i64(val, base, ofs);
   2635        break;
   2636    case MO_16:
   2637        tcg_gen_st16_i64(val, base, ofs);
   2638        break;
   2639    case MO_32:
   2640        tcg_gen_st32_i64(val, base, ofs);
   2641        break;
   2642    case MO_64:
   2643        tcg_gen_st_i64(val, base, ofs);
   2644        break;
   2645    default:
   2646        g_assert_not_reached();
   2647        break;
   2648    }
   2649}
   2650
   2651/*
   2652 * Store vreg[idx] = val.
   2653 * The index must be in range of VLMAX.
   2654 */
   2655static void vec_element_storei(DisasContext *s, int vreg,
   2656                               int idx, TCGv_i64 val)
   2657{
   2658    store_element(val, cpu_env, endian_ofs(s, vreg, idx), s->sew);
   2659}
   2660
   2661/* vmv.s.x vd, rs1 # vd[0] = rs1 */
   2662static bool trans_vmv_s_x(DisasContext *s, arg_vmv_s_x *a)
   2663{
   2664    if (vext_check_isa_ill(s)) {
   2665        /* This instruction ignores LMUL and vector register groups */
   2666        int maxsz = s->vlen >> 3;
   2667        TCGv_i64 t1;
   2668        TCGLabel *over = gen_new_label();
   2669
   2670        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
   2671        tcg_gen_gvec_dup_imm(SEW64, vreg_ofs(s, a->rd), maxsz, maxsz, 0);
   2672        if (a->rs1 == 0) {
   2673            goto done;
   2674        }
   2675
   2676        t1 = tcg_temp_new_i64();
   2677        tcg_gen_extu_tl_i64(t1, cpu_gpr[a->rs1]);
   2678        vec_element_storei(s, a->rd, 0, t1);
   2679        tcg_temp_free_i64(t1);
   2680    done:
   2681        gen_set_label(over);
   2682        return true;
   2683    }
   2684    return false;
   2685}
   2686
   2687/* Floating-Point Scalar Move Instructions */
   2688static bool trans_vfmv_f_s(DisasContext *s, arg_vfmv_f_s *a)
   2689{
   2690    if (!s->vill && has_ext(s, RVF) &&
   2691        (s->mstatus_fs != 0) && (s->sew != 0)) {
   2692        unsigned int len = 8 << s->sew;
   2693
   2694        vec_element_loadi(s, cpu_fpr[a->rd], a->rs2, 0);
   2695        if (len < 64) {
   2696            tcg_gen_ori_i64(cpu_fpr[a->rd], cpu_fpr[a->rd],
   2697                            MAKE_64BIT_MASK(len, 64 - len));
   2698        }
   2699
   2700        mark_fs_dirty(s);
   2701        return true;
   2702    }
   2703    return false;
   2704}
   2705
   2706/* vfmv.s.f vd, rs1 # vd[0] = rs1 (vs2=0) */
   2707static bool trans_vfmv_s_f(DisasContext *s, arg_vfmv_s_f *a)
   2708{
   2709    if (!s->vill && has_ext(s, RVF) && (s->sew != 0)) {
   2710        TCGv_i64 t1;
   2711        /* The instructions ignore LMUL and vector register group. */
   2712        uint32_t vlmax = s->vlen >> 3;
   2713
   2714        /* if vl == 0, skip vector register write back */
   2715        TCGLabel *over = gen_new_label();
   2716        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
   2717
   2718        /* zeroed all elements */
   2719        tcg_gen_gvec_dup_imm(SEW64, vreg_ofs(s, a->rd), vlmax, vlmax, 0);
   2720
   2721        /* NaN-box f[rs1] as necessary for SEW */
   2722        t1 = tcg_temp_new_i64();
   2723        if (s->sew == MO_64 && !has_ext(s, RVD)) {
   2724            tcg_gen_ori_i64(t1, cpu_fpr[a->rs1], MAKE_64BIT_MASK(32, 32));
   2725        } else {
   2726            tcg_gen_mov_i64(t1, cpu_fpr[a->rs1]);
   2727        }
   2728        vec_element_storei(s, a->rd, 0, t1);
   2729        tcg_temp_free_i64(t1);
   2730        gen_set_label(over);
   2731        return true;
   2732    }
   2733    return false;
   2734}
   2735
   2736/* Vector Slide Instructions */
   2737static bool slideup_check(DisasContext *s, arg_rmrr *a)
   2738{
   2739    return (vext_check_isa_ill(s) &&
   2740            vext_check_overlap_mask(s, a->rd, a->vm, true) &&
   2741            vext_check_reg(s, a->rd, false) &&
   2742            vext_check_reg(s, a->rs2, false) &&
   2743            (a->rd != a->rs2));
   2744}
   2745
   2746GEN_OPIVX_TRANS(vslideup_vx, slideup_check)
   2747GEN_OPIVX_TRANS(vslide1up_vx, slideup_check)
   2748GEN_OPIVI_TRANS(vslideup_vi, 1, vslideup_vx, slideup_check)
   2749
   2750GEN_OPIVX_TRANS(vslidedown_vx, opivx_check)
   2751GEN_OPIVX_TRANS(vslide1down_vx, opivx_check)
   2752GEN_OPIVI_TRANS(vslidedown_vi, 1, vslidedown_vx, opivx_check)
   2753
   2754/* Vector Register Gather Instruction */
   2755static bool vrgather_vv_check(DisasContext *s, arg_rmrr *a)
   2756{
   2757    return (vext_check_isa_ill(s) &&
   2758            vext_check_overlap_mask(s, a->rd, a->vm, true) &&
   2759            vext_check_reg(s, a->rd, false) &&
   2760            vext_check_reg(s, a->rs1, false) &&
   2761            vext_check_reg(s, a->rs2, false) &&
   2762            (a->rd != a->rs2) && (a->rd != a->rs1));
   2763}
   2764
   2765GEN_OPIVV_TRANS(vrgather_vv, vrgather_vv_check)
   2766
   2767static bool vrgather_vx_check(DisasContext *s, arg_rmrr *a)
   2768{
   2769    return (vext_check_isa_ill(s) &&
   2770            vext_check_overlap_mask(s, a->rd, a->vm, true) &&
   2771            vext_check_reg(s, a->rd, false) &&
   2772            vext_check_reg(s, a->rs2, false) &&
   2773            (a->rd != a->rs2));
   2774}
   2775
   2776/* vrgather.vx vd, vs2, rs1, vm # vd[i] = (x[rs1] >= VLMAX) ? 0 : vs2[rs1] */
   2777static bool trans_vrgather_vx(DisasContext *s, arg_rmrr *a)
   2778{
   2779    if (!vrgather_vx_check(s, a)) {
   2780        return false;
   2781    }
   2782
   2783    if (a->vm && s->vl_eq_vlmax) {
   2784        int vlmax = s->vlen / s->mlen;
   2785        TCGv_i64 dest = tcg_temp_new_i64();
   2786
   2787        if (a->rs1 == 0) {
   2788            vec_element_loadi(s, dest, a->rs2, 0);
   2789        } else {
   2790            vec_element_loadx(s, dest, a->rs2, cpu_gpr[a->rs1], vlmax);
   2791        }
   2792
   2793        tcg_gen_gvec_dup_i64(s->sew, vreg_ofs(s, a->rd),
   2794                             MAXSZ(s), MAXSZ(s), dest);
   2795        tcg_temp_free_i64(dest);
   2796    } else {
   2797        static gen_helper_opivx * const fns[4] = {
   2798            gen_helper_vrgather_vx_b, gen_helper_vrgather_vx_h,
   2799            gen_helper_vrgather_vx_w, gen_helper_vrgather_vx_d
   2800        };
   2801        return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s);
   2802    }
   2803    return true;
   2804}
   2805
   2806/* vrgather.vi vd, vs2, imm, vm # vd[i] = (imm >= VLMAX) ? 0 : vs2[imm] */
   2807static bool trans_vrgather_vi(DisasContext *s, arg_rmrr *a)
   2808{
   2809    if (!vrgather_vx_check(s, a)) {
   2810        return false;
   2811    }
   2812
   2813    if (a->vm && s->vl_eq_vlmax) {
   2814        if (a->rs1 >= s->vlen / s->mlen) {
   2815            tcg_gen_gvec_dup_imm(SEW64, vreg_ofs(s, a->rd),
   2816                                 MAXSZ(s), MAXSZ(s), 0);
   2817        } else {
   2818            tcg_gen_gvec_dup_mem(s->sew, vreg_ofs(s, a->rd),
   2819                                 endian_ofs(s, a->rs2, a->rs1),
   2820                                 MAXSZ(s), MAXSZ(s));
   2821        }
   2822    } else {
   2823        static gen_helper_opivx * const fns[4] = {
   2824            gen_helper_vrgather_vx_b, gen_helper_vrgather_vx_h,
   2825            gen_helper_vrgather_vx_w, gen_helper_vrgather_vx_d
   2826        };
   2827        return opivi_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s, 1);
   2828    }
   2829    return true;
   2830}
   2831
   2832/* Vector Compress Instruction */
   2833static bool vcompress_vm_check(DisasContext *s, arg_r *a)
   2834{
   2835    return (vext_check_isa_ill(s) &&
   2836            vext_check_reg(s, a->rd, false) &&
   2837            vext_check_reg(s, a->rs2, false) &&
   2838            vext_check_overlap_group(a->rd, 1 << s->lmul, a->rs1, 1) &&
   2839            (a->rd != a->rs2));
   2840}
   2841
   2842static bool trans_vcompress_vm(DisasContext *s, arg_r *a)
   2843{
   2844    if (vcompress_vm_check(s, a)) {
   2845        uint32_t data = 0;
   2846        static gen_helper_gvec_4_ptr * const fns[4] = {
   2847            gen_helper_vcompress_vm_b, gen_helper_vcompress_vm_h,
   2848            gen_helper_vcompress_vm_w, gen_helper_vcompress_vm_d,
   2849        };
   2850        TCGLabel *over = gen_new_label();
   2851        tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
   2852
   2853        data = FIELD_DP32(data, VDATA, MLEN, s->mlen);
   2854        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
   2855        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
   2856                           vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2),
   2857                           cpu_env, s->vlen / 8, s->vlen / 8, data,
   2858                           fns[s->sew]);
   2859        gen_set_label(over);
   2860        return true;
   2861    }
   2862    return false;
   2863}