xref: /openbmc/qemu/target/riscv/insn_trans/trans_rvv.c.inc (revision feef1866d1366d651e6a3cb8c9cf1a9aabb81395)
1139c1837SPaolo Bonzini/*
2139c1837SPaolo Bonzini *
3139c1837SPaolo Bonzini * Copyright (c) 2020 T-Head Semiconductor Co., Ltd. All rights reserved.
4139c1837SPaolo Bonzini *
5139c1837SPaolo Bonzini * This program is free software; you can redistribute it and/or modify it
6139c1837SPaolo Bonzini * under the terms and conditions of the GNU General Public License,
7139c1837SPaolo Bonzini * version 2 or later, as published by the Free Software Foundation.
8139c1837SPaolo Bonzini *
9139c1837SPaolo Bonzini * This program is distributed in the hope it will be useful, but WITHOUT
10139c1837SPaolo Bonzini * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11139c1837SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12139c1837SPaolo Bonzini * more details.
13139c1837SPaolo Bonzini *
14139c1837SPaolo Bonzini * You should have received a copy of the GNU General Public License along with
15139c1837SPaolo Bonzini * this program.  If not, see <http://www.gnu.org/licenses/>.
16139c1837SPaolo Bonzini */
17139c1837SPaolo Bonzini#include "tcg/tcg-op-gvec.h"
18139c1837SPaolo Bonzini#include "tcg/tcg-gvec-desc.h"
19139c1837SPaolo Bonzini#include "internals.h"
20139c1837SPaolo Bonzini
21f31dacd7SFrank Changstatic inline bool is_overlapped(const int8_t astart, int8_t asize,
22f31dacd7SFrank Chang                                 const int8_t bstart, int8_t bsize)
23f31dacd7SFrank Chang{
24f31dacd7SFrank Chang    const int8_t aend = astart + asize;
25f31dacd7SFrank Chang    const int8_t bend = bstart + bsize;
26f31dacd7SFrank Chang
27f31dacd7SFrank Chang    return MAX(aend, bend) - MIN(astart, bstart) < asize + bsize;
28f31dacd7SFrank Chang}
29f31dacd7SFrank Chang
30f31dacd7SFrank Changstatic bool require_rvv(DisasContext *s)
31f31dacd7SFrank Chang{
32ebd47648SLIU Zhiwei    return s->mstatus_vs != EXT_STATUS_DISABLED;
33f31dacd7SFrank Chang}
34f31dacd7SFrank Chang
35f31dacd7SFrank Changstatic bool require_rvf(DisasContext *s)
36f31dacd7SFrank Chang{
37ebd47648SLIU Zhiwei    if (s->mstatus_fs == EXT_STATUS_DISABLED) {
38f31dacd7SFrank Chang        return false;
39f31dacd7SFrank Chang    }
40f31dacd7SFrank Chang
41f31dacd7SFrank Chang    switch (s->sew) {
42f31dacd7SFrank Chang    case MO_16:
43e80865e5SWeiwei Li        return s->cfg_ptr->ext_zvfh;
44f31dacd7SFrank Chang    case MO_32:
45732b902dSWeiwei Li        return s->cfg_ptr->ext_zve32f;
46f31dacd7SFrank Chang    case MO_64:
47732b902dSWeiwei Li        return s->cfg_ptr->ext_zve64d;
48f31dacd7SFrank Chang    default:
49f31dacd7SFrank Chang        return false;
50f31dacd7SFrank Chang    }
51f31dacd7SFrank Chang}
52f31dacd7SFrank Chang
5317b713c0SMax Choustatic bool require_rvfmin(DisasContext *s)
5417b713c0SMax Chou{
5517b713c0SMax Chou    if (s->mstatus_fs == EXT_STATUS_DISABLED) {
5617b713c0SMax Chou        return false;
5717b713c0SMax Chou    }
5817b713c0SMax Chou
5917b713c0SMax Chou    switch (s->sew) {
6017b713c0SMax Chou    case MO_16:
6117b713c0SMax Chou        return s->cfg_ptr->ext_zvfhmin;
6217b713c0SMax Chou    case MO_32:
6317b713c0SMax Chou        return s->cfg_ptr->ext_zve32f;
6417b713c0SMax Chou    default:
6517b713c0SMax Chou        return false;
6617b713c0SMax Chou    }
6717b713c0SMax Chou}
6817b713c0SMax Chou
69f31dacd7SFrank Changstatic bool require_scale_rvf(DisasContext *s)
70f31dacd7SFrank Chang{
71ebd47648SLIU Zhiwei    if (s->mstatus_fs == EXT_STATUS_DISABLED) {
72f31dacd7SFrank Chang        return false;
73f31dacd7SFrank Chang    }
74f31dacd7SFrank Chang
75f31dacd7SFrank Chang    switch (s->sew) {
76f31dacd7SFrank Chang    case MO_8:
77e80865e5SWeiwei Li        return s->cfg_ptr->ext_zvfh;
78e80865e5SWeiwei Li    case MO_16:
79e80865e5SWeiwei Li        return s->cfg_ptr->ext_zve32f;
80e80865e5SWeiwei Li    case MO_32:
81e80865e5SWeiwei Li        return s->cfg_ptr->ext_zve64d;
82e80865e5SWeiwei Li    default:
83e80865e5SWeiwei Li        return false;
84e80865e5SWeiwei Li    }
85e80865e5SWeiwei Li}
86e80865e5SWeiwei Li
87e80865e5SWeiwei Listatic bool require_scale_rvfmin(DisasContext *s)
88e80865e5SWeiwei Li{
89ebd47648SLIU Zhiwei    if (s->mstatus_fs == EXT_STATUS_DISABLED) {
90e80865e5SWeiwei Li        return false;
91e80865e5SWeiwei Li    }
92e80865e5SWeiwei Li
93e80865e5SWeiwei Li    switch (s->sew) {
94f31dacd7SFrank Chang    case MO_16:
95732b902dSWeiwei Li        return s->cfg_ptr->ext_zve32f;
96f31dacd7SFrank Chang    case MO_32:
97732b902dSWeiwei Li        return s->cfg_ptr->ext_zve64d;
98f31dacd7SFrank Chang    default:
99f31dacd7SFrank Chang        return false;
100f31dacd7SFrank Chang    }
101f31dacd7SFrank Chang}
102f31dacd7SFrank Chang
103f31dacd7SFrank Chang/* Destination vector register group cannot overlap source mask register. */
104f31dacd7SFrank Changstatic bool require_vm(int vm, int vd)
105f31dacd7SFrank Chang{
106f31dacd7SFrank Chang    return (vm != 0 || vd != 0);
107f31dacd7SFrank Chang}
108f31dacd7SFrank Chang
10979556fb6SFrank Changstatic bool require_nf(int vd, int nf, int lmul)
11079556fb6SFrank Chang{
11179556fb6SFrank Chang    int size = nf << MAX(lmul, 0);
11279556fb6SFrank Chang    return size <= 8 && vd + size <= 32;
11379556fb6SFrank Chang}
11479556fb6SFrank Chang
115f31dacd7SFrank Chang/*
116f31dacd7SFrank Chang * Vector register should aligned with the passed-in LMUL (EMUL).
117f31dacd7SFrank Chang * If LMUL < 0, i.e. fractional LMUL, any vector register is allowed.
118f31dacd7SFrank Chang */
119f31dacd7SFrank Changstatic bool require_align(const int8_t val, const int8_t lmul)
120f31dacd7SFrank Chang{
121f31dacd7SFrank Chang    return lmul <= 0 || extract32(val, 0, lmul) == 0;
122f31dacd7SFrank Chang}
123f31dacd7SFrank Chang
124f31dacd7SFrank Chang/*
125f31dacd7SFrank Chang * A destination vector register group can overlap a source vector
126f31dacd7SFrank Chang * register group only if one of the following holds:
127f31dacd7SFrank Chang *  1. The destination EEW equals the source EEW.
128f31dacd7SFrank Chang *  2. The destination EEW is smaller than the source EEW and the overlap
129f31dacd7SFrank Chang *     is in the lowest-numbered part of the source register group.
130f31dacd7SFrank Chang *  3. The destination EEW is greater than the source EEW, the source EMUL
131f31dacd7SFrank Chang *     is at least 1, and the overlap is in the highest-numbered part of
132f31dacd7SFrank Chang *     the destination register group.
133f31dacd7SFrank Chang * (Section 5.2)
134f31dacd7SFrank Chang *
135f31dacd7SFrank Chang * This function returns true if one of the following holds:
136f31dacd7SFrank Chang *  * Destination vector register group does not overlap a source vector
137f31dacd7SFrank Chang *    register group.
138f31dacd7SFrank Chang *  * Rule 3 met.
139f31dacd7SFrank Chang * For rule 1, overlap is allowed so this function doesn't need to be called.
140f31dacd7SFrank Chang * For rule 2, (vd == vs). Caller has to check whether: (vd != vs) before
141f31dacd7SFrank Chang * calling this function.
142f31dacd7SFrank Chang */
143f31dacd7SFrank Changstatic bool require_noover(const int8_t dst, const int8_t dst_lmul,
144f31dacd7SFrank Chang                           const int8_t src, const int8_t src_lmul)
145f31dacd7SFrank Chang{
146f31dacd7SFrank Chang    int8_t dst_size = dst_lmul <= 0 ? 1 : 1 << dst_lmul;
147f31dacd7SFrank Chang    int8_t src_size = src_lmul <= 0 ? 1 : 1 << src_lmul;
148f31dacd7SFrank Chang
149f31dacd7SFrank Chang    /* Destination EEW is greater than the source EEW, check rule 3. */
150f31dacd7SFrank Chang    if (dst_size > src_size) {
151f31dacd7SFrank Chang        if (dst < src &&
152f31dacd7SFrank Chang            src_lmul >= 0 &&
153f31dacd7SFrank Chang            is_overlapped(dst, dst_size, src, src_size) &&
154f31dacd7SFrank Chang            !is_overlapped(dst, dst_size, src + src_size, src_size)) {
155f31dacd7SFrank Chang            return true;
156f31dacd7SFrank Chang        }
157f31dacd7SFrank Chang    }
158f31dacd7SFrank Chang
159f31dacd7SFrank Chang    return !is_overlapped(dst, dst_size, src, src_size);
160f31dacd7SFrank Chang}
161f31dacd7SFrank Chang
162d9b7609aSFrank Changstatic bool do_vsetvl(DisasContext *s, int rd, int rs1, TCGv s2)
163139c1837SPaolo Bonzini{
164d9b7609aSFrank Chang    TCGv s1, dst;
165139c1837SPaolo Bonzini
1669fb41a44SJason Chien    if (!require_rvv(s) || !s->cfg_ptr->ext_zve32x) {
167139c1837SPaolo Bonzini        return false;
168139c1837SPaolo Bonzini    }
169139c1837SPaolo Bonzini
170d9b7609aSFrank Chang    dst = dest_gpr(s, rd);
171139c1837SPaolo Bonzini
172d9b7609aSFrank Chang    if (rd == 0 && rs1 == 0) {
173d9b7609aSFrank Chang        s1 = tcg_temp_new();
174d9b7609aSFrank Chang        tcg_gen_mov_tl(s1, cpu_vl);
175d9b7609aSFrank Chang    } else if (rs1 == 0) {
176139c1837SPaolo Bonzini        /* As the mask is at least one bit, RV_VLEN_MAX is >= VLMAX */
17705b80ed0SRichard Henderson        s1 = tcg_constant_tl(RV_VLEN_MAX);
178139c1837SPaolo Bonzini    } else {
179d9b7609aSFrank Chang        s1 = get_gpr(s, rs1, EXT_ZERO);
180139c1837SPaolo Bonzini    }
1818e034ae4SRichard Henderson
182ad75a51eSRichard Henderson    gen_helper_vsetvl(dst, tcg_env, s1, s2);
183d9b7609aSFrank Chang    gen_set_gpr(s, rd, dst);
184bac802adSIvan Klokov    finalize_rvv_inst(s);
185d9b7609aSFrank Chang
186022c7550SWeiwei Li    gen_update_pc(s, s->cur_insn_len);
1872c9d7471SLIU Zhiwei    lookup_and_goto_ptr(s);
188d9b7609aSFrank Chang    s->base.is_jmp = DISAS_NORETURN;
189139c1837SPaolo Bonzini    return true;
190139c1837SPaolo Bonzini}
191139c1837SPaolo Bonzini
19234a2c2d8SFrank Changstatic bool do_vsetivli(DisasContext *s, int rd, TCGv s1, TCGv s2)
19334a2c2d8SFrank Chang{
19434a2c2d8SFrank Chang    TCGv dst;
19534a2c2d8SFrank Chang
1969fb41a44SJason Chien    if (!require_rvv(s) || !s->cfg_ptr->ext_zve32x) {
19734a2c2d8SFrank Chang        return false;
19834a2c2d8SFrank Chang    }
19934a2c2d8SFrank Chang
20034a2c2d8SFrank Chang    dst = dest_gpr(s, rd);
20134a2c2d8SFrank Chang
202ad75a51eSRichard Henderson    gen_helper_vsetvl(dst, tcg_env, s1, s2);
20334a2c2d8SFrank Chang    gen_set_gpr(s, rd, dst);
204bac802adSIvan Klokov    finalize_rvv_inst(s);
205022c7550SWeiwei Li    gen_update_pc(s, s->cur_insn_len);
2062c9d7471SLIU Zhiwei    lookup_and_goto_ptr(s);
20734a2c2d8SFrank Chang    s->base.is_jmp = DISAS_NORETURN;
20834a2c2d8SFrank Chang
20934a2c2d8SFrank Chang    return true;
21034a2c2d8SFrank Chang}
21134a2c2d8SFrank Chang
212d9b7609aSFrank Changstatic bool trans_vsetvl(DisasContext *s, arg_vsetvl *a)
213139c1837SPaolo Bonzini{
214d9b7609aSFrank Chang    TCGv s2 = get_gpr(s, a->rs2, EXT_ZERO);
215d9b7609aSFrank Chang    return do_vsetvl(s, a->rd, a->rs1, s2);
216139c1837SPaolo Bonzini}
217139c1837SPaolo Bonzini
218d9b7609aSFrank Changstatic bool trans_vsetvli(DisasContext *s, arg_vsetvli *a)
219d9b7609aSFrank Chang{
220d9b7609aSFrank Chang    TCGv s2 = tcg_constant_tl(a->zimm);
221d9b7609aSFrank Chang    return do_vsetvl(s, a->rd, a->rs1, s2);
222139c1837SPaolo Bonzini}
223139c1837SPaolo Bonzini
22434a2c2d8SFrank Changstatic bool trans_vsetivli(DisasContext *s, arg_vsetivli *a)
22534a2c2d8SFrank Chang{
2262f668fabSRichard Henderson    TCGv s1 = tcg_constant_tl(a->rs1);
2272f668fabSRichard Henderson    TCGv s2 = tcg_constant_tl(a->zimm);
22834a2c2d8SFrank Chang    return do_vsetivli(s, a->rd, s1, s2);
22934a2c2d8SFrank Chang}
23034a2c2d8SFrank Chang
231139c1837SPaolo Bonzini/* vector register offset from env */
232139c1837SPaolo Bonzinistatic uint32_t vreg_ofs(DisasContext *s, int reg)
233139c1837SPaolo Bonzini{
23481b9ef99SDaniel Henrique Barboza    return offsetof(CPURISCVState, vreg) + reg * s->cfg_ptr->vlenb;
235139c1837SPaolo Bonzini}
236139c1837SPaolo Bonzini
237139c1837SPaolo Bonzini/* check functions */
238139c1837SPaolo Bonzini
23979556fb6SFrank Chang/*
24079556fb6SFrank Chang * Vector unit-stride, strided, unit-stride segment, strided segment
24179556fb6SFrank Chang * store check function.
24279556fb6SFrank Chang *
24379556fb6SFrank Chang * Rules to be checked here:
24479556fb6SFrank Chang *   1. EMUL must within the range: 1/8 <= EMUL <= 8. (Section 7.3)
24579556fb6SFrank Chang *   2. Destination vector register number is multiples of EMUL.
24679556fb6SFrank Chang *      (Section 3.4.2, 7.3)
24779556fb6SFrank Chang *   3. The EMUL setting must be such that EMUL * NFIELDS ≤ 8. (Section 7.8)
24879556fb6SFrank Chang *   4. Vector register numbers accessed by the segment load or store
24979556fb6SFrank Chang *      cannot increment past 31. (Section 7.8)
25079556fb6SFrank Chang */
25179556fb6SFrank Changstatic bool vext_check_store(DisasContext *s, int vd, int nf, uint8_t eew)
25279556fb6SFrank Chang{
25379556fb6SFrank Chang    int8_t emul = eew - s->sew + s->lmul;
25479556fb6SFrank Chang    return (emul >= -3 && emul <= 3) &&
25579556fb6SFrank Chang           require_align(vd, emul) &&
25679556fb6SFrank Chang           require_nf(vd, nf, emul);
25779556fb6SFrank Chang}
25879556fb6SFrank Chang
25979556fb6SFrank Chang/*
26079556fb6SFrank Chang * Vector unit-stride, strided, unit-stride segment, strided segment
26179556fb6SFrank Chang * load check function.
26279556fb6SFrank Chang *
26379556fb6SFrank Chang * Rules to be checked here:
26479556fb6SFrank Chang *   1. All rules applies to store instructions are applies
26579556fb6SFrank Chang *      to load instructions.
26679556fb6SFrank Chang *   2. Destination vector register group for a masked vector
26779556fb6SFrank Chang *      instruction cannot overlap the source mask register (v0).
26879556fb6SFrank Chang *      (Section 5.3)
26979556fb6SFrank Chang */
27079556fb6SFrank Changstatic bool vext_check_load(DisasContext *s, int vd, int nf, int vm,
27179556fb6SFrank Chang                            uint8_t eew)
27279556fb6SFrank Chang{
27379556fb6SFrank Chang    return vext_check_store(s, vd, nf, eew) && require_vm(vm, vd);
27479556fb6SFrank Chang}
27579556fb6SFrank Chang
27679556fb6SFrank Chang/*
27779556fb6SFrank Chang * Vector indexed, indexed segment store check function.
27879556fb6SFrank Chang *
27979556fb6SFrank Chang * Rules to be checked here:
28079556fb6SFrank Chang *   1. EMUL must within the range: 1/8 <= EMUL <= 8. (Section 7.3)
28179556fb6SFrank Chang *   2. Index vector register number is multiples of EMUL.
28279556fb6SFrank Chang *      (Section 3.4.2, 7.3)
28379556fb6SFrank Chang *   3. Destination vector register number is multiples of LMUL.
28479556fb6SFrank Chang *      (Section 3.4.2, 7.3)
28579556fb6SFrank Chang *   4. The EMUL setting must be such that EMUL * NFIELDS ≤ 8. (Section 7.8)
28679556fb6SFrank Chang *   5. Vector register numbers accessed by the segment load or store
28779556fb6SFrank Chang *      cannot increment past 31. (Section 7.8)
28879556fb6SFrank Chang */
28979556fb6SFrank Changstatic bool vext_check_st_index(DisasContext *s, int vd, int vs2, int nf,
29079556fb6SFrank Chang                                uint8_t eew)
29179556fb6SFrank Chang{
29279556fb6SFrank Chang    int8_t emul = eew - s->sew + s->lmul;
29349410409SFrank Chang    bool ret = (emul >= -3 && emul <= 3) &&
29479556fb6SFrank Chang               require_align(vs2, emul) &&
29579556fb6SFrank Chang               require_align(vd, s->lmul) &&
29679556fb6SFrank Chang               require_nf(vd, nf, s->lmul);
29749410409SFrank Chang
29849410409SFrank Chang    /*
2996ad831ebSWeiwei Li     * V extension supports all vector load and store instructions,
3006ad831ebSWeiwei Li     * except V extension does not support EEW=64 for index values
3016ad831ebSWeiwei Li     * when XLEN=32. (Section 18.3)
30249410409SFrank Chang     */
30349410409SFrank Chang    if (get_xl(s) == MXL_RV32) {
3046ad831ebSWeiwei Li        ret &= (eew != MO_64);
30549410409SFrank Chang    }
30649410409SFrank Chang
30749410409SFrank Chang    return ret;
30879556fb6SFrank Chang}
30979556fb6SFrank Chang
31079556fb6SFrank Chang/*
31179556fb6SFrank Chang * Vector indexed, indexed segment load check function.
31279556fb6SFrank Chang *
31379556fb6SFrank Chang * Rules to be checked here:
31479556fb6SFrank Chang *   1. All rules applies to store instructions are applies
31579556fb6SFrank Chang *      to load instructions.
31679556fb6SFrank Chang *   2. Destination vector register group for a masked vector
31779556fb6SFrank Chang *      instruction cannot overlap the source mask register (v0).
31879556fb6SFrank Chang *      (Section 5.3)
31979556fb6SFrank Chang *   3. Destination vector register cannot overlap a source vector
32079556fb6SFrank Chang *      register (vs2) group.
32179556fb6SFrank Chang *      (Section 5.2)
32279556fb6SFrank Chang *   4. Destination vector register groups cannot overlap
32379556fb6SFrank Chang *      the source vector register (vs2) group for
32479556fb6SFrank Chang *      indexed segment load instructions. (Section 7.8.3)
32579556fb6SFrank Chang */
32679556fb6SFrank Changstatic bool vext_check_ld_index(DisasContext *s, int vd, int vs2,
32779556fb6SFrank Chang                                int nf, int vm, uint8_t eew)
32879556fb6SFrank Chang{
32979556fb6SFrank Chang    int8_t seg_vd;
33079556fb6SFrank Chang    int8_t emul = eew - s->sew + s->lmul;
33179556fb6SFrank Chang    bool ret = vext_check_st_index(s, vd, vs2, nf, eew) &&
33279556fb6SFrank Chang               require_vm(vm, vd);
33379556fb6SFrank Chang
33479556fb6SFrank Chang    /* Each segment register group has to follow overlap rules. */
33579556fb6SFrank Chang    for (int i = 0; i < nf; ++i) {
33679556fb6SFrank Chang        seg_vd = vd + (1 << MAX(s->lmul, 0)) * i;
33779556fb6SFrank Chang
33879556fb6SFrank Chang        if (eew > s->sew) {
33979556fb6SFrank Chang            if (seg_vd != vs2) {
34079556fb6SFrank Chang                ret &= require_noover(seg_vd, s->lmul, vs2, emul);
34179556fb6SFrank Chang            }
34279556fb6SFrank Chang        } else if (eew < s->sew) {
34379556fb6SFrank Chang            ret &= require_noover(seg_vd, s->lmul, vs2, emul);
34479556fb6SFrank Chang        }
34579556fb6SFrank Chang
34679556fb6SFrank Chang        /*
34779556fb6SFrank Chang         * Destination vector register groups cannot overlap
34879556fb6SFrank Chang         * the source vector register (vs2) group for
34979556fb6SFrank Chang         * indexed segment load instructions.
35079556fb6SFrank Chang         */
35179556fb6SFrank Chang        if (nf > 1) {
35279556fb6SFrank Chang            ret &= !is_overlapped(seg_vd, 1 << MAX(s->lmul, 0),
35379556fb6SFrank Chang                                  vs2, 1 << MAX(emul, 0));
35479556fb6SFrank Chang        }
35579556fb6SFrank Chang    }
35679556fb6SFrank Chang    return ret;
35779556fb6SFrank Chang}
35879556fb6SFrank Chang
359f31dacd7SFrank Changstatic bool vext_check_ss(DisasContext *s, int vd, int vs, int vm)
360f31dacd7SFrank Chang{
361f31dacd7SFrank Chang    return require_vm(vm, vd) &&
362f31dacd7SFrank Chang           require_align(vd, s->lmul) &&
363f31dacd7SFrank Chang           require_align(vs, s->lmul);
364f31dacd7SFrank Chang}
365f31dacd7SFrank Chang
366f31dacd7SFrank Chang/*
367f31dacd7SFrank Chang * Check function for vector instruction with format:
368f31dacd7SFrank Chang * single-width result and single-width sources (SEW = SEW op SEW)
369f31dacd7SFrank Chang *
370f31dacd7SFrank Chang * Rules to be checked here:
371f31dacd7SFrank Chang *   1. Destination vector register group for a masked vector
372f31dacd7SFrank Chang *      instruction cannot overlap the source mask register (v0).
373f31dacd7SFrank Chang *      (Section 5.3)
374f31dacd7SFrank Chang *   2. Destination vector register number is multiples of LMUL.
375f31dacd7SFrank Chang *      (Section 3.4.2)
376f31dacd7SFrank Chang *   3. Source (vs2, vs1) vector register number are multiples of LMUL.
377f31dacd7SFrank Chang *      (Section 3.4.2)
378f31dacd7SFrank Chang */
379f31dacd7SFrank Changstatic bool vext_check_sss(DisasContext *s, int vd, int vs1, int vs2, int vm)
380f31dacd7SFrank Chang{
381f31dacd7SFrank Chang    return vext_check_ss(s, vd, vs2, vm) &&
382f31dacd7SFrank Chang           require_align(vs1, s->lmul);
383f31dacd7SFrank Chang}
384f31dacd7SFrank Chang
385f31dacd7SFrank Changstatic bool vext_check_ms(DisasContext *s, int vd, int vs)
386f31dacd7SFrank Chang{
387f31dacd7SFrank Chang    bool ret = require_align(vs, s->lmul);
388f31dacd7SFrank Chang    if (vd != vs) {
389f31dacd7SFrank Chang        ret &= require_noover(vd, 0, vs, s->lmul);
390f31dacd7SFrank Chang    }
391f31dacd7SFrank Chang    return ret;
392f31dacd7SFrank Chang}
393f31dacd7SFrank Chang
394f31dacd7SFrank Chang/*
395f31dacd7SFrank Chang * Check function for maskable vector instruction with format:
396f31dacd7SFrank Chang * single-width result and single-width sources (SEW = SEW op SEW)
397f31dacd7SFrank Chang *
398f31dacd7SFrank Chang * Rules to be checked here:
399f31dacd7SFrank Chang *   1. Source (vs2, vs1) vector register number are multiples of LMUL.
400f31dacd7SFrank Chang *      (Section 3.4.2)
401f31dacd7SFrank Chang *   2. Destination vector register cannot overlap a source vector
402f31dacd7SFrank Chang *      register (vs2, vs1) group.
403f31dacd7SFrank Chang *      (Section 5.2)
404f31dacd7SFrank Chang *   3. The destination vector register group for a masked vector
405f31dacd7SFrank Chang *      instruction cannot overlap the source mask register (v0),
406f31dacd7SFrank Chang *      unless the destination vector register is being written
407f31dacd7SFrank Chang *      with a mask value (e.g., comparisons) or the scalar result
408f31dacd7SFrank Chang *      of a reduction. (Section 5.3)
409f31dacd7SFrank Chang */
410f31dacd7SFrank Changstatic bool vext_check_mss(DisasContext *s, int vd, int vs1, int vs2)
411f31dacd7SFrank Chang{
412f31dacd7SFrank Chang    bool ret = vext_check_ms(s, vd, vs2) &&
413f31dacd7SFrank Chang               require_align(vs1, s->lmul);
414f31dacd7SFrank Chang    if (vd != vs1) {
415f31dacd7SFrank Chang        ret &= require_noover(vd, 0, vs1, s->lmul);
416f31dacd7SFrank Chang    }
417f31dacd7SFrank Chang    return ret;
418f31dacd7SFrank Chang}
419f31dacd7SFrank Chang
420f31dacd7SFrank Chang/*
421f31dacd7SFrank Chang * Common check function for vector widening instructions
422f31dacd7SFrank Chang * of double-width result (2*SEW).
423f31dacd7SFrank Chang *
424f31dacd7SFrank Chang * Rules to be checked here:
425f31dacd7SFrank Chang *   1. The largest vector register group used by an instruction
426f31dacd7SFrank Chang *      can not be greater than 8 vector registers (Section 5.2):
427f31dacd7SFrank Chang *      => LMUL < 8.
428f31dacd7SFrank Chang *      => SEW < 64.
429cc13aa36SFrank Chang *   2. Double-width SEW cannot greater than ELEN.
430cc13aa36SFrank Chang *   3. Destination vector register number is multiples of 2 * LMUL.
431f31dacd7SFrank Chang *      (Section 3.4.2)
432cc13aa36SFrank Chang *   4. Destination vector register group for a masked vector
433f31dacd7SFrank Chang *      instruction cannot overlap the source mask register (v0).
434f31dacd7SFrank Chang *      (Section 5.3)
435f31dacd7SFrank Chang */
436f31dacd7SFrank Changstatic bool vext_wide_check_common(DisasContext *s, int vd, int vm)
437f31dacd7SFrank Chang{
438f31dacd7SFrank Chang    return (s->lmul <= 2) &&
439f31dacd7SFrank Chang           (s->sew < MO_64) &&
44079bf3b51SPhilipp Tomsich           ((s->sew + 1) <= (s->cfg_ptr->elen >> 4)) &&
441f31dacd7SFrank Chang           require_align(vd, s->lmul + 1) &&
442f31dacd7SFrank Chang           require_vm(vm, vd);
443f31dacd7SFrank Chang}
444f31dacd7SFrank Chang
445f31dacd7SFrank Chang/*
446f31dacd7SFrank Chang * Common check function for vector narrowing instructions
447f31dacd7SFrank Chang * of single-width result (SEW) and double-width source (2*SEW).
448f31dacd7SFrank Chang *
449f31dacd7SFrank Chang * Rules to be checked here:
450f31dacd7SFrank Chang *   1. The largest vector register group used by an instruction
451f31dacd7SFrank Chang *      can not be greater than 8 vector registers (Section 5.2):
452f31dacd7SFrank Chang *      => LMUL < 8.
453f31dacd7SFrank Chang *      => SEW < 64.
454cc13aa36SFrank Chang *   2. Double-width SEW cannot greater than ELEN.
455cc13aa36SFrank Chang *   3. Source vector register number is multiples of 2 * LMUL.
456f31dacd7SFrank Chang *      (Section 3.4.2)
457cc13aa36SFrank Chang *   4. Destination vector register number is multiples of LMUL.
458f31dacd7SFrank Chang *      (Section 3.4.2)
459cc13aa36SFrank Chang *   5. Destination vector register group for a masked vector
460f31dacd7SFrank Chang *      instruction cannot overlap the source mask register (v0).
461f31dacd7SFrank Chang *      (Section 5.3)
462f31dacd7SFrank Chang */
463f31dacd7SFrank Changstatic bool vext_narrow_check_common(DisasContext *s, int vd, int vs2,
464f31dacd7SFrank Chang                                     int vm)
465f31dacd7SFrank Chang{
466f31dacd7SFrank Chang    return (s->lmul <= 2) &&
467f31dacd7SFrank Chang           (s->sew < MO_64) &&
46879bf3b51SPhilipp Tomsich           ((s->sew + 1) <= (s->cfg_ptr->elen >> 4)) &&
469f31dacd7SFrank Chang           require_align(vs2, s->lmul + 1) &&
470f31dacd7SFrank Chang           require_align(vd, s->lmul) &&
471f31dacd7SFrank Chang           require_vm(vm, vd);
472f31dacd7SFrank Chang}
473f31dacd7SFrank Chang
474f31dacd7SFrank Changstatic bool vext_check_ds(DisasContext *s, int vd, int vs, int vm)
475f31dacd7SFrank Chang{
476f31dacd7SFrank Chang    return vext_wide_check_common(s, vd, vm) &&
477f31dacd7SFrank Chang           require_align(vs, s->lmul) &&
478f31dacd7SFrank Chang           require_noover(vd, s->lmul + 1, vs, s->lmul);
479f31dacd7SFrank Chang}
480f31dacd7SFrank Chang
481f31dacd7SFrank Changstatic bool vext_check_dd(DisasContext *s, int vd, int vs, int vm)
482f31dacd7SFrank Chang{
483f31dacd7SFrank Chang    return vext_wide_check_common(s, vd, vm) &&
484f31dacd7SFrank Chang           require_align(vs, s->lmul + 1);
485f31dacd7SFrank Chang}
486f31dacd7SFrank Chang
487f31dacd7SFrank Chang/*
488f31dacd7SFrank Chang * Check function for vector instruction with format:
489f31dacd7SFrank Chang * double-width result and single-width sources (2*SEW = SEW op SEW)
490f31dacd7SFrank Chang *
491f31dacd7SFrank Chang * Rules to be checked here:
492f31dacd7SFrank Chang *   1. All rules in defined in widen common rules are applied.
493f31dacd7SFrank Chang *   2. Source (vs2, vs1) vector register number are multiples of LMUL.
494f31dacd7SFrank Chang *      (Section 3.4.2)
495f31dacd7SFrank Chang *   3. Destination vector register cannot overlap a source vector
496f31dacd7SFrank Chang *      register (vs2, vs1) group.
497f31dacd7SFrank Chang *      (Section 5.2)
498f31dacd7SFrank Chang */
499f31dacd7SFrank Changstatic bool vext_check_dss(DisasContext *s, int vd, int vs1, int vs2, int vm)
500f31dacd7SFrank Chang{
501f31dacd7SFrank Chang    return vext_check_ds(s, vd, vs2, vm) &&
502f31dacd7SFrank Chang           require_align(vs1, s->lmul) &&
503f31dacd7SFrank Chang           require_noover(vd, s->lmul + 1, vs1, s->lmul);
504f31dacd7SFrank Chang}
505f31dacd7SFrank Chang
506f31dacd7SFrank Chang/*
507f31dacd7SFrank Chang * Check function for vector instruction with format:
508f31dacd7SFrank Chang * double-width result and double-width source1 and single-width
509f31dacd7SFrank Chang * source2 (2*SEW = 2*SEW op SEW)
510f31dacd7SFrank Chang *
511f31dacd7SFrank Chang * Rules to be checked here:
512f31dacd7SFrank Chang *   1. All rules in defined in widen common rules are applied.
513f31dacd7SFrank Chang *   2. Source 1 (vs2) vector register number is multiples of 2 * LMUL.
514f31dacd7SFrank Chang *      (Section 3.4.2)
515f31dacd7SFrank Chang *   3. Source 2 (vs1) vector register number is multiples of LMUL.
516f31dacd7SFrank Chang *      (Section 3.4.2)
517f31dacd7SFrank Chang *   4. Destination vector register cannot overlap a source vector
518f31dacd7SFrank Chang *      register (vs1) group.
519f31dacd7SFrank Chang *      (Section 5.2)
520f31dacd7SFrank Chang */
521f31dacd7SFrank Changstatic bool vext_check_dds(DisasContext *s, int vd, int vs1, int vs2, int vm)
522f31dacd7SFrank Chang{
523f31dacd7SFrank Chang    return vext_check_ds(s, vd, vs1, vm) &&
524f31dacd7SFrank Chang           require_align(vs2, s->lmul + 1);
525f31dacd7SFrank Chang}
526f31dacd7SFrank Chang
527f31dacd7SFrank Changstatic bool vext_check_sd(DisasContext *s, int vd, int vs, int vm)
528f31dacd7SFrank Chang{
529f31dacd7SFrank Chang    bool ret = vext_narrow_check_common(s, vd, vs, vm);
530f31dacd7SFrank Chang    if (vd != vs) {
531f31dacd7SFrank Chang        ret &= require_noover(vd, s->lmul, vs, s->lmul + 1);
532f31dacd7SFrank Chang    }
533f31dacd7SFrank Chang    return ret;
534f31dacd7SFrank Chang}
535f31dacd7SFrank Chang
536f31dacd7SFrank Chang/*
537f31dacd7SFrank Chang * Check function for vector instruction with format:
538f31dacd7SFrank Chang * single-width result and double-width source 1 and single-width
539f31dacd7SFrank Chang * source 2 (SEW = 2*SEW op SEW)
540f31dacd7SFrank Chang *
541f31dacd7SFrank Chang * Rules to be checked here:
542f31dacd7SFrank Chang *   1. All rules in defined in narrow common rules are applied.
543f31dacd7SFrank Chang *   2. Destination vector register cannot overlap a source vector
544f31dacd7SFrank Chang *      register (vs2) group.
545f31dacd7SFrank Chang *      (Section 5.2)
546f31dacd7SFrank Chang *   3. Source 2 (vs1) vector register number is multiples of LMUL.
547f31dacd7SFrank Chang *      (Section 3.4.2)
548f31dacd7SFrank Chang */
549f31dacd7SFrank Changstatic bool vext_check_sds(DisasContext *s, int vd, int vs1, int vs2, int vm)
550f31dacd7SFrank Chang{
551f31dacd7SFrank Chang    return vext_check_sd(s, vd, vs2, vm) &&
552f31dacd7SFrank Chang           require_align(vs1, s->lmul);
553f31dacd7SFrank Chang}
554f31dacd7SFrank Chang
555f31dacd7SFrank Chang/*
556f31dacd7SFrank Chang * Check function for vector reduction instructions.
557f31dacd7SFrank Chang *
558f31dacd7SFrank Chang * Rules to be checked here:
559f31dacd7SFrank Chang *   1. Source 1 (vs2) vector register number is multiples of LMUL.
560f31dacd7SFrank Chang *      (Section 3.4.2)
561f31dacd7SFrank Chang */
562f31dacd7SFrank Changstatic bool vext_check_reduction(DisasContext *s, int vs2)
563f31dacd7SFrank Chang{
5644acaa133SLIU Zhiwei    return require_align(vs2, s->lmul) && s->vstart_eq_zero;
565f31dacd7SFrank Chang}
566f31dacd7SFrank Chang
567f31dacd7SFrank Chang/*
568f31dacd7SFrank Chang * Check function for vector slide instructions.
569f31dacd7SFrank Chang *
570f31dacd7SFrank Chang * Rules to be checked here:
571f31dacd7SFrank Chang *   1. Source 1 (vs2) vector register number is multiples of LMUL.
572f31dacd7SFrank Chang *      (Section 3.4.2)
573f31dacd7SFrank Chang *   2. Destination vector register number is multiples of LMUL.
574f31dacd7SFrank Chang *      (Section 3.4.2)
575f31dacd7SFrank Chang *   3. Destination vector register group for a masked vector
576f31dacd7SFrank Chang *      instruction cannot overlap the source mask register (v0).
577f31dacd7SFrank Chang *      (Section 5.3)
578f31dacd7SFrank Chang *   4. The destination vector register group for vslideup, vslide1up,
579f31dacd7SFrank Chang *      vfslide1up, cannot overlap the source vector register (vs2) group.
580f31dacd7SFrank Chang *      (Section 5.2, 16.3.1, 16.3.3)
581f31dacd7SFrank Chang */
582f31dacd7SFrank Changstatic bool vext_check_slide(DisasContext *s, int vd, int vs2,
583f31dacd7SFrank Chang                             int vm, bool is_over)
584f31dacd7SFrank Chang{
585f31dacd7SFrank Chang    bool ret = require_align(vs2, s->lmul) &&
586f31dacd7SFrank Chang               require_align(vd, s->lmul) &&
587f31dacd7SFrank Chang               require_vm(vm, vd);
588f31dacd7SFrank Chang    if (is_over) {
589f31dacd7SFrank Chang        ret &= (vd != vs2);
590f31dacd7SFrank Chang    }
591f31dacd7SFrank Chang    return ret;
592f31dacd7SFrank Chang}
593f31dacd7SFrank Chang
594139c1837SPaolo Bonzini/*
595139c1837SPaolo Bonzini * In cpu_get_tb_cpu_state(), set VILL if RVV was not present.
596139c1837SPaolo Bonzini * So RVV is also be checked in this function.
597139c1837SPaolo Bonzini */
598139c1837SPaolo Bonzinistatic bool vext_check_isa_ill(DisasContext *s)
599139c1837SPaolo Bonzini{
600139c1837SPaolo Bonzini    return !s->vill;
601139c1837SPaolo Bonzini}
602139c1837SPaolo Bonzini
603139c1837SPaolo Bonzini/* common translation macro */
60479556fb6SFrank Chang#define GEN_VEXT_TRANS(NAME, EEW, ARGTYPE, OP, CHECK)        \
605139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_##ARGTYPE * a) \
606139c1837SPaolo Bonzini{                                                            \
60779556fb6SFrank Chang    if (CHECK(s, a, EEW)) {                                  \
60879556fb6SFrank Chang        return OP(s, a, EEW);                                \
609139c1837SPaolo Bonzini    }                                                        \
610139c1837SPaolo Bonzini    return false;                                            \
611139c1837SPaolo Bonzini}
612139c1837SPaolo Bonzini
6135a9f8e15SFrank Changstatic uint8_t vext_get_emul(DisasContext *s, uint8_t eew)
6145a9f8e15SFrank Chang{
6155a9f8e15SFrank Chang    int8_t emul = eew - s->sew + s->lmul;
6165a9f8e15SFrank Chang    return emul < 0 ? 0 : emul;
6175a9f8e15SFrank Chang}
6185a9f8e15SFrank Chang
619139c1837SPaolo Bonzini/*
620139c1837SPaolo Bonzini *** unit stride load and store
621139c1837SPaolo Bonzini */
622139c1837SPaolo Bonzinitypedef void gen_helper_ldst_us(TCGv_ptr, TCGv_ptr, TCGv,
623139c1837SPaolo Bonzini                                TCGv_env, TCGv_i32);
624139c1837SPaolo Bonzini
625139c1837SPaolo Bonzinistatic bool ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data,
6268e1ee1fbSFrank Chang                          gen_helper_ldst_us *fn, DisasContext *s,
6278e1ee1fbSFrank Chang                          bool is_store)
628139c1837SPaolo Bonzini{
629139c1837SPaolo Bonzini    TCGv_ptr dest, mask;
630139c1837SPaolo Bonzini    TCGv base;
631139c1837SPaolo Bonzini    TCGv_i32 desc;
632139c1837SPaolo Bonzini
633139c1837SPaolo Bonzini    dest = tcg_temp_new_ptr();
634139c1837SPaolo Bonzini    mask = tcg_temp_new_ptr();
6358e034ae4SRichard Henderson    base = get_gpr(s, rs1, EXT_NONE);
636139c1837SPaolo Bonzini
637139c1837SPaolo Bonzini    /*
6388a4b5257SFrank Chang     * As simd_desc supports at most 2048 bytes, and in this implementation,
6398a4b5257SFrank Chang     * the max vector group length is 4096 bytes. So split it into two parts.
640139c1837SPaolo Bonzini     *
64181b9ef99SDaniel Henrique Barboza     * The first part is vlen in bytes (vlenb), encoded in maxsz of simd_desc.
642139c1837SPaolo Bonzini     * The second part is lmul, encoded in data of simd_desc.
643139c1837SPaolo Bonzini     */
64481b9ef99SDaniel Henrique Barboza    desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlenb,
64581b9ef99SDaniel Henrique Barboza                                      s->cfg_ptr->vlenb, data));
646139c1837SPaolo Bonzini
647ad75a51eSRichard Henderson    tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, vd));
648ad75a51eSRichard Henderson    tcg_gen_addi_ptr(mask, tcg_env, vreg_ofs(s, 0));
649139c1837SPaolo Bonzini
65009c4e887SPalmer Dabbelt    /*
65109c4e887SPalmer Dabbelt     * According to the specification
65209c4e887SPalmer Dabbelt     *
65309c4e887SPalmer Dabbelt     *   Additionally, if the Ztso extension is implemented, then vector memory
65409c4e887SPalmer Dabbelt     *   instructions in the V extension and Zve family of extensions follow
65509c4e887SPalmer Dabbelt     *   RVTSO at the instruction level.  The Ztso extension does not
65609c4e887SPalmer Dabbelt     *   strengthen the ordering of intra-instruction element accesses.
65709c4e887SPalmer Dabbelt     *
65809c4e887SPalmer Dabbelt     * as a result neither ordered nor unordered accesses from the V
65909c4e887SPalmer Dabbelt     * instructions need ordering within the loop but we do still need barriers
66009c4e887SPalmer Dabbelt     * around the loop.
66109c4e887SPalmer Dabbelt     */
66209c4e887SPalmer Dabbelt    if (is_store && s->ztso) {
66309c4e887SPalmer Dabbelt        tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
66409c4e887SPalmer Dabbelt    }
66509c4e887SPalmer Dabbelt
666944b6dfdSDaniel Henrique Barboza    mark_vs_dirty(s);
667944b6dfdSDaniel Henrique Barboza
668ad75a51eSRichard Henderson    fn(dest, mask, base, tcg_env, desc);
669139c1837SPaolo Bonzini
67009c4e887SPalmer Dabbelt    if (!is_store && s->ztso) {
67109c4e887SPalmer Dabbelt        tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
67209c4e887SPalmer Dabbelt    }
67309c4e887SPalmer Dabbelt
674bac802adSIvan Klokov    finalize_rvv_inst(s);
675139c1837SPaolo Bonzini    return true;
676139c1837SPaolo Bonzini}
677139c1837SPaolo Bonzini
67879556fb6SFrank Changstatic bool ld_us_op(DisasContext *s, arg_r2nfvm *a, uint8_t eew)
679139c1837SPaolo Bonzini{
680139c1837SPaolo Bonzini    uint32_t data = 0;
681139c1837SPaolo Bonzini    gen_helper_ldst_us *fn;
68279556fb6SFrank Chang    static gen_helper_ldst_us * const fns[2][4] = {
683139c1837SPaolo Bonzini        /* masked unit stride load */
68479556fb6SFrank Chang        { gen_helper_vle8_v_mask, gen_helper_vle16_v_mask,
68579556fb6SFrank Chang          gen_helper_vle32_v_mask, gen_helper_vle64_v_mask },
686139c1837SPaolo Bonzini        /* unmasked unit stride load */
68779556fb6SFrank Chang        { gen_helper_vle8_v, gen_helper_vle16_v,
68879556fb6SFrank Chang          gen_helper_vle32_v, gen_helper_vle64_v }
689139c1837SPaolo Bonzini    };
690139c1837SPaolo Bonzini
69179556fb6SFrank Chang    fn =  fns[a->vm][eew];
692139c1837SPaolo Bonzini    if (fn == NULL) {
693139c1837SPaolo Bonzini        return false;
694139c1837SPaolo Bonzini    }
695139c1837SPaolo Bonzini
6965a9f8e15SFrank Chang    /*
6975a9f8e15SFrank Chang     * Vector load/store instructions have the EEW encoded
6985a9f8e15SFrank Chang     * directly in the instructions. The maximum vector size is
6995a9f8e15SFrank Chang     * calculated with EMUL rather than LMUL.
7005a9f8e15SFrank Chang     */
7015a9f8e15SFrank Chang    uint8_t emul = vext_get_emul(s, eew);
702139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, VM, a->vm);
7035a9f8e15SFrank Chang    data = FIELD_DP32(data, VDATA, LMUL, emul);
704139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, NF, a->nf);
705752614caSeopXD    data = FIELD_DP32(data, VDATA, VTA, s->vta);
706265ecd4cSYueh-Ting (eop) Chen    data = FIELD_DP32(data, VDATA, VMA, s->vma);
7078e1ee1fbSFrank Chang    return ldst_us_trans(a->rd, a->rs1, data, fn, s, false);
708139c1837SPaolo Bonzini}
709139c1837SPaolo Bonzini
71079556fb6SFrank Changstatic bool ld_us_check(DisasContext *s, arg_r2nfvm* a, uint8_t eew)
711139c1837SPaolo Bonzini{
71279556fb6SFrank Chang    return require_rvv(s) &&
71379556fb6SFrank Chang           vext_check_isa_ill(s) &&
71479556fb6SFrank Chang           vext_check_load(s, a->rd, a->nf, a->vm, eew);
715139c1837SPaolo Bonzini}
716139c1837SPaolo Bonzini
71779556fb6SFrank ChangGEN_VEXT_TRANS(vle8_v,  MO_8,  r2nfvm, ld_us_op, ld_us_check)
71879556fb6SFrank ChangGEN_VEXT_TRANS(vle16_v, MO_16, r2nfvm, ld_us_op, ld_us_check)
71979556fb6SFrank ChangGEN_VEXT_TRANS(vle32_v, MO_32, r2nfvm, ld_us_op, ld_us_check)
72079556fb6SFrank ChangGEN_VEXT_TRANS(vle64_v, MO_64, r2nfvm, ld_us_op, ld_us_check)
721139c1837SPaolo Bonzini
72279556fb6SFrank Changstatic bool st_us_op(DisasContext *s, arg_r2nfvm *a, uint8_t eew)
723139c1837SPaolo Bonzini{
724139c1837SPaolo Bonzini    uint32_t data = 0;
725139c1837SPaolo Bonzini    gen_helper_ldst_us *fn;
72679556fb6SFrank Chang    static gen_helper_ldst_us * const fns[2][4] = {
72779556fb6SFrank Chang        /* masked unit stride store */
72879556fb6SFrank Chang        { gen_helper_vse8_v_mask, gen_helper_vse16_v_mask,
72979556fb6SFrank Chang          gen_helper_vse32_v_mask, gen_helper_vse64_v_mask },
730139c1837SPaolo Bonzini        /* unmasked unit stride store */
73179556fb6SFrank Chang        { gen_helper_vse8_v, gen_helper_vse16_v,
73279556fb6SFrank Chang          gen_helper_vse32_v, gen_helper_vse64_v }
733139c1837SPaolo Bonzini    };
734139c1837SPaolo Bonzini
73579556fb6SFrank Chang    fn =  fns[a->vm][eew];
736139c1837SPaolo Bonzini    if (fn == NULL) {
737139c1837SPaolo Bonzini        return false;
738139c1837SPaolo Bonzini    }
739139c1837SPaolo Bonzini
7405a9f8e15SFrank Chang    uint8_t emul = vext_get_emul(s, eew);
741139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, VM, a->vm);
7425a9f8e15SFrank Chang    data = FIELD_DP32(data, VDATA, LMUL, emul);
743139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, NF, a->nf);
7448e1ee1fbSFrank Chang    return ldst_us_trans(a->rd, a->rs1, data, fn, s, true);
745139c1837SPaolo Bonzini}
746139c1837SPaolo Bonzini
74779556fb6SFrank Changstatic bool st_us_check(DisasContext *s, arg_r2nfvm* a, uint8_t eew)
748139c1837SPaolo Bonzini{
74979556fb6SFrank Chang    return require_rvv(s) &&
75079556fb6SFrank Chang           vext_check_isa_ill(s) &&
75179556fb6SFrank Chang           vext_check_store(s, a->rd, a->nf, eew);
752139c1837SPaolo Bonzini}
753139c1837SPaolo Bonzini
75479556fb6SFrank ChangGEN_VEXT_TRANS(vse8_v,  MO_8,  r2nfvm, st_us_op, st_us_check)
75579556fb6SFrank ChangGEN_VEXT_TRANS(vse16_v, MO_16, r2nfvm, st_us_op, st_us_check)
75679556fb6SFrank ChangGEN_VEXT_TRANS(vse32_v, MO_32, r2nfvm, st_us_op, st_us_check)
75779556fb6SFrank ChangGEN_VEXT_TRANS(vse64_v, MO_64, r2nfvm, st_us_op, st_us_check)
758139c1837SPaolo Bonzini
759139c1837SPaolo Bonzini/*
76026086aeaSFrank Chang *** unit stride mask load and store
76126086aeaSFrank Chang */
76226086aeaSFrank Changstatic bool ld_us_mask_op(DisasContext *s, arg_vlm_v *a, uint8_t eew)
76326086aeaSFrank Chang{
76426086aeaSFrank Chang    uint32_t data = 0;
76526086aeaSFrank Chang    gen_helper_ldst_us *fn = gen_helper_vlm_v;
76626086aeaSFrank Chang
76726086aeaSFrank Chang    /* EMUL = 1, NFIELDS = 1 */
76826086aeaSFrank Chang    data = FIELD_DP32(data, VDATA, LMUL, 0);
76926086aeaSFrank Chang    data = FIELD_DP32(data, VDATA, NF, 1);
770752614caSeopXD    /* Mask destination register are always tail-agnostic */
771752614caSeopXD    data = FIELD_DP32(data, VDATA, VTA, s->cfg_vta_all_1s);
772265ecd4cSYueh-Ting (eop) Chen    data = FIELD_DP32(data, VDATA, VMA, s->vma);
773*b48381b1SMax Chou    data = FIELD_DP32(data, VDATA, VM, 1);
77426086aeaSFrank Chang    return ldst_us_trans(a->rd, a->rs1, data, fn, s, false);
77526086aeaSFrank Chang}
77626086aeaSFrank Chang
77726086aeaSFrank Changstatic bool ld_us_mask_check(DisasContext *s, arg_vlm_v *a, uint8_t eew)
77826086aeaSFrank Chang{
77926086aeaSFrank Chang    /* EMUL = 1, NFIELDS = 1 */
78026086aeaSFrank Chang    return require_rvv(s) && vext_check_isa_ill(s);
78126086aeaSFrank Chang}
78226086aeaSFrank Chang
78326086aeaSFrank Changstatic bool st_us_mask_op(DisasContext *s, arg_vsm_v *a, uint8_t eew)
78426086aeaSFrank Chang{
78526086aeaSFrank Chang    uint32_t data = 0;
78626086aeaSFrank Chang    gen_helper_ldst_us *fn = gen_helper_vsm_v;
78726086aeaSFrank Chang
78826086aeaSFrank Chang    /* EMUL = 1, NFIELDS = 1 */
78926086aeaSFrank Chang    data = FIELD_DP32(data, VDATA, LMUL, 0);
79026086aeaSFrank Chang    data = FIELD_DP32(data, VDATA, NF, 1);
791*b48381b1SMax Chou    data = FIELD_DP32(data, VDATA, VM, 1);
79226086aeaSFrank Chang    return ldst_us_trans(a->rd, a->rs1, data, fn, s, true);
79326086aeaSFrank Chang}
79426086aeaSFrank Chang
79526086aeaSFrank Changstatic bool st_us_mask_check(DisasContext *s, arg_vsm_v *a, uint8_t eew)
79626086aeaSFrank Chang{
79726086aeaSFrank Chang    /* EMUL = 1, NFIELDS = 1 */
79826086aeaSFrank Chang    return require_rvv(s) && vext_check_isa_ill(s);
79926086aeaSFrank Chang}
80026086aeaSFrank Chang
80126086aeaSFrank ChangGEN_VEXT_TRANS(vlm_v, MO_8, vlm_v, ld_us_mask_op, ld_us_mask_check)
80226086aeaSFrank ChangGEN_VEXT_TRANS(vsm_v, MO_8, vsm_v, st_us_mask_op, st_us_mask_check)
80326086aeaSFrank Chang
80426086aeaSFrank Chang/*
805139c1837SPaolo Bonzini *** stride load and store
806139c1837SPaolo Bonzini */
807139c1837SPaolo Bonzinitypedef void gen_helper_ldst_stride(TCGv_ptr, TCGv_ptr, TCGv,
808139c1837SPaolo Bonzini                                    TCGv, TCGv_env, TCGv_i32);
809139c1837SPaolo Bonzini
810139c1837SPaolo Bonzinistatic bool ldst_stride_trans(uint32_t vd, uint32_t rs1, uint32_t rs2,
811139c1837SPaolo Bonzini                              uint32_t data, gen_helper_ldst_stride *fn,
812a506c428SDaniel Henrique Barboza                              DisasContext *s)
813139c1837SPaolo Bonzini{
814139c1837SPaolo Bonzini    TCGv_ptr dest, mask;
815139c1837SPaolo Bonzini    TCGv base, stride;
816139c1837SPaolo Bonzini    TCGv_i32 desc;
817139c1837SPaolo Bonzini
818139c1837SPaolo Bonzini    dest = tcg_temp_new_ptr();
819139c1837SPaolo Bonzini    mask = tcg_temp_new_ptr();
8208e034ae4SRichard Henderson    base = get_gpr(s, rs1, EXT_NONE);
8218e034ae4SRichard Henderson    stride = get_gpr(s, rs2, EXT_NONE);
82281b9ef99SDaniel Henrique Barboza    desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlenb,
82381b9ef99SDaniel Henrique Barboza                                      s->cfg_ptr->vlenb, data));
824139c1837SPaolo Bonzini
825ad75a51eSRichard Henderson    tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, vd));
826ad75a51eSRichard Henderson    tcg_gen_addi_ptr(mask, tcg_env, vreg_ofs(s, 0));
827139c1837SPaolo Bonzini
8288e1ee1fbSFrank Chang    mark_vs_dirty(s);
829944b6dfdSDaniel Henrique Barboza
830944b6dfdSDaniel Henrique Barboza    fn(dest, mask, base, stride, tcg_env, desc);
8318e1ee1fbSFrank Chang
832bac802adSIvan Klokov    finalize_rvv_inst(s);
833139c1837SPaolo Bonzini    return true;
834139c1837SPaolo Bonzini}
835139c1837SPaolo Bonzini
83679556fb6SFrank Changstatic bool ld_stride_op(DisasContext *s, arg_rnfvm *a, uint8_t eew)
837139c1837SPaolo Bonzini{
838139c1837SPaolo Bonzini    uint32_t data = 0;
839139c1837SPaolo Bonzini    gen_helper_ldst_stride *fn;
84079556fb6SFrank Chang    static gen_helper_ldst_stride * const fns[4] = {
84179556fb6SFrank Chang        gen_helper_vlse8_v, gen_helper_vlse16_v,
84279556fb6SFrank Chang        gen_helper_vlse32_v, gen_helper_vlse64_v
843139c1837SPaolo Bonzini    };
844139c1837SPaolo Bonzini
84579556fb6SFrank Chang    fn = fns[eew];
846139c1837SPaolo Bonzini    if (fn == NULL) {
847139c1837SPaolo Bonzini        return false;
848139c1837SPaolo Bonzini    }
849139c1837SPaolo Bonzini
8505a9f8e15SFrank Chang    uint8_t emul = vext_get_emul(s, eew);
851139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, VM, a->vm);
8525a9f8e15SFrank Chang    data = FIELD_DP32(data, VDATA, LMUL, emul);
853139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, NF, a->nf);
854752614caSeopXD    data = FIELD_DP32(data, VDATA, VTA, s->vta);
855265ecd4cSYueh-Ting (eop) Chen    data = FIELD_DP32(data, VDATA, VMA, s->vma);
856a506c428SDaniel Henrique Barboza    return ldst_stride_trans(a->rd, a->rs1, a->rs2, data, fn, s);
857139c1837SPaolo Bonzini}
858139c1837SPaolo Bonzini
85979556fb6SFrank Changstatic bool ld_stride_check(DisasContext *s, arg_rnfvm* a, uint8_t eew)
860139c1837SPaolo Bonzini{
86179556fb6SFrank Chang    return require_rvv(s) &&
86279556fb6SFrank Chang           vext_check_isa_ill(s) &&
86379556fb6SFrank Chang           vext_check_load(s, a->rd, a->nf, a->vm, eew);
864139c1837SPaolo Bonzini}
865139c1837SPaolo Bonzini
86679556fb6SFrank ChangGEN_VEXT_TRANS(vlse8_v,  MO_8,  rnfvm, ld_stride_op, ld_stride_check)
86779556fb6SFrank ChangGEN_VEXT_TRANS(vlse16_v, MO_16, rnfvm, ld_stride_op, ld_stride_check)
86879556fb6SFrank ChangGEN_VEXT_TRANS(vlse32_v, MO_32, rnfvm, ld_stride_op, ld_stride_check)
86979556fb6SFrank ChangGEN_VEXT_TRANS(vlse64_v, MO_64, rnfvm, ld_stride_op, ld_stride_check)
870139c1837SPaolo Bonzini
87179556fb6SFrank Changstatic bool st_stride_op(DisasContext *s, arg_rnfvm *a, uint8_t eew)
872139c1837SPaolo Bonzini{
873139c1837SPaolo Bonzini    uint32_t data = 0;
874139c1837SPaolo Bonzini    gen_helper_ldst_stride *fn;
87579556fb6SFrank Chang    static gen_helper_ldst_stride * const fns[4] = {
876139c1837SPaolo Bonzini        /* masked stride store */
87779556fb6SFrank Chang        gen_helper_vsse8_v,  gen_helper_vsse16_v,
87879556fb6SFrank Chang        gen_helper_vsse32_v,  gen_helper_vsse64_v
879139c1837SPaolo Bonzini    };
880139c1837SPaolo Bonzini
8815a9f8e15SFrank Chang    uint8_t emul = vext_get_emul(s, eew);
882139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, VM, a->vm);
8835a9f8e15SFrank Chang    data = FIELD_DP32(data, VDATA, LMUL, emul);
884139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, NF, a->nf);
88579556fb6SFrank Chang    fn = fns[eew];
886139c1837SPaolo Bonzini    if (fn == NULL) {
887139c1837SPaolo Bonzini        return false;
888139c1837SPaolo Bonzini    }
889139c1837SPaolo Bonzini
890a506c428SDaniel Henrique Barboza    return ldst_stride_trans(a->rd, a->rs1, a->rs2, data, fn, s);
891139c1837SPaolo Bonzini}
892139c1837SPaolo Bonzini
89379556fb6SFrank Changstatic bool st_stride_check(DisasContext *s, arg_rnfvm* a, uint8_t eew)
894139c1837SPaolo Bonzini{
89579556fb6SFrank Chang    return require_rvv(s) &&
89679556fb6SFrank Chang           vext_check_isa_ill(s) &&
89779556fb6SFrank Chang           vext_check_store(s, a->rd, a->nf, eew);
898139c1837SPaolo Bonzini}
899139c1837SPaolo Bonzini
90079556fb6SFrank ChangGEN_VEXT_TRANS(vsse8_v,  MO_8,  rnfvm, st_stride_op, st_stride_check)
90179556fb6SFrank ChangGEN_VEXT_TRANS(vsse16_v, MO_16, rnfvm, st_stride_op, st_stride_check)
90279556fb6SFrank ChangGEN_VEXT_TRANS(vsse32_v, MO_32, rnfvm, st_stride_op, st_stride_check)
90379556fb6SFrank ChangGEN_VEXT_TRANS(vsse64_v, MO_64, rnfvm, st_stride_op, st_stride_check)
904139c1837SPaolo Bonzini
905139c1837SPaolo Bonzini/*
906139c1837SPaolo Bonzini *** index load and store
907139c1837SPaolo Bonzini */
908139c1837SPaolo Bonzinitypedef void gen_helper_ldst_index(TCGv_ptr, TCGv_ptr, TCGv,
909139c1837SPaolo Bonzini                                   TCGv_ptr, TCGv_env, TCGv_i32);
910139c1837SPaolo Bonzini
911139c1837SPaolo Bonzinistatic bool ldst_index_trans(uint32_t vd, uint32_t rs1, uint32_t vs2,
912139c1837SPaolo Bonzini                             uint32_t data, gen_helper_ldst_index *fn,
913a506c428SDaniel Henrique Barboza                             DisasContext *s)
914139c1837SPaolo Bonzini{
915139c1837SPaolo Bonzini    TCGv_ptr dest, mask, index;
916139c1837SPaolo Bonzini    TCGv base;
917139c1837SPaolo Bonzini    TCGv_i32 desc;
918139c1837SPaolo Bonzini
919139c1837SPaolo Bonzini    dest = tcg_temp_new_ptr();
920139c1837SPaolo Bonzini    mask = tcg_temp_new_ptr();
921139c1837SPaolo Bonzini    index = tcg_temp_new_ptr();
9228e034ae4SRichard Henderson    base = get_gpr(s, rs1, EXT_NONE);
92381b9ef99SDaniel Henrique Barboza    desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlenb,
92481b9ef99SDaniel Henrique Barboza                                      s->cfg_ptr->vlenb, data));
925139c1837SPaolo Bonzini
926ad75a51eSRichard Henderson    tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, vd));
927ad75a51eSRichard Henderson    tcg_gen_addi_ptr(index, tcg_env, vreg_ofs(s, vs2));
928ad75a51eSRichard Henderson    tcg_gen_addi_ptr(mask, tcg_env, vreg_ofs(s, 0));
929139c1837SPaolo Bonzini
9308e1ee1fbSFrank Chang    mark_vs_dirty(s);
931944b6dfdSDaniel Henrique Barboza
932944b6dfdSDaniel Henrique Barboza    fn(dest, mask, base, index, tcg_env, desc);
9338e1ee1fbSFrank Chang
934bac802adSIvan Klokov    finalize_rvv_inst(s);
935139c1837SPaolo Bonzini    return true;
936139c1837SPaolo Bonzini}
937139c1837SPaolo Bonzini
93808b9d0edSFrank Changstatic bool ld_index_op(DisasContext *s, arg_rnfvm *a, uint8_t eew)
939139c1837SPaolo Bonzini{
940139c1837SPaolo Bonzini    uint32_t data = 0;
941139c1837SPaolo Bonzini    gen_helper_ldst_index *fn;
94208b9d0edSFrank Chang    static gen_helper_ldst_index * const fns[4][4] = {
94308b9d0edSFrank Chang        /*
94408b9d0edSFrank Chang         * offset vector register group EEW = 8,
94508b9d0edSFrank Chang         * data vector register group EEW = SEW
94608b9d0edSFrank Chang         */
94708b9d0edSFrank Chang        { gen_helper_vlxei8_8_v,  gen_helper_vlxei8_16_v,
94808b9d0edSFrank Chang          gen_helper_vlxei8_32_v, gen_helper_vlxei8_64_v },
94908b9d0edSFrank Chang        /*
95008b9d0edSFrank Chang         * offset vector register group EEW = 16,
95108b9d0edSFrank Chang         * data vector register group EEW = SEW
95208b9d0edSFrank Chang         */
95308b9d0edSFrank Chang        { gen_helper_vlxei16_8_v, gen_helper_vlxei16_16_v,
95408b9d0edSFrank Chang          gen_helper_vlxei16_32_v, gen_helper_vlxei16_64_v },
95508b9d0edSFrank Chang        /*
95608b9d0edSFrank Chang         * offset vector register group EEW = 32,
95708b9d0edSFrank Chang         * data vector register group EEW = SEW
95808b9d0edSFrank Chang         */
95908b9d0edSFrank Chang        { gen_helper_vlxei32_8_v, gen_helper_vlxei32_16_v,
96008b9d0edSFrank Chang          gen_helper_vlxei32_32_v, gen_helper_vlxei32_64_v },
96108b9d0edSFrank Chang        /*
96208b9d0edSFrank Chang         * offset vector register group EEW = 64,
96308b9d0edSFrank Chang         * data vector register group EEW = SEW
96408b9d0edSFrank Chang         */
96508b9d0edSFrank Chang        { gen_helper_vlxei64_8_v, gen_helper_vlxei64_16_v,
96608b9d0edSFrank Chang          gen_helper_vlxei64_32_v, gen_helper_vlxei64_64_v }
967139c1837SPaolo Bonzini    };
968139c1837SPaolo Bonzini
96908b9d0edSFrank Chang    fn = fns[eew][s->sew];
970139c1837SPaolo Bonzini
9715a9f8e15SFrank Chang    uint8_t emul = vext_get_emul(s, s->sew);
972139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, VM, a->vm);
9735a9f8e15SFrank Chang    data = FIELD_DP32(data, VDATA, LMUL, emul);
974139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, NF, a->nf);
975752614caSeopXD    data = FIELD_DP32(data, VDATA, VTA, s->vta);
976265ecd4cSYueh-Ting (eop) Chen    data = FIELD_DP32(data, VDATA, VMA, s->vma);
977a506c428SDaniel Henrique Barboza    return ldst_index_trans(a->rd, a->rs1, a->rs2, data, fn, s);
978139c1837SPaolo Bonzini}
979139c1837SPaolo Bonzini
98079556fb6SFrank Changstatic bool ld_index_check(DisasContext *s, arg_rnfvm* a, uint8_t eew)
981139c1837SPaolo Bonzini{
98279556fb6SFrank Chang    return require_rvv(s) &&
98379556fb6SFrank Chang           vext_check_isa_ill(s) &&
98479556fb6SFrank Chang           vext_check_ld_index(s, a->rd, a->rs2, a->nf, a->vm, eew);
985139c1837SPaolo Bonzini}
986139c1837SPaolo Bonzini
98708b9d0edSFrank ChangGEN_VEXT_TRANS(vlxei8_v,  MO_8,  rnfvm, ld_index_op, ld_index_check)
98808b9d0edSFrank ChangGEN_VEXT_TRANS(vlxei16_v, MO_16, rnfvm, ld_index_op, ld_index_check)
98908b9d0edSFrank ChangGEN_VEXT_TRANS(vlxei32_v, MO_32, rnfvm, ld_index_op, ld_index_check)
99008b9d0edSFrank ChangGEN_VEXT_TRANS(vlxei64_v, MO_64, rnfvm, ld_index_op, ld_index_check)
991139c1837SPaolo Bonzini
99208b9d0edSFrank Changstatic bool st_index_op(DisasContext *s, arg_rnfvm *a, uint8_t eew)
993139c1837SPaolo Bonzini{
994139c1837SPaolo Bonzini    uint32_t data = 0;
995139c1837SPaolo Bonzini    gen_helper_ldst_index *fn;
996139c1837SPaolo Bonzini    static gen_helper_ldst_index * const fns[4][4] = {
99708b9d0edSFrank Chang        /*
99808b9d0edSFrank Chang         * offset vector register group EEW = 8,
99908b9d0edSFrank Chang         * data vector register group EEW = SEW
100008b9d0edSFrank Chang         */
100108b9d0edSFrank Chang        { gen_helper_vsxei8_8_v,  gen_helper_vsxei8_16_v,
100208b9d0edSFrank Chang          gen_helper_vsxei8_32_v, gen_helper_vsxei8_64_v },
100308b9d0edSFrank Chang        /*
100408b9d0edSFrank Chang         * offset vector register group EEW = 16,
100508b9d0edSFrank Chang         * data vector register group EEW = SEW
100608b9d0edSFrank Chang         */
100708b9d0edSFrank Chang        { gen_helper_vsxei16_8_v, gen_helper_vsxei16_16_v,
100808b9d0edSFrank Chang          gen_helper_vsxei16_32_v, gen_helper_vsxei16_64_v },
100908b9d0edSFrank Chang        /*
101008b9d0edSFrank Chang         * offset vector register group EEW = 32,
101108b9d0edSFrank Chang         * data vector register group EEW = SEW
101208b9d0edSFrank Chang         */
101308b9d0edSFrank Chang        { gen_helper_vsxei32_8_v, gen_helper_vsxei32_16_v,
101408b9d0edSFrank Chang          gen_helper_vsxei32_32_v, gen_helper_vsxei32_64_v },
101508b9d0edSFrank Chang        /*
101608b9d0edSFrank Chang         * offset vector register group EEW = 64,
101708b9d0edSFrank Chang         * data vector register group EEW = SEW
101808b9d0edSFrank Chang         */
101908b9d0edSFrank Chang        { gen_helper_vsxei64_8_v, gen_helper_vsxei64_16_v,
102008b9d0edSFrank Chang          gen_helper_vsxei64_32_v, gen_helper_vsxei64_64_v }
1021139c1837SPaolo Bonzini    };
1022139c1837SPaolo Bonzini
102308b9d0edSFrank Chang    fn = fns[eew][s->sew];
1024139c1837SPaolo Bonzini
10255a9f8e15SFrank Chang    uint8_t emul = vext_get_emul(s, s->sew);
1026139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, VM, a->vm);
10275a9f8e15SFrank Chang    data = FIELD_DP32(data, VDATA, LMUL, emul);
1028139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, NF, a->nf);
1029a506c428SDaniel Henrique Barboza    return ldst_index_trans(a->rd, a->rs1, a->rs2, data, fn, s);
1030139c1837SPaolo Bonzini}
1031139c1837SPaolo Bonzini
103279556fb6SFrank Changstatic bool st_index_check(DisasContext *s, arg_rnfvm* a, uint8_t eew)
1033139c1837SPaolo Bonzini{
103479556fb6SFrank Chang    return require_rvv(s) &&
103579556fb6SFrank Chang           vext_check_isa_ill(s) &&
103679556fb6SFrank Chang           vext_check_st_index(s, a->rd, a->rs2, a->nf, eew);
1037139c1837SPaolo Bonzini}
1038139c1837SPaolo Bonzini
103908b9d0edSFrank ChangGEN_VEXT_TRANS(vsxei8_v,  MO_8,  rnfvm, st_index_op, st_index_check)
104008b9d0edSFrank ChangGEN_VEXT_TRANS(vsxei16_v, MO_16, rnfvm, st_index_op, st_index_check)
104108b9d0edSFrank ChangGEN_VEXT_TRANS(vsxei32_v, MO_32, rnfvm, st_index_op, st_index_check)
104208b9d0edSFrank ChangGEN_VEXT_TRANS(vsxei64_v, MO_64, rnfvm, st_index_op, st_index_check)
1043139c1837SPaolo Bonzini
1044139c1837SPaolo Bonzini/*
1045139c1837SPaolo Bonzini *** unit stride fault-only-first load
1046139c1837SPaolo Bonzini */
1047139c1837SPaolo Bonzinistatic bool ldff_trans(uint32_t vd, uint32_t rs1, uint32_t data,
1048139c1837SPaolo Bonzini                       gen_helper_ldst_us *fn, DisasContext *s)
1049139c1837SPaolo Bonzini{
1050139c1837SPaolo Bonzini    TCGv_ptr dest, mask;
1051139c1837SPaolo Bonzini    TCGv base;
1052139c1837SPaolo Bonzini    TCGv_i32 desc;
1053139c1837SPaolo Bonzini
1054139c1837SPaolo Bonzini    dest = tcg_temp_new_ptr();
1055139c1837SPaolo Bonzini    mask = tcg_temp_new_ptr();
10568e034ae4SRichard Henderson    base = get_gpr(s, rs1, EXT_NONE);
105781b9ef99SDaniel Henrique Barboza    desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlenb,
105881b9ef99SDaniel Henrique Barboza                                      s->cfg_ptr->vlenb, data));
1059139c1837SPaolo Bonzini
1060ad75a51eSRichard Henderson    tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, vd));
1061ad75a51eSRichard Henderson    tcg_gen_addi_ptr(mask, tcg_env, vreg_ofs(s, 0));
1062139c1837SPaolo Bonzini
1063ad75a51eSRichard Henderson    fn(dest, mask, base, tcg_env, desc);
1064139c1837SPaolo Bonzini
1065bac802adSIvan Klokov    finalize_rvv_inst(s);
1066139c1837SPaolo Bonzini    return true;
1067139c1837SPaolo Bonzini}
1068139c1837SPaolo Bonzini
1069d3e5e2ffSFrank Changstatic bool ldff_op(DisasContext *s, arg_r2nfvm *a, uint8_t eew)
1070139c1837SPaolo Bonzini{
1071139c1837SPaolo Bonzini    uint32_t data = 0;
1072139c1837SPaolo Bonzini    gen_helper_ldst_us *fn;
1073d3e5e2ffSFrank Chang    static gen_helper_ldst_us * const fns[4] = {
1074d3e5e2ffSFrank Chang        gen_helper_vle8ff_v, gen_helper_vle16ff_v,
1075d3e5e2ffSFrank Chang        gen_helper_vle32ff_v, gen_helper_vle64ff_v
1076139c1837SPaolo Bonzini    };
1077139c1837SPaolo Bonzini
1078d3e5e2ffSFrank Chang    fn = fns[eew];
1079139c1837SPaolo Bonzini    if (fn == NULL) {
1080139c1837SPaolo Bonzini        return false;
1081139c1837SPaolo Bonzini    }
1082139c1837SPaolo Bonzini
10835a9f8e15SFrank Chang    uint8_t emul = vext_get_emul(s, eew);
1084139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, VM, a->vm);
10855a9f8e15SFrank Chang    data = FIELD_DP32(data, VDATA, LMUL, emul);
1086139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, NF, a->nf);
1087752614caSeopXD    data = FIELD_DP32(data, VDATA, VTA, s->vta);
1088265ecd4cSYueh-Ting (eop) Chen    data = FIELD_DP32(data, VDATA, VMA, s->vma);
1089139c1837SPaolo Bonzini    return ldff_trans(a->rd, a->rs1, data, fn, s);
1090139c1837SPaolo Bonzini}
1091139c1837SPaolo Bonzini
1092d3e5e2ffSFrank ChangGEN_VEXT_TRANS(vle8ff_v,  MO_8,  r2nfvm, ldff_op, ld_us_check)
1093d3e5e2ffSFrank ChangGEN_VEXT_TRANS(vle16ff_v, MO_16, r2nfvm, ldff_op, ld_us_check)
1094d3e5e2ffSFrank ChangGEN_VEXT_TRANS(vle32ff_v, MO_32, r2nfvm, ldff_op, ld_us_check)
1095d3e5e2ffSFrank ChangGEN_VEXT_TRANS(vle64ff_v, MO_64, r2nfvm, ldff_op, ld_us_check)
1096139c1837SPaolo Bonzini
1097139c1837SPaolo Bonzini/*
109830206bd8SFrank Chang * load and store whole register instructions
109930206bd8SFrank Chang */
110030206bd8SFrank Changtypedef void gen_helper_ldst_whole(TCGv_ptr, TCGv, TCGv_env, TCGv_i32);
110130206bd8SFrank Chang
110230206bd8SFrank Changstatic bool ldst_whole_trans(uint32_t vd, uint32_t rs1, uint32_t nf,
1103929e521aSDaniel Henrique Barboza                             gen_helper_ldst_whole *fn,
1104a506c428SDaniel Henrique Barboza                             DisasContext *s)
110530206bd8SFrank Chang{
110630206bd8SFrank Chang    TCGv_ptr dest;
110730206bd8SFrank Chang    TCGv base;
110830206bd8SFrank Chang    TCGv_i32 desc;
110930206bd8SFrank Chang
111030206bd8SFrank Chang    uint32_t data = FIELD_DP32(0, VDATA, NF, nf);
1111*b48381b1SMax Chou    data = FIELD_DP32(data, VDATA, VM, 1);
111230206bd8SFrank Chang    dest = tcg_temp_new_ptr();
111381b9ef99SDaniel Henrique Barboza    desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlenb,
111481b9ef99SDaniel Henrique Barboza                                      s->cfg_ptr->vlenb, data));
111530206bd8SFrank Chang
111630206bd8SFrank Chang    base = get_gpr(s, rs1, EXT_NONE);
1117ad75a51eSRichard Henderson    tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, vd));
111830206bd8SFrank Chang
1119944b6dfdSDaniel Henrique Barboza    mark_vs_dirty(s);
1120944b6dfdSDaniel Henrique Barboza
1121ad75a51eSRichard Henderson    fn(dest, base, tcg_env, desc);
112230206bd8SFrank Chang
1123bac802adSIvan Klokov    finalize_rvv_inst(s);
112430206bd8SFrank Chang    return true;
112530206bd8SFrank Chang}
112630206bd8SFrank Chang
112730206bd8SFrank Chang/*
112830206bd8SFrank Chang * load and store whole register instructions ignore vtype and vl setting.
112930206bd8SFrank Chang * Thus, we don't need to check vill bit. (Section 7.9)
113030206bd8SFrank Chang */
1131929e521aSDaniel Henrique Barboza#define GEN_LDST_WHOLE_TRANS(NAME, ARG_NF)                                \
113230206bd8SFrank Changstatic bool trans_##NAME(DisasContext *s, arg_##NAME * a)                 \
113330206bd8SFrank Chang{                                                                         \
113430206bd8SFrank Chang    if (require_rvv(s) &&                                                 \
113530206bd8SFrank Chang        QEMU_IS_ALIGNED(a->rd, ARG_NF)) {                                 \
1136929e521aSDaniel Henrique Barboza        return ldst_whole_trans(a->rd, a->rs1, ARG_NF,                    \
1137a506c428SDaniel Henrique Barboza                                gen_helper_##NAME, s);                    \
113830206bd8SFrank Chang    }                                                                     \
113930206bd8SFrank Chang    return false;                                                         \
114030206bd8SFrank Chang}
114130206bd8SFrank Chang
1142929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vl1re8_v,  1)
1143929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vl1re16_v, 1)
1144929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vl1re32_v, 1)
1145929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vl1re64_v, 1)
1146929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vl2re8_v,  2)
1147929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vl2re16_v, 2)
1148929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vl2re32_v, 2)
1149929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vl2re64_v, 2)
1150929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vl4re8_v,  4)
1151929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vl4re16_v, 4)
1152929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vl4re32_v, 4)
1153929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vl4re64_v, 4)
1154929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vl8re8_v,  8)
1155929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vl8re16_v, 8)
1156929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vl8re32_v, 8)
1157929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vl8re64_v, 8)
115830206bd8SFrank Chang
115902b51198SeopXD/*
116002b51198SeopXD * The vector whole register store instructions are encoded similar to
116102b51198SeopXD * unmasked unit-stride store of elements with EEW=8.
116202b51198SeopXD */
1163929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vs1r_v, 1)
1164929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vs2r_v, 2)
1165929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vs4r_v, 4)
1166929e521aSDaniel Henrique BarbozaGEN_LDST_WHOLE_TRANS(vs8r_v, 8)
116730206bd8SFrank Chang
116830206bd8SFrank Chang/*
1169139c1837SPaolo Bonzini *** Vector Integer Arithmetic Instructions
1170139c1837SPaolo Bonzini */
1171a689a82bSFrank Chang
1172a689a82bSFrank Chang/*
1173a689a82bSFrank Chang * MAXSZ returns the maximum vector size can be operated in bytes,
1174a689a82bSFrank Chang * which is used in GVEC IR when vl_eq_vlmax flag is set to true
1175bd2c8228SDaniel Henrique Barboza * to accelerate vector operation.
1176a689a82bSFrank Chang */
1177a689a82bSFrank Changstatic inline uint32_t MAXSZ(DisasContext *s)
1178a689a82bSFrank Chang{
1179bd2c8228SDaniel Henrique Barboza    int max_sz = s->cfg_ptr->vlenb * 8;
1180bd2c8228SDaniel Henrique Barboza    return max_sz >> (3 - s->lmul);
1181a689a82bSFrank Chang}
1182139c1837SPaolo Bonzini
1183139c1837SPaolo Bonzinistatic bool opivv_check(DisasContext *s, arg_rmrr *a)
1184139c1837SPaolo Bonzini{
1185f31dacd7SFrank Chang    return require_rvv(s) &&
1186f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
1187f31dacd7SFrank Chang           vext_check_sss(s, a->rd, a->rs1, a->rs2, a->vm);
1188139c1837SPaolo Bonzini}
1189139c1837SPaolo Bonzini
1190139c1837SPaolo Bonzinitypedef void GVecGen3Fn(unsigned, uint32_t, uint32_t,
1191139c1837SPaolo Bonzini                        uint32_t, uint32_t, uint32_t);
1192139c1837SPaolo Bonzini
1193139c1837SPaolo Bonzinistatic inline bool
1194139c1837SPaolo Bonzinido_opivv_gvec(DisasContext *s, arg_rmrr *a, GVecGen3Fn *gvec_fn,
1195139c1837SPaolo Bonzini              gen_helper_gvec_4_ptr *fn)
1196139c1837SPaolo Bonzini{
1197f1eed927SeopXD    if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
1198139c1837SPaolo Bonzini        gvec_fn(s->sew, vreg_ofs(s, a->rd),
1199139c1837SPaolo Bonzini                vreg_ofs(s, a->rs2), vreg_ofs(s, a->rs1),
1200139c1837SPaolo Bonzini                MAXSZ(s), MAXSZ(s));
1201139c1837SPaolo Bonzini    } else {
1202139c1837SPaolo Bonzini        uint32_t data = 0;
1203139c1837SPaolo Bonzini
1204139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, VM, a->vm);
1205139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
1206f1eed927SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);
1207355d5584SYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);
1208139c1837SPaolo Bonzini        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
1209139c1837SPaolo Bonzini                           vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2),
121081b9ef99SDaniel Henrique Barboza                           tcg_env, s->cfg_ptr->vlenb,
121181b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb, data, fn);
1212139c1837SPaolo Bonzini    }
1213bac802adSIvan Klokov    finalize_rvv_inst(s);
1214139c1837SPaolo Bonzini    return true;
1215139c1837SPaolo Bonzini}
1216139c1837SPaolo Bonzini
1217139c1837SPaolo Bonzini/* OPIVV with GVEC IR */
1218139c1837SPaolo Bonzini#define GEN_OPIVV_GVEC_TRANS(NAME, SUF) \
1219139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
1220139c1837SPaolo Bonzini{                                                                  \
1221139c1837SPaolo Bonzini    static gen_helper_gvec_4_ptr * const fns[4] = {                \
1222139c1837SPaolo Bonzini        gen_helper_##NAME##_b, gen_helper_##NAME##_h,              \
1223139c1837SPaolo Bonzini        gen_helper_##NAME##_w, gen_helper_##NAME##_d,              \
1224139c1837SPaolo Bonzini    };                                                             \
12251ac7a501SNazar Kazakov    if (!opivv_check(s, a)) {                                      \
12261ac7a501SNazar Kazakov        return false;                                              \
12271ac7a501SNazar Kazakov    }                                                              \
1228139c1837SPaolo Bonzini    return do_opivv_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]);   \
1229139c1837SPaolo Bonzini}
1230139c1837SPaolo Bonzini
1231139c1837SPaolo BonziniGEN_OPIVV_GVEC_TRANS(vadd_vv, add)
1232139c1837SPaolo BonziniGEN_OPIVV_GVEC_TRANS(vsub_vv, sub)
1233139c1837SPaolo Bonzini
1234139c1837SPaolo Bonzinitypedef void gen_helper_opivx(TCGv_ptr, TCGv_ptr, TCGv, TCGv_ptr,
1235139c1837SPaolo Bonzini                              TCGv_env, TCGv_i32);
1236139c1837SPaolo Bonzini
1237139c1837SPaolo Bonzinistatic bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm,
1238139c1837SPaolo Bonzini                        gen_helper_opivx *fn, DisasContext *s)
1239139c1837SPaolo Bonzini{
1240139c1837SPaolo Bonzini    TCGv_ptr dest, src2, mask;
1241139c1837SPaolo Bonzini    TCGv src1;
1242139c1837SPaolo Bonzini    TCGv_i32 desc;
1243139c1837SPaolo Bonzini    uint32_t data = 0;
1244139c1837SPaolo Bonzini
1245139c1837SPaolo Bonzini    dest = tcg_temp_new_ptr();
1246139c1837SPaolo Bonzini    mask = tcg_temp_new_ptr();
1247139c1837SPaolo Bonzini    src2 = tcg_temp_new_ptr();
1248d8c40c24SLIU Zhiwei    src1 = get_gpr(s, rs1, EXT_SIGN);
1249139c1837SPaolo Bonzini
1250139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, VM, vm);
1251139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
12525c19fc15SeopXD    data = FIELD_DP32(data, VDATA, VTA, s->vta);
12535c19fc15SeopXD    data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
1254bce9a636SYueh-Ting (eop) Chen    data = FIELD_DP32(data, VDATA, VMA, s->vma);
125581b9ef99SDaniel Henrique Barboza    desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlenb,
125681b9ef99SDaniel Henrique Barboza                                      s->cfg_ptr->vlenb, data));
1257139c1837SPaolo Bonzini
1258ad75a51eSRichard Henderson    tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, vd));
1259ad75a51eSRichard Henderson    tcg_gen_addi_ptr(src2, tcg_env, vreg_ofs(s, vs2));
1260ad75a51eSRichard Henderson    tcg_gen_addi_ptr(mask, tcg_env, vreg_ofs(s, 0));
1261139c1837SPaolo Bonzini
1262ad75a51eSRichard Henderson    fn(dest, mask, src1, src2, tcg_env, desc);
1263139c1837SPaolo Bonzini
1264bac802adSIvan Klokov    finalize_rvv_inst(s);
1265139c1837SPaolo Bonzini    return true;
1266139c1837SPaolo Bonzini}
1267139c1837SPaolo Bonzini
1268139c1837SPaolo Bonzinistatic bool opivx_check(DisasContext *s, arg_rmrr *a)
1269139c1837SPaolo Bonzini{
1270f31dacd7SFrank Chang    return require_rvv(s) &&
1271f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
1272f31dacd7SFrank Chang           vext_check_ss(s, a->rd, a->rs2, a->vm);
1273139c1837SPaolo Bonzini}
1274139c1837SPaolo Bonzini
1275139c1837SPaolo Bonzinitypedef void GVecGen2sFn(unsigned, uint32_t, uint32_t, TCGv_i64,
1276139c1837SPaolo Bonzini                         uint32_t, uint32_t);
1277139c1837SPaolo Bonzini
1278139c1837SPaolo Bonzinistatic inline bool
1279139c1837SPaolo Bonzinido_opivx_gvec(DisasContext *s, arg_rmrr *a, GVecGen2sFn *gvec_fn,
1280139c1837SPaolo Bonzini              gen_helper_opivx *fn)
1281139c1837SPaolo Bonzini{
12825c19fc15SeopXD    if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
1283139c1837SPaolo Bonzini        TCGv_i64 src1 = tcg_temp_new_i64();
1284139c1837SPaolo Bonzini
12858e034ae4SRichard Henderson        tcg_gen_ext_tl_i64(src1, get_gpr(s, a->rs1, EXT_SIGN));
1286139c1837SPaolo Bonzini        gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2),
1287139c1837SPaolo Bonzini                src1, MAXSZ(s), MAXSZ(s));
1288139c1837SPaolo Bonzini
1289bac802adSIvan Klokov        finalize_rvv_inst(s);
1290139c1837SPaolo Bonzini        return true;
1291139c1837SPaolo Bonzini    }
1292139c1837SPaolo Bonzini    return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s);
1293139c1837SPaolo Bonzini}
1294139c1837SPaolo Bonzini
1295139c1837SPaolo Bonzini/* OPIVX with GVEC IR */
1296139c1837SPaolo Bonzini#define GEN_OPIVX_GVEC_TRANS(NAME, SUF) \
1297139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
1298139c1837SPaolo Bonzini{                                                                  \
1299139c1837SPaolo Bonzini    static gen_helper_opivx * const fns[4] = {                     \
1300139c1837SPaolo Bonzini        gen_helper_##NAME##_b, gen_helper_##NAME##_h,              \
1301139c1837SPaolo Bonzini        gen_helper_##NAME##_w, gen_helper_##NAME##_d,              \
1302139c1837SPaolo Bonzini    };                                                             \
13031ac7a501SNazar Kazakov    if (!opivx_check(s, a)) {                                      \
13041ac7a501SNazar Kazakov        return false;                                              \
13051ac7a501SNazar Kazakov    }                                                              \
1306139c1837SPaolo Bonzini    return do_opivx_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]);   \
1307139c1837SPaolo Bonzini}
1308139c1837SPaolo Bonzini
1309139c1837SPaolo BonziniGEN_OPIVX_GVEC_TRANS(vadd_vx, adds)
1310139c1837SPaolo BonziniGEN_OPIVX_GVEC_TRANS(vsub_vx, subs)
1311139c1837SPaolo Bonzini
1312139c1837SPaolo Bonzinistatic void gen_vec_rsub8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
1313139c1837SPaolo Bonzini{
1314139c1837SPaolo Bonzini    tcg_gen_vec_sub8_i64(d, b, a);
1315139c1837SPaolo Bonzini}
1316139c1837SPaolo Bonzini
1317139c1837SPaolo Bonzinistatic void gen_vec_rsub16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
1318139c1837SPaolo Bonzini{
1319139c1837SPaolo Bonzini    tcg_gen_vec_sub16_i64(d, b, a);
1320139c1837SPaolo Bonzini}
1321139c1837SPaolo Bonzini
1322139c1837SPaolo Bonzinistatic void gen_rsub_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
1323139c1837SPaolo Bonzini{
1324139c1837SPaolo Bonzini    tcg_gen_sub_i32(ret, arg2, arg1);
1325139c1837SPaolo Bonzini}
1326139c1837SPaolo Bonzini
1327139c1837SPaolo Bonzinistatic void gen_rsub_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1328139c1837SPaolo Bonzini{
1329139c1837SPaolo Bonzini    tcg_gen_sub_i64(ret, arg2, arg1);
1330139c1837SPaolo Bonzini}
1331139c1837SPaolo Bonzini
1332139c1837SPaolo Bonzinistatic void gen_rsub_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
1333139c1837SPaolo Bonzini{
1334139c1837SPaolo Bonzini    tcg_gen_sub_vec(vece, r, b, a);
1335139c1837SPaolo Bonzini}
1336139c1837SPaolo Bonzini
1337139c1837SPaolo Bonzinistatic void tcg_gen_gvec_rsubs(unsigned vece, uint32_t dofs, uint32_t aofs,
1338139c1837SPaolo Bonzini                               TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
1339139c1837SPaolo Bonzini{
1340139c1837SPaolo Bonzini    static const TCGOpcode vecop_list[] = { INDEX_op_sub_vec, 0 };
1341139c1837SPaolo Bonzini    static const GVecGen2s rsub_op[4] = {
1342139c1837SPaolo Bonzini        { .fni8 = gen_vec_rsub8_i64,
1343139c1837SPaolo Bonzini          .fniv = gen_rsub_vec,
1344139c1837SPaolo Bonzini          .fno = gen_helper_vec_rsubs8,
1345139c1837SPaolo Bonzini          .opt_opc = vecop_list,
1346139c1837SPaolo Bonzini          .vece = MO_8 },
1347139c1837SPaolo Bonzini        { .fni8 = gen_vec_rsub16_i64,
1348139c1837SPaolo Bonzini          .fniv = gen_rsub_vec,
1349139c1837SPaolo Bonzini          .fno = gen_helper_vec_rsubs16,
1350139c1837SPaolo Bonzini          .opt_opc = vecop_list,
1351139c1837SPaolo Bonzini          .vece = MO_16 },
1352139c1837SPaolo Bonzini        { .fni4 = gen_rsub_i32,
1353139c1837SPaolo Bonzini          .fniv = gen_rsub_vec,
1354139c1837SPaolo Bonzini          .fno = gen_helper_vec_rsubs32,
1355139c1837SPaolo Bonzini          .opt_opc = vecop_list,
1356139c1837SPaolo Bonzini          .vece = MO_32 },
1357139c1837SPaolo Bonzini        { .fni8 = gen_rsub_i64,
1358139c1837SPaolo Bonzini          .fniv = gen_rsub_vec,
1359139c1837SPaolo Bonzini          .fno = gen_helper_vec_rsubs64,
1360139c1837SPaolo Bonzini          .opt_opc = vecop_list,
1361139c1837SPaolo Bonzini          .prefer_i64 = TCG_TARGET_REG_BITS == 64,
1362139c1837SPaolo Bonzini          .vece = MO_64 },
1363139c1837SPaolo Bonzini    };
1364139c1837SPaolo Bonzini
1365139c1837SPaolo Bonzini    tcg_debug_assert(vece <= MO_64);
1366139c1837SPaolo Bonzini    tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, c, &rsub_op[vece]);
1367139c1837SPaolo Bonzini}
1368139c1837SPaolo Bonzini
1369139c1837SPaolo BonziniGEN_OPIVX_GVEC_TRANS(vrsub_vx, rsubs)
1370139c1837SPaolo Bonzini
1371ff64fc91SFrank Changtypedef enum {
1372ff64fc91SFrank Chang    IMM_ZX,         /* Zero-extended */
1373ff64fc91SFrank Chang    IMM_SX,         /* Sign-extended */
1374ff64fc91SFrank Chang    IMM_TRUNC_SEW,  /* Truncate to log(SEW) bits */
1375ff64fc91SFrank Chang    IMM_TRUNC_2SEW, /* Truncate to log(2*SEW) bits */
1376ff64fc91SFrank Chang} imm_mode_t;
1377ff64fc91SFrank Chang
1378ff64fc91SFrank Changstatic int64_t extract_imm(DisasContext *s, uint32_t imm, imm_mode_t imm_mode)
1379ff64fc91SFrank Chang{
1380ff64fc91SFrank Chang    switch (imm_mode) {
1381ff64fc91SFrank Chang    case IMM_ZX:
1382ff64fc91SFrank Chang        return extract64(imm, 0, 5);
1383ff64fc91SFrank Chang    case IMM_SX:
1384ff64fc91SFrank Chang        return sextract64(imm, 0, 5);
1385ff64fc91SFrank Chang    case IMM_TRUNC_SEW:
1386ff64fc91SFrank Chang        return extract64(imm, 0, s->sew + 3);
1387ff64fc91SFrank Chang    case IMM_TRUNC_2SEW:
1388ff64fc91SFrank Chang        return extract64(imm, 0, s->sew + 4);
1389ff64fc91SFrank Chang    default:
1390ff64fc91SFrank Chang        g_assert_not_reached();
1391ff64fc91SFrank Chang    }
1392ff64fc91SFrank Chang}
1393ff64fc91SFrank Chang
1394139c1837SPaolo Bonzinistatic bool opivi_trans(uint32_t vd, uint32_t imm, uint32_t vs2, uint32_t vm,
1395ff64fc91SFrank Chang                        gen_helper_opivx *fn, DisasContext *s,
1396ff64fc91SFrank Chang                        imm_mode_t imm_mode)
1397139c1837SPaolo Bonzini{
1398139c1837SPaolo Bonzini    TCGv_ptr dest, src2, mask;
1399139c1837SPaolo Bonzini    TCGv src1;
1400139c1837SPaolo Bonzini    TCGv_i32 desc;
1401139c1837SPaolo Bonzini    uint32_t data = 0;
1402139c1837SPaolo Bonzini
1403139c1837SPaolo Bonzini    dest = tcg_temp_new_ptr();
1404139c1837SPaolo Bonzini    mask = tcg_temp_new_ptr();
1405139c1837SPaolo Bonzini    src2 = tcg_temp_new_ptr();
1406ff64fc91SFrank Chang    src1 = tcg_constant_tl(extract_imm(s, imm, imm_mode));
1407ff64fc91SFrank Chang
1408139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, VM, vm);
1409139c1837SPaolo Bonzini    data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
14105c19fc15SeopXD    data = FIELD_DP32(data, VDATA, VTA, s->vta);
14115c19fc15SeopXD    data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
1412bce9a636SYueh-Ting (eop) Chen    data = FIELD_DP32(data, VDATA, VMA, s->vma);
141381b9ef99SDaniel Henrique Barboza    desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlenb,
141481b9ef99SDaniel Henrique Barboza                                      s->cfg_ptr->vlenb, data));
1415139c1837SPaolo Bonzini
1416ad75a51eSRichard Henderson    tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, vd));
1417ad75a51eSRichard Henderson    tcg_gen_addi_ptr(src2, tcg_env, vreg_ofs(s, vs2));
1418ad75a51eSRichard Henderson    tcg_gen_addi_ptr(mask, tcg_env, vreg_ofs(s, 0));
1419139c1837SPaolo Bonzini
1420ad75a51eSRichard Henderson    fn(dest, mask, src1, src2, tcg_env, desc);
1421139c1837SPaolo Bonzini
1422bac802adSIvan Klokov    finalize_rvv_inst(s);
1423139c1837SPaolo Bonzini    return true;
1424139c1837SPaolo Bonzini}
1425139c1837SPaolo Bonzini
1426139c1837SPaolo Bonzinitypedef void GVecGen2iFn(unsigned, uint32_t, uint32_t, int64_t,
1427139c1837SPaolo Bonzini                         uint32_t, uint32_t);
1428139c1837SPaolo Bonzini
1429139c1837SPaolo Bonzinistatic inline bool
1430139c1837SPaolo Bonzinido_opivi_gvec(DisasContext *s, arg_rmrr *a, GVecGen2iFn *gvec_fn,
1431ff64fc91SFrank Chang              gen_helper_opivx *fn, imm_mode_t imm_mode)
1432139c1837SPaolo Bonzini{
14335c19fc15SeopXD    if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
1434139c1837SPaolo Bonzini        gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2),
1435ff64fc91SFrank Chang                extract_imm(s, a->rs1, imm_mode), MAXSZ(s), MAXSZ(s));
1436bac802adSIvan Klokov        finalize_rvv_inst(s);
1437139c1837SPaolo Bonzini        return true;
1438139c1837SPaolo Bonzini    }
1439ff64fc91SFrank Chang    return opivi_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s, imm_mode);
14408e1ee1fbSFrank Chang}
1441139c1837SPaolo Bonzini
1442139c1837SPaolo Bonzini/* OPIVI with GVEC IR */
1443ff64fc91SFrank Chang#define GEN_OPIVI_GVEC_TRANS(NAME, IMM_MODE, OPIVX, SUF) \
1444139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
1445139c1837SPaolo Bonzini{                                                                  \
1446139c1837SPaolo Bonzini    static gen_helper_opivx * const fns[4] = {                     \
1447139c1837SPaolo Bonzini        gen_helper_##OPIVX##_b, gen_helper_##OPIVX##_h,            \
1448139c1837SPaolo Bonzini        gen_helper_##OPIVX##_w, gen_helper_##OPIVX##_d,            \
1449139c1837SPaolo Bonzini    };                                                             \
14501ac7a501SNazar Kazakov    if (!opivx_check(s, a)) {                                      \
14511ac7a501SNazar Kazakov        return false;                                              \
14521ac7a501SNazar Kazakov    }                                                              \
1453139c1837SPaolo Bonzini    return do_opivi_gvec(s, a, tcg_gen_gvec_##SUF,                 \
1454ff64fc91SFrank Chang                         fns[s->sew], IMM_MODE);                   \
1455139c1837SPaolo Bonzini}
1456139c1837SPaolo Bonzini
1457ff64fc91SFrank ChangGEN_OPIVI_GVEC_TRANS(vadd_vi, IMM_SX, vadd_vx, addi)
1458139c1837SPaolo Bonzini
1459139c1837SPaolo Bonzinistatic void tcg_gen_gvec_rsubi(unsigned vece, uint32_t dofs, uint32_t aofs,
1460139c1837SPaolo Bonzini                               int64_t c, uint32_t oprsz, uint32_t maxsz)
1461139c1837SPaolo Bonzini{
146205b80ed0SRichard Henderson    TCGv_i64 tmp = tcg_constant_i64(c);
1463139c1837SPaolo Bonzini    tcg_gen_gvec_rsubs(vece, dofs, aofs, tmp, oprsz, maxsz);
1464139c1837SPaolo Bonzini}
1465139c1837SPaolo Bonzini
1466ff64fc91SFrank ChangGEN_OPIVI_GVEC_TRANS(vrsub_vi, IMM_SX, vrsub_vx, rsubi)
1467139c1837SPaolo Bonzini
1468139c1837SPaolo Bonzini/* Vector Widening Integer Add/Subtract */
1469139c1837SPaolo Bonzini
1470139c1837SPaolo Bonzini/* OPIVV with WIDEN */
1471139c1837SPaolo Bonzinistatic bool opivv_widen_check(DisasContext *s, arg_rmrr *a)
1472139c1837SPaolo Bonzini{
1473f31dacd7SFrank Chang    return require_rvv(s) &&
1474f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
1475f31dacd7SFrank Chang           vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm);
1476139c1837SPaolo Bonzini}
1477139c1837SPaolo Bonzini
1478139c1837SPaolo Bonzinistatic bool do_opivv_widen(DisasContext *s, arg_rmrr *a,
1479139c1837SPaolo Bonzini                           gen_helper_gvec_4_ptr *fn,
1480139c1837SPaolo Bonzini                           bool (*checkfn)(DisasContext *, arg_rmrr *))
1481139c1837SPaolo Bonzini{
1482139c1837SPaolo Bonzini    if (checkfn(s, a)) {
1483139c1837SPaolo Bonzini        uint32_t data = 0;
1484139c1837SPaolo Bonzini
1485139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, VM, a->vm);
1486139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
14875c19fc15SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);
1488355d5584SYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);
1489139c1837SPaolo Bonzini        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
1490139c1837SPaolo Bonzini                           vreg_ofs(s, a->rs1),
1491139c1837SPaolo Bonzini                           vreg_ofs(s, a->rs2),
149281b9ef99SDaniel Henrique Barboza                           tcg_env, s->cfg_ptr->vlenb,
149381b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb,
1494139c1837SPaolo Bonzini                           data, fn);
1495bac802adSIvan Klokov        finalize_rvv_inst(s);
1496139c1837SPaolo Bonzini        return true;
1497139c1837SPaolo Bonzini    }
1498139c1837SPaolo Bonzini    return false;
1499139c1837SPaolo Bonzini}
1500139c1837SPaolo Bonzini
1501139c1837SPaolo Bonzini#define GEN_OPIVV_WIDEN_TRANS(NAME, CHECK) \
1502139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)       \
1503139c1837SPaolo Bonzini{                                                            \
1504139c1837SPaolo Bonzini    static gen_helper_gvec_4_ptr * const fns[3] = {          \
1505139c1837SPaolo Bonzini        gen_helper_##NAME##_b,                               \
1506139c1837SPaolo Bonzini        gen_helper_##NAME##_h,                               \
1507139c1837SPaolo Bonzini        gen_helper_##NAME##_w                                \
1508139c1837SPaolo Bonzini    };                                                       \
1509139c1837SPaolo Bonzini    return do_opivv_widen(s, a, fns[s->sew], CHECK);         \
1510139c1837SPaolo Bonzini}
1511139c1837SPaolo Bonzini
1512139c1837SPaolo BonziniGEN_OPIVV_WIDEN_TRANS(vwaddu_vv, opivv_widen_check)
1513139c1837SPaolo BonziniGEN_OPIVV_WIDEN_TRANS(vwadd_vv, opivv_widen_check)
1514139c1837SPaolo BonziniGEN_OPIVV_WIDEN_TRANS(vwsubu_vv, opivv_widen_check)
1515139c1837SPaolo BonziniGEN_OPIVV_WIDEN_TRANS(vwsub_vv, opivv_widen_check)
1516139c1837SPaolo Bonzini
1517139c1837SPaolo Bonzini/* OPIVX with WIDEN */
1518139c1837SPaolo Bonzinistatic bool opivx_widen_check(DisasContext *s, arg_rmrr *a)
1519139c1837SPaolo Bonzini{
1520f31dacd7SFrank Chang    return require_rvv(s) &&
1521f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
1522f31dacd7SFrank Chang           vext_check_ds(s, a->rd, a->rs2, a->vm);
1523139c1837SPaolo Bonzini}
1524139c1837SPaolo Bonzini
152562cb3e8eSDickon Hood#define GEN_OPIVX_WIDEN_TRANS(NAME, CHECK) \
1526139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)                    \
1527139c1837SPaolo Bonzini{                                                                         \
152862cb3e8eSDickon Hood    if (CHECK(s, a)) {                                                    \
1529139c1837SPaolo Bonzini        static gen_helper_opivx * const fns[3] = {                        \
1530139c1837SPaolo Bonzini            gen_helper_##NAME##_b,                                        \
1531139c1837SPaolo Bonzini            gen_helper_##NAME##_h,                                        \
1532139c1837SPaolo Bonzini            gen_helper_##NAME##_w                                         \
1533139c1837SPaolo Bonzini        };                                                                \
153462cb3e8eSDickon Hood        return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s); \
153562cb3e8eSDickon Hood    }                                                                     \
153662cb3e8eSDickon Hood    return false;                                                         \
1537139c1837SPaolo Bonzini}
1538139c1837SPaolo Bonzini
153962cb3e8eSDickon HoodGEN_OPIVX_WIDEN_TRANS(vwaddu_vx, opivx_widen_check)
154062cb3e8eSDickon HoodGEN_OPIVX_WIDEN_TRANS(vwadd_vx, opivx_widen_check)
154162cb3e8eSDickon HoodGEN_OPIVX_WIDEN_TRANS(vwsubu_vx, opivx_widen_check)
154262cb3e8eSDickon HoodGEN_OPIVX_WIDEN_TRANS(vwsub_vx, opivx_widen_check)
1543139c1837SPaolo Bonzini
1544139c1837SPaolo Bonzini/* WIDEN OPIVV with WIDEN */
1545139c1837SPaolo Bonzinistatic bool opiwv_widen_check(DisasContext *s, arg_rmrr *a)
1546139c1837SPaolo Bonzini{
1547f31dacd7SFrank Chang    return require_rvv(s) &&
1548f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
1549f31dacd7SFrank Chang           vext_check_dds(s, a->rd, a->rs1, a->rs2, a->vm);
1550139c1837SPaolo Bonzini}
1551139c1837SPaolo Bonzini
1552139c1837SPaolo Bonzinistatic bool do_opiwv_widen(DisasContext *s, arg_rmrr *a,
1553139c1837SPaolo Bonzini                           gen_helper_gvec_4_ptr *fn)
1554139c1837SPaolo Bonzini{
1555139c1837SPaolo Bonzini    if (opiwv_widen_check(s, a)) {
1556139c1837SPaolo Bonzini        uint32_t data = 0;
1557139c1837SPaolo Bonzini
1558139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, VM, a->vm);
1559139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
15605c19fc15SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);
1561355d5584SYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);
1562139c1837SPaolo Bonzini        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
1563139c1837SPaolo Bonzini                           vreg_ofs(s, a->rs1),
1564139c1837SPaolo Bonzini                           vreg_ofs(s, a->rs2),
156581b9ef99SDaniel Henrique Barboza                           tcg_env, s->cfg_ptr->vlenb,
156681b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb, data, fn);
1567bac802adSIvan Klokov        finalize_rvv_inst(s);
1568139c1837SPaolo Bonzini        return true;
1569139c1837SPaolo Bonzini    }
1570139c1837SPaolo Bonzini    return false;
1571139c1837SPaolo Bonzini}
1572139c1837SPaolo Bonzini
1573139c1837SPaolo Bonzini#define GEN_OPIWV_WIDEN_TRANS(NAME) \
1574139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)       \
1575139c1837SPaolo Bonzini{                                                            \
1576139c1837SPaolo Bonzini    static gen_helper_gvec_4_ptr * const fns[3] = {          \
1577139c1837SPaolo Bonzini        gen_helper_##NAME##_b,                               \
1578139c1837SPaolo Bonzini        gen_helper_##NAME##_h,                               \
1579139c1837SPaolo Bonzini        gen_helper_##NAME##_w                                \
1580139c1837SPaolo Bonzini    };                                                       \
1581139c1837SPaolo Bonzini    return do_opiwv_widen(s, a, fns[s->sew]);                \
1582139c1837SPaolo Bonzini}
1583139c1837SPaolo Bonzini
1584139c1837SPaolo BonziniGEN_OPIWV_WIDEN_TRANS(vwaddu_wv)
1585139c1837SPaolo BonziniGEN_OPIWV_WIDEN_TRANS(vwadd_wv)
1586139c1837SPaolo BonziniGEN_OPIWV_WIDEN_TRANS(vwsubu_wv)
1587139c1837SPaolo BonziniGEN_OPIWV_WIDEN_TRANS(vwsub_wv)
1588139c1837SPaolo Bonzini
1589139c1837SPaolo Bonzini/* WIDEN OPIVX with WIDEN */
1590139c1837SPaolo Bonzinistatic bool opiwx_widen_check(DisasContext *s, arg_rmrr *a)
1591139c1837SPaolo Bonzini{
1592f31dacd7SFrank Chang    return require_rvv(s) &&
1593f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
1594f31dacd7SFrank Chang           vext_check_dd(s, a->rd, a->rs2, a->vm);
1595139c1837SPaolo Bonzini}
1596139c1837SPaolo Bonzini
1597139c1837SPaolo Bonzinistatic bool do_opiwx_widen(DisasContext *s, arg_rmrr *a,
1598139c1837SPaolo Bonzini                           gen_helper_opivx *fn)
1599139c1837SPaolo Bonzini{
1600139c1837SPaolo Bonzini    if (opiwx_widen_check(s, a)) {
1601139c1837SPaolo Bonzini        return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s);
1602139c1837SPaolo Bonzini    }
1603139c1837SPaolo Bonzini    return false;
1604139c1837SPaolo Bonzini}
1605139c1837SPaolo Bonzini
1606139c1837SPaolo Bonzini#define GEN_OPIWX_WIDEN_TRANS(NAME) \
1607139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)       \
1608139c1837SPaolo Bonzini{                                                            \
1609139c1837SPaolo Bonzini    static gen_helper_opivx * const fns[3] = {               \
1610139c1837SPaolo Bonzini        gen_helper_##NAME##_b,                               \
1611139c1837SPaolo Bonzini        gen_helper_##NAME##_h,                               \
1612139c1837SPaolo Bonzini        gen_helper_##NAME##_w                                \
1613139c1837SPaolo Bonzini    };                                                       \
1614139c1837SPaolo Bonzini    return do_opiwx_widen(s, a, fns[s->sew]);                \
1615139c1837SPaolo Bonzini}
1616139c1837SPaolo Bonzini
1617139c1837SPaolo BonziniGEN_OPIWX_WIDEN_TRANS(vwaddu_wx)
1618139c1837SPaolo BonziniGEN_OPIWX_WIDEN_TRANS(vwadd_wx)
1619139c1837SPaolo BonziniGEN_OPIWX_WIDEN_TRANS(vwsubu_wx)
1620139c1837SPaolo BonziniGEN_OPIWX_WIDEN_TRANS(vwsub_wx)
1621139c1837SPaolo Bonzini
1622a44f19f6SKiran Ostrolenkstatic bool opivv_trans(uint32_t vd, uint32_t vs1, uint32_t vs2, uint32_t vm,
1623a44f19f6SKiran Ostrolenk                        gen_helper_gvec_4_ptr *fn, DisasContext *s)
1624a44f19f6SKiran Ostrolenk{
1625a44f19f6SKiran Ostrolenk    uint32_t data = 0;
1626a44f19f6SKiran Ostrolenk
1627a44f19f6SKiran Ostrolenk    data = FIELD_DP32(data, VDATA, VM, vm);
1628a44f19f6SKiran Ostrolenk    data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
1629a44f19f6SKiran Ostrolenk    data = FIELD_DP32(data, VDATA, VTA, s->vta);
1630a44f19f6SKiran Ostrolenk    data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
1631a44f19f6SKiran Ostrolenk    data = FIELD_DP32(data, VDATA, VMA, s->vma);
1632a44f19f6SKiran Ostrolenk    tcg_gen_gvec_4_ptr(vreg_ofs(s, vd), vreg_ofs(s, 0), vreg_ofs(s, vs1),
163381b9ef99SDaniel Henrique Barboza                       vreg_ofs(s, vs2), tcg_env, s->cfg_ptr->vlenb,
163481b9ef99SDaniel Henrique Barboza                       s->cfg_ptr->vlenb, data, fn);
1635bac802adSIvan Klokov    finalize_rvv_inst(s);
1636a44f19f6SKiran Ostrolenk    return true;
1637a44f19f6SKiran Ostrolenk}
1638a44f19f6SKiran Ostrolenk
1639139c1837SPaolo Bonzini/* Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions */
1640139c1837SPaolo Bonzini/* OPIVV without GVEC IR */
1641139c1837SPaolo Bonzini#define GEN_OPIVV_TRANS(NAME, CHECK)                                     \
1642139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)                   \
1643139c1837SPaolo Bonzini{                                                                        \
1644139c1837SPaolo Bonzini    if (CHECK(s, a)) {                                                   \
1645139c1837SPaolo Bonzini        static gen_helper_gvec_4_ptr * const fns[4] = {                  \
1646139c1837SPaolo Bonzini            gen_helper_##NAME##_b, gen_helper_##NAME##_h,                \
1647139c1837SPaolo Bonzini            gen_helper_##NAME##_w, gen_helper_##NAME##_d,                \
1648139c1837SPaolo Bonzini        };                                                               \
1649a44f19f6SKiran Ostrolenk        return opivv_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s);\
1650139c1837SPaolo Bonzini    }                                                                    \
1651139c1837SPaolo Bonzini    return false;                                                        \
1652139c1837SPaolo Bonzini}
1653139c1837SPaolo Bonzini
1654139c1837SPaolo Bonzini/*
1655139c1837SPaolo Bonzini * For vadc and vsbc, an illegal instruction exception is raised if the
165645ca2ca6SFrank Chang * destination vector register is v0 and LMUL > 1. (Section 11.4)
1657139c1837SPaolo Bonzini */
1658139c1837SPaolo Bonzinistatic bool opivv_vadc_check(DisasContext *s, arg_rmrr *a)
1659139c1837SPaolo Bonzini{
1660f31dacd7SFrank Chang    return require_rvv(s) &&
1661f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
1662f31dacd7SFrank Chang           (a->rd != 0) &&
1663f31dacd7SFrank Chang           vext_check_sss(s, a->rd, a->rs1, a->rs2, a->vm);
1664139c1837SPaolo Bonzini}
1665139c1837SPaolo Bonzini
1666139c1837SPaolo BonziniGEN_OPIVV_TRANS(vadc_vvm, opivv_vadc_check)
1667139c1837SPaolo BonziniGEN_OPIVV_TRANS(vsbc_vvm, opivv_vadc_check)
1668139c1837SPaolo Bonzini
1669139c1837SPaolo Bonzini/*
1670139c1837SPaolo Bonzini * For vmadc and vmsbc, an illegal instruction exception is raised if the
1671139c1837SPaolo Bonzini * destination vector register overlaps a source vector register group.
1672139c1837SPaolo Bonzini */
1673139c1837SPaolo Bonzinistatic bool opivv_vmadc_check(DisasContext *s, arg_rmrr *a)
1674139c1837SPaolo Bonzini{
1675f31dacd7SFrank Chang    return require_rvv(s) &&
1676f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
1677f31dacd7SFrank Chang           vext_check_mss(s, a->rd, a->rs1, a->rs2);
1678139c1837SPaolo Bonzini}
1679139c1837SPaolo Bonzini
1680139c1837SPaolo BonziniGEN_OPIVV_TRANS(vmadc_vvm, opivv_vmadc_check)
1681139c1837SPaolo BonziniGEN_OPIVV_TRANS(vmsbc_vvm, opivv_vmadc_check)
1682139c1837SPaolo Bonzini
1683139c1837SPaolo Bonzinistatic bool opivx_vadc_check(DisasContext *s, arg_rmrr *a)
1684139c1837SPaolo Bonzini{
1685f31dacd7SFrank Chang    return require_rvv(s) &&
1686f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
1687f31dacd7SFrank Chang           (a->rd != 0) &&
1688f31dacd7SFrank Chang           vext_check_ss(s, a->rd, a->rs2, a->vm);
1689139c1837SPaolo Bonzini}
1690139c1837SPaolo Bonzini
1691139c1837SPaolo Bonzini/* OPIVX without GVEC IR */
1692139c1837SPaolo Bonzini#define GEN_OPIVX_TRANS(NAME, CHECK)                                     \
1693139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)                   \
1694139c1837SPaolo Bonzini{                                                                        \
1695139c1837SPaolo Bonzini    if (CHECK(s, a)) {                                                   \
1696139c1837SPaolo Bonzini        static gen_helper_opivx * const fns[4] = {                       \
1697139c1837SPaolo Bonzini            gen_helper_##NAME##_b, gen_helper_##NAME##_h,                \
1698139c1837SPaolo Bonzini            gen_helper_##NAME##_w, gen_helper_##NAME##_d,                \
1699139c1837SPaolo Bonzini        };                                                               \
1700139c1837SPaolo Bonzini                                                                         \
1701139c1837SPaolo Bonzini        return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s);\
1702139c1837SPaolo Bonzini    }                                                                    \
1703139c1837SPaolo Bonzini    return false;                                                        \
1704139c1837SPaolo Bonzini}
1705139c1837SPaolo Bonzini
1706139c1837SPaolo BonziniGEN_OPIVX_TRANS(vadc_vxm, opivx_vadc_check)
1707139c1837SPaolo BonziniGEN_OPIVX_TRANS(vsbc_vxm, opivx_vadc_check)
1708139c1837SPaolo Bonzini
1709139c1837SPaolo Bonzinistatic bool opivx_vmadc_check(DisasContext *s, arg_rmrr *a)
1710139c1837SPaolo Bonzini{
1711f31dacd7SFrank Chang    return require_rvv(s) &&
1712f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
1713f31dacd7SFrank Chang           vext_check_ms(s, a->rd, a->rs2);
1714139c1837SPaolo Bonzini}
1715139c1837SPaolo Bonzini
1716139c1837SPaolo BonziniGEN_OPIVX_TRANS(vmadc_vxm, opivx_vmadc_check)
1717139c1837SPaolo BonziniGEN_OPIVX_TRANS(vmsbc_vxm, opivx_vmadc_check)
1718139c1837SPaolo Bonzini
1719139c1837SPaolo Bonzini/* OPIVI without GVEC IR */
1720ff64fc91SFrank Chang#define GEN_OPIVI_TRANS(NAME, IMM_MODE, OPIVX, CHECK)                    \
1721139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)                   \
1722139c1837SPaolo Bonzini{                                                                        \
1723139c1837SPaolo Bonzini    if (CHECK(s, a)) {                                                   \
1724139c1837SPaolo Bonzini        static gen_helper_opivx * const fns[4] = {                       \
1725139c1837SPaolo Bonzini            gen_helper_##OPIVX##_b, gen_helper_##OPIVX##_h,              \
1726139c1837SPaolo Bonzini            gen_helper_##OPIVX##_w, gen_helper_##OPIVX##_d,              \
1727139c1837SPaolo Bonzini        };                                                               \
1728139c1837SPaolo Bonzini        return opivi_trans(a->rd, a->rs1, a->rs2, a->vm,                 \
1729ff64fc91SFrank Chang                           fns[s->sew], s, IMM_MODE);                    \
1730139c1837SPaolo Bonzini    }                                                                    \
1731139c1837SPaolo Bonzini    return false;                                                        \
1732139c1837SPaolo Bonzini}
1733139c1837SPaolo Bonzini
1734ff64fc91SFrank ChangGEN_OPIVI_TRANS(vadc_vim, IMM_SX, vadc_vxm, opivx_vadc_check)
1735ff64fc91SFrank ChangGEN_OPIVI_TRANS(vmadc_vim, IMM_SX, vmadc_vxm, opivx_vmadc_check)
1736139c1837SPaolo Bonzini
1737139c1837SPaolo Bonzini/* Vector Bitwise Logical Instructions */
1738139c1837SPaolo BonziniGEN_OPIVV_GVEC_TRANS(vand_vv, and)
1739139c1837SPaolo BonziniGEN_OPIVV_GVEC_TRANS(vor_vv,  or)
1740139c1837SPaolo BonziniGEN_OPIVV_GVEC_TRANS(vxor_vv, xor)
1741139c1837SPaolo BonziniGEN_OPIVX_GVEC_TRANS(vand_vx, ands)
1742139c1837SPaolo BonziniGEN_OPIVX_GVEC_TRANS(vor_vx,  ors)
1743139c1837SPaolo BonziniGEN_OPIVX_GVEC_TRANS(vxor_vx, xors)
1744ff64fc91SFrank ChangGEN_OPIVI_GVEC_TRANS(vand_vi, IMM_SX, vand_vx, andi)
1745ff64fc91SFrank ChangGEN_OPIVI_GVEC_TRANS(vor_vi, IMM_SX, vor_vx,  ori)
1746ff64fc91SFrank ChangGEN_OPIVI_GVEC_TRANS(vxor_vi, IMM_SX, vxor_vx, xori)
1747139c1837SPaolo Bonzini
1748139c1837SPaolo Bonzini/* Vector Single-Width Bit Shift Instructions */
1749139c1837SPaolo BonziniGEN_OPIVV_GVEC_TRANS(vsll_vv,  shlv)
1750139c1837SPaolo BonziniGEN_OPIVV_GVEC_TRANS(vsrl_vv,  shrv)
1751139c1837SPaolo BonziniGEN_OPIVV_GVEC_TRANS(vsra_vv,  sarv)
1752139c1837SPaolo Bonzini
1753139c1837SPaolo Bonzinitypedef void GVecGen2sFn32(unsigned, uint32_t, uint32_t, TCGv_i32,
1754139c1837SPaolo Bonzini                           uint32_t, uint32_t);
1755139c1837SPaolo Bonzini
1756139c1837SPaolo Bonzinistatic inline bool
1757139c1837SPaolo Bonzinido_opivx_gvec_shift(DisasContext *s, arg_rmrr *a, GVecGen2sFn32 *gvec_fn,
1758139c1837SPaolo Bonzini                    gen_helper_opivx *fn)
1759139c1837SPaolo Bonzini{
17607b1bff41SeopXD    if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
1761139c1837SPaolo Bonzini        TCGv_i32 src1 = tcg_temp_new_i32();
1762139c1837SPaolo Bonzini
17638e034ae4SRichard Henderson        tcg_gen_trunc_tl_i32(src1, get_gpr(s, a->rs1, EXT_NONE));
1764139c1837SPaolo Bonzini        tcg_gen_extract_i32(src1, src1, 0, s->sew + 3);
1765139c1837SPaolo Bonzini        gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2),
1766139c1837SPaolo Bonzini                src1, MAXSZ(s), MAXSZ(s));
1767139c1837SPaolo Bonzini
1768bac802adSIvan Klokov        finalize_rvv_inst(s);
1769139c1837SPaolo Bonzini        return true;
1770139c1837SPaolo Bonzini    }
1771139c1837SPaolo Bonzini    return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s);
1772139c1837SPaolo Bonzini}
1773139c1837SPaolo Bonzini
1774139c1837SPaolo Bonzini#define GEN_OPIVX_GVEC_SHIFT_TRANS(NAME, SUF) \
1775139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)                    \
1776139c1837SPaolo Bonzini{                                                                         \
1777139c1837SPaolo Bonzini    static gen_helper_opivx * const fns[4] = {                            \
1778139c1837SPaolo Bonzini        gen_helper_##NAME##_b, gen_helper_##NAME##_h,                     \
1779139c1837SPaolo Bonzini        gen_helper_##NAME##_w, gen_helper_##NAME##_d,                     \
1780139c1837SPaolo Bonzini    };                                                                    \
17811ac7a501SNazar Kazakov    if (!opivx_check(s, a)) {                                             \
17821ac7a501SNazar Kazakov        return false;                                                     \
17831ac7a501SNazar Kazakov    }                                                                     \
1784139c1837SPaolo Bonzini    return do_opivx_gvec_shift(s, a, tcg_gen_gvec_##SUF, fns[s->sew]);    \
1785139c1837SPaolo Bonzini}
1786139c1837SPaolo Bonzini
1787139c1837SPaolo BonziniGEN_OPIVX_GVEC_SHIFT_TRANS(vsll_vx,  shls)
1788139c1837SPaolo BonziniGEN_OPIVX_GVEC_SHIFT_TRANS(vsrl_vx,  shrs)
1789139c1837SPaolo BonziniGEN_OPIVX_GVEC_SHIFT_TRANS(vsra_vx,  sars)
1790139c1837SPaolo Bonzini
1791a75ae09fSFrank ChangGEN_OPIVI_GVEC_TRANS(vsll_vi, IMM_TRUNC_SEW, vsll_vx, shli)
1792a75ae09fSFrank ChangGEN_OPIVI_GVEC_TRANS(vsrl_vi, IMM_TRUNC_SEW, vsrl_vx, shri)
1793a75ae09fSFrank ChangGEN_OPIVI_GVEC_TRANS(vsra_vi, IMM_TRUNC_SEW, vsra_vx, sari)
1794139c1837SPaolo Bonzini
1795139c1837SPaolo Bonzini/* Vector Narrowing Integer Right Shift Instructions */
17967daa5852SFrank Changstatic bool opiwv_narrow_check(DisasContext *s, arg_rmrr *a)
1797139c1837SPaolo Bonzini{
1798f31dacd7SFrank Chang    return require_rvv(s) &&
1799f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
1800f31dacd7SFrank Chang           vext_check_sds(s, a->rd, a->rs1, a->rs2, a->vm);
1801139c1837SPaolo Bonzini}
1802139c1837SPaolo Bonzini
1803139c1837SPaolo Bonzini/* OPIVV with NARROW */
18047daa5852SFrank Chang#define GEN_OPIWV_NARROW_TRANS(NAME)                               \
1805139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
1806139c1837SPaolo Bonzini{                                                                  \
18077daa5852SFrank Chang    if (opiwv_narrow_check(s, a)) {                                \
1808139c1837SPaolo Bonzini        uint32_t data = 0;                                         \
1809139c1837SPaolo Bonzini        static gen_helper_gvec_4_ptr * const fns[3] = {            \
1810139c1837SPaolo Bonzini            gen_helper_##NAME##_b,                                 \
1811139c1837SPaolo Bonzini            gen_helper_##NAME##_h,                                 \
1812139c1837SPaolo Bonzini            gen_helper_##NAME##_w,                                 \
1813139c1837SPaolo Bonzini        };                                                         \
1814139c1837SPaolo Bonzini                                                                   \
1815139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
1816139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
18177b1bff41SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);               \
1818fd93045eSYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);               \
1819139c1837SPaolo Bonzini        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
1820139c1837SPaolo Bonzini                           vreg_ofs(s, a->rs1),                    \
1821ad75a51eSRichard Henderson                           vreg_ofs(s, a->rs2), tcg_env,           \
182281b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb,                      \
182381b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb, data,                \
1824eee2d61eSLIU Zhiwei                           fns[s->sew]);                           \
1825bac802adSIvan Klokov        finalize_rvv_inst(s);                                      \
1826139c1837SPaolo Bonzini        return true;                                               \
1827139c1837SPaolo Bonzini    }                                                              \
1828139c1837SPaolo Bonzini    return false;                                                  \
1829139c1837SPaolo Bonzini}
18307daa5852SFrank ChangGEN_OPIWV_NARROW_TRANS(vnsra_wv)
18317daa5852SFrank ChangGEN_OPIWV_NARROW_TRANS(vnsrl_wv)
1832139c1837SPaolo Bonzini
18337daa5852SFrank Changstatic bool opiwx_narrow_check(DisasContext *s, arg_rmrr *a)
1834139c1837SPaolo Bonzini{
1835f31dacd7SFrank Chang    return require_rvv(s) &&
1836f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
1837f31dacd7SFrank Chang           vext_check_sd(s, a->rd, a->rs2, a->vm);
1838139c1837SPaolo Bonzini}
1839139c1837SPaolo Bonzini
1840139c1837SPaolo Bonzini/* OPIVX with NARROW */
18417daa5852SFrank Chang#define GEN_OPIWX_NARROW_TRANS(NAME)                                     \
1842139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)                   \
1843139c1837SPaolo Bonzini{                                                                        \
18447daa5852SFrank Chang    if (opiwx_narrow_check(s, a)) {                                      \
1845139c1837SPaolo Bonzini        static gen_helper_opivx * const fns[3] = {                       \
1846139c1837SPaolo Bonzini            gen_helper_##NAME##_b,                                       \
1847139c1837SPaolo Bonzini            gen_helper_##NAME##_h,                                       \
1848139c1837SPaolo Bonzini            gen_helper_##NAME##_w,                                       \
1849139c1837SPaolo Bonzini        };                                                               \
1850139c1837SPaolo Bonzini        return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s);\
1851139c1837SPaolo Bonzini    }                                                                    \
1852139c1837SPaolo Bonzini    return false;                                                        \
1853139c1837SPaolo Bonzini}
1854139c1837SPaolo Bonzini
18557daa5852SFrank ChangGEN_OPIWX_NARROW_TRANS(vnsra_wx)
18567daa5852SFrank ChangGEN_OPIWX_NARROW_TRANS(vnsrl_wx)
1857139c1837SPaolo Bonzini
18587daa5852SFrank Chang/* OPIWI with NARROW */
18597daa5852SFrank Chang#define GEN_OPIWI_NARROW_TRANS(NAME, IMM_MODE, OPIVX)                    \
1860139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)                   \
1861139c1837SPaolo Bonzini{                                                                        \
18627daa5852SFrank Chang    if (opiwx_narrow_check(s, a)) {                                      \
1863139c1837SPaolo Bonzini        static gen_helper_opivx * const fns[3] = {                       \
1864139c1837SPaolo Bonzini            gen_helper_##OPIVX##_b,                                      \
1865139c1837SPaolo Bonzini            gen_helper_##OPIVX##_h,                                      \
1866139c1837SPaolo Bonzini            gen_helper_##OPIVX##_w,                                      \
1867139c1837SPaolo Bonzini        };                                                               \
1868139c1837SPaolo Bonzini        return opivi_trans(a->rd, a->rs1, a->rs2, a->vm,                 \
1869ff64fc91SFrank Chang                           fns[s->sew], s, IMM_MODE);                    \
1870139c1837SPaolo Bonzini    }                                                                    \
1871139c1837SPaolo Bonzini    return false;                                                        \
1872139c1837SPaolo Bonzini}
1873139c1837SPaolo Bonzini
18747daa5852SFrank ChangGEN_OPIWI_NARROW_TRANS(vnsra_wi, IMM_ZX, vnsra_wx)
18757daa5852SFrank ChangGEN_OPIWI_NARROW_TRANS(vnsrl_wi, IMM_ZX, vnsrl_wx)
1876139c1837SPaolo Bonzini
1877139c1837SPaolo Bonzini/* Vector Integer Comparison Instructions */
1878139c1837SPaolo Bonzini/*
1879139c1837SPaolo Bonzini * For all comparison instructions, an illegal instruction exception is raised
1880139c1837SPaolo Bonzini * if the destination vector register overlaps a source vector register group
1881139c1837SPaolo Bonzini * and LMUL > 1.
1882139c1837SPaolo Bonzini */
1883139c1837SPaolo Bonzinistatic bool opivv_cmp_check(DisasContext *s, arg_rmrr *a)
1884139c1837SPaolo Bonzini{
1885f31dacd7SFrank Chang    return require_rvv(s) &&
1886f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
1887f31dacd7SFrank Chang           vext_check_mss(s, a->rd, a->rs1, a->rs2);
1888139c1837SPaolo Bonzini}
1889f31dacd7SFrank Chang
1890139c1837SPaolo BonziniGEN_OPIVV_TRANS(vmseq_vv, opivv_cmp_check)
1891139c1837SPaolo BonziniGEN_OPIVV_TRANS(vmsne_vv, opivv_cmp_check)
1892139c1837SPaolo BonziniGEN_OPIVV_TRANS(vmsltu_vv, opivv_cmp_check)
1893139c1837SPaolo BonziniGEN_OPIVV_TRANS(vmslt_vv, opivv_cmp_check)
1894139c1837SPaolo BonziniGEN_OPIVV_TRANS(vmsleu_vv, opivv_cmp_check)
1895139c1837SPaolo BonziniGEN_OPIVV_TRANS(vmsle_vv, opivv_cmp_check)
1896139c1837SPaolo Bonzini
1897139c1837SPaolo Bonzinistatic bool opivx_cmp_check(DisasContext *s, arg_rmrr *a)
1898139c1837SPaolo Bonzini{
1899f31dacd7SFrank Chang    return require_rvv(s) &&
1900f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
1901f31dacd7SFrank Chang           vext_check_ms(s, a->rd, a->rs2);
1902139c1837SPaolo Bonzini}
1903139c1837SPaolo Bonzini
1904139c1837SPaolo BonziniGEN_OPIVX_TRANS(vmseq_vx, opivx_cmp_check)
1905139c1837SPaolo BonziniGEN_OPIVX_TRANS(vmsne_vx, opivx_cmp_check)
1906139c1837SPaolo BonziniGEN_OPIVX_TRANS(vmsltu_vx, opivx_cmp_check)
1907139c1837SPaolo BonziniGEN_OPIVX_TRANS(vmslt_vx, opivx_cmp_check)
1908139c1837SPaolo BonziniGEN_OPIVX_TRANS(vmsleu_vx, opivx_cmp_check)
1909139c1837SPaolo BonziniGEN_OPIVX_TRANS(vmsle_vx, opivx_cmp_check)
1910139c1837SPaolo BonziniGEN_OPIVX_TRANS(vmsgtu_vx, opivx_cmp_check)
1911139c1837SPaolo BonziniGEN_OPIVX_TRANS(vmsgt_vx, opivx_cmp_check)
1912139c1837SPaolo Bonzini
1913ff64fc91SFrank ChangGEN_OPIVI_TRANS(vmseq_vi, IMM_SX, vmseq_vx, opivx_cmp_check)
1914ff64fc91SFrank ChangGEN_OPIVI_TRANS(vmsne_vi, IMM_SX, vmsne_vx, opivx_cmp_check)
1915063f8bbcSFrank ChangGEN_OPIVI_TRANS(vmsleu_vi, IMM_SX, vmsleu_vx, opivx_cmp_check)
1916ff64fc91SFrank ChangGEN_OPIVI_TRANS(vmsle_vi, IMM_SX, vmsle_vx, opivx_cmp_check)
1917063f8bbcSFrank ChangGEN_OPIVI_TRANS(vmsgtu_vi, IMM_SX, vmsgtu_vx, opivx_cmp_check)
1918ff64fc91SFrank ChangGEN_OPIVI_TRANS(vmsgt_vi, IMM_SX, vmsgt_vx, opivx_cmp_check)
1919139c1837SPaolo Bonzini
1920139c1837SPaolo Bonzini/* Vector Integer Min/Max Instructions */
1921139c1837SPaolo BonziniGEN_OPIVV_GVEC_TRANS(vminu_vv, umin)
1922139c1837SPaolo BonziniGEN_OPIVV_GVEC_TRANS(vmin_vv,  smin)
1923139c1837SPaolo BonziniGEN_OPIVV_GVEC_TRANS(vmaxu_vv, umax)
1924139c1837SPaolo BonziniGEN_OPIVV_GVEC_TRANS(vmax_vv,  smax)
1925139c1837SPaolo BonziniGEN_OPIVX_TRANS(vminu_vx, opivx_check)
1926139c1837SPaolo BonziniGEN_OPIVX_TRANS(vmin_vx,  opivx_check)
1927139c1837SPaolo BonziniGEN_OPIVX_TRANS(vmaxu_vx, opivx_check)
1928139c1837SPaolo BonziniGEN_OPIVX_TRANS(vmax_vx,  opivx_check)
1929139c1837SPaolo Bonzini
1930139c1837SPaolo Bonzini/* Vector Single-Width Integer Multiply Instructions */
1931aaae6994SFrank Chang
1932aaae6994SFrank Changstatic bool vmulh_vv_check(DisasContext *s, arg_rmrr *a)
1933aaae6994SFrank Chang{
1934aaae6994SFrank Chang    /*
1935aaae6994SFrank Chang     * All Zve* extensions support all vector integer instructions,
1936aaae6994SFrank Chang     * except that the vmulh integer multiply variants
1937aaae6994SFrank Chang     * that return the high word of the product
1938aaae6994SFrank Chang     * (vmulh.vv, vmulh.vx, vmulhu.vv, vmulhu.vx, vmulhsu.vv, vmulhsu.vx)
1939aaae6994SFrank Chang     * are not included for EEW=64 in Zve64*. (Section 18.2)
1940aaae6994SFrank Chang     */
1941aaae6994SFrank Chang    return opivv_check(s, a) &&
1942c1027460SWeiwei Li           (!has_ext(s, RVV) ? s->sew != MO_64 : true);
1943aaae6994SFrank Chang}
1944aaae6994SFrank Chang
1945aaae6994SFrank Changstatic bool vmulh_vx_check(DisasContext *s, arg_rmrr *a)
1946aaae6994SFrank Chang{
1947aaae6994SFrank Chang    /*
1948aaae6994SFrank Chang     * All Zve* extensions support all vector integer instructions,
1949aaae6994SFrank Chang     * except that the vmulh integer multiply variants
1950aaae6994SFrank Chang     * that return the high word of the product
1951aaae6994SFrank Chang     * (vmulh.vv, vmulh.vx, vmulhu.vv, vmulhu.vx, vmulhsu.vv, vmulhsu.vx)
1952aaae6994SFrank Chang     * are not included for EEW=64 in Zve64*. (Section 18.2)
1953aaae6994SFrank Chang     */
1954aaae6994SFrank Chang    return opivx_check(s, a) &&
1955c1027460SWeiwei Li           (!has_ext(s, RVV) ? s->sew != MO_64 : true);
1956aaae6994SFrank Chang}
1957aaae6994SFrank Chang
1958139c1837SPaolo BonziniGEN_OPIVV_GVEC_TRANS(vmul_vv,  mul)
1959aaae6994SFrank ChangGEN_OPIVV_TRANS(vmulh_vv, vmulh_vv_check)
1960aaae6994SFrank ChangGEN_OPIVV_TRANS(vmulhu_vv, vmulh_vv_check)
1961aaae6994SFrank ChangGEN_OPIVV_TRANS(vmulhsu_vv, vmulh_vv_check)
1962139c1837SPaolo BonziniGEN_OPIVX_GVEC_TRANS(vmul_vx,  muls)
1963aaae6994SFrank ChangGEN_OPIVX_TRANS(vmulh_vx, vmulh_vx_check)
1964aaae6994SFrank ChangGEN_OPIVX_TRANS(vmulhu_vx, vmulh_vx_check)
1965aaae6994SFrank ChangGEN_OPIVX_TRANS(vmulhsu_vx, vmulh_vx_check)
1966139c1837SPaolo Bonzini
1967139c1837SPaolo Bonzini/* Vector Integer Divide Instructions */
1968139c1837SPaolo BonziniGEN_OPIVV_TRANS(vdivu_vv, opivv_check)
1969139c1837SPaolo BonziniGEN_OPIVV_TRANS(vdiv_vv, opivv_check)
1970139c1837SPaolo BonziniGEN_OPIVV_TRANS(vremu_vv, opivv_check)
1971139c1837SPaolo BonziniGEN_OPIVV_TRANS(vrem_vv, opivv_check)
1972139c1837SPaolo BonziniGEN_OPIVX_TRANS(vdivu_vx, opivx_check)
1973139c1837SPaolo BonziniGEN_OPIVX_TRANS(vdiv_vx, opivx_check)
1974139c1837SPaolo BonziniGEN_OPIVX_TRANS(vremu_vx, opivx_check)
1975139c1837SPaolo BonziniGEN_OPIVX_TRANS(vrem_vx, opivx_check)
1976139c1837SPaolo Bonzini
1977139c1837SPaolo Bonzini/* Vector Widening Integer Multiply Instructions */
1978139c1837SPaolo BonziniGEN_OPIVV_WIDEN_TRANS(vwmul_vv, opivv_widen_check)
1979139c1837SPaolo BonziniGEN_OPIVV_WIDEN_TRANS(vwmulu_vv, opivv_widen_check)
1980139c1837SPaolo BonziniGEN_OPIVV_WIDEN_TRANS(vwmulsu_vv, opivv_widen_check)
198162cb3e8eSDickon HoodGEN_OPIVX_WIDEN_TRANS(vwmul_vx, opivx_widen_check)
198262cb3e8eSDickon HoodGEN_OPIVX_WIDEN_TRANS(vwmulu_vx, opivx_widen_check)
198362cb3e8eSDickon HoodGEN_OPIVX_WIDEN_TRANS(vwmulsu_vx, opivx_widen_check)
1984139c1837SPaolo Bonzini
1985139c1837SPaolo Bonzini/* Vector Single-Width Integer Multiply-Add Instructions */
1986139c1837SPaolo BonziniGEN_OPIVV_TRANS(vmacc_vv, opivv_check)
1987139c1837SPaolo BonziniGEN_OPIVV_TRANS(vnmsac_vv, opivv_check)
1988139c1837SPaolo BonziniGEN_OPIVV_TRANS(vmadd_vv, opivv_check)
1989139c1837SPaolo BonziniGEN_OPIVV_TRANS(vnmsub_vv, opivv_check)
1990139c1837SPaolo BonziniGEN_OPIVX_TRANS(vmacc_vx, opivx_check)
1991139c1837SPaolo BonziniGEN_OPIVX_TRANS(vnmsac_vx, opivx_check)
1992139c1837SPaolo BonziniGEN_OPIVX_TRANS(vmadd_vx, opivx_check)
1993139c1837SPaolo BonziniGEN_OPIVX_TRANS(vnmsub_vx, opivx_check)
1994139c1837SPaolo Bonzini
1995139c1837SPaolo Bonzini/* Vector Widening Integer Multiply-Add Instructions */
1996139c1837SPaolo BonziniGEN_OPIVV_WIDEN_TRANS(vwmaccu_vv, opivv_widen_check)
1997139c1837SPaolo BonziniGEN_OPIVV_WIDEN_TRANS(vwmacc_vv, opivv_widen_check)
1998139c1837SPaolo BonziniGEN_OPIVV_WIDEN_TRANS(vwmaccsu_vv, opivv_widen_check)
199962cb3e8eSDickon HoodGEN_OPIVX_WIDEN_TRANS(vwmaccu_vx, opivx_widen_check)
200062cb3e8eSDickon HoodGEN_OPIVX_WIDEN_TRANS(vwmacc_vx, opivx_widen_check)
200162cb3e8eSDickon HoodGEN_OPIVX_WIDEN_TRANS(vwmaccsu_vx, opivx_widen_check)
200262cb3e8eSDickon HoodGEN_OPIVX_WIDEN_TRANS(vwmaccus_vx, opivx_widen_check)
2003139c1837SPaolo Bonzini
2004139c1837SPaolo Bonzini/* Vector Integer Merge and Move Instructions */
2005139c1837SPaolo Bonzinistatic bool trans_vmv_v_v(DisasContext *s, arg_vmv_v_v *a)
2006139c1837SPaolo Bonzini{
2007f31dacd7SFrank Chang    if (require_rvv(s) &&
2008f31dacd7SFrank Chang        vext_check_isa_ill(s) &&
2009f31dacd7SFrank Chang        /* vmv.v.v has rs2 = 0 and vm = 1 */
2010f31dacd7SFrank Chang        vext_check_sss(s, a->rd, a->rs1, 0, 1)) {
201189a32de2SeopXD        if (s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
2012139c1837SPaolo Bonzini            tcg_gen_gvec_mov(s->sew, vreg_ofs(s, a->rd),
2013139c1837SPaolo Bonzini                             vreg_ofs(s, a->rs1),
2014139c1837SPaolo Bonzini                             MAXSZ(s), MAXSZ(s));
2015139c1837SPaolo Bonzini        } else {
2016139c1837SPaolo Bonzini            uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul);
201789a32de2SeopXD            data = FIELD_DP32(data, VDATA, VTA, s->vta);
2018139c1837SPaolo Bonzini            static gen_helper_gvec_2_ptr * const fns[4] = {
2019139c1837SPaolo Bonzini                gen_helper_vmv_v_v_b, gen_helper_vmv_v_v_h,
2020139c1837SPaolo Bonzini                gen_helper_vmv_v_v_w, gen_helper_vmv_v_v_d,
2021139c1837SPaolo Bonzini            };
2022139c1837SPaolo Bonzini
2023139c1837SPaolo Bonzini            tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),
202481b9ef99SDaniel Henrique Barboza                               tcg_env, s->cfg_ptr->vlenb,
202581b9ef99SDaniel Henrique Barboza                               s->cfg_ptr->vlenb, data,
2026c672f19fSFrank Chang                               fns[s->sew]);
2027139c1837SPaolo Bonzini        }
2028bac802adSIvan Klokov        finalize_rvv_inst(s);
2029139c1837SPaolo Bonzini        return true;
2030139c1837SPaolo Bonzini    }
2031139c1837SPaolo Bonzini    return false;
2032139c1837SPaolo Bonzini}
2033139c1837SPaolo Bonzini
2034139c1837SPaolo Bonzinitypedef void gen_helper_vmv_vx(TCGv_ptr, TCGv_i64, TCGv_env, TCGv_i32);
2035139c1837SPaolo Bonzinistatic bool trans_vmv_v_x(DisasContext *s, arg_vmv_v_x *a)
2036139c1837SPaolo Bonzini{
2037f31dacd7SFrank Chang    if (require_rvv(s) &&
2038f31dacd7SFrank Chang        vext_check_isa_ill(s) &&
2039f31dacd7SFrank Chang        /* vmv.v.x has rs2 = 0 and vm = 1 */
2040f31dacd7SFrank Chang        vext_check_ss(s, a->rd, 0, 1)) {
2041139c1837SPaolo Bonzini        TCGv s1;
2042139c1837SPaolo Bonzini
20438e034ae4SRichard Henderson        s1 = get_gpr(s, a->rs1, EXT_SIGN);
2044139c1837SPaolo Bonzini
204589a32de2SeopXD        if (s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
204607314158SAlistair Francis            if (get_xl(s) == MXL_RV32 && s->sew == MO_64) {
204707314158SAlistair Francis                TCGv_i64 s1_i64 = tcg_temp_new_i64();
204807314158SAlistair Francis                tcg_gen_ext_tl_i64(s1_i64, s1);
204907314158SAlistair Francis                tcg_gen_gvec_dup_i64(s->sew, vreg_ofs(s, a->rd),
205007314158SAlistair Francis                                     MAXSZ(s), MAXSZ(s), s1_i64);
205107314158SAlistair Francis            } else {
2052139c1837SPaolo Bonzini                tcg_gen_gvec_dup_tl(s->sew, vreg_ofs(s, a->rd),
2053139c1837SPaolo Bonzini                                    MAXSZ(s), MAXSZ(s), s1);
205407314158SAlistair Francis            }
2055139c1837SPaolo Bonzini        } else {
2056139c1837SPaolo Bonzini            TCGv_i32 desc;
2057139c1837SPaolo Bonzini            TCGv_i64 s1_i64 = tcg_temp_new_i64();
2058139c1837SPaolo Bonzini            TCGv_ptr dest = tcg_temp_new_ptr();
2059139c1837SPaolo Bonzini            uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul);
206089a32de2SeopXD            data = FIELD_DP32(data, VDATA, VTA, s->vta);
2061139c1837SPaolo Bonzini            static gen_helper_vmv_vx * const fns[4] = {
2062139c1837SPaolo Bonzini                gen_helper_vmv_v_x_b, gen_helper_vmv_v_x_h,
2063139c1837SPaolo Bonzini                gen_helper_vmv_v_x_w, gen_helper_vmv_v_x_d,
2064139c1837SPaolo Bonzini            };
2065139c1837SPaolo Bonzini
2066139c1837SPaolo Bonzini            tcg_gen_ext_tl_i64(s1_i64, s1);
206781b9ef99SDaniel Henrique Barboza            desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlenb,
206881b9ef99SDaniel Henrique Barboza                                              s->cfg_ptr->vlenb, data));
2069ad75a51eSRichard Henderson            tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, a->rd));
2070ad75a51eSRichard Henderson            fns[s->sew](dest, s1_i64, tcg_env, desc);
2071139c1837SPaolo Bonzini        }
2072139c1837SPaolo Bonzini
2073bac802adSIvan Klokov        finalize_rvv_inst(s);
2074139c1837SPaolo Bonzini        return true;
2075139c1837SPaolo Bonzini    }
2076139c1837SPaolo Bonzini    return false;
2077139c1837SPaolo Bonzini}
2078139c1837SPaolo Bonzini
2079139c1837SPaolo Bonzinistatic bool trans_vmv_v_i(DisasContext *s, arg_vmv_v_i *a)
2080139c1837SPaolo Bonzini{
2081f31dacd7SFrank Chang    if (require_rvv(s) &&
2082f31dacd7SFrank Chang        vext_check_isa_ill(s) &&
2083f31dacd7SFrank Chang        /* vmv.v.i has rs2 = 0 and vm = 1 */
2084f31dacd7SFrank Chang        vext_check_ss(s, a->rd, 0, 1)) {
2085139c1837SPaolo Bonzini        int64_t simm = sextract64(a->rs1, 0, 5);
208689a32de2SeopXD        if (s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
2087139c1837SPaolo Bonzini            tcg_gen_gvec_dup_imm(s->sew, vreg_ofs(s, a->rd),
2088139c1837SPaolo Bonzini                                 MAXSZ(s), MAXSZ(s), simm);
2089139c1837SPaolo Bonzini        } else {
2090139c1837SPaolo Bonzini            TCGv_i32 desc;
2091139c1837SPaolo Bonzini            TCGv_i64 s1;
2092139c1837SPaolo Bonzini            TCGv_ptr dest;
2093139c1837SPaolo Bonzini            uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul);
209489a32de2SeopXD            data = FIELD_DP32(data, VDATA, VTA, s->vta);
2095139c1837SPaolo Bonzini            static gen_helper_vmv_vx * const fns[4] = {
2096139c1837SPaolo Bonzini                gen_helper_vmv_v_x_b, gen_helper_vmv_v_x_h,
2097139c1837SPaolo Bonzini                gen_helper_vmv_v_x_w, gen_helper_vmv_v_x_d,
2098139c1837SPaolo Bonzini            };
2099139c1837SPaolo Bonzini
210005b80ed0SRichard Henderson            s1 = tcg_constant_i64(simm);
2101139c1837SPaolo Bonzini            dest = tcg_temp_new_ptr();
210281b9ef99SDaniel Henrique Barboza            desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlenb,
210381b9ef99SDaniel Henrique Barboza                                              s->cfg_ptr->vlenb, data));
2104ad75a51eSRichard Henderson            tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, a->rd));
2105ad75a51eSRichard Henderson            fns[s->sew](dest, s1, tcg_env, desc);
2106139c1837SPaolo Bonzini        }
2107bac802adSIvan Klokov        finalize_rvv_inst(s);
2108139c1837SPaolo Bonzini        return true;
2109139c1837SPaolo Bonzini    }
2110139c1837SPaolo Bonzini    return false;
2111139c1837SPaolo Bonzini}
2112139c1837SPaolo Bonzini
2113139c1837SPaolo BonziniGEN_OPIVV_TRANS(vmerge_vvm, opivv_vadc_check)
2114139c1837SPaolo BonziniGEN_OPIVX_TRANS(vmerge_vxm, opivx_vadc_check)
2115ff64fc91SFrank ChangGEN_OPIVI_TRANS(vmerge_vim, IMM_SX, vmerge_vxm, opivx_vadc_check)
2116139c1837SPaolo Bonzini
2117139c1837SPaolo Bonzini/*
2118139c1837SPaolo Bonzini *** Vector Fixed-Point Arithmetic Instructions
2119139c1837SPaolo Bonzini */
2120139c1837SPaolo Bonzini
2121139c1837SPaolo Bonzini/* Vector Single-Width Saturating Add and Subtract */
2122139c1837SPaolo BonziniGEN_OPIVV_TRANS(vsaddu_vv, opivv_check)
2123139c1837SPaolo BonziniGEN_OPIVV_TRANS(vsadd_vv,  opivv_check)
2124139c1837SPaolo BonziniGEN_OPIVV_TRANS(vssubu_vv, opivv_check)
2125139c1837SPaolo BonziniGEN_OPIVV_TRANS(vssub_vv,  opivv_check)
2126139c1837SPaolo BonziniGEN_OPIVX_TRANS(vsaddu_vx,  opivx_check)
2127139c1837SPaolo BonziniGEN_OPIVX_TRANS(vsadd_vx,  opivx_check)
2128139c1837SPaolo BonziniGEN_OPIVX_TRANS(vssubu_vx,  opivx_check)
2129139c1837SPaolo BonziniGEN_OPIVX_TRANS(vssub_vx,  opivx_check)
2130d6be7a35SFrank ChangGEN_OPIVI_TRANS(vsaddu_vi, IMM_SX, vsaddu_vx, opivx_check)
2131ff64fc91SFrank ChangGEN_OPIVI_TRANS(vsadd_vi, IMM_SX, vsadd_vx, opivx_check)
2132139c1837SPaolo Bonzini
2133139c1837SPaolo Bonzini/* Vector Single-Width Averaging Add and Subtract */
2134139c1837SPaolo BonziniGEN_OPIVV_TRANS(vaadd_vv, opivv_check)
21358b99a110SFrank ChangGEN_OPIVV_TRANS(vaaddu_vv, opivv_check)
2136139c1837SPaolo BonziniGEN_OPIVV_TRANS(vasub_vv, opivv_check)
21378b99a110SFrank ChangGEN_OPIVV_TRANS(vasubu_vv, opivv_check)
2138139c1837SPaolo BonziniGEN_OPIVX_TRANS(vaadd_vx,  opivx_check)
21398b99a110SFrank ChangGEN_OPIVX_TRANS(vaaddu_vx,  opivx_check)
2140139c1837SPaolo BonziniGEN_OPIVX_TRANS(vasub_vx,  opivx_check)
21418b99a110SFrank ChangGEN_OPIVX_TRANS(vasubu_vx,  opivx_check)
2142139c1837SPaolo Bonzini
2143139c1837SPaolo Bonzini/* Vector Single-Width Fractional Multiply with Rounding and Saturation */
214413dbc826SFrank Chang
214513dbc826SFrank Changstatic bool vsmul_vv_check(DisasContext *s, arg_rmrr *a)
214613dbc826SFrank Chang{
214713dbc826SFrank Chang    /*
214813dbc826SFrank Chang     * All Zve* extensions support all vector fixed-point arithmetic
214913dbc826SFrank Chang     * instructions, except that vsmul.vv and vsmul.vx are not supported
215013dbc826SFrank Chang     * for EEW=64 in Zve64*. (Section 18.2)
215113dbc826SFrank Chang     */
215213dbc826SFrank Chang    return opivv_check(s, a) &&
2153c1027460SWeiwei Li           (!has_ext(s, RVV) ? s->sew != MO_64 : true);
215413dbc826SFrank Chang}
215513dbc826SFrank Chang
215613dbc826SFrank Changstatic bool vsmul_vx_check(DisasContext *s, arg_rmrr *a)
215713dbc826SFrank Chang{
215813dbc826SFrank Chang    /*
215913dbc826SFrank Chang     * All Zve* extensions support all vector fixed-point arithmetic
216013dbc826SFrank Chang     * instructions, except that vsmul.vv and vsmul.vx are not supported
216113dbc826SFrank Chang     * for EEW=64 in Zve64*. (Section 18.2)
216213dbc826SFrank Chang     */
216313dbc826SFrank Chang    return opivx_check(s, a) &&
2164c1027460SWeiwei Li           (!has_ext(s, RVV) ? s->sew != MO_64 : true);
216513dbc826SFrank Chang}
216613dbc826SFrank Chang
216713dbc826SFrank ChangGEN_OPIVV_TRANS(vsmul_vv, vsmul_vv_check)
216813dbc826SFrank ChangGEN_OPIVX_TRANS(vsmul_vx,  vsmul_vx_check)
2169139c1837SPaolo Bonzini
2170139c1837SPaolo Bonzini/* Vector Single-Width Scaling Shift Instructions */
2171139c1837SPaolo BonziniGEN_OPIVV_TRANS(vssrl_vv, opivv_check)
2172139c1837SPaolo BonziniGEN_OPIVV_TRANS(vssra_vv, opivv_check)
2173139c1837SPaolo BonziniGEN_OPIVX_TRANS(vssrl_vx,  opivx_check)
2174139c1837SPaolo BonziniGEN_OPIVX_TRANS(vssra_vx,  opivx_check)
217574eb7834SFrank ChangGEN_OPIVI_TRANS(vssrl_vi, IMM_TRUNC_SEW, vssrl_vx, opivx_check)
217674eb7834SFrank ChangGEN_OPIVI_TRANS(vssra_vi, IMM_TRUNC_SEW, vssra_vx, opivx_check)
2177139c1837SPaolo Bonzini
2178139c1837SPaolo Bonzini/* Vector Narrowing Fixed-Point Clip Instructions */
2179a70b3a73SFrank ChangGEN_OPIWV_NARROW_TRANS(vnclipu_wv)
2180a70b3a73SFrank ChangGEN_OPIWV_NARROW_TRANS(vnclip_wv)
2181a70b3a73SFrank ChangGEN_OPIWX_NARROW_TRANS(vnclipu_wx)
2182a70b3a73SFrank ChangGEN_OPIWX_NARROW_TRANS(vnclip_wx)
2183a70b3a73SFrank ChangGEN_OPIWI_NARROW_TRANS(vnclipu_wi, IMM_ZX, vnclipu_wx)
2184a70b3a73SFrank ChangGEN_OPIWI_NARROW_TRANS(vnclip_wi, IMM_ZX, vnclip_wx)
2185139c1837SPaolo Bonzini
2186139c1837SPaolo Bonzini/*
2187139c1837SPaolo Bonzini *** Vector Float Point Arithmetic Instructions
2188139c1837SPaolo Bonzini */
21899b4a40a7SFrank Chang
21909b4a40a7SFrank Chang/*
21919b4a40a7SFrank Chang * As RVF-only cpus always have values NaN-boxed to 64-bits,
21929b4a40a7SFrank Chang * RVF and RVD can be treated equally.
21939b4a40a7SFrank Chang * We don't have to deal with the cases of: SEW > FLEN.
21949b4a40a7SFrank Chang *
21959b4a40a7SFrank Chang * If SEW < FLEN, check whether input fp register is a valid
21969b4a40a7SFrank Chang * NaN-boxed value, in which case the least-significant SEW bits
219742fe7499SMichael Tokarev * of the f register are used, else the canonical NaN value is used.
21989b4a40a7SFrank Chang */
21999b4a40a7SFrank Changstatic void do_nanbox(DisasContext *s, TCGv_i64 out, TCGv_i64 in)
22009b4a40a7SFrank Chang{
22019b4a40a7SFrank Chang    switch (s->sew) {
22029b4a40a7SFrank Chang    case 1:
22039b4a40a7SFrank Chang        gen_check_nanbox_h(out, in);
22049b4a40a7SFrank Chang        break;
22059b4a40a7SFrank Chang    case 2:
22069b4a40a7SFrank Chang        gen_check_nanbox_s(out, in);
22079b4a40a7SFrank Chang        break;
22089b4a40a7SFrank Chang    case 3:
22099b4a40a7SFrank Chang        tcg_gen_mov_i64(out, in);
22109b4a40a7SFrank Chang        break;
22119b4a40a7SFrank Chang    default:
22129b4a40a7SFrank Chang        g_assert_not_reached();
22139b4a40a7SFrank Chang    }
22149b4a40a7SFrank Chang}
22159b4a40a7SFrank Chang
2216139c1837SPaolo Bonzini/* Vector Single-Width Floating-Point Add/Subtract Instructions */
2217139c1837SPaolo Bonzini
2218139c1837SPaolo Bonzini/*
2219139c1837SPaolo Bonzini * If the current SEW does not correspond to a supported IEEE floating-point
2220139c1837SPaolo Bonzini * type, an illegal instruction exception is raised.
2221139c1837SPaolo Bonzini */
2222139c1837SPaolo Bonzinistatic bool opfvv_check(DisasContext *s, arg_rmrr *a)
2223139c1837SPaolo Bonzini{
2224f31dacd7SFrank Chang    return require_rvv(s) &&
2225f31dacd7SFrank Chang           require_rvf(s) &&
2226f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
22272bc2853fSWeiwei Li           vext_check_sss(s, a->rd, a->rs1, a->rs2, a->vm);
2228139c1837SPaolo Bonzini}
2229139c1837SPaolo Bonzini
2230139c1837SPaolo Bonzini/* OPFVV without GVEC IR */
2231139c1837SPaolo Bonzini#define GEN_OPFVV_TRANS(NAME, CHECK)                               \
2232139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
2233139c1837SPaolo Bonzini{                                                                  \
2234139c1837SPaolo Bonzini    if (CHECK(s, a)) {                                             \
2235139c1837SPaolo Bonzini        uint32_t data = 0;                                         \
2236139c1837SPaolo Bonzini        static gen_helper_gvec_4_ptr * const fns[3] = {            \
2237139c1837SPaolo Bonzini            gen_helper_##NAME##_h,                                 \
2238139c1837SPaolo Bonzini            gen_helper_##NAME##_w,                                 \
2239139c1837SPaolo Bonzini            gen_helper_##NAME##_d,                                 \
2240139c1837SPaolo Bonzini        };                                                         \
2241986c895dSFrank Chang        gen_set_rm(s, RISCV_FRM_DYN);                              \
2242139c1837SPaolo Bonzini                                                                   \
2243139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
2244139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
22455eacf7d8SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);               \
22465eacf7d8SeopXD        data =                                                     \
22475eacf7d8SeopXD            FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);\
22485b448f44SYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);               \
2249139c1837SPaolo Bonzini        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
2250139c1837SPaolo Bonzini                           vreg_ofs(s, a->rs1),                    \
2251ad75a51eSRichard Henderson                           vreg_ofs(s, a->rs2), tcg_env,           \
225281b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb,                      \
225381b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb, data,                \
2254eee2d61eSLIU Zhiwei                           fns[s->sew - 1]);                       \
2255bac802adSIvan Klokov        finalize_rvv_inst(s);                                      \
2256139c1837SPaolo Bonzini        return true;                                               \
2257139c1837SPaolo Bonzini    }                                                              \
2258139c1837SPaolo Bonzini    return false;                                                  \
2259139c1837SPaolo Bonzini}
2260139c1837SPaolo BonziniGEN_OPFVV_TRANS(vfadd_vv, opfvv_check)
2261139c1837SPaolo BonziniGEN_OPFVV_TRANS(vfsub_vv, opfvv_check)
2262139c1837SPaolo Bonzini
2263139c1837SPaolo Bonzinitypedef void gen_helper_opfvf(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv_ptr,
2264139c1837SPaolo Bonzini                              TCGv_env, TCGv_i32);
2265139c1837SPaolo Bonzini
2266139c1837SPaolo Bonzinistatic bool opfvf_trans(uint32_t vd, uint32_t rs1, uint32_t vs2,
2267139c1837SPaolo Bonzini                        uint32_t data, gen_helper_opfvf *fn, DisasContext *s)
2268139c1837SPaolo Bonzini{
2269139c1837SPaolo Bonzini    TCGv_ptr dest, src2, mask;
2270139c1837SPaolo Bonzini    TCGv_i32 desc;
22719b4a40a7SFrank Chang    TCGv_i64 t1;
2272139c1837SPaolo Bonzini
2273139c1837SPaolo Bonzini    dest = tcg_temp_new_ptr();
2274139c1837SPaolo Bonzini    mask = tcg_temp_new_ptr();
2275139c1837SPaolo Bonzini    src2 = tcg_temp_new_ptr();
227681b9ef99SDaniel Henrique Barboza    desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlenb,
227781b9ef99SDaniel Henrique Barboza                                      s->cfg_ptr->vlenb, data));
2278139c1837SPaolo Bonzini
2279ad75a51eSRichard Henderson    tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, vd));
2280ad75a51eSRichard Henderson    tcg_gen_addi_ptr(src2, tcg_env, vreg_ofs(s, vs2));
2281ad75a51eSRichard Henderson    tcg_gen_addi_ptr(mask, tcg_env, vreg_ofs(s, 0));
2282139c1837SPaolo Bonzini
22839b4a40a7SFrank Chang    /* NaN-box f[rs1] */
22849b4a40a7SFrank Chang    t1 = tcg_temp_new_i64();
22859b4a40a7SFrank Chang    do_nanbox(s, t1, cpu_fpr[rs1]);
22869b4a40a7SFrank Chang
2287ad75a51eSRichard Henderson    fn(dest, mask, t1, src2, tcg_env, desc);
2288139c1837SPaolo Bonzini
2289bac802adSIvan Klokov    finalize_rvv_inst(s);
2290139c1837SPaolo Bonzini    return true;
2291139c1837SPaolo Bonzini}
2292139c1837SPaolo Bonzini
2293139c1837SPaolo Bonzini/*
2294139c1837SPaolo Bonzini * If the current SEW does not correspond to a supported IEEE floating-point
2295139c1837SPaolo Bonzini * type, an illegal instruction exception is raised
2296139c1837SPaolo Bonzini */
2297f31dacd7SFrank Changstatic bool opfvf_check(DisasContext *s, arg_rmrr *a)
2298f31dacd7SFrank Chang{
2299f31dacd7SFrank Chang    return require_rvv(s) &&
2300f31dacd7SFrank Chang           require_rvf(s) &&
2301f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
23022bc2853fSWeiwei Li           vext_check_ss(s, a->rd, a->rs2, a->vm);
2303139c1837SPaolo Bonzini}
2304139c1837SPaolo Bonzini
2305139c1837SPaolo Bonzini/* OPFVF without GVEC IR */
2306139c1837SPaolo Bonzini#define GEN_OPFVF_TRANS(NAME, CHECK)                              \
2307139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)            \
2308139c1837SPaolo Bonzini{                                                                 \
2309139c1837SPaolo Bonzini    if (CHECK(s, a)) {                                            \
2310139c1837SPaolo Bonzini        uint32_t data = 0;                                        \
2311139c1837SPaolo Bonzini        static gen_helper_opfvf *const fns[3] = {                 \
2312139c1837SPaolo Bonzini            gen_helper_##NAME##_h,                                \
2313139c1837SPaolo Bonzini            gen_helper_##NAME##_w,                                \
2314139c1837SPaolo Bonzini            gen_helper_##NAME##_d,                                \
2315139c1837SPaolo Bonzini        };                                                        \
2316986c895dSFrank Chang        gen_set_rm(s, RISCV_FRM_DYN);                             \
2317139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, VM, a->vm);                \
2318139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);            \
23195eacf7d8SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);              \
23205eacf7d8SeopXD        data = FIELD_DP32(data, VDATA, VTA_ALL_1S,                \
23215eacf7d8SeopXD                          s->cfg_vta_all_1s);                     \
23225b448f44SYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);              \
2323139c1837SPaolo Bonzini        return opfvf_trans(a->rd, a->rs1, a->rs2, data,           \
2324139c1837SPaolo Bonzini                           fns[s->sew - 1], s);                   \
2325139c1837SPaolo Bonzini    }                                                             \
2326139c1837SPaolo Bonzini    return false;                                                 \
2327139c1837SPaolo Bonzini}
2328139c1837SPaolo Bonzini
2329139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfadd_vf,  opfvf_check)
2330139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfsub_vf,  opfvf_check)
2331139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfrsub_vf,  opfvf_check)
2332139c1837SPaolo Bonzini
2333139c1837SPaolo Bonzini/* Vector Widening Floating-Point Add/Subtract Instructions */
2334139c1837SPaolo Bonzinistatic bool opfvv_widen_check(DisasContext *s, arg_rmrr *a)
2335139c1837SPaolo Bonzini{
2336f31dacd7SFrank Chang    return require_rvv(s) &&
23377a999d4dSMax Chou           require_rvf(s) &&
2338629ccdaaSFrank Chang           require_scale_rvf(s) &&
2339f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
23402bc2853fSWeiwei Li           vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm);
2341139c1837SPaolo Bonzini}
2342139c1837SPaolo Bonzini
2343139c1837SPaolo Bonzini/* OPFVV with WIDEN */
2344139c1837SPaolo Bonzini#define GEN_OPFVV_WIDEN_TRANS(NAME, CHECK)                       \
2345139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)           \
2346139c1837SPaolo Bonzini{                                                                \
2347139c1837SPaolo Bonzini    if (CHECK(s, a)) {                                           \
2348139c1837SPaolo Bonzini        uint32_t data = 0;                                       \
2349139c1837SPaolo Bonzini        static gen_helper_gvec_4_ptr * const fns[2] = {          \
2350139c1837SPaolo Bonzini            gen_helper_##NAME##_h, gen_helper_##NAME##_w,        \
2351139c1837SPaolo Bonzini        };                                                       \
2352986c895dSFrank Chang        gen_set_rm(s, RISCV_FRM_DYN);                            \
2353139c1837SPaolo Bonzini                                                                 \
2354139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, VM, a->vm);               \
2355139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);           \
23565eacf7d8SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);             \
23575b448f44SYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);             \
2358139c1837SPaolo Bonzini        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),   \
2359139c1837SPaolo Bonzini                           vreg_ofs(s, a->rs1),                  \
2360ad75a51eSRichard Henderson                           vreg_ofs(s, a->rs2), tcg_env,         \
236181b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb,                    \
236281b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb, data,              \
2363eee2d61eSLIU Zhiwei                           fns[s->sew - 1]);                     \
2364bac802adSIvan Klokov        finalize_rvv_inst(s);                                    \
2365139c1837SPaolo Bonzini        return true;                                             \
2366139c1837SPaolo Bonzini    }                                                            \
2367139c1837SPaolo Bonzini    return false;                                                \
2368139c1837SPaolo Bonzini}
2369139c1837SPaolo Bonzini
2370139c1837SPaolo BonziniGEN_OPFVV_WIDEN_TRANS(vfwadd_vv, opfvv_widen_check)
2371139c1837SPaolo BonziniGEN_OPFVV_WIDEN_TRANS(vfwsub_vv, opfvv_widen_check)
2372139c1837SPaolo Bonzini
2373139c1837SPaolo Bonzinistatic bool opfvf_widen_check(DisasContext *s, arg_rmrr *a)
2374139c1837SPaolo Bonzini{
2375f31dacd7SFrank Chang    return require_rvv(s) &&
23767a999d4dSMax Chou           require_rvf(s) &&
2377629ccdaaSFrank Chang           require_scale_rvf(s) &&
2378f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
23792bc2853fSWeiwei Li           vext_check_ds(s, a->rd, a->rs2, a->vm);
2380139c1837SPaolo Bonzini}
2381139c1837SPaolo Bonzini
2382139c1837SPaolo Bonzini/* OPFVF with WIDEN */
2383139c1837SPaolo Bonzini#define GEN_OPFVF_WIDEN_TRANS(NAME)                              \
2384139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)           \
2385139c1837SPaolo Bonzini{                                                                \
2386139c1837SPaolo Bonzini    if (opfvf_widen_check(s, a)) {                               \
2387139c1837SPaolo Bonzini        uint32_t data = 0;                                       \
2388139c1837SPaolo Bonzini        static gen_helper_opfvf *const fns[2] = {                \
2389139c1837SPaolo Bonzini            gen_helper_##NAME##_h, gen_helper_##NAME##_w,        \
2390139c1837SPaolo Bonzini        };                                                       \
2391986c895dSFrank Chang        gen_set_rm(s, RISCV_FRM_DYN);                            \
2392139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, VM, a->vm);               \
2393139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);           \
23945eacf7d8SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);             \
23955b448f44SYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);             \
2396139c1837SPaolo Bonzini        return opfvf_trans(a->rd, a->rs1, a->rs2, data,          \
2397139c1837SPaolo Bonzini                           fns[s->sew - 1], s);                  \
2398139c1837SPaolo Bonzini    }                                                            \
2399139c1837SPaolo Bonzini    return false;                                                \
2400139c1837SPaolo Bonzini}
2401139c1837SPaolo Bonzini
2402139c1837SPaolo BonziniGEN_OPFVF_WIDEN_TRANS(vfwadd_vf)
2403139c1837SPaolo BonziniGEN_OPFVF_WIDEN_TRANS(vfwsub_vf)
2404139c1837SPaolo Bonzini
2405139c1837SPaolo Bonzinistatic bool opfwv_widen_check(DisasContext *s, arg_rmrr *a)
2406139c1837SPaolo Bonzini{
2407f31dacd7SFrank Chang    return require_rvv(s) &&
24087a999d4dSMax Chou           require_rvf(s) &&
2409629ccdaaSFrank Chang           require_scale_rvf(s) &&
2410f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
24112bc2853fSWeiwei Li           vext_check_dds(s, a->rd, a->rs1, a->rs2, a->vm);
2412139c1837SPaolo Bonzini}
2413139c1837SPaolo Bonzini
2414139c1837SPaolo Bonzini/* WIDEN OPFVV with WIDEN */
2415139c1837SPaolo Bonzini#define GEN_OPFWV_WIDEN_TRANS(NAME)                                \
2416139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
2417139c1837SPaolo Bonzini{                                                                  \
2418139c1837SPaolo Bonzini    if (opfwv_widen_check(s, a)) {                                 \
2419139c1837SPaolo Bonzini        uint32_t data = 0;                                         \
2420139c1837SPaolo Bonzini        static gen_helper_gvec_4_ptr * const fns[2] = {            \
2421139c1837SPaolo Bonzini            gen_helper_##NAME##_h, gen_helper_##NAME##_w,          \
2422139c1837SPaolo Bonzini        };                                                         \
2423986c895dSFrank Chang        gen_set_rm(s, RISCV_FRM_DYN);                              \
2424139c1837SPaolo Bonzini                                                                   \
2425139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
2426139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
24275eacf7d8SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);               \
24285b448f44SYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);               \
2429139c1837SPaolo Bonzini        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
2430139c1837SPaolo Bonzini                           vreg_ofs(s, a->rs1),                    \
2431ad75a51eSRichard Henderson                           vreg_ofs(s, a->rs2), tcg_env,           \
243281b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb,                      \
243381b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb, data,                \
2434eee2d61eSLIU Zhiwei                           fns[s->sew - 1]);                       \
2435bac802adSIvan Klokov        finalize_rvv_inst(s);                                      \
2436139c1837SPaolo Bonzini        return true;                                               \
2437139c1837SPaolo Bonzini    }                                                              \
2438139c1837SPaolo Bonzini    return false;                                                  \
2439139c1837SPaolo Bonzini}
2440139c1837SPaolo Bonzini
2441139c1837SPaolo BonziniGEN_OPFWV_WIDEN_TRANS(vfwadd_wv)
2442139c1837SPaolo BonziniGEN_OPFWV_WIDEN_TRANS(vfwsub_wv)
2443139c1837SPaolo Bonzini
2444139c1837SPaolo Bonzinistatic bool opfwf_widen_check(DisasContext *s, arg_rmrr *a)
2445139c1837SPaolo Bonzini{
2446f31dacd7SFrank Chang    return require_rvv(s) &&
24477a999d4dSMax Chou           require_rvf(s) &&
2448629ccdaaSFrank Chang           require_scale_rvf(s) &&
2449f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
24502bc2853fSWeiwei Li           vext_check_dd(s, a->rd, a->rs2, a->vm);
2451139c1837SPaolo Bonzini}
2452139c1837SPaolo Bonzini
2453139c1837SPaolo Bonzini/* WIDEN OPFVF with WIDEN */
2454139c1837SPaolo Bonzini#define GEN_OPFWF_WIDEN_TRANS(NAME)                              \
2455139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmrr *a)           \
2456139c1837SPaolo Bonzini{                                                                \
2457139c1837SPaolo Bonzini    if (opfwf_widen_check(s, a)) {                               \
2458139c1837SPaolo Bonzini        uint32_t data = 0;                                       \
2459139c1837SPaolo Bonzini        static gen_helper_opfvf *const fns[2] = {                \
2460139c1837SPaolo Bonzini            gen_helper_##NAME##_h, gen_helper_##NAME##_w,        \
2461139c1837SPaolo Bonzini        };                                                       \
2462986c895dSFrank Chang        gen_set_rm(s, RISCV_FRM_DYN);                            \
2463139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, VM, a->vm);               \
2464139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);           \
24655eacf7d8SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);             \
24665b448f44SYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);             \
2467139c1837SPaolo Bonzini        return opfvf_trans(a->rd, a->rs1, a->rs2, data,          \
2468139c1837SPaolo Bonzini                           fns[s->sew - 1], s);                  \
2469139c1837SPaolo Bonzini    }                                                            \
2470139c1837SPaolo Bonzini    return false;                                                \
2471139c1837SPaolo Bonzini}
2472139c1837SPaolo Bonzini
2473139c1837SPaolo BonziniGEN_OPFWF_WIDEN_TRANS(vfwadd_wf)
2474139c1837SPaolo BonziniGEN_OPFWF_WIDEN_TRANS(vfwsub_wf)
2475139c1837SPaolo Bonzini
2476139c1837SPaolo Bonzini/* Vector Single-Width Floating-Point Multiply/Divide Instructions */
2477139c1837SPaolo BonziniGEN_OPFVV_TRANS(vfmul_vv, opfvv_check)
2478139c1837SPaolo BonziniGEN_OPFVV_TRANS(vfdiv_vv, opfvv_check)
2479139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfmul_vf,  opfvf_check)
2480139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfdiv_vf,  opfvf_check)
2481139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfrdiv_vf,  opfvf_check)
2482139c1837SPaolo Bonzini
2483139c1837SPaolo Bonzini/* Vector Widening Floating-Point Multiply */
2484139c1837SPaolo BonziniGEN_OPFVV_WIDEN_TRANS(vfwmul_vv, opfvv_widen_check)
2485139c1837SPaolo BonziniGEN_OPFVF_WIDEN_TRANS(vfwmul_vf)
2486139c1837SPaolo Bonzini
2487139c1837SPaolo Bonzini/* Vector Single-Width Floating-Point Fused Multiply-Add Instructions */
2488139c1837SPaolo BonziniGEN_OPFVV_TRANS(vfmacc_vv, opfvv_check)
2489139c1837SPaolo BonziniGEN_OPFVV_TRANS(vfnmacc_vv, opfvv_check)
2490139c1837SPaolo BonziniGEN_OPFVV_TRANS(vfmsac_vv, opfvv_check)
2491139c1837SPaolo BonziniGEN_OPFVV_TRANS(vfnmsac_vv, opfvv_check)
2492139c1837SPaolo BonziniGEN_OPFVV_TRANS(vfmadd_vv, opfvv_check)
2493139c1837SPaolo BonziniGEN_OPFVV_TRANS(vfnmadd_vv, opfvv_check)
2494139c1837SPaolo BonziniGEN_OPFVV_TRANS(vfmsub_vv, opfvv_check)
2495139c1837SPaolo BonziniGEN_OPFVV_TRANS(vfnmsub_vv, opfvv_check)
2496139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfmacc_vf, opfvf_check)
2497139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfnmacc_vf, opfvf_check)
2498139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfmsac_vf, opfvf_check)
2499139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfnmsac_vf, opfvf_check)
2500139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfmadd_vf, opfvf_check)
2501139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfnmadd_vf, opfvf_check)
2502139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfmsub_vf, opfvf_check)
2503139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfnmsub_vf, opfvf_check)
2504139c1837SPaolo Bonzini
2505139c1837SPaolo Bonzini/* Vector Widening Floating-Point Fused Multiply-Add Instructions */
2506139c1837SPaolo BonziniGEN_OPFVV_WIDEN_TRANS(vfwmacc_vv, opfvv_widen_check)
2507139c1837SPaolo BonziniGEN_OPFVV_WIDEN_TRANS(vfwnmacc_vv, opfvv_widen_check)
2508139c1837SPaolo BonziniGEN_OPFVV_WIDEN_TRANS(vfwmsac_vv, opfvv_widen_check)
2509139c1837SPaolo BonziniGEN_OPFVV_WIDEN_TRANS(vfwnmsac_vv, opfvv_widen_check)
2510139c1837SPaolo BonziniGEN_OPFVF_WIDEN_TRANS(vfwmacc_vf)
2511139c1837SPaolo BonziniGEN_OPFVF_WIDEN_TRANS(vfwnmacc_vf)
2512139c1837SPaolo BonziniGEN_OPFVF_WIDEN_TRANS(vfwmsac_vf)
2513139c1837SPaolo BonziniGEN_OPFVF_WIDEN_TRANS(vfwnmsac_vf)
2514139c1837SPaolo Bonzini
2515139c1837SPaolo Bonzini/* Vector Floating-Point Square-Root Instruction */
2516139c1837SPaolo Bonzini
2517139c1837SPaolo Bonzini/*
2518139c1837SPaolo Bonzini * If the current SEW does not correspond to a supported IEEE floating-point
2519139c1837SPaolo Bonzini * type, an illegal instruction exception is raised
2520139c1837SPaolo Bonzini */
2521139c1837SPaolo Bonzinistatic bool opfv_check(DisasContext *s, arg_rmr *a)
2522139c1837SPaolo Bonzini{
2523f31dacd7SFrank Chang    return require_rvv(s) &&
2524f31dacd7SFrank Chang           require_rvf(s) &&
2525f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
2526f31dacd7SFrank Chang           /* OPFV instructions ignore vs1 check */
25272bc2853fSWeiwei Li           vext_check_ss(s, a->rd, a->rs2, a->vm);
2528139c1837SPaolo Bonzini}
2529139c1837SPaolo Bonzini
2530900da87aSFrank Changstatic bool do_opfv(DisasContext *s, arg_rmr *a,
2531900da87aSFrank Chang                    gen_helper_gvec_3_ptr *fn,
2532900da87aSFrank Chang                    bool (*checkfn)(DisasContext *, arg_rmr *),
2533900da87aSFrank Chang                    int rm)
2534900da87aSFrank Chang{
2535900da87aSFrank Chang    if (checkfn(s, a)) {
2536900da87aSFrank Chang        uint32_t data = 0;
25373ceeb19aSRichard Henderson        gen_set_rm_chkfrm(s, rm);
2538900da87aSFrank Chang
2539900da87aSFrank Chang        data = FIELD_DP32(data, VDATA, VM, a->vm);
2540900da87aSFrank Chang        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
25415eacf7d8SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);
25425b448f44SYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);
2543900da87aSFrank Chang        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
2544ad75a51eSRichard Henderson                           vreg_ofs(s, a->rs2), tcg_env,
254581b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb,
254681b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb, data, fn);
2547bac802adSIvan Klokov        finalize_rvv_inst(s);
2548900da87aSFrank Chang        return true;
2549900da87aSFrank Chang    }
2550900da87aSFrank Chang    return false;
2551900da87aSFrank Chang}
2552900da87aSFrank Chang
2553900da87aSFrank Chang#define GEN_OPFV_TRANS(NAME, CHECK, FRM)               \
2554139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmr *a)  \
2555139c1837SPaolo Bonzini{                                                      \
2556139c1837SPaolo Bonzini    static gen_helper_gvec_3_ptr * const fns[3] = {    \
2557139c1837SPaolo Bonzini        gen_helper_##NAME##_h,                         \
2558139c1837SPaolo Bonzini        gen_helper_##NAME##_w,                         \
2559900da87aSFrank Chang        gen_helper_##NAME##_d                          \
2560139c1837SPaolo Bonzini    };                                                 \
2561900da87aSFrank Chang    return do_opfv(s, a, fns[s->sew - 1], CHECK, FRM); \
2562139c1837SPaolo Bonzini}
2563139c1837SPaolo Bonzini
2564900da87aSFrank ChangGEN_OPFV_TRANS(vfsqrt_v, opfv_check, RISCV_FRM_DYN)
2565e848a1e5SFrank ChangGEN_OPFV_TRANS(vfrsqrt7_v, opfv_check, RISCV_FRM_DYN)
256655c35407SFrank ChangGEN_OPFV_TRANS(vfrec7_v, opfv_check, RISCV_FRM_DYN)
2567139c1837SPaolo Bonzini
2568139c1837SPaolo Bonzini/* Vector Floating-Point MIN/MAX Instructions */
2569139c1837SPaolo BonziniGEN_OPFVV_TRANS(vfmin_vv, opfvv_check)
2570139c1837SPaolo BonziniGEN_OPFVV_TRANS(vfmax_vv, opfvv_check)
2571139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfmin_vf, opfvf_check)
2572139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfmax_vf, opfvf_check)
2573139c1837SPaolo Bonzini
2574139c1837SPaolo Bonzini/* Vector Floating-Point Sign-Injection Instructions */
2575139c1837SPaolo BonziniGEN_OPFVV_TRANS(vfsgnj_vv, opfvv_check)
2576139c1837SPaolo BonziniGEN_OPFVV_TRANS(vfsgnjn_vv, opfvv_check)
2577139c1837SPaolo BonziniGEN_OPFVV_TRANS(vfsgnjx_vv, opfvv_check)
2578139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfsgnj_vf, opfvf_check)
2579139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfsgnjn_vf, opfvf_check)
2580139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfsgnjx_vf, opfvf_check)
2581139c1837SPaolo Bonzini
2582139c1837SPaolo Bonzini/* Vector Floating-Point Compare Instructions */
2583139c1837SPaolo Bonzinistatic bool opfvv_cmp_check(DisasContext *s, arg_rmrr *a)
2584139c1837SPaolo Bonzini{
2585f31dacd7SFrank Chang    return require_rvv(s) &&
2586f31dacd7SFrank Chang           require_rvf(s) &&
2587f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
25882bc2853fSWeiwei Li           vext_check_mss(s, a->rd, a->rs1, a->rs2);
2589139c1837SPaolo Bonzini}
2590139c1837SPaolo Bonzini
2591139c1837SPaolo BonziniGEN_OPFVV_TRANS(vmfeq_vv, opfvv_cmp_check)
2592139c1837SPaolo BonziniGEN_OPFVV_TRANS(vmfne_vv, opfvv_cmp_check)
2593139c1837SPaolo BonziniGEN_OPFVV_TRANS(vmflt_vv, opfvv_cmp_check)
2594139c1837SPaolo BonziniGEN_OPFVV_TRANS(vmfle_vv, opfvv_cmp_check)
2595139c1837SPaolo Bonzini
2596139c1837SPaolo Bonzinistatic bool opfvf_cmp_check(DisasContext *s, arg_rmrr *a)
2597139c1837SPaolo Bonzini{
2598f31dacd7SFrank Chang    return require_rvv(s) &&
2599f31dacd7SFrank Chang           require_rvf(s) &&
2600f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
26012bc2853fSWeiwei Li           vext_check_ms(s, a->rd, a->rs2);
2602139c1837SPaolo Bonzini}
2603139c1837SPaolo Bonzini
2604139c1837SPaolo BonziniGEN_OPFVF_TRANS(vmfeq_vf, opfvf_cmp_check)
2605139c1837SPaolo BonziniGEN_OPFVF_TRANS(vmfne_vf, opfvf_cmp_check)
2606139c1837SPaolo BonziniGEN_OPFVF_TRANS(vmflt_vf, opfvf_cmp_check)
2607139c1837SPaolo BonziniGEN_OPFVF_TRANS(vmfle_vf, opfvf_cmp_check)
2608139c1837SPaolo BonziniGEN_OPFVF_TRANS(vmfgt_vf, opfvf_cmp_check)
2609139c1837SPaolo BonziniGEN_OPFVF_TRANS(vmfge_vf, opfvf_cmp_check)
2610139c1837SPaolo Bonzini
2611139c1837SPaolo Bonzini/* Vector Floating-Point Classify Instruction */
2612900da87aSFrank ChangGEN_OPFV_TRANS(vfclass_v, opfv_check, RISCV_FRM_DYN)
2613139c1837SPaolo Bonzini
2614139c1837SPaolo Bonzini/* Vector Floating-Point Merge Instruction */
2615139c1837SPaolo BonziniGEN_OPFVF_TRANS(vfmerge_vfm,  opfvf_check)
2616139c1837SPaolo Bonzini
2617139c1837SPaolo Bonzinistatic bool trans_vfmv_v_f(DisasContext *s, arg_vfmv_v_f *a)
2618139c1837SPaolo Bonzini{
2619f31dacd7SFrank Chang    if (require_rvv(s) &&
2620f31dacd7SFrank Chang        require_rvf(s) &&
2621f31dacd7SFrank Chang        vext_check_isa_ill(s) &&
26222bc2853fSWeiwei Li        require_align(a->rd, s->lmul)) {
2623d6c4d3f2SFrank Chang        gen_set_rm(s, RISCV_FRM_DYN);
2624d6c4d3f2SFrank Chang
2625c4b3e46fSFrank Chang        TCGv_i64 t1;
2626c4b3e46fSFrank Chang
262789a32de2SeopXD        if (s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
2628c4b3e46fSFrank Chang            t1 = tcg_temp_new_i64();
2629c4b3e46fSFrank Chang            /* NaN-box f[rs1] */
2630c4b3e46fSFrank Chang            do_nanbox(s, t1, cpu_fpr[a->rs1]);
2631c4b3e46fSFrank Chang
2632139c1837SPaolo Bonzini            tcg_gen_gvec_dup_i64(s->sew, vreg_ofs(s, a->rd),
2633c4b3e46fSFrank Chang                                 MAXSZ(s), MAXSZ(s), t1);
2634139c1837SPaolo Bonzini        } else {
2635139c1837SPaolo Bonzini            TCGv_ptr dest;
2636139c1837SPaolo Bonzini            TCGv_i32 desc;
2637139c1837SPaolo Bonzini            uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul);
263889a32de2SeopXD            data = FIELD_DP32(data, VDATA, VTA, s->vta);
26395b448f44SYueh-Ting (eop) Chen            data = FIELD_DP32(data, VDATA, VMA, s->vma);
2640139c1837SPaolo Bonzini            static gen_helper_vmv_vx * const fns[3] = {
2641139c1837SPaolo Bonzini                gen_helper_vmv_v_x_h,
2642139c1837SPaolo Bonzini                gen_helper_vmv_v_x_w,
2643139c1837SPaolo Bonzini                gen_helper_vmv_v_x_d,
2644139c1837SPaolo Bonzini            };
2645139c1837SPaolo Bonzini
2646c4b3e46fSFrank Chang            t1 = tcg_temp_new_i64();
2647c4b3e46fSFrank Chang            /* NaN-box f[rs1] */
2648c4b3e46fSFrank Chang            do_nanbox(s, t1, cpu_fpr[a->rs1]);
2649c4b3e46fSFrank Chang
2650139c1837SPaolo Bonzini            dest = tcg_temp_new_ptr();
265181b9ef99SDaniel Henrique Barboza            desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlenb,
265281b9ef99SDaniel Henrique Barboza                                              s->cfg_ptr->vlenb, data));
2653ad75a51eSRichard Henderson            tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, a->rd));
2654c4b3e46fSFrank Chang
2655ad75a51eSRichard Henderson            fns[s->sew - 1](dest, t1, tcg_env, desc);
2656139c1837SPaolo Bonzini        }
2657bac802adSIvan Klokov        finalize_rvv_inst(s);
2658139c1837SPaolo Bonzini        return true;
2659139c1837SPaolo Bonzini    }
2660139c1837SPaolo Bonzini    return false;
2661139c1837SPaolo Bonzini}
2662139c1837SPaolo Bonzini
2663139c1837SPaolo Bonzini/* Single-Width Floating-Point/Integer Type-Convert Instructions */
2664900da87aSFrank Chang#define GEN_OPFV_CVT_TRANS(NAME, HELPER, FRM)               \
2665900da87aSFrank Changstatic bool trans_##NAME(DisasContext *s, arg_rmr *a)       \
2666900da87aSFrank Chang{                                                           \
2667900da87aSFrank Chang    static gen_helper_gvec_3_ptr * const fns[3] = {         \
2668900da87aSFrank Chang        gen_helper_##HELPER##_h,                            \
2669900da87aSFrank Chang        gen_helper_##HELPER##_w,                            \
2670900da87aSFrank Chang        gen_helper_##HELPER##_d                             \
2671900da87aSFrank Chang    };                                                      \
2672900da87aSFrank Chang    return do_opfv(s, a, fns[s->sew - 1], opfv_check, FRM); \
2673900da87aSFrank Chang}
2674900da87aSFrank Chang
2675900da87aSFrank ChangGEN_OPFV_CVT_TRANS(vfcvt_xu_f_v, vfcvt_xu_f_v, RISCV_FRM_DYN)
2676900da87aSFrank ChangGEN_OPFV_CVT_TRANS(vfcvt_x_f_v, vfcvt_x_f_v, RISCV_FRM_DYN)
2677900da87aSFrank ChangGEN_OPFV_CVT_TRANS(vfcvt_f_xu_v, vfcvt_f_xu_v, RISCV_FRM_DYN)
2678900da87aSFrank ChangGEN_OPFV_CVT_TRANS(vfcvt_f_x_v, vfcvt_f_x_v, RISCV_FRM_DYN)
2679900da87aSFrank Chang/* Reuse the helper functions from vfcvt.xu.f.v and vfcvt.x.f.v */
2680900da87aSFrank ChangGEN_OPFV_CVT_TRANS(vfcvt_rtz_xu_f_v, vfcvt_xu_f_v, RISCV_FRM_RTZ)
2681900da87aSFrank ChangGEN_OPFV_CVT_TRANS(vfcvt_rtz_x_f_v, vfcvt_x_f_v, RISCV_FRM_RTZ)
2682139c1837SPaolo Bonzini
2683139c1837SPaolo Bonzini/* Widening Floating-Point/Integer Type-Convert Instructions */
2684139c1837SPaolo Bonzini
2685139c1837SPaolo Bonzini/*
2686139c1837SPaolo Bonzini * If the current SEW does not correspond to a supported IEEE floating-point
2687139c1837SPaolo Bonzini * type, an illegal instruction exception is raised
2688139c1837SPaolo Bonzini */
2689139c1837SPaolo Bonzinistatic bool opfv_widen_check(DisasContext *s, arg_rmr *a)
2690139c1837SPaolo Bonzini{
2691f31dacd7SFrank Chang    return require_rvv(s) &&
2692f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
2693f31dacd7SFrank Chang           vext_check_ds(s, a->rd, a->rs2, a->vm);
2694139c1837SPaolo Bonzini}
2695139c1837SPaolo Bonzini
269691cade44SFrank Changstatic bool opxfv_widen_check(DisasContext *s, arg_rmr *a)
269791cade44SFrank Chang{
269891cade44SFrank Chang    return opfv_widen_check(s, a) &&
26992bc2853fSWeiwei Li           require_rvf(s);
270091cade44SFrank Chang}
270191cade44SFrank Chang
270291cade44SFrank Changstatic bool opffv_widen_check(DisasContext *s, arg_rmr *a)
270391cade44SFrank Chang{
270491cade44SFrank Chang    return opfv_widen_check(s, a) &&
270517b713c0SMax Chou           require_rvfmin(s) &&
270693cb52b7SMax Chou           require_scale_rvfmin(s);
270791cade44SFrank Chang}
270891cade44SFrank Chang
270991cade44SFrank Chang#define GEN_OPFV_WIDEN_TRANS(NAME, CHECK, HELPER, FRM)             \
2710139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
2711139c1837SPaolo Bonzini{                                                                  \
271291cade44SFrank Chang    if (CHECK(s, a)) {                                             \
2713139c1837SPaolo Bonzini        uint32_t data = 0;                                         \
2714139c1837SPaolo Bonzini        static gen_helper_gvec_3_ptr * const fns[2] = {            \
27153ce4c09dSFrank Chang            gen_helper_##HELPER##_h,                               \
27163ce4c09dSFrank Chang            gen_helper_##HELPER##_w,                               \
2717139c1837SPaolo Bonzini        };                                                         \
27183ceeb19aSRichard Henderson        gen_set_rm_chkfrm(s, FRM);                                 \
2719139c1837SPaolo Bonzini                                                                   \
2720139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
2721139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
27225eacf7d8SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);               \
27235b448f44SYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);               \
2724139c1837SPaolo Bonzini        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
2725ad75a51eSRichard Henderson                           vreg_ofs(s, a->rs2), tcg_env,           \
272681b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb,                      \
272781b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb, data,                \
2728eee2d61eSLIU Zhiwei                           fns[s->sew - 1]);                       \
2729bac802adSIvan Klokov        finalize_rvv_inst(s);                                      \
2730139c1837SPaolo Bonzini        return true;                                               \
2731139c1837SPaolo Bonzini    }                                                              \
2732139c1837SPaolo Bonzini    return false;                                                  \
2733139c1837SPaolo Bonzini}
2734139c1837SPaolo Bonzini
273591cade44SFrank ChangGEN_OPFV_WIDEN_TRANS(vfwcvt_xu_f_v, opxfv_widen_check, vfwcvt_xu_f_v,
273691cade44SFrank Chang                     RISCV_FRM_DYN)
273791cade44SFrank ChangGEN_OPFV_WIDEN_TRANS(vfwcvt_x_f_v, opxfv_widen_check, vfwcvt_x_f_v,
273891cade44SFrank Chang                     RISCV_FRM_DYN)
273991cade44SFrank ChangGEN_OPFV_WIDEN_TRANS(vfwcvt_f_f_v, opffv_widen_check, vfwcvt_f_f_v,
274091cade44SFrank Chang                     RISCV_FRM_DYN)
27413ce4c09dSFrank Chang/* Reuse the helper functions from vfwcvt.xu.f.v and vfwcvt.x.f.v */
274291cade44SFrank ChangGEN_OPFV_WIDEN_TRANS(vfwcvt_rtz_xu_f_v, opxfv_widen_check, vfwcvt_xu_f_v,
274391cade44SFrank Chang                     RISCV_FRM_RTZ)
274491cade44SFrank ChangGEN_OPFV_WIDEN_TRANS(vfwcvt_rtz_x_f_v, opxfv_widen_check, vfwcvt_x_f_v,
274591cade44SFrank Chang                     RISCV_FRM_RTZ)
27463ce4c09dSFrank Chang
27473ce4c09dSFrank Changstatic bool opfxv_widen_check(DisasContext *s, arg_rmr *a)
27483ce4c09dSFrank Chang{
27493ce4c09dSFrank Chang    return require_rvv(s) &&
27503ce4c09dSFrank Chang           require_scale_rvf(s) &&
27513ce4c09dSFrank Chang           vext_check_isa_ill(s) &&
27523ce4c09dSFrank Chang           /* OPFV widening instructions ignore vs1 check */
27532bc2853fSWeiwei Li           vext_check_ds(s, a->rd, a->rs2, a->vm);
27543ce4c09dSFrank Chang}
27553ce4c09dSFrank Chang
27563ce4c09dSFrank Chang#define GEN_OPFXV_WIDEN_TRANS(NAME)                                \
27573ce4c09dSFrank Changstatic bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
27583ce4c09dSFrank Chang{                                                                  \
27593ce4c09dSFrank Chang    if (opfxv_widen_check(s, a)) {                                 \
27603ce4c09dSFrank Chang        uint32_t data = 0;                                         \
27613ce4c09dSFrank Chang        static gen_helper_gvec_3_ptr * const fns[3] = {            \
27623ce4c09dSFrank Chang            gen_helper_##NAME##_b,                                 \
27633ce4c09dSFrank Chang            gen_helper_##NAME##_h,                                 \
27643ce4c09dSFrank Chang            gen_helper_##NAME##_w,                                 \
27653ce4c09dSFrank Chang        };                                                         \
27663ce4c09dSFrank Chang        gen_set_rm(s, RISCV_FRM_DYN);                              \
27673ce4c09dSFrank Chang                                                                   \
27683ce4c09dSFrank Chang        data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
27695eacf7d8SeopXD        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
27705eacf7d8SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);               \
27715b448f44SYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);               \
27723ce4c09dSFrank Chang        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
2773ad75a51eSRichard Henderson                           vreg_ofs(s, a->rs2), tcg_env,           \
277481b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb,                      \
277581b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb, data,                \
27763ce4c09dSFrank Chang                           fns[s->sew]);                           \
2777bac802adSIvan Klokov        finalize_rvv_inst(s);                                      \
27783ce4c09dSFrank Chang        return true;                                               \
27793ce4c09dSFrank Chang    }                                                              \
27803ce4c09dSFrank Chang    return false;                                                  \
27813ce4c09dSFrank Chang}
27823ce4c09dSFrank Chang
27833ce4c09dSFrank ChangGEN_OPFXV_WIDEN_TRANS(vfwcvt_f_xu_v)
27843ce4c09dSFrank ChangGEN_OPFXV_WIDEN_TRANS(vfwcvt_f_x_v)
2785139c1837SPaolo Bonzini
2786139c1837SPaolo Bonzini/* Narrowing Floating-Point/Integer Type-Convert Instructions */
2787139c1837SPaolo Bonzini
2788139c1837SPaolo Bonzini/*
2789139c1837SPaolo Bonzini * If the current SEW does not correspond to a supported IEEE floating-point
2790139c1837SPaolo Bonzini * type, an illegal instruction exception is raised
2791139c1837SPaolo Bonzini */
2792139c1837SPaolo Bonzinistatic bool opfv_narrow_check(DisasContext *s, arg_rmr *a)
2793139c1837SPaolo Bonzini{
2794f31dacd7SFrank Chang    return require_rvv(s) &&
2795f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
2796f31dacd7SFrank Chang           /* OPFV narrowing instructions ignore vs1 check */
2797f31dacd7SFrank Chang           vext_check_sd(s, a->rd, a->rs2, a->vm);
2798139c1837SPaolo Bonzini}
2799139c1837SPaolo Bonzini
280079e6176eSFrank Changstatic bool opfxv_narrow_check(DisasContext *s, arg_rmr *a)
280179e6176eSFrank Chang{
280279e6176eSFrank Chang    return opfv_narrow_check(s, a) &&
280379e6176eSFrank Chang           require_rvf(s) &&
28042bc2853fSWeiwei Li           (s->sew != MO_64);
280579e6176eSFrank Chang}
280679e6176eSFrank Chang
280779e6176eSFrank Changstatic bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
280879e6176eSFrank Chang{
280979e6176eSFrank Chang    return opfv_narrow_check(s, a) &&
281017b713c0SMax Chou           require_rvfmin(s) &&
281193cb52b7SMax Chou           require_scale_rvfmin(s);
2812e80865e5SWeiwei Li}
2813e80865e5SWeiwei Li
2814e80865e5SWeiwei Listatic bool opffv_rod_narrow_check(DisasContext *s, arg_rmr *a)
2815e80865e5SWeiwei Li{
2816e80865e5SWeiwei Li    return opfv_narrow_check(s, a) &&
2817692f33a3SMax Chou           require_rvf(s) &&
281893cb52b7SMax Chou           require_scale_rvf(s);
281979e6176eSFrank Chang}
282079e6176eSFrank Chang
282179e6176eSFrank Chang#define GEN_OPFV_NARROW_TRANS(NAME, CHECK, HELPER, FRM)            \
2822139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
2823139c1837SPaolo Bonzini{                                                                  \
282479e6176eSFrank Chang    if (CHECK(s, a)) {                                             \
2825139c1837SPaolo Bonzini        uint32_t data = 0;                                         \
2826139c1837SPaolo Bonzini        static gen_helper_gvec_3_ptr * const fns[2] = {            \
2827ff679b58SFrank Chang            gen_helper_##HELPER##_h,                               \
2828ff679b58SFrank Chang            gen_helper_##HELPER##_w,                               \
2829139c1837SPaolo Bonzini        };                                                         \
28303ceeb19aSRichard Henderson        gen_set_rm_chkfrm(s, FRM);                                 \
2831139c1837SPaolo Bonzini                                                                   \
2832139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
2833139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
28345eacf7d8SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);               \
28355b448f44SYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);               \
2836139c1837SPaolo Bonzini        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
2837ad75a51eSRichard Henderson                           vreg_ofs(s, a->rs2), tcg_env,           \
283881b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb,                      \
283981b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb, data,                \
2840eee2d61eSLIU Zhiwei                           fns[s->sew - 1]);                       \
2841bac802adSIvan Klokov        finalize_rvv_inst(s);                                      \
2842139c1837SPaolo Bonzini        return true;                                               \
2843139c1837SPaolo Bonzini    }                                                              \
2844139c1837SPaolo Bonzini    return false;                                                  \
2845139c1837SPaolo Bonzini}
2846139c1837SPaolo Bonzini
284779e6176eSFrank ChangGEN_OPFV_NARROW_TRANS(vfncvt_f_xu_w, opfxv_narrow_check, vfncvt_f_xu_w,
284879e6176eSFrank Chang                      RISCV_FRM_DYN)
284979e6176eSFrank ChangGEN_OPFV_NARROW_TRANS(vfncvt_f_x_w, opfxv_narrow_check, vfncvt_f_x_w,
285079e6176eSFrank Chang                      RISCV_FRM_DYN)
285179e6176eSFrank ChangGEN_OPFV_NARROW_TRANS(vfncvt_f_f_w, opffv_narrow_check, vfncvt_f_f_w,
285279e6176eSFrank Chang                      RISCV_FRM_DYN)
2853ff679b58SFrank Chang/* Reuse the helper function from vfncvt.f.f.w */
2854e80865e5SWeiwei LiGEN_OPFV_NARROW_TRANS(vfncvt_rod_f_f_w, opffv_rod_narrow_check, vfncvt_f_f_w,
285579e6176eSFrank Chang                      RISCV_FRM_ROD)
2856ff679b58SFrank Chang
2857ff679b58SFrank Changstatic bool opxfv_narrow_check(DisasContext *s, arg_rmr *a)
2858ff679b58SFrank Chang{
2859ff679b58SFrank Chang    return require_rvv(s) &&
2860ff679b58SFrank Chang           require_scale_rvf(s) &&
2861ff679b58SFrank Chang           vext_check_isa_ill(s) &&
2862ff679b58SFrank Chang           /* OPFV narrowing instructions ignore vs1 check */
28632bc2853fSWeiwei Li           vext_check_sd(s, a->rd, a->rs2, a->vm);
2864ff679b58SFrank Chang}
2865ff679b58SFrank Chang
2866ff679b58SFrank Chang#define GEN_OPXFV_NARROW_TRANS(NAME, HELPER, FRM)                  \
2867ff679b58SFrank Changstatic bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
2868ff679b58SFrank Chang{                                                                  \
2869ff679b58SFrank Chang    if (opxfv_narrow_check(s, a)) {                                \
2870ff679b58SFrank Chang        uint32_t data = 0;                                         \
2871ff679b58SFrank Chang        static gen_helper_gvec_3_ptr * const fns[3] = {            \
2872ff679b58SFrank Chang            gen_helper_##HELPER##_b,                               \
2873ff679b58SFrank Chang            gen_helper_##HELPER##_h,                               \
2874ff679b58SFrank Chang            gen_helper_##HELPER##_w,                               \
2875ff679b58SFrank Chang        };                                                         \
28763ceeb19aSRichard Henderson        gen_set_rm_chkfrm(s, FRM);                                 \
2877ff679b58SFrank Chang                                                                   \
2878ff679b58SFrank Chang        data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
28795eacf7d8SeopXD        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
28805eacf7d8SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);               \
28815b448f44SYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);               \
2882ff679b58SFrank Chang        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
2883ad75a51eSRichard Henderson                           vreg_ofs(s, a->rs2), tcg_env,           \
288481b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb,                      \
288581b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb, data,                \
2886ff679b58SFrank Chang                           fns[s->sew]);                           \
2887bac802adSIvan Klokov        finalize_rvv_inst(s);                                      \
2888ff679b58SFrank Chang        return true;                                               \
2889ff679b58SFrank Chang    }                                                              \
2890ff679b58SFrank Chang    return false;                                                  \
2891ff679b58SFrank Chang}
2892ff679b58SFrank Chang
2893ff679b58SFrank ChangGEN_OPXFV_NARROW_TRANS(vfncvt_xu_f_w, vfncvt_xu_f_w, RISCV_FRM_DYN)
2894ff679b58SFrank ChangGEN_OPXFV_NARROW_TRANS(vfncvt_x_f_w, vfncvt_x_f_w, RISCV_FRM_DYN)
2895ff679b58SFrank Chang/* Reuse the helper functions from vfncvt.xu.f.w and vfncvt.x.f.w */
2896ff679b58SFrank ChangGEN_OPXFV_NARROW_TRANS(vfncvt_rtz_xu_f_w, vfncvt_xu_f_w, RISCV_FRM_RTZ)
2897ff679b58SFrank ChangGEN_OPXFV_NARROW_TRANS(vfncvt_rtz_x_f_w, vfncvt_x_f_w, RISCV_FRM_RTZ)
2898139c1837SPaolo Bonzini
2899139c1837SPaolo Bonzini/*
2900139c1837SPaolo Bonzini *** Vector Reduction Operations
2901139c1837SPaolo Bonzini */
2902139c1837SPaolo Bonzini/* Vector Single-Width Integer Reduction Instructions */
2903139c1837SPaolo Bonzinistatic bool reduction_check(DisasContext *s, arg_rmrr *a)
2904139c1837SPaolo Bonzini{
2905f31dacd7SFrank Chang    return require_rvv(s) &&
2906f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
2907f31dacd7SFrank Chang           vext_check_reduction(s, a->rs2);
2908139c1837SPaolo Bonzini}
2909139c1837SPaolo Bonzini
2910139c1837SPaolo BonziniGEN_OPIVV_TRANS(vredsum_vs, reduction_check)
2911139c1837SPaolo BonziniGEN_OPIVV_TRANS(vredmaxu_vs, reduction_check)
2912139c1837SPaolo BonziniGEN_OPIVV_TRANS(vredmax_vs, reduction_check)
2913139c1837SPaolo BonziniGEN_OPIVV_TRANS(vredminu_vs, reduction_check)
2914139c1837SPaolo BonziniGEN_OPIVV_TRANS(vredmin_vs, reduction_check)
2915139c1837SPaolo BonziniGEN_OPIVV_TRANS(vredand_vs, reduction_check)
2916139c1837SPaolo BonziniGEN_OPIVV_TRANS(vredor_vs, reduction_check)
2917139c1837SPaolo BonziniGEN_OPIVV_TRANS(vredxor_vs, reduction_check)
2918139c1837SPaolo Bonzini
2919139c1837SPaolo Bonzini/* Vector Widening Integer Reduction Instructions */
2920f31dacd7SFrank Changstatic bool reduction_widen_check(DisasContext *s, arg_rmrr *a)
2921f31dacd7SFrank Chang{
2922cc13aa36SFrank Chang    return reduction_check(s, a) && (s->sew < MO_64) &&
292379bf3b51SPhilipp Tomsich           ((s->sew + 1) <= (s->cfg_ptr->elen >> 4));
2924f31dacd7SFrank Chang}
2925f31dacd7SFrank Chang
2926f31dacd7SFrank ChangGEN_OPIVV_WIDEN_TRANS(vwredsum_vs, reduction_widen_check)
2927f31dacd7SFrank ChangGEN_OPIVV_WIDEN_TRANS(vwredsumu_vs, reduction_widen_check)
2928139c1837SPaolo Bonzini
2929139c1837SPaolo Bonzini/* Vector Single-Width Floating-Point Reduction Instructions */
293008b60eebSFrank Changstatic bool freduction_check(DisasContext *s, arg_rmrr *a)
293108b60eebSFrank Chang{
293208b60eebSFrank Chang    return reduction_check(s, a) &&
29332bc2853fSWeiwei Li           require_rvf(s);
293408b60eebSFrank Chang}
293508b60eebSFrank Chang
2936a3ab69f9SYang LiuGEN_OPFVV_TRANS(vfredusum_vs, freduction_check)
2937a3ab69f9SYang LiuGEN_OPFVV_TRANS(vfredosum_vs, freduction_check)
293808b60eebSFrank ChangGEN_OPFVV_TRANS(vfredmax_vs, freduction_check)
293908b60eebSFrank ChangGEN_OPFVV_TRANS(vfredmin_vs, freduction_check)
2940139c1837SPaolo Bonzini
2941139c1837SPaolo Bonzini/* Vector Widening Floating-Point Reduction Instructions */
2942b8dd99f2SFrank Changstatic bool freduction_widen_check(DisasContext *s, arg_rmrr *a)
2943b8dd99f2SFrank Chang{
2944b8dd99f2SFrank Chang    return reduction_widen_check(s, a) &&
29457a999d4dSMax Chou           require_rvf(s) &&
294693cb52b7SMax Chou           require_scale_rvf(s);
2947b8dd99f2SFrank Chang}
2948b8dd99f2SFrank Chang
2949a3ab69f9SYang LiuGEN_OPFVV_WIDEN_TRANS(vfwredusum_vs, freduction_widen_check)
2950a3ab69f9SYang LiuGEN_OPFVV_WIDEN_TRANS(vfwredosum_vs, freduction_widen_check)
2951139c1837SPaolo Bonzini
2952139c1837SPaolo Bonzini/*
2953139c1837SPaolo Bonzini *** Vector Mask Operations
2954139c1837SPaolo Bonzini */
2955139c1837SPaolo Bonzini
2956139c1837SPaolo Bonzini/* Vector Mask-Register Logical Instructions */
2957139c1837SPaolo Bonzini#define GEN_MM_TRANS(NAME)                                         \
2958139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_r *a)                \
2959139c1837SPaolo Bonzini{                                                                  \
296050f6696cSFrank Chang    if (require_rvv(s) &&                                          \
296150f6696cSFrank Chang        vext_check_isa_ill(s)) {                                   \
2962139c1837SPaolo Bonzini        uint32_t data = 0;                                         \
2963139c1837SPaolo Bonzini        gen_helper_gvec_4_ptr *fn = gen_helper_##NAME;             \
2964139c1837SPaolo Bonzini                                                                   \
2965139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
2966acc6ffd4SeopXD        data =                                                     \
2967acc6ffd4SeopXD            FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);\
2968139c1837SPaolo Bonzini        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
2969139c1837SPaolo Bonzini                           vreg_ofs(s, a->rs1),                    \
2970ad75a51eSRichard Henderson                           vreg_ofs(s, a->rs2), tcg_env,           \
297181b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb,                      \
297281b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb, data, fn);           \
2973bac802adSIvan Klokov        finalize_rvv_inst(s);                                      \
2974139c1837SPaolo Bonzini        return true;                                               \
2975139c1837SPaolo Bonzini    }                                                              \
2976139c1837SPaolo Bonzini    return false;                                                  \
2977139c1837SPaolo Bonzini}
2978139c1837SPaolo Bonzini
2979139c1837SPaolo BonziniGEN_MM_TRANS(vmand_mm)
2980139c1837SPaolo BonziniGEN_MM_TRANS(vmnand_mm)
29819c0d2559SFrank ChangGEN_MM_TRANS(vmandn_mm)
2982139c1837SPaolo BonziniGEN_MM_TRANS(vmxor_mm)
2983139c1837SPaolo BonziniGEN_MM_TRANS(vmor_mm)
2984139c1837SPaolo BonziniGEN_MM_TRANS(vmnor_mm)
29859c0d2559SFrank ChangGEN_MM_TRANS(vmorn_mm)
2986139c1837SPaolo BonziniGEN_MM_TRANS(vmxnor_mm)
2987139c1837SPaolo Bonzini
29880014aa74SFrank Chang/* Vector count population in mask vcpop */
29890014aa74SFrank Changstatic bool trans_vcpop_m(DisasContext *s, arg_rmr *a)
2990139c1837SPaolo Bonzini{
2991f31dacd7SFrank Chang    if (require_rvv(s) &&
2992f714361eSFrank Chang        vext_check_isa_ill(s) &&
29934acaa133SLIU Zhiwei        s->vstart_eq_zero) {
2994139c1837SPaolo Bonzini        TCGv_ptr src2, mask;
2995139c1837SPaolo Bonzini        TCGv dst;
2996139c1837SPaolo Bonzini        TCGv_i32 desc;
2997139c1837SPaolo Bonzini        uint32_t data = 0;
2998139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, VM, a->vm);
2999139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
3000139c1837SPaolo Bonzini
3001139c1837SPaolo Bonzini        mask = tcg_temp_new_ptr();
3002139c1837SPaolo Bonzini        src2 = tcg_temp_new_ptr();
30038e034ae4SRichard Henderson        dst = dest_gpr(s, a->rd);
300481b9ef99SDaniel Henrique Barboza        desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlenb,
300581b9ef99SDaniel Henrique Barboza                                          s->cfg_ptr->vlenb, data));
3006139c1837SPaolo Bonzini
3007ad75a51eSRichard Henderson        tcg_gen_addi_ptr(src2, tcg_env, vreg_ofs(s, a->rs2));
3008ad75a51eSRichard Henderson        tcg_gen_addi_ptr(mask, tcg_env, vreg_ofs(s, 0));
3009139c1837SPaolo Bonzini
3010ad75a51eSRichard Henderson        gen_helper_vcpop_m(dst, mask, src2, tcg_env, desc);
3011867c8196SRichard Henderson        gen_set_gpr(s, a->rd, dst);
3012139c1837SPaolo Bonzini        return true;
3013139c1837SPaolo Bonzini    }
3014139c1837SPaolo Bonzini    return false;
3015139c1837SPaolo Bonzini}
3016139c1837SPaolo Bonzini
3017139c1837SPaolo Bonzini/* vmfirst find-first-set mask bit */
3018d71a24fcSFrank Changstatic bool trans_vfirst_m(DisasContext *s, arg_rmr *a)
3019139c1837SPaolo Bonzini{
3020f31dacd7SFrank Chang    if (require_rvv(s) &&
3021f714361eSFrank Chang        vext_check_isa_ill(s) &&
30224acaa133SLIU Zhiwei        s->vstart_eq_zero) {
3023139c1837SPaolo Bonzini        TCGv_ptr src2, mask;
3024139c1837SPaolo Bonzini        TCGv dst;
3025139c1837SPaolo Bonzini        TCGv_i32 desc;
3026139c1837SPaolo Bonzini        uint32_t data = 0;
3027139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, VM, a->vm);
3028139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
3029139c1837SPaolo Bonzini
3030139c1837SPaolo Bonzini        mask = tcg_temp_new_ptr();
3031139c1837SPaolo Bonzini        src2 = tcg_temp_new_ptr();
30328e034ae4SRichard Henderson        dst = dest_gpr(s, a->rd);
303381b9ef99SDaniel Henrique Barboza        desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlenb,
303481b9ef99SDaniel Henrique Barboza                                          s->cfg_ptr->vlenb, data));
3035139c1837SPaolo Bonzini
3036ad75a51eSRichard Henderson        tcg_gen_addi_ptr(src2, tcg_env, vreg_ofs(s, a->rs2));
3037ad75a51eSRichard Henderson        tcg_gen_addi_ptr(mask, tcg_env, vreg_ofs(s, 0));
3038139c1837SPaolo Bonzini
3039ad75a51eSRichard Henderson        gen_helper_vfirst_m(dst, mask, src2, tcg_env, desc);
3040867c8196SRichard Henderson        gen_set_gpr(s, a->rd, dst);
3041139c1837SPaolo Bonzini        return true;
3042139c1837SPaolo Bonzini    }
3043139c1837SPaolo Bonzini    return false;
3044139c1837SPaolo Bonzini}
3045139c1837SPaolo Bonzini
30463b57254dSWeiwei Li/*
30473b57254dSWeiwei Li * vmsbf.m set-before-first mask bit
30483b57254dSWeiwei Li * vmsif.m set-including-first mask bit
30493b57254dSWeiwei Li * vmsof.m set-only-first mask bit
30503b57254dSWeiwei Li */
3051139c1837SPaolo Bonzini#define GEN_M_TRANS(NAME)                                          \
3052139c1837SPaolo Bonzinistatic bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
3053139c1837SPaolo Bonzini{                                                                  \
305440c1495dSFrank Chang    if (require_rvv(s) &&                                          \
305540c1495dSFrank Chang        vext_check_isa_ill(s) &&                                   \
305640c1495dSFrank Chang        require_vm(a->vm, a->rd) &&                                \
3057f714361eSFrank Chang        (a->rd != a->rs2) &&                                       \
30584acaa133SLIU Zhiwei        s->vstart_eq_zero) {                                       \
3059139c1837SPaolo Bonzini        uint32_t data = 0;                                         \
3060139c1837SPaolo Bonzini        gen_helper_gvec_3_ptr *fn = gen_helper_##NAME;             \
3061139c1837SPaolo Bonzini                                                                   \
3062139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
3063139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
3064acc6ffd4SeopXD        data =                                                     \
3065acc6ffd4SeopXD            FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);\
306635f2d795SYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);               \
3067139c1837SPaolo Bonzini        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd),                     \
3068139c1837SPaolo Bonzini                           vreg_ofs(s, 0), vreg_ofs(s, a->rs2),    \
306981b9ef99SDaniel Henrique Barboza                           tcg_env, s->cfg_ptr->vlenb,             \
307081b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb,                      \
3071eee2d61eSLIU Zhiwei                           data, fn);                              \
3072bac802adSIvan Klokov        finalize_rvv_inst(s);                                      \
3073139c1837SPaolo Bonzini        return true;                                               \
3074139c1837SPaolo Bonzini    }                                                              \
3075139c1837SPaolo Bonzini    return false;                                                  \
3076139c1837SPaolo Bonzini}
3077139c1837SPaolo Bonzini
3078139c1837SPaolo BonziniGEN_M_TRANS(vmsbf_m)
3079139c1837SPaolo BonziniGEN_M_TRANS(vmsif_m)
3080139c1837SPaolo BonziniGEN_M_TRANS(vmsof_m)
3081139c1837SPaolo Bonzini
3082ee17eaa1SFrank Chang/*
3083ee17eaa1SFrank Chang * Vector Iota Instruction
3084ee17eaa1SFrank Chang *
3085ee17eaa1SFrank Chang * 1. The destination register cannot overlap the source register.
3086ee17eaa1SFrank Chang * 2. If masked, cannot overlap the mask register ('v0').
3087ee17eaa1SFrank Chang * 3. An illegal instruction exception is raised if vstart is non-zero.
3088ee17eaa1SFrank Chang */
3089139c1837SPaolo Bonzinistatic bool trans_viota_m(DisasContext *s, arg_viota_m *a)
3090139c1837SPaolo Bonzini{
3091f31dacd7SFrank Chang    if (require_rvv(s) &&
3092f31dacd7SFrank Chang        vext_check_isa_ill(s) &&
3093ee17eaa1SFrank Chang        !is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs2, 1) &&
3094f31dacd7SFrank Chang        require_vm(a->vm, a->rd) &&
3095f714361eSFrank Chang        require_align(a->rd, s->lmul) &&
30964acaa133SLIU Zhiwei        s->vstart_eq_zero) {
3097139c1837SPaolo Bonzini        uint32_t data = 0;
3098139c1837SPaolo Bonzini
3099139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, VM, a->vm);
3100139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
3101acc6ffd4SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);
310235f2d795SYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);
3103139c1837SPaolo Bonzini        static gen_helper_gvec_3_ptr * const fns[4] = {
3104139c1837SPaolo Bonzini            gen_helper_viota_m_b, gen_helper_viota_m_h,
3105139c1837SPaolo Bonzini            gen_helper_viota_m_w, gen_helper_viota_m_d,
3106139c1837SPaolo Bonzini        };
3107139c1837SPaolo Bonzini        tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
3108ad75a51eSRichard Henderson                           vreg_ofs(s, a->rs2), tcg_env,
310981b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb,
311081b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb, data, fns[s->sew]);
3111bac802adSIvan Klokov        finalize_rvv_inst(s);
3112139c1837SPaolo Bonzini        return true;
3113139c1837SPaolo Bonzini    }
3114139c1837SPaolo Bonzini    return false;
3115139c1837SPaolo Bonzini}
3116139c1837SPaolo Bonzini
3117139c1837SPaolo Bonzini/* Vector Element Index Instruction */
3118139c1837SPaolo Bonzinistatic bool trans_vid_v(DisasContext *s, arg_vid_v *a)
3119139c1837SPaolo Bonzini{
3120f31dacd7SFrank Chang    if (require_rvv(s) &&
3121f31dacd7SFrank Chang        vext_check_isa_ill(s) &&
3122f31dacd7SFrank Chang        require_align(a->rd, s->lmul) &&
3123f31dacd7SFrank Chang        require_vm(a->vm, a->rd)) {
3124139c1837SPaolo Bonzini        uint32_t data = 0;
3125139c1837SPaolo Bonzini
3126139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, VM, a->vm);
3127139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
3128acc6ffd4SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);
312935f2d795SYueh-Ting (eop) Chen        data = FIELD_DP32(data, VDATA, VMA, s->vma);
3130139c1837SPaolo Bonzini        static gen_helper_gvec_2_ptr * const fns[4] = {
3131139c1837SPaolo Bonzini            gen_helper_vid_v_b, gen_helper_vid_v_h,
3132139c1837SPaolo Bonzini            gen_helper_vid_v_w, gen_helper_vid_v_d,
3133139c1837SPaolo Bonzini        };
3134139c1837SPaolo Bonzini        tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
313581b9ef99SDaniel Henrique Barboza                           tcg_env, s->cfg_ptr->vlenb,
313681b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb,
3137eee2d61eSLIU Zhiwei                           data, fns[s->sew]);
3138bac802adSIvan Klokov        finalize_rvv_inst(s);
3139139c1837SPaolo Bonzini        return true;
3140139c1837SPaolo Bonzini    }
3141139c1837SPaolo Bonzini    return false;
3142139c1837SPaolo Bonzini}
3143139c1837SPaolo Bonzini
3144139c1837SPaolo Bonzini/*
3145139c1837SPaolo Bonzini *** Vector Permutation Instructions
3146139c1837SPaolo Bonzini */
3147139c1837SPaolo Bonzini
3148139c1837SPaolo Bonzinistatic void load_element(TCGv_i64 dest, TCGv_ptr base,
3149308ee805SFrank Chang                         int ofs, int sew, bool sign)
3150139c1837SPaolo Bonzini{
3151139c1837SPaolo Bonzini    switch (sew) {
3152139c1837SPaolo Bonzini    case MO_8:
3153308ee805SFrank Chang        if (!sign) {
3154139c1837SPaolo Bonzini            tcg_gen_ld8u_i64(dest, base, ofs);
3155308ee805SFrank Chang        } else {
3156308ee805SFrank Chang            tcg_gen_ld8s_i64(dest, base, ofs);
3157308ee805SFrank Chang        }
3158139c1837SPaolo Bonzini        break;
3159139c1837SPaolo Bonzini    case MO_16:
3160308ee805SFrank Chang        if (!sign) {
3161139c1837SPaolo Bonzini            tcg_gen_ld16u_i64(dest, base, ofs);
3162308ee805SFrank Chang        } else {
3163308ee805SFrank Chang            tcg_gen_ld16s_i64(dest, base, ofs);
3164308ee805SFrank Chang        }
3165139c1837SPaolo Bonzini        break;
3166139c1837SPaolo Bonzini    case MO_32:
3167308ee805SFrank Chang        if (!sign) {
3168139c1837SPaolo Bonzini            tcg_gen_ld32u_i64(dest, base, ofs);
3169308ee805SFrank Chang        } else {
3170308ee805SFrank Chang            tcg_gen_ld32s_i64(dest, base, ofs);
3171308ee805SFrank Chang        }
3172139c1837SPaolo Bonzini        break;
3173139c1837SPaolo Bonzini    case MO_64:
3174139c1837SPaolo Bonzini        tcg_gen_ld_i64(dest, base, ofs);
3175139c1837SPaolo Bonzini        break;
3176139c1837SPaolo Bonzini    default:
3177139c1837SPaolo Bonzini        g_assert_not_reached();
3178139c1837SPaolo Bonzini    }
3179139c1837SPaolo Bonzini}
3180139c1837SPaolo Bonzini
318142fe7499SMichael Tokarev/* offset of the idx element with base register r */
3182139c1837SPaolo Bonzinistatic uint32_t endian_ofs(DisasContext *s, int r, int idx)
3183139c1837SPaolo Bonzini{
3184e03b5686SMarc-André Lureau#if HOST_BIG_ENDIAN
3185139c1837SPaolo Bonzini    return vreg_ofs(s, r) + ((idx ^ (7 >> s->sew)) << s->sew);
3186139c1837SPaolo Bonzini#else
3187139c1837SPaolo Bonzini    return vreg_ofs(s, r) + (idx << s->sew);
3188139c1837SPaolo Bonzini#endif
3189139c1837SPaolo Bonzini}
3190139c1837SPaolo Bonzini
3191139c1837SPaolo Bonzini/* adjust the index according to the endian */
3192139c1837SPaolo Bonzinistatic void endian_adjust(TCGv_i32 ofs, int sew)
3193139c1837SPaolo Bonzini{
3194e03b5686SMarc-André Lureau#if HOST_BIG_ENDIAN
3195139c1837SPaolo Bonzini    tcg_gen_xori_i32(ofs, ofs, 7 >> sew);
3196139c1837SPaolo Bonzini#endif
3197139c1837SPaolo Bonzini}
3198139c1837SPaolo Bonzini
3199139c1837SPaolo Bonzini/* Load idx >= VLMAX ? 0 : vreg[idx] */
3200139c1837SPaolo Bonzinistatic void vec_element_loadx(DisasContext *s, TCGv_i64 dest,
3201139c1837SPaolo Bonzini                              int vreg, TCGv idx, int vlmax)
3202139c1837SPaolo Bonzini{
3203139c1837SPaolo Bonzini    TCGv_i32 ofs = tcg_temp_new_i32();
3204139c1837SPaolo Bonzini    TCGv_ptr base = tcg_temp_new_ptr();
3205139c1837SPaolo Bonzini    TCGv_i64 t_idx = tcg_temp_new_i64();
3206139c1837SPaolo Bonzini    TCGv_i64 t_vlmax, t_zero;
3207139c1837SPaolo Bonzini
3208139c1837SPaolo Bonzini    /*
3209139c1837SPaolo Bonzini     * Mask the index to the length so that we do
3210139c1837SPaolo Bonzini     * not produce an out-of-range load.
3211139c1837SPaolo Bonzini     */
3212139c1837SPaolo Bonzini    tcg_gen_trunc_tl_i32(ofs, idx);
3213139c1837SPaolo Bonzini    tcg_gen_andi_i32(ofs, ofs, vlmax - 1);
3214139c1837SPaolo Bonzini
3215139c1837SPaolo Bonzini    /* Convert the index to an offset. */
3216139c1837SPaolo Bonzini    endian_adjust(ofs, s->sew);
3217139c1837SPaolo Bonzini    tcg_gen_shli_i32(ofs, ofs, s->sew);
3218139c1837SPaolo Bonzini
3219139c1837SPaolo Bonzini    /* Convert the index to a pointer. */
3220139c1837SPaolo Bonzini    tcg_gen_ext_i32_ptr(base, ofs);
3221ad75a51eSRichard Henderson    tcg_gen_add_ptr(base, base, tcg_env);
3222139c1837SPaolo Bonzini
3223139c1837SPaolo Bonzini    /* Perform the load. */
3224139c1837SPaolo Bonzini    load_element(dest, base,
3225308ee805SFrank Chang                 vreg_ofs(s, vreg), s->sew, false);
3226139c1837SPaolo Bonzini
3227139c1837SPaolo Bonzini    /* Flush out-of-range indexing to zero.  */
322805b80ed0SRichard Henderson    t_vlmax = tcg_constant_i64(vlmax);
322905b80ed0SRichard Henderson    t_zero = tcg_constant_i64(0);
3230139c1837SPaolo Bonzini    tcg_gen_extu_tl_i64(t_idx, idx);
3231139c1837SPaolo Bonzini
3232139c1837SPaolo Bonzini    tcg_gen_movcond_i64(TCG_COND_LTU, dest, t_idx,
3233139c1837SPaolo Bonzini                        t_vlmax, dest, t_zero);
3234139c1837SPaolo Bonzini}
3235139c1837SPaolo Bonzini
3236139c1837SPaolo Bonzinistatic void vec_element_loadi(DisasContext *s, TCGv_i64 dest,
3237308ee805SFrank Chang                              int vreg, int idx, bool sign)
3238139c1837SPaolo Bonzini{
3239ad75a51eSRichard Henderson    load_element(dest, tcg_env, endian_ofs(s, vreg, idx), s->sew, sign);
3240139c1837SPaolo Bonzini}
3241139c1837SPaolo Bonzini
3242139c1837SPaolo Bonzini/* Integer Scalar Move Instruction */
3243139c1837SPaolo Bonzini
3244139c1837SPaolo Bonzinistatic void store_element(TCGv_i64 val, TCGv_ptr base,
3245139c1837SPaolo Bonzini                          int ofs, int sew)
3246139c1837SPaolo Bonzini{
3247139c1837SPaolo Bonzini    switch (sew) {
3248139c1837SPaolo Bonzini    case MO_8:
3249139c1837SPaolo Bonzini        tcg_gen_st8_i64(val, base, ofs);
3250139c1837SPaolo Bonzini        break;
3251139c1837SPaolo Bonzini    case MO_16:
3252139c1837SPaolo Bonzini        tcg_gen_st16_i64(val, base, ofs);
3253139c1837SPaolo Bonzini        break;
3254139c1837SPaolo Bonzini    case MO_32:
3255139c1837SPaolo Bonzini        tcg_gen_st32_i64(val, base, ofs);
3256139c1837SPaolo Bonzini        break;
3257139c1837SPaolo Bonzini    case MO_64:
3258139c1837SPaolo Bonzini        tcg_gen_st_i64(val, base, ofs);
3259139c1837SPaolo Bonzini        break;
3260139c1837SPaolo Bonzini    default:
3261139c1837SPaolo Bonzini        g_assert_not_reached();
3262139c1837SPaolo Bonzini    }
3263139c1837SPaolo Bonzini}
3264139c1837SPaolo Bonzini
3265139c1837SPaolo Bonzini/*
3266139c1837SPaolo Bonzini * Store vreg[idx] = val.
3267139c1837SPaolo Bonzini * The index must be in range of VLMAX.
3268139c1837SPaolo Bonzini */
3269139c1837SPaolo Bonzinistatic void vec_element_storei(DisasContext *s, int vreg,
3270139c1837SPaolo Bonzini                               int idx, TCGv_i64 val)
3271139c1837SPaolo Bonzini{
3272ad75a51eSRichard Henderson    store_element(val, tcg_env, endian_ofs(s, vreg, idx), s->sew);
3273139c1837SPaolo Bonzini}
3274139c1837SPaolo Bonzini
3275dedc53cbSFrank Chang/* vmv.x.s rd, vs2 # x[rd] = vs2[0] */
3276dedc53cbSFrank Changstatic bool trans_vmv_x_s(DisasContext *s, arg_vmv_x_s *a)
3277dedc53cbSFrank Chang{
3278dedc53cbSFrank Chang    if (require_rvv(s) &&
3279dedc53cbSFrank Chang        vext_check_isa_ill(s)) {
3280dedc53cbSFrank Chang        TCGv_i64 t1;
3281dedc53cbSFrank Chang        TCGv dest;
3282dedc53cbSFrank Chang
3283dedc53cbSFrank Chang        t1 = tcg_temp_new_i64();
3284dedc53cbSFrank Chang        dest = tcg_temp_new();
3285dedc53cbSFrank Chang        /*
3286dedc53cbSFrank Chang         * load vreg and sign-extend to 64 bits,
3287dedc53cbSFrank Chang         * then truncate to XLEN bits before storing to gpr.
3288dedc53cbSFrank Chang         */
3289dedc53cbSFrank Chang        vec_element_loadi(s, t1, a->rs2, 0, true);
3290dedc53cbSFrank Chang        tcg_gen_trunc_i64_tl(dest, t1);
3291dedc53cbSFrank Chang        gen_set_gpr(s, a->rd, dest);
32920848f7c1SDaniel Henrique Barboza        tcg_gen_movi_tl(cpu_vstart, 0);
3293bac802adSIvan Klokov        finalize_rvv_inst(s);
3294dedc53cbSFrank Chang        return true;
3295dedc53cbSFrank Chang    }
3296dedc53cbSFrank Chang    return false;
3297dedc53cbSFrank Chang}
3298dedc53cbSFrank Chang
3299139c1837SPaolo Bonzini/* vmv.s.x vd, rs1 # vd[0] = rs1 */
3300139c1837SPaolo Bonzinistatic bool trans_vmv_s_x(DisasContext *s, arg_vmv_s_x *a)
3301139c1837SPaolo Bonzini{
3302dedc53cbSFrank Chang    if (require_rvv(s) &&
3303dedc53cbSFrank Chang        vext_check_isa_ill(s)) {
3304139c1837SPaolo Bonzini        /* This instruction ignores LMUL and vector register groups */
3305139c1837SPaolo Bonzini        TCGv_i64 t1;
3306dedc53cbSFrank Chang        TCGv s1;
3307139c1837SPaolo Bonzini        TCGLabel *over = gen_new_label();
3308139c1837SPaolo Bonzini
3309f714361eSFrank Chang        tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
3310139c1837SPaolo Bonzini
3311139c1837SPaolo Bonzini        t1 = tcg_temp_new_i64();
3312dedc53cbSFrank Chang
3313dedc53cbSFrank Chang        /*
3314dedc53cbSFrank Chang         * load gpr and sign-extend to 64 bits,
3315dedc53cbSFrank Chang         * then truncate to SEW bits when storing to vreg.
3316dedc53cbSFrank Chang         */
3317dedc53cbSFrank Chang        s1 = get_gpr(s, a->rs1, EXT_NONE);
3318dedc53cbSFrank Chang        tcg_gen_ext_tl_i64(t1, s1);
3319139c1837SPaolo Bonzini        vec_element_storei(s, a->rd, 0, t1);
3320139c1837SPaolo Bonzini        gen_set_label(over);
33210848f7c1SDaniel Henrique Barboza        tcg_gen_movi_tl(cpu_vstart, 0);
3322bac802adSIvan Klokov        finalize_rvv_inst(s);
3323139c1837SPaolo Bonzini        return true;
3324139c1837SPaolo Bonzini    }
3325139c1837SPaolo Bonzini    return false;
3326139c1837SPaolo Bonzini}
3327139c1837SPaolo Bonzini
3328139c1837SPaolo Bonzini/* Floating-Point Scalar Move Instructions */
3329139c1837SPaolo Bonzinistatic bool trans_vfmv_f_s(DisasContext *s, arg_vfmv_f_s *a)
3330139c1837SPaolo Bonzini{
33315c4eb8fbSFrank Chang    if (require_rvv(s) &&
33325c4eb8fbSFrank Chang        require_rvf(s) &&
33332bc2853fSWeiwei Li        vext_check_isa_ill(s)) {
3334d6c4d3f2SFrank Chang        gen_set_rm(s, RISCV_FRM_DYN);
3335d6c4d3f2SFrank Chang
33365c4eb8fbSFrank Chang        unsigned int ofs = (8 << s->sew);
33375c4eb8fbSFrank Chang        unsigned int len = 64 - ofs;
33385c4eb8fbSFrank Chang        TCGv_i64 t_nan;
3339139c1837SPaolo Bonzini
3340308ee805SFrank Chang        vec_element_loadi(s, cpu_fpr[a->rd], a->rs2, 0, false);
33415c4eb8fbSFrank Chang        /* NaN-box f[rd] as necessary for SEW */
33425c4eb8fbSFrank Chang        if (len) {
33435c4eb8fbSFrank Chang            t_nan = tcg_constant_i64(UINT64_MAX);
33445c4eb8fbSFrank Chang            tcg_gen_deposit_i64(cpu_fpr[a->rd], cpu_fpr[a->rd],
33455c4eb8fbSFrank Chang                                t_nan, ofs, len);
3346139c1837SPaolo Bonzini        }
3347139c1837SPaolo Bonzini
3348139c1837SPaolo Bonzini        mark_fs_dirty(s);
33490848f7c1SDaniel Henrique Barboza        tcg_gen_movi_tl(cpu_vstart, 0);
3350bac802adSIvan Klokov        finalize_rvv_inst(s);
3351139c1837SPaolo Bonzini        return true;
3352139c1837SPaolo Bonzini    }
3353139c1837SPaolo Bonzini    return false;
3354139c1837SPaolo Bonzini}
3355139c1837SPaolo Bonzini
3356139c1837SPaolo Bonzini/* vfmv.s.f vd, rs1 # vd[0] = rs1 (vs2=0) */
3357139c1837SPaolo Bonzinistatic bool trans_vfmv_s_f(DisasContext *s, arg_vfmv_s_f *a)
3358139c1837SPaolo Bonzini{
33595c4eb8fbSFrank Chang    if (require_rvv(s) &&
33605c4eb8fbSFrank Chang        require_rvf(s) &&
33612bc2853fSWeiwei Li        vext_check_isa_ill(s)) {
3362d6c4d3f2SFrank Chang        gen_set_rm(s, RISCV_FRM_DYN);
3363d6c4d3f2SFrank Chang
3364139c1837SPaolo Bonzini        /* The instructions ignore LMUL and vector register group. */
33655c4eb8fbSFrank Chang        TCGv_i64 t1;
33665c4eb8fbSFrank Chang        TCGLabel *over = gen_new_label();
3367139c1837SPaolo Bonzini
3368922f8735SNazar Kazakov        /* if vstart >= vl, skip vector register write back */
3369f714361eSFrank Chang        tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
3370139c1837SPaolo Bonzini
33715c4eb8fbSFrank Chang        /* NaN-box f[rs1] */
3372139c1837SPaolo Bonzini        t1 = tcg_temp_new_i64();
33735c4eb8fbSFrank Chang        do_nanbox(s, t1, cpu_fpr[a->rs1]);
33745c4eb8fbSFrank Chang
3375139c1837SPaolo Bonzini        vec_element_storei(s, a->rd, 0, t1);
3376bac802adSIvan Klokov
3377139c1837SPaolo Bonzini        gen_set_label(over);
33780848f7c1SDaniel Henrique Barboza        tcg_gen_movi_tl(cpu_vstart, 0);
3379bac802adSIvan Klokov        finalize_rvv_inst(s);
3380139c1837SPaolo Bonzini        return true;
3381139c1837SPaolo Bonzini    }
3382139c1837SPaolo Bonzini    return false;
3383139c1837SPaolo Bonzini}
3384139c1837SPaolo Bonzini
3385139c1837SPaolo Bonzini/* Vector Slide Instructions */
3386139c1837SPaolo Bonzinistatic bool slideup_check(DisasContext *s, arg_rmrr *a)
3387139c1837SPaolo Bonzini{
3388f31dacd7SFrank Chang    return require_rvv(s) &&
3389f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
3390f31dacd7SFrank Chang           vext_check_slide(s, a->rd, a->rs2, a->vm, true);
3391139c1837SPaolo Bonzini}
3392139c1837SPaolo Bonzini
3393139c1837SPaolo BonziniGEN_OPIVX_TRANS(vslideup_vx, slideup_check)
3394139c1837SPaolo BonziniGEN_OPIVX_TRANS(vslide1up_vx, slideup_check)
3395ff64fc91SFrank ChangGEN_OPIVI_TRANS(vslideup_vi, IMM_ZX, vslideup_vx, slideup_check)
3396139c1837SPaolo Bonzini
3397f31dacd7SFrank Changstatic bool slidedown_check(DisasContext *s, arg_rmrr *a)
3398f31dacd7SFrank Chang{
3399f31dacd7SFrank Chang    return require_rvv(s) &&
3400f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
3401f31dacd7SFrank Chang           vext_check_slide(s, a->rd, a->rs2, a->vm, false);
3402f31dacd7SFrank Chang}
3403f31dacd7SFrank Chang
3404f31dacd7SFrank ChangGEN_OPIVX_TRANS(vslidedown_vx, slidedown_check)
3405f31dacd7SFrank ChangGEN_OPIVX_TRANS(vslide1down_vx, slidedown_check)
3406ff64fc91SFrank ChangGEN_OPIVI_TRANS(vslidedown_vi, IMM_ZX, vslidedown_vx, slidedown_check)
3407139c1837SPaolo Bonzini
34088500d4abSFrank Chang/* Vector Floating-Point Slide Instructions */
34098500d4abSFrank Changstatic bool fslideup_check(DisasContext *s, arg_rmrr *a)
34108500d4abSFrank Chang{
34118500d4abSFrank Chang    return slideup_check(s, a) &&
34122bc2853fSWeiwei Li           require_rvf(s);
34138500d4abSFrank Chang}
34148500d4abSFrank Chang
34158500d4abSFrank Changstatic bool fslidedown_check(DisasContext *s, arg_rmrr *a)
34168500d4abSFrank Chang{
34178500d4abSFrank Chang    return slidedown_check(s, a) &&
34182bc2853fSWeiwei Li           require_rvf(s);
34198500d4abSFrank Chang}
34208500d4abSFrank Chang
34218500d4abSFrank ChangGEN_OPFVF_TRANS(vfslide1up_vf, fslideup_check)
34228500d4abSFrank ChangGEN_OPFVF_TRANS(vfslide1down_vf, fslidedown_check)
34238500d4abSFrank Chang
3424139c1837SPaolo Bonzini/* Vector Register Gather Instruction */
3425139c1837SPaolo Bonzinistatic bool vrgather_vv_check(DisasContext *s, arg_rmrr *a)
3426139c1837SPaolo Bonzini{
3427f31dacd7SFrank Chang    return require_rvv(s) &&
3428f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
3429f31dacd7SFrank Chang           require_align(a->rd, s->lmul) &&
3430f31dacd7SFrank Chang           require_align(a->rs1, s->lmul) &&
3431f31dacd7SFrank Chang           require_align(a->rs2, s->lmul) &&
3432f31dacd7SFrank Chang           (a->rd != a->rs2 && a->rd != a->rs1) &&
3433f31dacd7SFrank Chang           require_vm(a->vm, a->rd);
3434139c1837SPaolo Bonzini}
3435139c1837SPaolo Bonzini
343650bfb45bSFrank Changstatic bool vrgatherei16_vv_check(DisasContext *s, arg_rmrr *a)
343750bfb45bSFrank Chang{
343850bfb45bSFrank Chang    int8_t emul = MO_16 - s->sew + s->lmul;
343950bfb45bSFrank Chang    return require_rvv(s) &&
344050bfb45bSFrank Chang           vext_check_isa_ill(s) &&
344150bfb45bSFrank Chang           (emul >= -3 && emul <= 3) &&
344250bfb45bSFrank Chang           require_align(a->rd, s->lmul) &&
344350bfb45bSFrank Chang           require_align(a->rs1, emul) &&
344450bfb45bSFrank Chang           require_align(a->rs2, s->lmul) &&
344550bfb45bSFrank Chang           (a->rd != a->rs2 && a->rd != a->rs1) &&
344650bfb45bSFrank Chang           !is_overlapped(a->rd, 1 << MAX(s->lmul, 0),
344750bfb45bSFrank Chang                          a->rs1, 1 << MAX(emul, 0)) &&
344850bfb45bSFrank Chang           !is_overlapped(a->rd, 1 << MAX(s->lmul, 0),
344950bfb45bSFrank Chang                          a->rs2, 1 << MAX(s->lmul, 0)) &&
345050bfb45bSFrank Chang           require_vm(a->vm, a->rd);
345150bfb45bSFrank Chang}
345250bfb45bSFrank Chang
3453139c1837SPaolo BonziniGEN_OPIVV_TRANS(vrgather_vv, vrgather_vv_check)
345450bfb45bSFrank ChangGEN_OPIVV_TRANS(vrgatherei16_vv, vrgatherei16_vv_check)
3455139c1837SPaolo Bonzini
3456139c1837SPaolo Bonzinistatic bool vrgather_vx_check(DisasContext *s, arg_rmrr *a)
3457139c1837SPaolo Bonzini{
3458f31dacd7SFrank Chang    return require_rvv(s) &&
3459f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
3460f31dacd7SFrank Chang           require_align(a->rd, s->lmul) &&
3461f31dacd7SFrank Chang           require_align(a->rs2, s->lmul) &&
3462f31dacd7SFrank Chang           (a->rd != a->rs2) &&
3463f31dacd7SFrank Chang           require_vm(a->vm, a->rd);
3464139c1837SPaolo Bonzini}
3465139c1837SPaolo Bonzini
3466139c1837SPaolo Bonzini/* vrgather.vx vd, vs2, rs1, vm # vd[i] = (x[rs1] >= VLMAX) ? 0 : vs2[rs1] */
3467139c1837SPaolo Bonzinistatic bool trans_vrgather_vx(DisasContext *s, arg_rmrr *a)
3468139c1837SPaolo Bonzini{
3469139c1837SPaolo Bonzini    if (!vrgather_vx_check(s, a)) {
3470139c1837SPaolo Bonzini        return false;
3471139c1837SPaolo Bonzini    }
3472139c1837SPaolo Bonzini
3473803963f7SeopXD    if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
347425669d27SDaniel Henrique Barboza        int vlmax = vext_get_vlmax(s->cfg_ptr->vlenb, s->sew, s->lmul);
3475139c1837SPaolo Bonzini        TCGv_i64 dest = tcg_temp_new_i64();
3476139c1837SPaolo Bonzini
3477139c1837SPaolo Bonzini        if (a->rs1 == 0) {
3478308ee805SFrank Chang            vec_element_loadi(s, dest, a->rs2, 0, false);
3479139c1837SPaolo Bonzini        } else {
3480139c1837SPaolo Bonzini            vec_element_loadx(s, dest, a->rs2, cpu_gpr[a->rs1], vlmax);
3481139c1837SPaolo Bonzini        }
3482139c1837SPaolo Bonzini
3483139c1837SPaolo Bonzini        tcg_gen_gvec_dup_i64(s->sew, vreg_ofs(s, a->rd),
3484139c1837SPaolo Bonzini                             MAXSZ(s), MAXSZ(s), dest);
3485bac802adSIvan Klokov        finalize_rvv_inst(s);
3486139c1837SPaolo Bonzini    } else {
3487139c1837SPaolo Bonzini        static gen_helper_opivx * const fns[4] = {
3488139c1837SPaolo Bonzini            gen_helper_vrgather_vx_b, gen_helper_vrgather_vx_h,
3489139c1837SPaolo Bonzini            gen_helper_vrgather_vx_w, gen_helper_vrgather_vx_d
3490139c1837SPaolo Bonzini        };
3491139c1837SPaolo Bonzini        return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s);
3492139c1837SPaolo Bonzini    }
3493139c1837SPaolo Bonzini    return true;
3494139c1837SPaolo Bonzini}
3495139c1837SPaolo Bonzini
3496139c1837SPaolo Bonzini/* vrgather.vi vd, vs2, imm, vm # vd[i] = (imm >= VLMAX) ? 0 : vs2[imm] */
3497139c1837SPaolo Bonzinistatic bool trans_vrgather_vi(DisasContext *s, arg_rmrr *a)
3498139c1837SPaolo Bonzini{
3499139c1837SPaolo Bonzini    if (!vrgather_vx_check(s, a)) {
3500139c1837SPaolo Bonzini        return false;
3501139c1837SPaolo Bonzini    }
3502139c1837SPaolo Bonzini
3503803963f7SeopXD    if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
350425669d27SDaniel Henrique Barboza        int vlmax = vext_get_vlmax(s->cfg_ptr->vlenb, s->sew, s->lmul);
350550bfb45bSFrank Chang        if (a->rs1 >= vlmax) {
350650bfb45bSFrank Chang            tcg_gen_gvec_dup_imm(MO_64, vreg_ofs(s, a->rd),
3507139c1837SPaolo Bonzini                                 MAXSZ(s), MAXSZ(s), 0);
3508139c1837SPaolo Bonzini        } else {
3509139c1837SPaolo Bonzini            tcg_gen_gvec_dup_mem(s->sew, vreg_ofs(s, a->rd),
3510139c1837SPaolo Bonzini                                 endian_ofs(s, a->rs2, a->rs1),
3511139c1837SPaolo Bonzini                                 MAXSZ(s), MAXSZ(s));
3512139c1837SPaolo Bonzini        }
3513bac802adSIvan Klokov        finalize_rvv_inst(s);
3514139c1837SPaolo Bonzini    } else {
3515139c1837SPaolo Bonzini        static gen_helper_opivx * const fns[4] = {
3516139c1837SPaolo Bonzini            gen_helper_vrgather_vx_b, gen_helper_vrgather_vx_h,
3517139c1837SPaolo Bonzini            gen_helper_vrgather_vx_w, gen_helper_vrgather_vx_d
3518139c1837SPaolo Bonzini        };
3519ff64fc91SFrank Chang        return opivi_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew],
3520ff64fc91SFrank Chang                           s, IMM_ZX);
3521139c1837SPaolo Bonzini    }
3522139c1837SPaolo Bonzini    return true;
3523139c1837SPaolo Bonzini}
3524139c1837SPaolo Bonzini
3525f31dacd7SFrank Chang/*
3526f31dacd7SFrank Chang * Vector Compress Instruction
3527f31dacd7SFrank Chang *
3528f31dacd7SFrank Chang * The destination vector register group cannot overlap the
3529f31dacd7SFrank Chang * source vector register group or the source mask register.
3530f31dacd7SFrank Chang */
3531139c1837SPaolo Bonzinistatic bool vcompress_vm_check(DisasContext *s, arg_r *a)
3532139c1837SPaolo Bonzini{
3533f31dacd7SFrank Chang    return require_rvv(s) &&
3534f31dacd7SFrank Chang           vext_check_isa_ill(s) &&
3535f31dacd7SFrank Chang           require_align(a->rd, s->lmul) &&
3536f31dacd7SFrank Chang           require_align(a->rs2, s->lmul) &&
3537f31dacd7SFrank Chang           (a->rd != a->rs2) &&
3538f714361eSFrank Chang           !is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs1, 1) &&
35394acaa133SLIU Zhiwei           s->vstart_eq_zero;
3540139c1837SPaolo Bonzini}
3541139c1837SPaolo Bonzini
3542139c1837SPaolo Bonzinistatic bool trans_vcompress_vm(DisasContext *s, arg_r *a)
3543139c1837SPaolo Bonzini{
3544139c1837SPaolo Bonzini    if (vcompress_vm_check(s, a)) {
3545139c1837SPaolo Bonzini        uint32_t data = 0;
3546139c1837SPaolo Bonzini        static gen_helper_gvec_4_ptr * const fns[4] = {
3547139c1837SPaolo Bonzini            gen_helper_vcompress_vm_b, gen_helper_vcompress_vm_h,
3548139c1837SPaolo Bonzini            gen_helper_vcompress_vm_w, gen_helper_vcompress_vm_d,
3549139c1837SPaolo Bonzini        };
3550139c1837SPaolo Bonzini
3551139c1837SPaolo Bonzini        data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
3552803963f7SeopXD        data = FIELD_DP32(data, VDATA, VTA, s->vta);
3553139c1837SPaolo Bonzini        tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
3554139c1837SPaolo Bonzini                           vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2),
355581b9ef99SDaniel Henrique Barboza                           tcg_env, s->cfg_ptr->vlenb,
355681b9ef99SDaniel Henrique Barboza                           s->cfg_ptr->vlenb, data,
3557eee2d61eSLIU Zhiwei                           fns[s->sew]);
3558bac802adSIvan Klokov        finalize_rvv_inst(s);
3559139c1837SPaolo Bonzini        return true;
3560139c1837SPaolo Bonzini    }
3561139c1837SPaolo Bonzini    return false;
3562139c1837SPaolo Bonzini}
35636b85975eSFrank Chang
35646b85975eSFrank Chang/*
35654eff52cdSMax Chou * Whole Vector Register Move Instructions depend on vtype register(vsew).
35664eff52cdSMax Chou * Thus, we need to check vill bit. (Section 16.6)
35676b85975eSFrank Chang */
3568f32d82f6SWeiwei Li#define GEN_VMV_WHOLE_TRANS(NAME, LEN)                             \
35696b85975eSFrank Changstatic bool trans_##NAME(DisasContext *s, arg_##NAME * a)               \
35706b85975eSFrank Chang{                                                                       \
35716b85975eSFrank Chang    if (require_rvv(s) &&                                               \
35724eff52cdSMax Chou        vext_check_isa_ill(s) &&                                        \
35736b85975eSFrank Chang        QEMU_IS_ALIGNED(a->rd, LEN) &&                                  \
35746b85975eSFrank Chang        QEMU_IS_ALIGNED(a->rs2, LEN)) {                                 \
357581b9ef99SDaniel Henrique Barboza        uint32_t maxsz = s->cfg_ptr->vlenb * LEN;                       \
35764acaa133SLIU Zhiwei        if (s->vstart_eq_zero) {                                        \
357779fc6d38SMax Chou            tcg_gen_gvec_mov(s->sew, vreg_ofs(s, a->rd),                \
3578f714361eSFrank Chang                             vreg_ofs(s, a->rs2), maxsz, maxsz);        \
3579f714361eSFrank Chang        } else {                                                        \
3580f714361eSFrank Chang            tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2), \
3581ad75a51eSRichard Henderson                               tcg_env, maxsz, maxsz, 0, gen_helper_vmvr_v); \
3582f714361eSFrank Chang        }                                                               \
3583bac802adSIvan Klokov        finalize_rvv_inst(s);                                           \
35846b85975eSFrank Chang        return true;                                                    \
35856b85975eSFrank Chang    }                                                                   \
35866b85975eSFrank Chang    return false;                                                       \
35876b85975eSFrank Chang}
35886b85975eSFrank Chang
3589f32d82f6SWeiwei LiGEN_VMV_WHOLE_TRANS(vmv1r_v, 1)
3590f32d82f6SWeiwei LiGEN_VMV_WHOLE_TRANS(vmv2r_v, 2)
3591f32d82f6SWeiwei LiGEN_VMV_WHOLE_TRANS(vmv4r_v, 4)
3592f32d82f6SWeiwei LiGEN_VMV_WHOLE_TRANS(vmv8r_v, 8)
3593cd01340eSFrank Chang
3594cd01340eSFrank Changstatic bool int_ext_check(DisasContext *s, arg_rmr *a, uint8_t div)
3595cd01340eSFrank Chang{
3596cd01340eSFrank Chang    uint8_t from = (s->sew + 3) - div;
3597cd01340eSFrank Chang    bool ret = require_rvv(s) &&
3598cd01340eSFrank Chang        (from >= 3 && from <= 8) &&
3599cd01340eSFrank Chang        (a->rd != a->rs2) &&
3600cd01340eSFrank Chang        require_align(a->rd, s->lmul) &&
3601cd01340eSFrank Chang        require_align(a->rs2, s->lmul - div) &&
3602cd01340eSFrank Chang        require_vm(a->vm, a->rd) &&
3603cd01340eSFrank Chang        require_noover(a->rd, s->lmul, a->rs2, s->lmul - div);
3604cd01340eSFrank Chang    return ret;
3605cd01340eSFrank Chang}
3606cd01340eSFrank Chang
3607cd01340eSFrank Changstatic bool int_ext_op(DisasContext *s, arg_rmr *a, uint8_t seq)
3608cd01340eSFrank Chang{
3609cd01340eSFrank Chang    uint32_t data = 0;
3610cd01340eSFrank Chang    gen_helper_gvec_3_ptr *fn;
3611cd01340eSFrank Chang
3612cd01340eSFrank Chang    static gen_helper_gvec_3_ptr * const fns[6][4] = {
3613cd01340eSFrank Chang        {
3614cd01340eSFrank Chang            NULL, gen_helper_vzext_vf2_h,
3615cd01340eSFrank Chang            gen_helper_vzext_vf2_w, gen_helper_vzext_vf2_d
3616cd01340eSFrank Chang        },
3617cd01340eSFrank Chang        {
3618cd01340eSFrank Chang            NULL, NULL,
3619cd01340eSFrank Chang            gen_helper_vzext_vf4_w, gen_helper_vzext_vf4_d,
3620cd01340eSFrank Chang        },
3621cd01340eSFrank Chang        {
3622cd01340eSFrank Chang            NULL, NULL,
3623cd01340eSFrank Chang            NULL, gen_helper_vzext_vf8_d
3624cd01340eSFrank Chang        },
3625cd01340eSFrank Chang        {
3626cd01340eSFrank Chang            NULL, gen_helper_vsext_vf2_h,
3627cd01340eSFrank Chang            gen_helper_vsext_vf2_w, gen_helper_vsext_vf2_d
3628cd01340eSFrank Chang        },
3629cd01340eSFrank Chang        {
3630cd01340eSFrank Chang            NULL, NULL,
3631cd01340eSFrank Chang            gen_helper_vsext_vf4_w, gen_helper_vsext_vf4_d,
3632cd01340eSFrank Chang        },
3633cd01340eSFrank Chang        {
3634cd01340eSFrank Chang            NULL, NULL,
3635cd01340eSFrank Chang            NULL, gen_helper_vsext_vf8_d
3636cd01340eSFrank Chang        }
3637cd01340eSFrank Chang    };
3638cd01340eSFrank Chang
3639cd01340eSFrank Chang    fn = fns[seq][s->sew];
3640cd01340eSFrank Chang    if (fn == NULL) {
3641cd01340eSFrank Chang        return false;
3642cd01340eSFrank Chang    }
3643cd01340eSFrank Chang
3644cd01340eSFrank Chang    data = FIELD_DP32(data, VDATA, VM, a->vm);
3645803963f7SeopXD    data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
3646803963f7SeopXD    data = FIELD_DP32(data, VDATA, VTA, s->vta);
3647edabcd0eSYueh-Ting (eop) Chen    data = FIELD_DP32(data, VDATA, VMA, s->vma);
3648cd01340eSFrank Chang
3649cd01340eSFrank Chang    tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
3650ad75a51eSRichard Henderson                       vreg_ofs(s, a->rs2), tcg_env,
365181b9ef99SDaniel Henrique Barboza                       s->cfg_ptr->vlenb,
365281b9ef99SDaniel Henrique Barboza                       s->cfg_ptr->vlenb, data, fn);
3653cd01340eSFrank Chang
3654bac802adSIvan Klokov    finalize_rvv_inst(s);
3655cd01340eSFrank Chang    return true;
3656cd01340eSFrank Chang}
3657cd01340eSFrank Chang
3658cd01340eSFrank Chang/* Vector Integer Extension */
3659cd01340eSFrank Chang#define GEN_INT_EXT_TRANS(NAME, DIV, SEQ)             \
3660cd01340eSFrank Changstatic bool trans_##NAME(DisasContext *s, arg_rmr *a) \
3661cd01340eSFrank Chang{                                                     \
3662cd01340eSFrank Chang    if (int_ext_check(s, a, DIV)) {                   \
3663cd01340eSFrank Chang        return int_ext_op(s, a, SEQ);                 \
3664cd01340eSFrank Chang    }                                                 \
3665cd01340eSFrank Chang    return false;                                     \
3666cd01340eSFrank Chang}
3667cd01340eSFrank Chang
3668cd01340eSFrank ChangGEN_INT_EXT_TRANS(vzext_vf2, 1, 0)
3669cd01340eSFrank ChangGEN_INT_EXT_TRANS(vzext_vf4, 2, 1)
3670cd01340eSFrank ChangGEN_INT_EXT_TRANS(vzext_vf8, 3, 2)
3671cd01340eSFrank ChangGEN_INT_EXT_TRANS(vsext_vf2, 1, 3)
3672cd01340eSFrank ChangGEN_INT_EXT_TRANS(vsext_vf4, 2, 4)
3673cd01340eSFrank ChangGEN_INT_EXT_TRANS(vsext_vf8, 3, 5)
3674