target/riscv: rvv: Add mask agnostic for vector mask instructions
[qemu.git] / target / riscv / insn_trans / trans_rvv.c.inc
blobc1bd29329efcf5bf7addca3691c51d5879d02def
1 /*
2  *
3  * Copyright (c) 2020 T-Head Semiconductor Co., Ltd. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2 or later, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 #include "tcg/tcg-op-gvec.h"
18 #include "tcg/tcg-gvec-desc.h"
19 #include "internals.h"
21 static inline bool is_overlapped(const int8_t astart, int8_t asize,
22                                  const int8_t bstart, int8_t bsize)
24     const int8_t aend = astart + asize;
25     const int8_t bend = bstart + bsize;
27     return MAX(aend, bend) - MIN(astart, bstart) < asize + bsize;
30 static bool require_rvv(DisasContext *s)
32     return s->mstatus_vs != 0;
35 static bool require_rvf(DisasContext *s)
37     if (s->mstatus_fs == 0) {
38         return false;
39     }
41     switch (s->sew) {
42     case MO_16:
43     case MO_32:
44         return has_ext(s, RVF);
45     case MO_64:
46         return has_ext(s, RVD);
47     default:
48         return false;
49     }
52 static bool require_scale_rvf(DisasContext *s)
54     if (s->mstatus_fs == 0) {
55         return false;
56     }
58     switch (s->sew) {
59     case MO_8:
60     case MO_16:
61         return has_ext(s, RVF);
62     case MO_32:
63         return has_ext(s, RVD);
64     default:
65         return false;
66     }
69 static bool require_zve32f(DisasContext *s)
71     /* RVV + Zve32f = RVV. */
72     if (has_ext(s, RVV)) {
73         return true;
74     }
76     /* Zve32f doesn't support FP64. (Section 18.2) */
77     return s->cfg_ptr->ext_zve32f ? s->sew <= MO_32 : true;
80 static bool require_scale_zve32f(DisasContext *s)
82     /* RVV + Zve32f = RVV. */
83     if (has_ext(s, RVV)) {
84         return true;
85     }
87     /* Zve32f doesn't support FP64. (Section 18.2) */
88     return s->cfg_ptr->ext_zve64f ? s->sew <= MO_16 : true;
91 static bool require_zve64f(DisasContext *s)
93     /* RVV + Zve64f = RVV. */
94     if (has_ext(s, RVV)) {
95         return true;
96     }
98     /* Zve64f doesn't support FP64. (Section 18.2) */
99     return s->cfg_ptr->ext_zve64f ? s->sew <= MO_32 : true;
102 static bool require_scale_zve64f(DisasContext *s)
104     /* RVV + Zve64f = RVV. */
105     if (has_ext(s, RVV)) {
106         return true;
107     }
109     /* Zve64f doesn't support FP64. (Section 18.2) */
110     return s->cfg_ptr->ext_zve64f ? s->sew <= MO_16 : true;
113 /* Destination vector register group cannot overlap source mask register. */
114 static bool require_vm(int vm, int vd)
116     return (vm != 0 || vd != 0);
119 static bool require_nf(int vd, int nf, int lmul)
121     int size = nf << MAX(lmul, 0);
122     return size <= 8 && vd + size <= 32;
126  * Vector register should aligned with the passed-in LMUL (EMUL).
127  * If LMUL < 0, i.e. fractional LMUL, any vector register is allowed.
128  */
129 static bool require_align(const int8_t val, const int8_t lmul)
131     return lmul <= 0 || extract32(val, 0, lmul) == 0;
135  * A destination vector register group can overlap a source vector
136  * register group only if one of the following holds:
137  *  1. The destination EEW equals the source EEW.
138  *  2. The destination EEW is smaller than the source EEW and the overlap
139  *     is in the lowest-numbered part of the source register group.
140  *  3. The destination EEW is greater than the source EEW, the source EMUL
141  *     is at least 1, and the overlap is in the highest-numbered part of
142  *     the destination register group.
143  * (Section 5.2)
145  * This function returns true if one of the following holds:
146  *  * Destination vector register group does not overlap a source vector
147  *    register group.
148  *  * Rule 3 met.
149  * For rule 1, overlap is allowed so this function doesn't need to be called.
150  * For rule 2, (vd == vs). Caller has to check whether: (vd != vs) before
151  * calling this function.
152  */
153 static bool require_noover(const int8_t dst, const int8_t dst_lmul,
154                            const int8_t src, const int8_t src_lmul)
156     int8_t dst_size = dst_lmul <= 0 ? 1 : 1 << dst_lmul;
157     int8_t src_size = src_lmul <= 0 ? 1 : 1 << src_lmul;
159     /* Destination EEW is greater than the source EEW, check rule 3. */
160     if (dst_size > src_size) {
161         if (dst < src &&
162             src_lmul >= 0 &&
163             is_overlapped(dst, dst_size, src, src_size) &&
164             !is_overlapped(dst, dst_size, src + src_size, src_size)) {
165             return true;
166         }
167     }
169     return !is_overlapped(dst, dst_size, src, src_size);
172 static bool do_vsetvl(DisasContext *s, int rd, int rs1, TCGv s2)
174     TCGv s1, dst;
176     if (!require_rvv(s) ||
177         !(has_ext(s, RVV) || s->cfg_ptr->ext_zve32f ||
178           s->cfg_ptr->ext_zve64f)) {
179         return false;
180     }
182     dst = dest_gpr(s, rd);
184     if (rd == 0 && rs1 == 0) {
185         s1 = tcg_temp_new();
186         tcg_gen_mov_tl(s1, cpu_vl);
187     } else if (rs1 == 0) {
188         /* As the mask is at least one bit, RV_VLEN_MAX is >= VLMAX */
189         s1 = tcg_constant_tl(RV_VLEN_MAX);
190     } else {
191         s1 = get_gpr(s, rs1, EXT_ZERO);
192     }
194     gen_helper_vsetvl(dst, cpu_env, s1, s2);
195     gen_set_gpr(s, rd, dst);
196     mark_vs_dirty(s);
198     gen_set_pc_imm(s, s->pc_succ_insn);
199     tcg_gen_lookup_and_goto_ptr();
200     s->base.is_jmp = DISAS_NORETURN;
202     if (rd == 0 && rs1 == 0) {
203         tcg_temp_free(s1);
204     }
206     return true;
209 static bool do_vsetivli(DisasContext *s, int rd, TCGv s1, TCGv s2)
211     TCGv dst;
213     if (!require_rvv(s) ||
214         !(has_ext(s, RVV) || s->cfg_ptr->ext_zve32f ||
215           s->cfg_ptr->ext_zve64f)) {
216         return false;
217     }
219     dst = dest_gpr(s, rd);
221     gen_helper_vsetvl(dst, cpu_env, s1, s2);
222     gen_set_gpr(s, rd, dst);
223     mark_vs_dirty(s);
224     gen_set_pc_imm(s, s->pc_succ_insn);
225     tcg_gen_lookup_and_goto_ptr();
226     s->base.is_jmp = DISAS_NORETURN;
228     return true;
231 static bool trans_vsetvl(DisasContext *s, arg_vsetvl *a)
233     TCGv s2 = get_gpr(s, a->rs2, EXT_ZERO);
234     return do_vsetvl(s, a->rd, a->rs1, s2);
237 static bool trans_vsetvli(DisasContext *s, arg_vsetvli *a)
239     TCGv s2 = tcg_constant_tl(a->zimm);
240     return do_vsetvl(s, a->rd, a->rs1, s2);
243 static bool trans_vsetivli(DisasContext *s, arg_vsetivli *a)
245     TCGv s1 = tcg_const_tl(a->rs1);
246     TCGv s2 = tcg_const_tl(a->zimm);
247     return do_vsetivli(s, a->rd, s1, s2);
250 /* vector register offset from env */
251 static uint32_t vreg_ofs(DisasContext *s, int reg)
253     return offsetof(CPURISCVState, vreg) + reg * s->cfg_ptr->vlen / 8;
256 /* check functions */
259  * Vector unit-stride, strided, unit-stride segment, strided segment
260  * store check function.
262  * Rules to be checked here:
263  *   1. EMUL must within the range: 1/8 <= EMUL <= 8. (Section 7.3)
264  *   2. Destination vector register number is multiples of EMUL.
265  *      (Section 3.4.2, 7.3)
266  *   3. The EMUL setting must be such that EMUL * NFIELDS â‰¤ 8. (Section 7.8)
267  *   4. Vector register numbers accessed by the segment load or store
268  *      cannot increment past 31. (Section 7.8)
269  */
270 static bool vext_check_store(DisasContext *s, int vd, int nf, uint8_t eew)
272     int8_t emul = eew - s->sew + s->lmul;
273     return (emul >= -3 && emul <= 3) &&
274             require_align(vd, emul) &&
275             require_nf(vd, nf, emul);
279  * Vector unit-stride, strided, unit-stride segment, strided segment
280  * load check function.
282  * Rules to be checked here:
283  *   1. All rules applies to store instructions are applies
284  *      to load instructions.
285  *   2. Destination vector register group for a masked vector
286  *      instruction cannot overlap the source mask register (v0).
287  *      (Section 5.3)
288  */
289 static bool vext_check_load(DisasContext *s, int vd, int nf, int vm,
290                             uint8_t eew)
292     return vext_check_store(s, vd, nf, eew) && require_vm(vm, vd);
296  * Vector indexed, indexed segment store check function.
298  * Rules to be checked here:
299  *   1. EMUL must within the range: 1/8 <= EMUL <= 8. (Section 7.3)
300  *   2. Index vector register number is multiples of EMUL.
301  *      (Section 3.4.2, 7.3)
302  *   3. Destination vector register number is multiples of LMUL.
303  *      (Section 3.4.2, 7.3)
304  *   4. The EMUL setting must be such that EMUL * NFIELDS â‰¤ 8. (Section 7.8)
305  *   5. Vector register numbers accessed by the segment load or store
306  *      cannot increment past 31. (Section 7.8)
307  */
308 static bool vext_check_st_index(DisasContext *s, int vd, int vs2, int nf,
309                                 uint8_t eew)
311     int8_t emul = eew - s->sew + s->lmul;
312     bool ret = (emul >= -3 && emul <= 3) &&
313                require_align(vs2, emul) &&
314                require_align(vd, s->lmul) &&
315                require_nf(vd, nf, s->lmul);
317     /*
318      * All Zve* extensions support all vector load and store instructions,
319      * except Zve64* extensions do not support EEW=64 for index values
320      * when XLEN=32. (Section 18.2)
321      */
322     if (get_xl(s) == MXL_RV32) {
323         ret &= (!has_ext(s, RVV) &&
324                 s->cfg_ptr->ext_zve64f ? eew != MO_64 : true);
325     }
327     return ret;
331  * Vector indexed, indexed segment load check function.
333  * Rules to be checked here:
334  *   1. All rules applies to store instructions are applies
335  *      to load instructions.
336  *   2. Destination vector register group for a masked vector
337  *      instruction cannot overlap the source mask register (v0).
338  *      (Section 5.3)
339  *   3. Destination vector register cannot overlap a source vector
340  *      register (vs2) group.
341  *      (Section 5.2)
342  *   4. Destination vector register groups cannot overlap
343  *      the source vector register (vs2) group for
344  *      indexed segment load instructions. (Section 7.8.3)
345  */
346 static bool vext_check_ld_index(DisasContext *s, int vd, int vs2,
347                                 int nf, int vm, uint8_t eew)
349     int8_t seg_vd;
350     int8_t emul = eew - s->sew + s->lmul;
351     bool ret = vext_check_st_index(s, vd, vs2, nf, eew) &&
352         require_vm(vm, vd);
354     /* Each segment register group has to follow overlap rules. */
355     for (int i = 0; i < nf; ++i) {
356         seg_vd = vd + (1 << MAX(s->lmul, 0)) * i;
358         if (eew > s->sew) {
359             if (seg_vd != vs2) {
360                 ret &= require_noover(seg_vd, s->lmul, vs2, emul);
361             }
362         } else if (eew < s->sew) {
363             ret &= require_noover(seg_vd, s->lmul, vs2, emul);
364         }
366         /*
367          * Destination vector register groups cannot overlap
368          * the source vector register (vs2) group for
369          * indexed segment load instructions.
370          */
371         if (nf > 1) {
372             ret &= !is_overlapped(seg_vd, 1 << MAX(s->lmul, 0),
373                                   vs2, 1 << MAX(emul, 0));
374         }
375     }
376     return ret;
379 static bool vext_check_ss(DisasContext *s, int vd, int vs, int vm)
381     return require_vm(vm, vd) &&
382         require_align(vd, s->lmul) &&
383         require_align(vs, s->lmul);
387  * Check function for vector instruction with format:
388  * single-width result and single-width sources (SEW = SEW op SEW)
390  * Rules to be checked here:
391  *   1. Destination vector register group for a masked vector
392  *      instruction cannot overlap the source mask register (v0).
393  *      (Section 5.3)
394  *   2. Destination vector register number is multiples of LMUL.
395  *      (Section 3.4.2)
396  *   3. Source (vs2, vs1) vector register number are multiples of LMUL.
397  *      (Section 3.4.2)
398  */
399 static bool vext_check_sss(DisasContext *s, int vd, int vs1, int vs2, int vm)
401     return vext_check_ss(s, vd, vs2, vm) &&
402         require_align(vs1, s->lmul);
405 static bool vext_check_ms(DisasContext *s, int vd, int vs)
407     bool ret = require_align(vs, s->lmul);
408     if (vd != vs) {
409         ret &= require_noover(vd, 0, vs, s->lmul);
410     }
411     return ret;
415  * Check function for maskable vector instruction with format:
416  * single-width result and single-width sources (SEW = SEW op SEW)
418  * Rules to be checked here:
419  *   1. Source (vs2, vs1) vector register number are multiples of LMUL.
420  *      (Section 3.4.2)
421  *   2. Destination vector register cannot overlap a source vector
422  *      register (vs2, vs1) group.
423  *      (Section 5.2)
424  *   3. The destination vector register group for a masked vector
425  *      instruction cannot overlap the source mask register (v0),
426  *      unless the destination vector register is being written
427  *      with a mask value (e.g., comparisons) or the scalar result
428  *      of a reduction. (Section 5.3)
429  */
430 static bool vext_check_mss(DisasContext *s, int vd, int vs1, int vs2)
432     bool ret = vext_check_ms(s, vd, vs2) &&
433         require_align(vs1, s->lmul);
434     if (vd != vs1) {
435         ret &= require_noover(vd, 0, vs1, s->lmul);
436     }
437     return ret;
441  * Common check function for vector widening instructions
442  * of double-width result (2*SEW).
444  * Rules to be checked here:
445  *   1. The largest vector register group used by an instruction
446  *      can not be greater than 8 vector registers (Section 5.2):
447  *      => LMUL < 8.
448  *      => SEW < 64.
449  *   2. Double-width SEW cannot greater than ELEN.
450  *   3. Destination vector register number is multiples of 2 * LMUL.
451  *      (Section 3.4.2)
452  *   4. Destination vector register group for a masked vector
453  *      instruction cannot overlap the source mask register (v0).
454  *      (Section 5.3)
455  */
456 static bool vext_wide_check_common(DisasContext *s, int vd, int vm)
458     return (s->lmul <= 2) &&
459            (s->sew < MO_64) &&
460            ((s->sew + 1) <= (s->cfg_ptr->elen >> 4)) &&
461            require_align(vd, s->lmul + 1) &&
462            require_vm(vm, vd);
466  * Common check function for vector narrowing instructions
467  * of single-width result (SEW) and double-width source (2*SEW).
469  * Rules to be checked here:
470  *   1. The largest vector register group used by an instruction
471  *      can not be greater than 8 vector registers (Section 5.2):
472  *      => LMUL < 8.
473  *      => SEW < 64.
474  *   2. Double-width SEW cannot greater than ELEN.
475  *   3. Source vector register number is multiples of 2 * LMUL.
476  *      (Section 3.4.2)
477  *   4. Destination vector register number is multiples of LMUL.
478  *      (Section 3.4.2)
479  *   5. Destination vector register group for a masked vector
480  *      instruction cannot overlap the source mask register (v0).
481  *      (Section 5.3)
482  */
483 static bool vext_narrow_check_common(DisasContext *s, int vd, int vs2,
484                                      int vm)
486     return (s->lmul <= 2) &&
487            (s->sew < MO_64) &&
488            ((s->sew + 1) <= (s->cfg_ptr->elen >> 4)) &&
489            require_align(vs2, s->lmul + 1) &&
490            require_align(vd, s->lmul) &&
491            require_vm(vm, vd);
494 static bool vext_check_ds(DisasContext *s, int vd, int vs, int vm)
496     return vext_wide_check_common(s, vd, vm) &&
497         require_align(vs, s->lmul) &&
498         require_noover(vd, s->lmul + 1, vs, s->lmul);
501 static bool vext_check_dd(DisasContext *s, int vd, int vs, int vm)
503     return vext_wide_check_common(s, vd, vm) &&
504         require_align(vs, s->lmul + 1);
508  * Check function for vector instruction with format:
509  * double-width result and single-width sources (2*SEW = SEW op SEW)
511  * Rules to be checked here:
512  *   1. All rules in defined in widen common rules are applied.
513  *   2. Source (vs2, vs1) vector register number are multiples of LMUL.
514  *      (Section 3.4.2)
515  *   3. Destination vector register cannot overlap a source vector
516  *      register (vs2, vs1) group.
517  *      (Section 5.2)
518  */
519 static bool vext_check_dss(DisasContext *s, int vd, int vs1, int vs2, int vm)
521     return vext_check_ds(s, vd, vs2, vm) &&
522         require_align(vs1, s->lmul) &&
523         require_noover(vd, s->lmul + 1, vs1, s->lmul);
527  * Check function for vector instruction with format:
528  * double-width result and double-width source1 and single-width
529  * source2 (2*SEW = 2*SEW op SEW)
531  * Rules to be checked here:
532  *   1. All rules in defined in widen common rules are applied.
533  *   2. Source 1 (vs2) vector register number is multiples of 2 * LMUL.
534  *      (Section 3.4.2)
535  *   3. Source 2 (vs1) vector register number is multiples of LMUL.
536  *      (Section 3.4.2)
537  *   4. Destination vector register cannot overlap a source vector
538  *      register (vs1) group.
539  *      (Section 5.2)
540  */
541 static bool vext_check_dds(DisasContext *s, int vd, int vs1, int vs2, int vm)
543     return vext_check_ds(s, vd, vs1, vm) &&
544         require_align(vs2, s->lmul + 1);
547 static bool vext_check_sd(DisasContext *s, int vd, int vs, int vm)
549     bool ret = vext_narrow_check_common(s, vd, vs, vm);
550     if (vd != vs) {
551         ret &= require_noover(vd, s->lmul, vs, s->lmul + 1);
552     }
553     return ret;
557  * Check function for vector instruction with format:
558  * single-width result and double-width source 1 and single-width
559  * source 2 (SEW = 2*SEW op SEW)
561  * Rules to be checked here:
562  *   1. All rules in defined in narrow common rules are applied.
563  *   2. Destination vector register cannot overlap a source vector
564  *      register (vs2) group.
565  *      (Section 5.2)
566  *   3. Source 2 (vs1) vector register number is multiples of LMUL.
567  *      (Section 3.4.2)
568  */
569 static bool vext_check_sds(DisasContext *s, int vd, int vs1, int vs2, int vm)
571     return vext_check_sd(s, vd, vs2, vm) &&
572         require_align(vs1, s->lmul);
576  * Check function for vector reduction instructions.
578  * Rules to be checked here:
579  *   1. Source 1 (vs2) vector register number is multiples of LMUL.
580  *      (Section 3.4.2)
581  */
582 static bool vext_check_reduction(DisasContext *s, int vs2)
584     return require_align(vs2, s->lmul) && (s->vstart == 0);
588  * Check function for vector slide instructions.
590  * Rules to be checked here:
591  *   1. Source 1 (vs2) vector register number is multiples of LMUL.
592  *      (Section 3.4.2)
593  *   2. Destination vector register number is multiples of LMUL.
594  *      (Section 3.4.2)
595  *   3. Destination vector register group for a masked vector
596  *      instruction cannot overlap the source mask register (v0).
597  *      (Section 5.3)
598  *   4. The destination vector register group for vslideup, vslide1up,
599  *      vfslide1up, cannot overlap the source vector register (vs2) group.
600  *      (Section 5.2, 16.3.1, 16.3.3)
601  */
602 static bool vext_check_slide(DisasContext *s, int vd, int vs2,
603                              int vm, bool is_over)
605     bool ret = require_align(vs2, s->lmul) &&
606                require_align(vd, s->lmul) &&
607                require_vm(vm, vd);
608     if (is_over) {
609         ret &= (vd != vs2);
610     }
611     return ret;
615  * In cpu_get_tb_cpu_state(), set VILL if RVV was not present.
616  * So RVV is also be checked in this function.
617  */
618 static bool vext_check_isa_ill(DisasContext *s)
620     return !s->vill;
623 /* common translation macro */
624 #define GEN_VEXT_TRANS(NAME, EEW, ARGTYPE, OP, CHECK)        \
625 static bool trans_##NAME(DisasContext *s, arg_##ARGTYPE * a) \
626 {                                                            \
627     if (CHECK(s, a, EEW)) {                                  \
628         return OP(s, a, EEW);                                \
629     }                                                        \
630     return false;                                            \
633 static uint8_t vext_get_emul(DisasContext *s, uint8_t eew)
635     int8_t emul = eew - s->sew + s->lmul;
636     return emul < 0 ? 0 : emul;
640  *** unit stride load and store
641  */
642 typedef void gen_helper_ldst_us(TCGv_ptr, TCGv_ptr, TCGv,
643                                 TCGv_env, TCGv_i32);
645 static bool ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data,
646                           gen_helper_ldst_us *fn, DisasContext *s,
647                           bool is_store)
649     TCGv_ptr dest, mask;
650     TCGv base;
651     TCGv_i32 desc;
653     TCGLabel *over = gen_new_label();
654     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
655     tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
657     dest = tcg_temp_new_ptr();
658     mask = tcg_temp_new_ptr();
659     base = get_gpr(s, rs1, EXT_NONE);
661     /*
662      * As simd_desc supports at most 2048 bytes, and in this implementation,
663      * the max vector group length is 4096 bytes. So split it into two parts.
664      *
665      * The first part is vlen in bytes, encoded in maxsz of simd_desc.
666      * The second part is lmul, encoded in data of simd_desc.
667      */
668     desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
669                                       s->cfg_ptr->vlen / 8, data));
671     tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
672     tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
674     fn(dest, mask, base, cpu_env, desc);
676     tcg_temp_free_ptr(dest);
677     tcg_temp_free_ptr(mask);
679     if (!is_store) {
680         mark_vs_dirty(s);
681     }
683     gen_set_label(over);
684     return true;
687 static bool ld_us_op(DisasContext *s, arg_r2nfvm *a, uint8_t eew)
689     uint32_t data = 0;
690     gen_helper_ldst_us *fn;
691     static gen_helper_ldst_us * const fns[2][4] = {
692         /* masked unit stride load */
693         { gen_helper_vle8_v_mask, gen_helper_vle16_v_mask,
694           gen_helper_vle32_v_mask, gen_helper_vle64_v_mask },
695         /* unmasked unit stride load */
696         { gen_helper_vle8_v, gen_helper_vle16_v,
697           gen_helper_vle32_v, gen_helper_vle64_v }
698     };
700     fn =  fns[a->vm][eew];
701     if (fn == NULL) {
702         return false;
703     }
705     /*
706      * Vector load/store instructions have the EEW encoded
707      * directly in the instructions. The maximum vector size is
708      * calculated with EMUL rather than LMUL.
709      */
710     uint8_t emul = vext_get_emul(s, eew);
711     data = FIELD_DP32(data, VDATA, VM, a->vm);
712     data = FIELD_DP32(data, VDATA, LMUL, emul);
713     data = FIELD_DP32(data, VDATA, NF, a->nf);
714     data = FIELD_DP32(data, VDATA, VTA, s->vta);
715     data = FIELD_DP32(data, VDATA, VMA, s->vma);
716     return ldst_us_trans(a->rd, a->rs1, data, fn, s, false);
719 static bool ld_us_check(DisasContext *s, arg_r2nfvm* a, uint8_t eew)
721     return require_rvv(s) &&
722            vext_check_isa_ill(s) &&
723            vext_check_load(s, a->rd, a->nf, a->vm, eew);
726 GEN_VEXT_TRANS(vle8_v,  MO_8,  r2nfvm, ld_us_op, ld_us_check)
727 GEN_VEXT_TRANS(vle16_v, MO_16, r2nfvm, ld_us_op, ld_us_check)
728 GEN_VEXT_TRANS(vle32_v, MO_32, r2nfvm, ld_us_op, ld_us_check)
729 GEN_VEXT_TRANS(vle64_v, MO_64, r2nfvm, ld_us_op, ld_us_check)
731 static bool st_us_op(DisasContext *s, arg_r2nfvm *a, uint8_t eew)
733     uint32_t data = 0;
734     gen_helper_ldst_us *fn;
735     static gen_helper_ldst_us * const fns[2][4] = {
736         /* masked unit stride store */
737         { gen_helper_vse8_v_mask, gen_helper_vse16_v_mask,
738           gen_helper_vse32_v_mask, gen_helper_vse64_v_mask },
739         /* unmasked unit stride store */
740         { gen_helper_vse8_v, gen_helper_vse16_v,
741           gen_helper_vse32_v, gen_helper_vse64_v }
742     };
744     fn =  fns[a->vm][eew];
745     if (fn == NULL) {
746         return false;
747     }
749     uint8_t emul = vext_get_emul(s, eew);
750     data = FIELD_DP32(data, VDATA, VM, a->vm);
751     data = FIELD_DP32(data, VDATA, LMUL, emul);
752     data = FIELD_DP32(data, VDATA, NF, a->nf);
753     return ldst_us_trans(a->rd, a->rs1, data, fn, s, true);
756 static bool st_us_check(DisasContext *s, arg_r2nfvm* a, uint8_t eew)
758     return require_rvv(s) &&
759            vext_check_isa_ill(s) &&
760            vext_check_store(s, a->rd, a->nf, eew);
763 GEN_VEXT_TRANS(vse8_v,  MO_8,  r2nfvm, st_us_op, st_us_check)
764 GEN_VEXT_TRANS(vse16_v, MO_16, r2nfvm, st_us_op, st_us_check)
765 GEN_VEXT_TRANS(vse32_v, MO_32, r2nfvm, st_us_op, st_us_check)
766 GEN_VEXT_TRANS(vse64_v, MO_64, r2nfvm, st_us_op, st_us_check)
769  *** unit stride mask load and store
770  */
771 static bool ld_us_mask_op(DisasContext *s, arg_vlm_v *a, uint8_t eew)
773     uint32_t data = 0;
774     gen_helper_ldst_us *fn = gen_helper_vlm_v;
776     /* EMUL = 1, NFIELDS = 1 */
777     data = FIELD_DP32(data, VDATA, LMUL, 0);
778     data = FIELD_DP32(data, VDATA, NF, 1);
779     /* Mask destination register are always tail-agnostic */
780     data = FIELD_DP32(data, VDATA, VTA, s->cfg_vta_all_1s);
781     data = FIELD_DP32(data, VDATA, VMA, s->vma);
782     return ldst_us_trans(a->rd, a->rs1, data, fn, s, false);
785 static bool ld_us_mask_check(DisasContext *s, arg_vlm_v *a, uint8_t eew)
787     /* EMUL = 1, NFIELDS = 1 */
788     return require_rvv(s) && vext_check_isa_ill(s);
791 static bool st_us_mask_op(DisasContext *s, arg_vsm_v *a, uint8_t eew)
793     uint32_t data = 0;
794     gen_helper_ldst_us *fn = gen_helper_vsm_v;
796     /* EMUL = 1, NFIELDS = 1 */
797     data = FIELD_DP32(data, VDATA, LMUL, 0);
798     data = FIELD_DP32(data, VDATA, NF, 1);
799     return ldst_us_trans(a->rd, a->rs1, data, fn, s, true);
802 static bool st_us_mask_check(DisasContext *s, arg_vsm_v *a, uint8_t eew)
804     /* EMUL = 1, NFIELDS = 1 */
805     return require_rvv(s) && vext_check_isa_ill(s);
808 GEN_VEXT_TRANS(vlm_v, MO_8, vlm_v, ld_us_mask_op, ld_us_mask_check)
809 GEN_VEXT_TRANS(vsm_v, MO_8, vsm_v, st_us_mask_op, st_us_mask_check)
812  *** stride load and store
813  */
814 typedef void gen_helper_ldst_stride(TCGv_ptr, TCGv_ptr, TCGv,
815                                     TCGv, TCGv_env, TCGv_i32);
817 static bool ldst_stride_trans(uint32_t vd, uint32_t rs1, uint32_t rs2,
818                               uint32_t data, gen_helper_ldst_stride *fn,
819                               DisasContext *s, bool is_store)
821     TCGv_ptr dest, mask;
822     TCGv base, stride;
823     TCGv_i32 desc;
825     TCGLabel *over = gen_new_label();
826     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
827     tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
829     dest = tcg_temp_new_ptr();
830     mask = tcg_temp_new_ptr();
831     base = get_gpr(s, rs1, EXT_NONE);
832     stride = get_gpr(s, rs2, EXT_NONE);
833     desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
834                                       s->cfg_ptr->vlen / 8, data));
836     tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
837     tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
839     fn(dest, mask, base, stride, cpu_env, desc);
841     tcg_temp_free_ptr(dest);
842     tcg_temp_free_ptr(mask);
844     if (!is_store) {
845         mark_vs_dirty(s);
846     }
848     gen_set_label(over);
849     return true;
852 static bool ld_stride_op(DisasContext *s, arg_rnfvm *a, uint8_t eew)
854     uint32_t data = 0;
855     gen_helper_ldst_stride *fn;
856     static gen_helper_ldst_stride * const fns[4] = {
857         gen_helper_vlse8_v, gen_helper_vlse16_v,
858         gen_helper_vlse32_v, gen_helper_vlse64_v
859     };
861     fn = fns[eew];
862     if (fn == NULL) {
863         return false;
864     }
866     uint8_t emul = vext_get_emul(s, eew);
867     data = FIELD_DP32(data, VDATA, VM, a->vm);
868     data = FIELD_DP32(data, VDATA, LMUL, emul);
869     data = FIELD_DP32(data, VDATA, NF, a->nf);
870     data = FIELD_DP32(data, VDATA, VTA, s->vta);
871     data = FIELD_DP32(data, VDATA, VMA, s->vma);
872     return ldst_stride_trans(a->rd, a->rs1, a->rs2, data, fn, s, false);
875 static bool ld_stride_check(DisasContext *s, arg_rnfvm* a, uint8_t eew)
877     return require_rvv(s) &&
878            vext_check_isa_ill(s) &&
879            vext_check_load(s, a->rd, a->nf, a->vm, eew);
882 GEN_VEXT_TRANS(vlse8_v,  MO_8,  rnfvm, ld_stride_op, ld_stride_check)
883 GEN_VEXT_TRANS(vlse16_v, MO_16, rnfvm, ld_stride_op, ld_stride_check)
884 GEN_VEXT_TRANS(vlse32_v, MO_32, rnfvm, ld_stride_op, ld_stride_check)
885 GEN_VEXT_TRANS(vlse64_v, MO_64, rnfvm, ld_stride_op, ld_stride_check)
887 static bool st_stride_op(DisasContext *s, arg_rnfvm *a, uint8_t eew)
889     uint32_t data = 0;
890     gen_helper_ldst_stride *fn;
891     static gen_helper_ldst_stride * const fns[4] = {
892         /* masked stride store */
893         gen_helper_vsse8_v,  gen_helper_vsse16_v,
894         gen_helper_vsse32_v,  gen_helper_vsse64_v
895     };
897     uint8_t emul = vext_get_emul(s, eew);
898     data = FIELD_DP32(data, VDATA, VM, a->vm);
899     data = FIELD_DP32(data, VDATA, LMUL, emul);
900     data = FIELD_DP32(data, VDATA, NF, a->nf);
901     fn = fns[eew];
902     if (fn == NULL) {
903         return false;
904     }
906     return ldst_stride_trans(a->rd, a->rs1, a->rs2, data, fn, s, true);
909 static bool st_stride_check(DisasContext *s, arg_rnfvm* a, uint8_t eew)
911     return require_rvv(s) &&
912            vext_check_isa_ill(s) &&
913            vext_check_store(s, a->rd, a->nf, eew);
916 GEN_VEXT_TRANS(vsse8_v,  MO_8,  rnfvm, st_stride_op, st_stride_check)
917 GEN_VEXT_TRANS(vsse16_v, MO_16, rnfvm, st_stride_op, st_stride_check)
918 GEN_VEXT_TRANS(vsse32_v, MO_32, rnfvm, st_stride_op, st_stride_check)
919 GEN_VEXT_TRANS(vsse64_v, MO_64, rnfvm, st_stride_op, st_stride_check)
922  *** index load and store
923  */
924 typedef void gen_helper_ldst_index(TCGv_ptr, TCGv_ptr, TCGv,
925                                    TCGv_ptr, TCGv_env, TCGv_i32);
927 static bool ldst_index_trans(uint32_t vd, uint32_t rs1, uint32_t vs2,
928                              uint32_t data, gen_helper_ldst_index *fn,
929                              DisasContext *s, bool is_store)
931     TCGv_ptr dest, mask, index;
932     TCGv base;
933     TCGv_i32 desc;
935     TCGLabel *over = gen_new_label();
936     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
937     tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
939     dest = tcg_temp_new_ptr();
940     mask = tcg_temp_new_ptr();
941     index = tcg_temp_new_ptr();
942     base = get_gpr(s, rs1, EXT_NONE);
943     desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
944                                       s->cfg_ptr->vlen / 8, data));
946     tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
947     tcg_gen_addi_ptr(index, cpu_env, vreg_ofs(s, vs2));
948     tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
950     fn(dest, mask, base, index, cpu_env, desc);
952     tcg_temp_free_ptr(dest);
953     tcg_temp_free_ptr(mask);
954     tcg_temp_free_ptr(index);
956     if (!is_store) {
957         mark_vs_dirty(s);
958     }
960     gen_set_label(over);
961     return true;
964 static bool ld_index_op(DisasContext *s, arg_rnfvm *a, uint8_t eew)
966     uint32_t data = 0;
967     gen_helper_ldst_index *fn;
968     static gen_helper_ldst_index * const fns[4][4] = {
969         /*
970          * offset vector register group EEW = 8,
971          * data vector register group EEW = SEW
972          */
973         { gen_helper_vlxei8_8_v,  gen_helper_vlxei8_16_v,
974           gen_helper_vlxei8_32_v, gen_helper_vlxei8_64_v },
975         /*
976          * offset vector register group EEW = 16,
977          * data vector register group EEW = SEW
978          */
979         { gen_helper_vlxei16_8_v, gen_helper_vlxei16_16_v,
980           gen_helper_vlxei16_32_v, gen_helper_vlxei16_64_v },
981         /*
982          * offset vector register group EEW = 32,
983          * data vector register group EEW = SEW
984          */
985         { gen_helper_vlxei32_8_v, gen_helper_vlxei32_16_v,
986           gen_helper_vlxei32_32_v, gen_helper_vlxei32_64_v },
987         /*
988          * offset vector register group EEW = 64,
989          * data vector register group EEW = SEW
990          */
991         { gen_helper_vlxei64_8_v, gen_helper_vlxei64_16_v,
992           gen_helper_vlxei64_32_v, gen_helper_vlxei64_64_v }
993     };
995     fn = fns[eew][s->sew];
997     uint8_t emul = vext_get_emul(s, s->sew);
998     data = FIELD_DP32(data, VDATA, VM, a->vm);
999     data = FIELD_DP32(data, VDATA, LMUL, emul);
1000     data = FIELD_DP32(data, VDATA, NF, a->nf);
1001     data = FIELD_DP32(data, VDATA, VTA, s->vta);
1002     data = FIELD_DP32(data, VDATA, VMA, s->vma);
1003     return ldst_index_trans(a->rd, a->rs1, a->rs2, data, fn, s, false);
1006 static bool ld_index_check(DisasContext *s, arg_rnfvm* a, uint8_t eew)
1008     return require_rvv(s) &&
1009            vext_check_isa_ill(s) &&
1010            vext_check_ld_index(s, a->rd, a->rs2, a->nf, a->vm, eew);
1013 GEN_VEXT_TRANS(vlxei8_v,  MO_8,  rnfvm, ld_index_op, ld_index_check)
1014 GEN_VEXT_TRANS(vlxei16_v, MO_16, rnfvm, ld_index_op, ld_index_check)
1015 GEN_VEXT_TRANS(vlxei32_v, MO_32, rnfvm, ld_index_op, ld_index_check)
1016 GEN_VEXT_TRANS(vlxei64_v, MO_64, rnfvm, ld_index_op, ld_index_check)
1018 static bool st_index_op(DisasContext *s, arg_rnfvm *a, uint8_t eew)
1020     uint32_t data = 0;
1021     gen_helper_ldst_index *fn;
1022     static gen_helper_ldst_index * const fns[4][4] = {
1023         /*
1024          * offset vector register group EEW = 8,
1025          * data vector register group EEW = SEW
1026          */
1027         { gen_helper_vsxei8_8_v,  gen_helper_vsxei8_16_v,
1028           gen_helper_vsxei8_32_v, gen_helper_vsxei8_64_v },
1029         /*
1030          * offset vector register group EEW = 16,
1031          * data vector register group EEW = SEW
1032          */
1033         { gen_helper_vsxei16_8_v, gen_helper_vsxei16_16_v,
1034           gen_helper_vsxei16_32_v, gen_helper_vsxei16_64_v },
1035         /*
1036          * offset vector register group EEW = 32,
1037          * data vector register group EEW = SEW
1038          */
1039         { gen_helper_vsxei32_8_v, gen_helper_vsxei32_16_v,
1040           gen_helper_vsxei32_32_v, gen_helper_vsxei32_64_v },
1041         /*
1042          * offset vector register group EEW = 64,
1043          * data vector register group EEW = SEW
1044          */
1045         { gen_helper_vsxei64_8_v, gen_helper_vsxei64_16_v,
1046           gen_helper_vsxei64_32_v, gen_helper_vsxei64_64_v }
1047     };
1049     fn = fns[eew][s->sew];
1051     uint8_t emul = vext_get_emul(s, s->sew);
1052     data = FIELD_DP32(data, VDATA, VM, a->vm);
1053     data = FIELD_DP32(data, VDATA, LMUL, emul);
1054     data = FIELD_DP32(data, VDATA, NF, a->nf);
1055     return ldst_index_trans(a->rd, a->rs1, a->rs2, data, fn, s, true);
1058 static bool st_index_check(DisasContext *s, arg_rnfvm* a, uint8_t eew)
1060     return require_rvv(s) &&
1061            vext_check_isa_ill(s) &&
1062            vext_check_st_index(s, a->rd, a->rs2, a->nf, eew);
1065 GEN_VEXT_TRANS(vsxei8_v,  MO_8,  rnfvm, st_index_op, st_index_check)
1066 GEN_VEXT_TRANS(vsxei16_v, MO_16, rnfvm, st_index_op, st_index_check)
1067 GEN_VEXT_TRANS(vsxei32_v, MO_32, rnfvm, st_index_op, st_index_check)
1068 GEN_VEXT_TRANS(vsxei64_v, MO_64, rnfvm, st_index_op, st_index_check)
1071  *** unit stride fault-only-first load
1072  */
1073 static bool ldff_trans(uint32_t vd, uint32_t rs1, uint32_t data,
1074                        gen_helper_ldst_us *fn, DisasContext *s)
1076     TCGv_ptr dest, mask;
1077     TCGv base;
1078     TCGv_i32 desc;
1080     TCGLabel *over = gen_new_label();
1081     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
1082     tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
1084     dest = tcg_temp_new_ptr();
1085     mask = tcg_temp_new_ptr();
1086     base = get_gpr(s, rs1, EXT_NONE);
1087     desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
1088                                       s->cfg_ptr->vlen / 8, data));
1090     tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
1091     tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
1093     fn(dest, mask, base, cpu_env, desc);
1095     tcg_temp_free_ptr(dest);
1096     tcg_temp_free_ptr(mask);
1097     mark_vs_dirty(s);
1098     gen_set_label(over);
1099     return true;
1102 static bool ldff_op(DisasContext *s, arg_r2nfvm *a, uint8_t eew)
1104     uint32_t data = 0;
1105     gen_helper_ldst_us *fn;
1106     static gen_helper_ldst_us * const fns[4] = {
1107         gen_helper_vle8ff_v, gen_helper_vle16ff_v,
1108         gen_helper_vle32ff_v, gen_helper_vle64ff_v
1109     };
1111     fn = fns[eew];
1112     if (fn == NULL) {
1113         return false;
1114     }
1116     uint8_t emul = vext_get_emul(s, eew);
1117     data = FIELD_DP32(data, VDATA, VM, a->vm);
1118     data = FIELD_DP32(data, VDATA, LMUL, emul);
1119     data = FIELD_DP32(data, VDATA, NF, a->nf);
1120     data = FIELD_DP32(data, VDATA, VTA, s->vta);
1121     data = FIELD_DP32(data, VDATA, VMA, s->vma);
1122     return ldff_trans(a->rd, a->rs1, data, fn, s);
1125 GEN_VEXT_TRANS(vle8ff_v,  MO_8,  r2nfvm, ldff_op, ld_us_check)
1126 GEN_VEXT_TRANS(vle16ff_v, MO_16, r2nfvm, ldff_op, ld_us_check)
1127 GEN_VEXT_TRANS(vle32ff_v, MO_32, r2nfvm, ldff_op, ld_us_check)
1128 GEN_VEXT_TRANS(vle64ff_v, MO_64, r2nfvm, ldff_op, ld_us_check)
1131  * load and store whole register instructions
1132  */
1133 typedef void gen_helper_ldst_whole(TCGv_ptr, TCGv, TCGv_env, TCGv_i32);
1135 static bool ldst_whole_trans(uint32_t vd, uint32_t rs1, uint32_t nf,
1136                              uint32_t width, gen_helper_ldst_whole *fn,
1137                              DisasContext *s, bool is_store)
1139     uint32_t evl = (s->cfg_ptr->vlen / 8) * nf / width;
1140     TCGLabel *over = gen_new_label();
1141     tcg_gen_brcondi_tl(TCG_COND_GEU, cpu_vstart, evl, over);
1143     TCGv_ptr dest;
1144     TCGv base;
1145     TCGv_i32 desc;
1147     uint32_t data = FIELD_DP32(0, VDATA, NF, nf);
1148     dest = tcg_temp_new_ptr();
1149     desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
1150                                       s->cfg_ptr->vlen / 8, data));
1152     base = get_gpr(s, rs1, EXT_NONE);
1153     tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
1155     fn(dest, base, cpu_env, desc);
1157     tcg_temp_free_ptr(dest);
1159     if (!is_store) {
1160         mark_vs_dirty(s);
1161     }
1162     gen_set_label(over);
1164     return true;
1168  * load and store whole register instructions ignore vtype and vl setting.
1169  * Thus, we don't need to check vill bit. (Section 7.9)
1170  */
1171 #define GEN_LDST_WHOLE_TRANS(NAME, ARG_NF, WIDTH, IS_STORE)               \
1172 static bool trans_##NAME(DisasContext *s, arg_##NAME * a)                 \
1173 {                                                                         \
1174     if (require_rvv(s) &&                                                 \
1175         QEMU_IS_ALIGNED(a->rd, ARG_NF)) {                                 \
1176         return ldst_whole_trans(a->rd, a->rs1, ARG_NF, WIDTH,             \
1177                                 gen_helper_##NAME, s, IS_STORE);          \
1178     }                                                                     \
1179     return false;                                                         \
1182 GEN_LDST_WHOLE_TRANS(vl1re8_v,  1, 1, false)
1183 GEN_LDST_WHOLE_TRANS(vl1re16_v, 1, 2, false)
1184 GEN_LDST_WHOLE_TRANS(vl1re32_v, 1, 4, false)
1185 GEN_LDST_WHOLE_TRANS(vl1re64_v, 1, 8, false)
1186 GEN_LDST_WHOLE_TRANS(vl2re8_v,  2, 1, false)
1187 GEN_LDST_WHOLE_TRANS(vl2re16_v, 2, 2, false)
1188 GEN_LDST_WHOLE_TRANS(vl2re32_v, 2, 4, false)
1189 GEN_LDST_WHOLE_TRANS(vl2re64_v, 2, 8, false)
1190 GEN_LDST_WHOLE_TRANS(vl4re8_v,  4, 1, false)
1191 GEN_LDST_WHOLE_TRANS(vl4re16_v, 4, 2, false)
1192 GEN_LDST_WHOLE_TRANS(vl4re32_v, 4, 4, false)
1193 GEN_LDST_WHOLE_TRANS(vl4re64_v, 4, 8, false)
1194 GEN_LDST_WHOLE_TRANS(vl8re8_v,  8, 1, false)
1195 GEN_LDST_WHOLE_TRANS(vl8re16_v, 8, 2, false)
1196 GEN_LDST_WHOLE_TRANS(vl8re32_v, 8, 4, false)
1197 GEN_LDST_WHOLE_TRANS(vl8re64_v, 8, 8, false)
1200  * The vector whole register store instructions are encoded similar to
1201  * unmasked unit-stride store of elements with EEW=8.
1202  */
1203 GEN_LDST_WHOLE_TRANS(vs1r_v, 1, 1, true)
1204 GEN_LDST_WHOLE_TRANS(vs2r_v, 2, 1, true)
1205 GEN_LDST_WHOLE_TRANS(vs4r_v, 4, 1, true)
1206 GEN_LDST_WHOLE_TRANS(vs8r_v, 8, 1, true)
1209  *** Vector Integer Arithmetic Instructions
1210  */
1213  * MAXSZ returns the maximum vector size can be operated in bytes,
1214  * which is used in GVEC IR when vl_eq_vlmax flag is set to true
1215  * to accerlate vector operation.
1216  */
1217 static inline uint32_t MAXSZ(DisasContext *s)
1219     int scale = s->lmul - 3;
1220     return s->cfg_ptr->vlen >> -scale;
1223 static bool opivv_check(DisasContext *s, arg_rmrr *a)
1225     return require_rvv(s) &&
1226            vext_check_isa_ill(s) &&
1227            vext_check_sss(s, a->rd, a->rs1, a->rs2, a->vm);
1230 typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t,
1231                         uint32_t, uint32_t, uint32_t);
1233 static inline bool
1234 do_opivv_gvec(DisasContext *s, arg_rmrr *a, GVecGen3Fn *gvec_fn,
1235               gen_helper_gvec_4_ptr *fn)
1237     TCGLabel *over = gen_new_label();
1238     if (!opivv_check(s, a)) {
1239         return false;
1240     }
1242     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
1243     tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
1245     if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
1246         gvec_fn(s->sew, vreg_ofs(s, a->rd),
1247                 vreg_ofs(s, a->rs2), vreg_ofs(s, a->rs1),
1248                 MAXSZ(s), MAXSZ(s));
1249     } else {
1250         uint32_t data = 0;
1252         data = FIELD_DP32(data, VDATA, VM, a->vm);
1253         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
1254         data = FIELD_DP32(data, VDATA, VTA, s->vta);
1255         data = FIELD_DP32(data, VDATA, VMA, s->vma);
1256         tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
1257                            vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2),
1258                            cpu_env, s->cfg_ptr->vlen / 8,
1259                            s->cfg_ptr->vlen / 8, data, fn);
1260     }
1261     mark_vs_dirty(s);
1262     gen_set_label(over);
1263     return true;
1266 /* OPIVV with GVEC IR */
1267 #define GEN_OPIVV_GVEC_TRANS(NAME, SUF) \
1268 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
1269 {                                                                  \
1270     static gen_helper_gvec_4_ptr * const fns[4] = {                \
1271         gen_helper_##NAME##_b, gen_helper_##NAME##_h,              \
1272         gen_helper_##NAME##_w, gen_helper_##NAME##_d,              \
1273     };                                                             \
1274     return do_opivv_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]);   \
1277 GEN_OPIVV_GVEC_TRANS(vadd_vv, add)
1278 GEN_OPIVV_GVEC_TRANS(vsub_vv, sub)
1280 typedef void gen_helper_opivx(TCGv_ptr, TCGv_ptr, TCGv, TCGv_ptr,
1281                               TCGv_env, TCGv_i32);
1283 static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm,
1284                         gen_helper_opivx *fn, DisasContext *s)
1286     TCGv_ptr dest, src2, mask;
1287     TCGv src1;
1288     TCGv_i32 desc;
1289     uint32_t data = 0;
1291     TCGLabel *over = gen_new_label();
1292     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
1293     tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
1295     dest = tcg_temp_new_ptr();
1296     mask = tcg_temp_new_ptr();
1297     src2 = tcg_temp_new_ptr();
1298     src1 = get_gpr(s, rs1, EXT_SIGN);
1300     data = FIELD_DP32(data, VDATA, VM, vm);
1301     data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
1302     data = FIELD_DP32(data, VDATA, VTA, s->vta);
1303     data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
1304     data = FIELD_DP32(data, VDATA, VMA, s->vma);
1305     desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
1306                                       s->cfg_ptr->vlen / 8, data));
1308     tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
1309     tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2));
1310     tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
1312     fn(dest, mask, src1, src2, cpu_env, desc);
1314     tcg_temp_free_ptr(dest);
1315     tcg_temp_free_ptr(mask);
1316     tcg_temp_free_ptr(src2);
1317     mark_vs_dirty(s);
1318     gen_set_label(over);
1319     return true;
1322 static bool opivx_check(DisasContext *s, arg_rmrr *a)
1324     return require_rvv(s) &&
1325            vext_check_isa_ill(s) &&
1326            vext_check_ss(s, a->rd, a->rs2, a->vm);
1329 typedef void GVecGen2sFn(unsigned, uint32_t, uint32_t, TCGv_i64,
1330                          uint32_t, uint32_t);
1332 static inline bool
1333 do_opivx_gvec(DisasContext *s, arg_rmrr *a, GVecGen2sFn *gvec_fn,
1334               gen_helper_opivx *fn)
1336     if (!opivx_check(s, a)) {
1337         return false;
1338     }
1340     if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
1341         TCGv_i64 src1 = tcg_temp_new_i64();
1343         tcg_gen_ext_tl_i64(src1, get_gpr(s, a->rs1, EXT_SIGN));
1344         gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2),
1345                 src1, MAXSZ(s), MAXSZ(s));
1347         tcg_temp_free_i64(src1);
1348         mark_vs_dirty(s);
1349         return true;
1350     }
1351     return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s);
1354 /* OPIVX with GVEC IR */
1355 #define GEN_OPIVX_GVEC_TRANS(NAME, SUF) \
1356 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
1357 {                                                                  \
1358     static gen_helper_opivx * const fns[4] = {                     \
1359         gen_helper_##NAME##_b, gen_helper_##NAME##_h,              \
1360         gen_helper_##NAME##_w, gen_helper_##NAME##_d,              \
1361     };                                                             \
1362     return do_opivx_gvec(s, a, tcg_gen_gvec_##SUF, fns[s->sew]);   \
1365 GEN_OPIVX_GVEC_TRANS(vadd_vx, adds)
1366 GEN_OPIVX_GVEC_TRANS(vsub_vx, subs)
1368 static void gen_vec_rsub8_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
1370     tcg_gen_vec_sub8_i64(d, b, a);
1373 static void gen_vec_rsub16_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
1375     tcg_gen_vec_sub16_i64(d, b, a);
1378 static void gen_rsub_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
1380     tcg_gen_sub_i32(ret, arg2, arg1);
1383 static void gen_rsub_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2)
1385     tcg_gen_sub_i64(ret, arg2, arg1);
1388 static void gen_rsub_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
1390     tcg_gen_sub_vec(vece, r, b, a);
1393 static void tcg_gen_gvec_rsubs(unsigned vece, uint32_t dofs, uint32_t aofs,
1394                                TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
1396     static const TCGOpcode vecop_list[] = { INDEX_op_sub_vec, 0 };
1397     static const GVecGen2s rsub_op[4] = {
1398         { .fni8 = gen_vec_rsub8_i64,
1399           .fniv = gen_rsub_vec,
1400           .fno = gen_helper_vec_rsubs8,
1401           .opt_opc = vecop_list,
1402           .vece = MO_8 },
1403         { .fni8 = gen_vec_rsub16_i64,
1404           .fniv = gen_rsub_vec,
1405           .fno = gen_helper_vec_rsubs16,
1406           .opt_opc = vecop_list,
1407           .vece = MO_16 },
1408         { .fni4 = gen_rsub_i32,
1409           .fniv = gen_rsub_vec,
1410           .fno = gen_helper_vec_rsubs32,
1411           .opt_opc = vecop_list,
1412           .vece = MO_32 },
1413         { .fni8 = gen_rsub_i64,
1414           .fniv = gen_rsub_vec,
1415           .fno = gen_helper_vec_rsubs64,
1416           .opt_opc = vecop_list,
1417           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
1418           .vece = MO_64 },
1419     };
1421     tcg_debug_assert(vece <= MO_64);
1422     tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, c, &rsub_op[vece]);
1425 GEN_OPIVX_GVEC_TRANS(vrsub_vx, rsubs)
1427 typedef enum {
1428     IMM_ZX,         /* Zero-extended */
1429     IMM_SX,         /* Sign-extended */
1430     IMM_TRUNC_SEW,  /* Truncate to log(SEW) bits */
1431     IMM_TRUNC_2SEW, /* Truncate to log(2*SEW) bits */
1432 } imm_mode_t;
1434 static int64_t extract_imm(DisasContext *s, uint32_t imm, imm_mode_t imm_mode)
1436     switch (imm_mode) {
1437     case IMM_ZX:
1438         return extract64(imm, 0, 5);
1439     case IMM_SX:
1440         return sextract64(imm, 0, 5);
1441     case IMM_TRUNC_SEW:
1442         return extract64(imm, 0, s->sew + 3);
1443     case IMM_TRUNC_2SEW:
1444         return extract64(imm, 0, s->sew + 4);
1445     default:
1446         g_assert_not_reached();
1447     }
1450 static bool opivi_trans(uint32_t vd, uint32_t imm, uint32_t vs2, uint32_t vm,
1451                         gen_helper_opivx *fn, DisasContext *s,
1452                         imm_mode_t imm_mode)
1454     TCGv_ptr dest, src2, mask;
1455     TCGv src1;
1456     TCGv_i32 desc;
1457     uint32_t data = 0;
1459     TCGLabel *over = gen_new_label();
1460     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
1461     tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
1463     dest = tcg_temp_new_ptr();
1464     mask = tcg_temp_new_ptr();
1465     src2 = tcg_temp_new_ptr();
1466     src1 = tcg_constant_tl(extract_imm(s, imm, imm_mode));
1468     data = FIELD_DP32(data, VDATA, VM, vm);
1469     data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
1470     data = FIELD_DP32(data, VDATA, VTA, s->vta);
1471     data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);
1472     data = FIELD_DP32(data, VDATA, VMA, s->vma);
1473     desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
1474                                       s->cfg_ptr->vlen / 8, data));
1476     tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
1477     tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2));
1478     tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
1480     fn(dest, mask, src1, src2, cpu_env, desc);
1482     tcg_temp_free_ptr(dest);
1483     tcg_temp_free_ptr(mask);
1484     tcg_temp_free_ptr(src2);
1485     mark_vs_dirty(s);
1486     gen_set_label(over);
1487     return true;
1490 typedef void GVecGen2iFn(unsigned, uint32_t, uint32_t, int64_t,
1491                          uint32_t, uint32_t);
1493 static inline bool
1494 do_opivi_gvec(DisasContext *s, arg_rmrr *a, GVecGen2iFn *gvec_fn,
1495               gen_helper_opivx *fn, imm_mode_t imm_mode)
1497     if (!opivx_check(s, a)) {
1498         return false;
1499     }
1501     if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
1502         gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2),
1503                 extract_imm(s, a->rs1, imm_mode), MAXSZ(s), MAXSZ(s));
1504         mark_vs_dirty(s);
1505         return true;
1506     }
1507     return opivi_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s, imm_mode);
1510 /* OPIVI with GVEC IR */
1511 #define GEN_OPIVI_GVEC_TRANS(NAME, IMM_MODE, OPIVX, SUF) \
1512 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
1513 {                                                                  \
1514     static gen_helper_opivx * const fns[4] = {                     \
1515         gen_helper_##OPIVX##_b, gen_helper_##OPIVX##_h,            \
1516         gen_helper_##OPIVX##_w, gen_helper_##OPIVX##_d,            \
1517     };                                                             \
1518     return do_opivi_gvec(s, a, tcg_gen_gvec_##SUF,                 \
1519                          fns[s->sew], IMM_MODE);                   \
1522 GEN_OPIVI_GVEC_TRANS(vadd_vi, IMM_SX, vadd_vx, addi)
1524 static void tcg_gen_gvec_rsubi(unsigned vece, uint32_t dofs, uint32_t aofs,
1525                                int64_t c, uint32_t oprsz, uint32_t maxsz)
1527     TCGv_i64 tmp = tcg_constant_i64(c);
1528     tcg_gen_gvec_rsubs(vece, dofs, aofs, tmp, oprsz, maxsz);
1531 GEN_OPIVI_GVEC_TRANS(vrsub_vi, IMM_SX, vrsub_vx, rsubi)
1533 /* Vector Widening Integer Add/Subtract */
1535 /* OPIVV with WIDEN */
1536 static bool opivv_widen_check(DisasContext *s, arg_rmrr *a)
1538     return require_rvv(s) &&
1539            vext_check_isa_ill(s) &&
1540            vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm);
1543 static bool do_opivv_widen(DisasContext *s, arg_rmrr *a,
1544                            gen_helper_gvec_4_ptr *fn,
1545                            bool (*checkfn)(DisasContext *, arg_rmrr *))
1547     if (checkfn(s, a)) {
1548         uint32_t data = 0;
1549         TCGLabel *over = gen_new_label();
1550         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
1551         tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
1553         data = FIELD_DP32(data, VDATA, VM, a->vm);
1554         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
1555         data = FIELD_DP32(data, VDATA, VTA, s->vta);
1556         data = FIELD_DP32(data, VDATA, VMA, s->vma);
1557         tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
1558                            vreg_ofs(s, a->rs1),
1559                            vreg_ofs(s, a->rs2),
1560                            cpu_env, s->cfg_ptr->vlen / 8,
1561                            s->cfg_ptr->vlen / 8,
1562                            data, fn);
1563         mark_vs_dirty(s);
1564         gen_set_label(over);
1565         return true;
1566     }
1567     return false;
1570 #define GEN_OPIVV_WIDEN_TRANS(NAME, CHECK) \
1571 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)       \
1572 {                                                            \
1573     static gen_helper_gvec_4_ptr * const fns[3] = {          \
1574         gen_helper_##NAME##_b,                               \
1575         gen_helper_##NAME##_h,                               \
1576         gen_helper_##NAME##_w                                \
1577     };                                                       \
1578     return do_opivv_widen(s, a, fns[s->sew], CHECK);         \
1581 GEN_OPIVV_WIDEN_TRANS(vwaddu_vv, opivv_widen_check)
1582 GEN_OPIVV_WIDEN_TRANS(vwadd_vv, opivv_widen_check)
1583 GEN_OPIVV_WIDEN_TRANS(vwsubu_vv, opivv_widen_check)
1584 GEN_OPIVV_WIDEN_TRANS(vwsub_vv, opivv_widen_check)
1586 /* OPIVX with WIDEN */
1587 static bool opivx_widen_check(DisasContext *s, arg_rmrr *a)
1589     return require_rvv(s) &&
1590            vext_check_isa_ill(s) &&
1591            vext_check_ds(s, a->rd, a->rs2, a->vm);
1594 static bool do_opivx_widen(DisasContext *s, arg_rmrr *a,
1595                            gen_helper_opivx *fn)
1597     if (opivx_widen_check(s, a)) {
1598         return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s);
1599     }
1600     return false;
1603 #define GEN_OPIVX_WIDEN_TRANS(NAME) \
1604 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)       \
1605 {                                                            \
1606     static gen_helper_opivx * const fns[3] = {               \
1607         gen_helper_##NAME##_b,                               \
1608         gen_helper_##NAME##_h,                               \
1609         gen_helper_##NAME##_w                                \
1610     };                                                       \
1611     return do_opivx_widen(s, a, fns[s->sew]);                \
1614 GEN_OPIVX_WIDEN_TRANS(vwaddu_vx)
1615 GEN_OPIVX_WIDEN_TRANS(vwadd_vx)
1616 GEN_OPIVX_WIDEN_TRANS(vwsubu_vx)
1617 GEN_OPIVX_WIDEN_TRANS(vwsub_vx)
1619 /* WIDEN OPIVV with WIDEN */
1620 static bool opiwv_widen_check(DisasContext *s, arg_rmrr *a)
1622     return require_rvv(s) &&
1623            vext_check_isa_ill(s) &&
1624            vext_check_dds(s, a->rd, a->rs1, a->rs2, a->vm);
1627 static bool do_opiwv_widen(DisasContext *s, arg_rmrr *a,
1628                            gen_helper_gvec_4_ptr *fn)
1630     if (opiwv_widen_check(s, a)) {
1631         uint32_t data = 0;
1632         TCGLabel *over = gen_new_label();
1633         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
1634         tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
1636         data = FIELD_DP32(data, VDATA, VM, a->vm);
1637         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
1638         data = FIELD_DP32(data, VDATA, VTA, s->vta);
1639         data = FIELD_DP32(data, VDATA, VMA, s->vma);
1640         tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
1641                            vreg_ofs(s, a->rs1),
1642                            vreg_ofs(s, a->rs2),
1643                            cpu_env, s->cfg_ptr->vlen / 8,
1644                            s->cfg_ptr->vlen / 8, data, fn);
1645         mark_vs_dirty(s);
1646         gen_set_label(over);
1647         return true;
1648     }
1649     return false;
1652 #define GEN_OPIWV_WIDEN_TRANS(NAME) \
1653 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)       \
1654 {                                                            \
1655     static gen_helper_gvec_4_ptr * const fns[3] = {          \
1656         gen_helper_##NAME##_b,                               \
1657         gen_helper_##NAME##_h,                               \
1658         gen_helper_##NAME##_w                                \
1659     };                                                       \
1660     return do_opiwv_widen(s, a, fns[s->sew]);                \
1663 GEN_OPIWV_WIDEN_TRANS(vwaddu_wv)
1664 GEN_OPIWV_WIDEN_TRANS(vwadd_wv)
1665 GEN_OPIWV_WIDEN_TRANS(vwsubu_wv)
1666 GEN_OPIWV_WIDEN_TRANS(vwsub_wv)
1668 /* WIDEN OPIVX with WIDEN */
1669 static bool opiwx_widen_check(DisasContext *s, arg_rmrr *a)
1671     return require_rvv(s) &&
1672            vext_check_isa_ill(s) &&
1673            vext_check_dd(s, a->rd, a->rs2, a->vm);
1676 static bool do_opiwx_widen(DisasContext *s, arg_rmrr *a,
1677                            gen_helper_opivx *fn)
1679     if (opiwx_widen_check(s, a)) {
1680         return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s);
1681     }
1682     return false;
1685 #define GEN_OPIWX_WIDEN_TRANS(NAME) \
1686 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)       \
1687 {                                                            \
1688     static gen_helper_opivx * const fns[3] = {               \
1689         gen_helper_##NAME##_b,                               \
1690         gen_helper_##NAME##_h,                               \
1691         gen_helper_##NAME##_w                                \
1692     };                                                       \
1693     return do_opiwx_widen(s, a, fns[s->sew]);                \
1696 GEN_OPIWX_WIDEN_TRANS(vwaddu_wx)
1697 GEN_OPIWX_WIDEN_TRANS(vwadd_wx)
1698 GEN_OPIWX_WIDEN_TRANS(vwsubu_wx)
1699 GEN_OPIWX_WIDEN_TRANS(vwsub_wx)
1701 /* Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions */
1702 /* OPIVV without GVEC IR */
1703 #define GEN_OPIVV_TRANS(NAME, CHECK)                               \
1704 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
1705 {                                                                  \
1706     if (CHECK(s, a)) {                                             \
1707         uint32_t data = 0;                                         \
1708         static gen_helper_gvec_4_ptr * const fns[4] = {            \
1709             gen_helper_##NAME##_b, gen_helper_##NAME##_h,          \
1710             gen_helper_##NAME##_w, gen_helper_##NAME##_d,          \
1711         };                                                         \
1712         TCGLabel *over = gen_new_label();                          \
1713         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
1714         tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
1715                                                                    \
1716         data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
1717         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
1718         data = FIELD_DP32(data, VDATA, VTA, s->vta);               \
1719         data =                                                     \
1720             FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);\
1721         data = FIELD_DP32(data, VDATA, VMA, s->vma);               \
1722         tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
1723                            vreg_ofs(s, a->rs1),                    \
1724                            vreg_ofs(s, a->rs2), cpu_env,           \
1725                            s->cfg_ptr->vlen / 8,                   \
1726                            s->cfg_ptr->vlen / 8, data,             \
1727                            fns[s->sew]);                           \
1728         mark_vs_dirty(s);                                          \
1729         gen_set_label(over);                                       \
1730         return true;                                               \
1731     }                                                              \
1732     return false;                                                  \
1736  * For vadc and vsbc, an illegal instruction exception is raised if the
1737  * destination vector register is v0 and LMUL > 1. (Section 11.4)
1738  */
1739 static bool opivv_vadc_check(DisasContext *s, arg_rmrr *a)
1741     return require_rvv(s) &&
1742            vext_check_isa_ill(s) &&
1743            (a->rd != 0) &&
1744            vext_check_sss(s, a->rd, a->rs1, a->rs2, a->vm);
1747 GEN_OPIVV_TRANS(vadc_vvm, opivv_vadc_check)
1748 GEN_OPIVV_TRANS(vsbc_vvm, opivv_vadc_check)
1751  * For vmadc and vmsbc, an illegal instruction exception is raised if the
1752  * destination vector register overlaps a source vector register group.
1753  */
1754 static bool opivv_vmadc_check(DisasContext *s, arg_rmrr *a)
1756     return require_rvv(s) &&
1757            vext_check_isa_ill(s) &&
1758            vext_check_mss(s, a->rd, a->rs1, a->rs2);
1761 GEN_OPIVV_TRANS(vmadc_vvm, opivv_vmadc_check)
1762 GEN_OPIVV_TRANS(vmsbc_vvm, opivv_vmadc_check)
1764 static bool opivx_vadc_check(DisasContext *s, arg_rmrr *a)
1766     return require_rvv(s) &&
1767            vext_check_isa_ill(s) &&
1768            (a->rd != 0) &&
1769            vext_check_ss(s, a->rd, a->rs2, a->vm);
1772 /* OPIVX without GVEC IR */
1773 #define GEN_OPIVX_TRANS(NAME, CHECK)                                     \
1774 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)                   \
1775 {                                                                        \
1776     if (CHECK(s, a)) {                                                   \
1777         static gen_helper_opivx * const fns[4] = {                       \
1778             gen_helper_##NAME##_b, gen_helper_##NAME##_h,                \
1779             gen_helper_##NAME##_w, gen_helper_##NAME##_d,                \
1780         };                                                               \
1781                                                                          \
1782         return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s);\
1783     }                                                                    \
1784     return false;                                                        \
1787 GEN_OPIVX_TRANS(vadc_vxm, opivx_vadc_check)
1788 GEN_OPIVX_TRANS(vsbc_vxm, opivx_vadc_check)
1790 static bool opivx_vmadc_check(DisasContext *s, arg_rmrr *a)
1792     return require_rvv(s) &&
1793            vext_check_isa_ill(s) &&
1794            vext_check_ms(s, a->rd, a->rs2);
1797 GEN_OPIVX_TRANS(vmadc_vxm, opivx_vmadc_check)
1798 GEN_OPIVX_TRANS(vmsbc_vxm, opivx_vmadc_check)
1800 /* OPIVI without GVEC IR */
1801 #define GEN_OPIVI_TRANS(NAME, IMM_MODE, OPIVX, CHECK)                    \
1802 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)                   \
1803 {                                                                        \
1804     if (CHECK(s, a)) {                                                   \
1805         static gen_helper_opivx * const fns[4] = {                       \
1806             gen_helper_##OPIVX##_b, gen_helper_##OPIVX##_h,              \
1807             gen_helper_##OPIVX##_w, gen_helper_##OPIVX##_d,              \
1808         };                                                               \
1809         return opivi_trans(a->rd, a->rs1, a->rs2, a->vm,                 \
1810                            fns[s->sew], s, IMM_MODE);                    \
1811     }                                                                    \
1812     return false;                                                        \
1815 GEN_OPIVI_TRANS(vadc_vim, IMM_SX, vadc_vxm, opivx_vadc_check)
1816 GEN_OPIVI_TRANS(vmadc_vim, IMM_SX, vmadc_vxm, opivx_vmadc_check)
1818 /* Vector Bitwise Logical Instructions */
1819 GEN_OPIVV_GVEC_TRANS(vand_vv, and)
1820 GEN_OPIVV_GVEC_TRANS(vor_vv,  or)
1821 GEN_OPIVV_GVEC_TRANS(vxor_vv, xor)
1822 GEN_OPIVX_GVEC_TRANS(vand_vx, ands)
1823 GEN_OPIVX_GVEC_TRANS(vor_vx,  ors)
1824 GEN_OPIVX_GVEC_TRANS(vxor_vx, xors)
1825 GEN_OPIVI_GVEC_TRANS(vand_vi, IMM_SX, vand_vx, andi)
1826 GEN_OPIVI_GVEC_TRANS(vor_vi, IMM_SX, vor_vx,  ori)
1827 GEN_OPIVI_GVEC_TRANS(vxor_vi, IMM_SX, vxor_vx, xori)
1829 /* Vector Single-Width Bit Shift Instructions */
1830 GEN_OPIVV_GVEC_TRANS(vsll_vv,  shlv)
1831 GEN_OPIVV_GVEC_TRANS(vsrl_vv,  shrv)
1832 GEN_OPIVV_GVEC_TRANS(vsra_vv,  sarv)
1834 typedef void GVecGen2sFn32(unsigned, uint32_t, uint32_t, TCGv_i32,
1835                            uint32_t, uint32_t);
1837 static inline bool
1838 do_opivx_gvec_shift(DisasContext *s, arg_rmrr *a, GVecGen2sFn32 *gvec_fn,
1839                     gen_helper_opivx *fn)
1841     if (!opivx_check(s, a)) {
1842         return false;
1843     }
1845     if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
1846         TCGv_i32 src1 = tcg_temp_new_i32();
1848         tcg_gen_trunc_tl_i32(src1, get_gpr(s, a->rs1, EXT_NONE));
1849         tcg_gen_extract_i32(src1, src1, 0, s->sew + 3);
1850         gvec_fn(s->sew, vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2),
1851                 src1, MAXSZ(s), MAXSZ(s));
1853         tcg_temp_free_i32(src1);
1854         mark_vs_dirty(s);
1855         return true;
1856     }
1857     return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fn, s);
1860 #define GEN_OPIVX_GVEC_SHIFT_TRANS(NAME, SUF) \
1861 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)                    \
1862 {                                                                         \
1863     static gen_helper_opivx * const fns[4] = {                            \
1864         gen_helper_##NAME##_b, gen_helper_##NAME##_h,                     \
1865         gen_helper_##NAME##_w, gen_helper_##NAME##_d,                     \
1866     };                                                                    \
1867                                                                           \
1868     return do_opivx_gvec_shift(s, a, tcg_gen_gvec_##SUF, fns[s->sew]);    \
1871 GEN_OPIVX_GVEC_SHIFT_TRANS(vsll_vx,  shls)
1872 GEN_OPIVX_GVEC_SHIFT_TRANS(vsrl_vx,  shrs)
1873 GEN_OPIVX_GVEC_SHIFT_TRANS(vsra_vx,  sars)
1875 GEN_OPIVI_GVEC_TRANS(vsll_vi, IMM_TRUNC_SEW, vsll_vx, shli)
1876 GEN_OPIVI_GVEC_TRANS(vsrl_vi, IMM_TRUNC_SEW, vsrl_vx, shri)
1877 GEN_OPIVI_GVEC_TRANS(vsra_vi, IMM_TRUNC_SEW, vsra_vx, sari)
1879 /* Vector Narrowing Integer Right Shift Instructions */
1880 static bool opiwv_narrow_check(DisasContext *s, arg_rmrr *a)
1882     return require_rvv(s) &&
1883            vext_check_isa_ill(s) &&
1884            vext_check_sds(s, a->rd, a->rs1, a->rs2, a->vm);
1887 /* OPIVV with NARROW */
1888 #define GEN_OPIWV_NARROW_TRANS(NAME)                               \
1889 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
1890 {                                                                  \
1891     if (opiwv_narrow_check(s, a)) {                                \
1892         uint32_t data = 0;                                         \
1893         static gen_helper_gvec_4_ptr * const fns[3] = {            \
1894             gen_helper_##NAME##_b,                                 \
1895             gen_helper_##NAME##_h,                                 \
1896             gen_helper_##NAME##_w,                                 \
1897         };                                                         \
1898         TCGLabel *over = gen_new_label();                          \
1899         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
1900         tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
1901                                                                    \
1902         data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
1903         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
1904         data = FIELD_DP32(data, VDATA, VTA, s->vta);               \
1905         data = FIELD_DP32(data, VDATA, VMA, s->vma);               \
1906         tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
1907                            vreg_ofs(s, a->rs1),                    \
1908                            vreg_ofs(s, a->rs2), cpu_env,           \
1909                            s->cfg_ptr->vlen / 8,                   \
1910                            s->cfg_ptr->vlen / 8, data,             \
1911                            fns[s->sew]);                           \
1912         mark_vs_dirty(s);                                          \
1913         gen_set_label(over);                                       \
1914         return true;                                               \
1915     }                                                              \
1916     return false;                                                  \
1918 GEN_OPIWV_NARROW_TRANS(vnsra_wv)
1919 GEN_OPIWV_NARROW_TRANS(vnsrl_wv)
1921 static bool opiwx_narrow_check(DisasContext *s, arg_rmrr *a)
1923     return require_rvv(s) &&
1924            vext_check_isa_ill(s) &&
1925            vext_check_sd(s, a->rd, a->rs2, a->vm);
1928 /* OPIVX with NARROW */
1929 #define GEN_OPIWX_NARROW_TRANS(NAME)                                     \
1930 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)                   \
1931 {                                                                        \
1932     if (opiwx_narrow_check(s, a)) {                                      \
1933         static gen_helper_opivx * const fns[3] = {                       \
1934             gen_helper_##NAME##_b,                                       \
1935             gen_helper_##NAME##_h,                                       \
1936             gen_helper_##NAME##_w,                                       \
1937         };                                                               \
1938         return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s);\
1939     }                                                                    \
1940     return false;                                                        \
1943 GEN_OPIWX_NARROW_TRANS(vnsra_wx)
1944 GEN_OPIWX_NARROW_TRANS(vnsrl_wx)
1946 /* OPIWI with NARROW */
1947 #define GEN_OPIWI_NARROW_TRANS(NAME, IMM_MODE, OPIVX)                    \
1948 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)                   \
1949 {                                                                        \
1950     if (opiwx_narrow_check(s, a)) {                                      \
1951         static gen_helper_opivx * const fns[3] = {                       \
1952             gen_helper_##OPIVX##_b,                                      \
1953             gen_helper_##OPIVX##_h,                                      \
1954             gen_helper_##OPIVX##_w,                                      \
1955         };                                                               \
1956         return opivi_trans(a->rd, a->rs1, a->rs2, a->vm,                 \
1957                            fns[s->sew], s, IMM_MODE);                    \
1958     }                                                                    \
1959     return false;                                                        \
1962 GEN_OPIWI_NARROW_TRANS(vnsra_wi, IMM_ZX, vnsra_wx)
1963 GEN_OPIWI_NARROW_TRANS(vnsrl_wi, IMM_ZX, vnsrl_wx)
1965 /* Vector Integer Comparison Instructions */
1967  * For all comparison instructions, an illegal instruction exception is raised
1968  * if the destination vector register overlaps a source vector register group
1969  * and LMUL > 1.
1970  */
1971 static bool opivv_cmp_check(DisasContext *s, arg_rmrr *a)
1973     return require_rvv(s) &&
1974            vext_check_isa_ill(s) &&
1975            vext_check_mss(s, a->rd, a->rs1, a->rs2);
1978 GEN_OPIVV_TRANS(vmseq_vv, opivv_cmp_check)
1979 GEN_OPIVV_TRANS(vmsne_vv, opivv_cmp_check)
1980 GEN_OPIVV_TRANS(vmsltu_vv, opivv_cmp_check)
1981 GEN_OPIVV_TRANS(vmslt_vv, opivv_cmp_check)
1982 GEN_OPIVV_TRANS(vmsleu_vv, opivv_cmp_check)
1983 GEN_OPIVV_TRANS(vmsle_vv, opivv_cmp_check)
1985 static bool opivx_cmp_check(DisasContext *s, arg_rmrr *a)
1987     return require_rvv(s) &&
1988            vext_check_isa_ill(s) &&
1989            vext_check_ms(s, a->rd, a->rs2);
1992 GEN_OPIVX_TRANS(vmseq_vx, opivx_cmp_check)
1993 GEN_OPIVX_TRANS(vmsne_vx, opivx_cmp_check)
1994 GEN_OPIVX_TRANS(vmsltu_vx, opivx_cmp_check)
1995 GEN_OPIVX_TRANS(vmslt_vx, opivx_cmp_check)
1996 GEN_OPIVX_TRANS(vmsleu_vx, opivx_cmp_check)
1997 GEN_OPIVX_TRANS(vmsle_vx, opivx_cmp_check)
1998 GEN_OPIVX_TRANS(vmsgtu_vx, opivx_cmp_check)
1999 GEN_OPIVX_TRANS(vmsgt_vx, opivx_cmp_check)
2001 GEN_OPIVI_TRANS(vmseq_vi, IMM_SX, vmseq_vx, opivx_cmp_check)
2002 GEN_OPIVI_TRANS(vmsne_vi, IMM_SX, vmsne_vx, opivx_cmp_check)
2003 GEN_OPIVI_TRANS(vmsleu_vi, IMM_SX, vmsleu_vx, opivx_cmp_check)
2004 GEN_OPIVI_TRANS(vmsle_vi, IMM_SX, vmsle_vx, opivx_cmp_check)
2005 GEN_OPIVI_TRANS(vmsgtu_vi, IMM_SX, vmsgtu_vx, opivx_cmp_check)
2006 GEN_OPIVI_TRANS(vmsgt_vi, IMM_SX, vmsgt_vx, opivx_cmp_check)
2008 /* Vector Integer Min/Max Instructions */
2009 GEN_OPIVV_GVEC_TRANS(vminu_vv, umin)
2010 GEN_OPIVV_GVEC_TRANS(vmin_vv,  smin)
2011 GEN_OPIVV_GVEC_TRANS(vmaxu_vv, umax)
2012 GEN_OPIVV_GVEC_TRANS(vmax_vv,  smax)
2013 GEN_OPIVX_TRANS(vminu_vx, opivx_check)
2014 GEN_OPIVX_TRANS(vmin_vx,  opivx_check)
2015 GEN_OPIVX_TRANS(vmaxu_vx, opivx_check)
2016 GEN_OPIVX_TRANS(vmax_vx,  opivx_check)
2018 /* Vector Single-Width Integer Multiply Instructions */
2020 static bool vmulh_vv_check(DisasContext *s, arg_rmrr *a)
2022     /*
2023      * All Zve* extensions support all vector integer instructions,
2024      * except that the vmulh integer multiply variants
2025      * that return the high word of the product
2026      * (vmulh.vv, vmulh.vx, vmulhu.vv, vmulhu.vx, vmulhsu.vv, vmulhsu.vx)
2027      * are not included for EEW=64 in Zve64*. (Section 18.2)
2028      */
2029     return opivv_check(s, a) &&
2030            (!has_ext(s, RVV) &&
2031             s->cfg_ptr->ext_zve64f ? s->sew != MO_64 : true);
2034 static bool vmulh_vx_check(DisasContext *s, arg_rmrr *a)
2036     /*
2037      * All Zve* extensions support all vector integer instructions,
2038      * except that the vmulh integer multiply variants
2039      * that return the high word of the product
2040      * (vmulh.vv, vmulh.vx, vmulhu.vv, vmulhu.vx, vmulhsu.vv, vmulhsu.vx)
2041      * are not included for EEW=64 in Zve64*. (Section 18.2)
2042      */
2043     return opivx_check(s, a) &&
2044            (!has_ext(s, RVV) &&
2045             s->cfg_ptr->ext_zve64f ? s->sew != MO_64 : true);
2048 GEN_OPIVV_GVEC_TRANS(vmul_vv,  mul)
2049 GEN_OPIVV_TRANS(vmulh_vv, vmulh_vv_check)
2050 GEN_OPIVV_TRANS(vmulhu_vv, vmulh_vv_check)
2051 GEN_OPIVV_TRANS(vmulhsu_vv, vmulh_vv_check)
2052 GEN_OPIVX_GVEC_TRANS(vmul_vx,  muls)
2053 GEN_OPIVX_TRANS(vmulh_vx, vmulh_vx_check)
2054 GEN_OPIVX_TRANS(vmulhu_vx, vmulh_vx_check)
2055 GEN_OPIVX_TRANS(vmulhsu_vx, vmulh_vx_check)
2057 /* Vector Integer Divide Instructions */
2058 GEN_OPIVV_TRANS(vdivu_vv, opivv_check)
2059 GEN_OPIVV_TRANS(vdiv_vv, opivv_check)
2060 GEN_OPIVV_TRANS(vremu_vv, opivv_check)
2061 GEN_OPIVV_TRANS(vrem_vv, opivv_check)
2062 GEN_OPIVX_TRANS(vdivu_vx, opivx_check)
2063 GEN_OPIVX_TRANS(vdiv_vx, opivx_check)
2064 GEN_OPIVX_TRANS(vremu_vx, opivx_check)
2065 GEN_OPIVX_TRANS(vrem_vx, opivx_check)
2067 /* Vector Widening Integer Multiply Instructions */
2068 GEN_OPIVV_WIDEN_TRANS(vwmul_vv, opivv_widen_check)
2069 GEN_OPIVV_WIDEN_TRANS(vwmulu_vv, opivv_widen_check)
2070 GEN_OPIVV_WIDEN_TRANS(vwmulsu_vv, opivv_widen_check)
2071 GEN_OPIVX_WIDEN_TRANS(vwmul_vx)
2072 GEN_OPIVX_WIDEN_TRANS(vwmulu_vx)
2073 GEN_OPIVX_WIDEN_TRANS(vwmulsu_vx)
2075 /* Vector Single-Width Integer Multiply-Add Instructions */
2076 GEN_OPIVV_TRANS(vmacc_vv, opivv_check)
2077 GEN_OPIVV_TRANS(vnmsac_vv, opivv_check)
2078 GEN_OPIVV_TRANS(vmadd_vv, opivv_check)
2079 GEN_OPIVV_TRANS(vnmsub_vv, opivv_check)
2080 GEN_OPIVX_TRANS(vmacc_vx, opivx_check)
2081 GEN_OPIVX_TRANS(vnmsac_vx, opivx_check)
2082 GEN_OPIVX_TRANS(vmadd_vx, opivx_check)
2083 GEN_OPIVX_TRANS(vnmsub_vx, opivx_check)
2085 /* Vector Widening Integer Multiply-Add Instructions */
2086 GEN_OPIVV_WIDEN_TRANS(vwmaccu_vv, opivv_widen_check)
2087 GEN_OPIVV_WIDEN_TRANS(vwmacc_vv, opivv_widen_check)
2088 GEN_OPIVV_WIDEN_TRANS(vwmaccsu_vv, opivv_widen_check)
2089 GEN_OPIVX_WIDEN_TRANS(vwmaccu_vx)
2090 GEN_OPIVX_WIDEN_TRANS(vwmacc_vx)
2091 GEN_OPIVX_WIDEN_TRANS(vwmaccsu_vx)
2092 GEN_OPIVX_WIDEN_TRANS(vwmaccus_vx)
2094 /* Vector Integer Merge and Move Instructions */
2095 static bool trans_vmv_v_v(DisasContext *s, arg_vmv_v_v *a)
2097     if (require_rvv(s) &&
2098         vext_check_isa_ill(s) &&
2099         /* vmv.v.v has rs2 = 0 and vm = 1 */
2100         vext_check_sss(s, a->rd, a->rs1, 0, 1)) {
2101         if (s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
2102             tcg_gen_gvec_mov(s->sew, vreg_ofs(s, a->rd),
2103                              vreg_ofs(s, a->rs1),
2104                              MAXSZ(s), MAXSZ(s));
2105         } else {
2106             uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul);
2107             data = FIELD_DP32(data, VDATA, VTA, s->vta);
2108             static gen_helper_gvec_2_ptr * const fns[4] = {
2109                 gen_helper_vmv_v_v_b, gen_helper_vmv_v_v_h,
2110                 gen_helper_vmv_v_v_w, gen_helper_vmv_v_v_d,
2111             };
2112             TCGLabel *over = gen_new_label();
2113             tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
2114             tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
2116             tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1),
2117                                cpu_env, s->cfg_ptr->vlen / 8,
2118                                s->cfg_ptr->vlen / 8, data,
2119                                fns[s->sew]);
2120             gen_set_label(over);
2121         }
2122         mark_vs_dirty(s);
2123         return true;
2124     }
2125     return false;
2128 typedef void gen_helper_vmv_vx(TCGv_ptr, TCGv_i64, TCGv_env, TCGv_i32);
2129 static bool trans_vmv_v_x(DisasContext *s, arg_vmv_v_x *a)
2131     if (require_rvv(s) &&
2132         vext_check_isa_ill(s) &&
2133         /* vmv.v.x has rs2 = 0 and vm = 1 */
2134         vext_check_ss(s, a->rd, 0, 1)) {
2135         TCGv s1;
2136         TCGLabel *over = gen_new_label();
2137         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
2138         tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
2140         s1 = get_gpr(s, a->rs1, EXT_SIGN);
2142         if (s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
2143             if (get_xl(s) == MXL_RV32 && s->sew == MO_64) {
2144                 TCGv_i64 s1_i64 = tcg_temp_new_i64();
2145                 tcg_gen_ext_tl_i64(s1_i64, s1);
2146                 tcg_gen_gvec_dup_i64(s->sew, vreg_ofs(s, a->rd),
2147                                      MAXSZ(s), MAXSZ(s), s1_i64);
2148                 tcg_temp_free_i64(s1_i64);
2149             } else {
2150                 tcg_gen_gvec_dup_tl(s->sew, vreg_ofs(s, a->rd),
2151                                     MAXSZ(s), MAXSZ(s), s1);
2152             }
2153         } else {
2154             TCGv_i32 desc;
2155             TCGv_i64 s1_i64 = tcg_temp_new_i64();
2156             TCGv_ptr dest = tcg_temp_new_ptr();
2157             uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul);
2158             data = FIELD_DP32(data, VDATA, VTA, s->vta);
2159             static gen_helper_vmv_vx * const fns[4] = {
2160                 gen_helper_vmv_v_x_b, gen_helper_vmv_v_x_h,
2161                 gen_helper_vmv_v_x_w, gen_helper_vmv_v_x_d,
2162             };
2164             tcg_gen_ext_tl_i64(s1_i64, s1);
2165             desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
2166                                               s->cfg_ptr->vlen / 8, data));
2167             tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd));
2168             fns[s->sew](dest, s1_i64, cpu_env, desc);
2170             tcg_temp_free_ptr(dest);
2171             tcg_temp_free_i64(s1_i64);
2172         }
2174         mark_vs_dirty(s);
2175         gen_set_label(over);
2176         return true;
2177     }
2178     return false;
2181 static bool trans_vmv_v_i(DisasContext *s, arg_vmv_v_i *a)
2183     if (require_rvv(s) &&
2184         vext_check_isa_ill(s) &&
2185         /* vmv.v.i has rs2 = 0 and vm = 1 */
2186         vext_check_ss(s, a->rd, 0, 1)) {
2187         int64_t simm = sextract64(a->rs1, 0, 5);
2188         if (s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
2189             tcg_gen_gvec_dup_imm(s->sew, vreg_ofs(s, a->rd),
2190                                  MAXSZ(s), MAXSZ(s), simm);
2191             mark_vs_dirty(s);
2192         } else {
2193             TCGv_i32 desc;
2194             TCGv_i64 s1;
2195             TCGv_ptr dest;
2196             uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul);
2197             data = FIELD_DP32(data, VDATA, VTA, s->vta);
2198             static gen_helper_vmv_vx * const fns[4] = {
2199                 gen_helper_vmv_v_x_b, gen_helper_vmv_v_x_h,
2200                 gen_helper_vmv_v_x_w, gen_helper_vmv_v_x_d,
2201             };
2202             TCGLabel *over = gen_new_label();
2203             tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
2204             tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
2206             s1 = tcg_constant_i64(simm);
2207             dest = tcg_temp_new_ptr();
2208             desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
2209                                               s->cfg_ptr->vlen / 8, data));
2210             tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd));
2211             fns[s->sew](dest, s1, cpu_env, desc);
2213             tcg_temp_free_ptr(dest);
2214             mark_vs_dirty(s);
2215             gen_set_label(over);
2216         }
2217         return true;
2218     }
2219     return false;
2222 GEN_OPIVV_TRANS(vmerge_vvm, opivv_vadc_check)
2223 GEN_OPIVX_TRANS(vmerge_vxm, opivx_vadc_check)
2224 GEN_OPIVI_TRANS(vmerge_vim, IMM_SX, vmerge_vxm, opivx_vadc_check)
2227  *** Vector Fixed-Point Arithmetic Instructions
2228  */
2230 /* Vector Single-Width Saturating Add and Subtract */
2231 GEN_OPIVV_TRANS(vsaddu_vv, opivv_check)
2232 GEN_OPIVV_TRANS(vsadd_vv,  opivv_check)
2233 GEN_OPIVV_TRANS(vssubu_vv, opivv_check)
2234 GEN_OPIVV_TRANS(vssub_vv,  opivv_check)
2235 GEN_OPIVX_TRANS(vsaddu_vx,  opivx_check)
2236 GEN_OPIVX_TRANS(vsadd_vx,  opivx_check)
2237 GEN_OPIVX_TRANS(vssubu_vx,  opivx_check)
2238 GEN_OPIVX_TRANS(vssub_vx,  opivx_check)
2239 GEN_OPIVI_TRANS(vsaddu_vi, IMM_SX, vsaddu_vx, opivx_check)
2240 GEN_OPIVI_TRANS(vsadd_vi, IMM_SX, vsadd_vx, opivx_check)
2242 /* Vector Single-Width Averaging Add and Subtract */
2243 GEN_OPIVV_TRANS(vaadd_vv, opivv_check)
2244 GEN_OPIVV_TRANS(vaaddu_vv, opivv_check)
2245 GEN_OPIVV_TRANS(vasub_vv, opivv_check)
2246 GEN_OPIVV_TRANS(vasubu_vv, opivv_check)
2247 GEN_OPIVX_TRANS(vaadd_vx,  opivx_check)
2248 GEN_OPIVX_TRANS(vaaddu_vx,  opivx_check)
2249 GEN_OPIVX_TRANS(vasub_vx,  opivx_check)
2250 GEN_OPIVX_TRANS(vasubu_vx,  opivx_check)
2252 /* Vector Single-Width Fractional Multiply with Rounding and Saturation */
2254 static bool vsmul_vv_check(DisasContext *s, arg_rmrr *a)
2256     /*
2257      * All Zve* extensions support all vector fixed-point arithmetic
2258      * instructions, except that vsmul.vv and vsmul.vx are not supported
2259      * for EEW=64 in Zve64*. (Section 18.2)
2260      */
2261     return opivv_check(s, a) &&
2262            (!has_ext(s, RVV) &&
2263             s->cfg_ptr->ext_zve64f ? s->sew != MO_64 : true);
2266 static bool vsmul_vx_check(DisasContext *s, arg_rmrr *a)
2268     /*
2269      * All Zve* extensions support all vector fixed-point arithmetic
2270      * instructions, except that vsmul.vv and vsmul.vx are not supported
2271      * for EEW=64 in Zve64*. (Section 18.2)
2272      */
2273     return opivx_check(s, a) &&
2274            (!has_ext(s, RVV) &&
2275             s->cfg_ptr->ext_zve64f ? s->sew != MO_64 : true);
2278 GEN_OPIVV_TRANS(vsmul_vv, vsmul_vv_check)
2279 GEN_OPIVX_TRANS(vsmul_vx,  vsmul_vx_check)
2281 /* Vector Single-Width Scaling Shift Instructions */
2282 GEN_OPIVV_TRANS(vssrl_vv, opivv_check)
2283 GEN_OPIVV_TRANS(vssra_vv, opivv_check)
2284 GEN_OPIVX_TRANS(vssrl_vx,  opivx_check)
2285 GEN_OPIVX_TRANS(vssra_vx,  opivx_check)
2286 GEN_OPIVI_TRANS(vssrl_vi, IMM_TRUNC_SEW, vssrl_vx, opivx_check)
2287 GEN_OPIVI_TRANS(vssra_vi, IMM_TRUNC_SEW, vssra_vx, opivx_check)
2289 /* Vector Narrowing Fixed-Point Clip Instructions */
2290 GEN_OPIWV_NARROW_TRANS(vnclipu_wv)
2291 GEN_OPIWV_NARROW_TRANS(vnclip_wv)
2292 GEN_OPIWX_NARROW_TRANS(vnclipu_wx)
2293 GEN_OPIWX_NARROW_TRANS(vnclip_wx)
2294 GEN_OPIWI_NARROW_TRANS(vnclipu_wi, IMM_ZX, vnclipu_wx)
2295 GEN_OPIWI_NARROW_TRANS(vnclip_wi, IMM_ZX, vnclip_wx)
2298  *** Vector Float Point Arithmetic Instructions
2299  */
2302  * As RVF-only cpus always have values NaN-boxed to 64-bits,
2303  * RVF and RVD can be treated equally.
2304  * We don't have to deal with the cases of: SEW > FLEN.
2306  * If SEW < FLEN, check whether input fp register is a valid
2307  * NaN-boxed value, in which case the least-significant SEW bits
2308  * of the f regsiter are used, else the canonical NaN value is used.
2309  */
2310 static void do_nanbox(DisasContext *s, TCGv_i64 out, TCGv_i64 in)
2312     switch (s->sew) {
2313     case 1:
2314         gen_check_nanbox_h(out, in);
2315         break;
2316     case 2:
2317         gen_check_nanbox_s(out, in);
2318         break;
2319     case 3:
2320         tcg_gen_mov_i64(out, in);
2321         break;
2322     default:
2323         g_assert_not_reached();
2324     }
2327 /* Vector Single-Width Floating-Point Add/Subtract Instructions */
2330  * If the current SEW does not correspond to a supported IEEE floating-point
2331  * type, an illegal instruction exception is raised.
2332  */
2333 static bool opfvv_check(DisasContext *s, arg_rmrr *a)
2335     return require_rvv(s) &&
2336            require_rvf(s) &&
2337            vext_check_isa_ill(s) &&
2338            vext_check_sss(s, a->rd, a->rs1, a->rs2, a->vm) &&
2339            require_zve32f(s) &&
2340            require_zve64f(s);
2343 /* OPFVV without GVEC IR */
2344 #define GEN_OPFVV_TRANS(NAME, CHECK)                               \
2345 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
2346 {                                                                  \
2347     if (CHECK(s, a)) {                                             \
2348         uint32_t data = 0;                                         \
2349         static gen_helper_gvec_4_ptr * const fns[3] = {            \
2350             gen_helper_##NAME##_h,                                 \
2351             gen_helper_##NAME##_w,                                 \
2352             gen_helper_##NAME##_d,                                 \
2353         };                                                         \
2354         TCGLabel *over = gen_new_label();                          \
2355         gen_set_rm(s, RISCV_FRM_DYN);                              \
2356         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
2357         tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
2358                                                                    \
2359         data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
2360         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
2361         data = FIELD_DP32(data, VDATA, VTA, s->vta);               \
2362         data =                                                     \
2363             FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);\
2364         data = FIELD_DP32(data, VDATA, VMA, s->vma);               \
2365         tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
2366                            vreg_ofs(s, a->rs1),                    \
2367                            vreg_ofs(s, a->rs2), cpu_env,           \
2368                            s->cfg_ptr->vlen / 8,                   \
2369                            s->cfg_ptr->vlen / 8, data,             \
2370                            fns[s->sew - 1]);                       \
2371         mark_vs_dirty(s);                                          \
2372         gen_set_label(over);                                       \
2373         return true;                                               \
2374     }                                                              \
2375     return false;                                                  \
2377 GEN_OPFVV_TRANS(vfadd_vv, opfvv_check)
2378 GEN_OPFVV_TRANS(vfsub_vv, opfvv_check)
2380 typedef void gen_helper_opfvf(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv_ptr,
2381                               TCGv_env, TCGv_i32);
2383 static bool opfvf_trans(uint32_t vd, uint32_t rs1, uint32_t vs2,
2384                         uint32_t data, gen_helper_opfvf *fn, DisasContext *s)
2386     TCGv_ptr dest, src2, mask;
2387     TCGv_i32 desc;
2388     TCGv_i64 t1;
2390     TCGLabel *over = gen_new_label();
2391     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
2392     tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
2394     dest = tcg_temp_new_ptr();
2395     mask = tcg_temp_new_ptr();
2396     src2 = tcg_temp_new_ptr();
2397     desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
2398                                       s->cfg_ptr->vlen / 8, data));
2400     tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, vd));
2401     tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, vs2));
2402     tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
2404     /* NaN-box f[rs1] */
2405     t1 = tcg_temp_new_i64();
2406     do_nanbox(s, t1, cpu_fpr[rs1]);
2408     fn(dest, mask, t1, src2, cpu_env, desc);
2410     tcg_temp_free_ptr(dest);
2411     tcg_temp_free_ptr(mask);
2412     tcg_temp_free_ptr(src2);
2413     tcg_temp_free_i64(t1);
2414     mark_vs_dirty(s);
2415     gen_set_label(over);
2416     return true;
2420  * If the current SEW does not correspond to a supported IEEE floating-point
2421  * type, an illegal instruction exception is raised
2422  */
2423 static bool opfvf_check(DisasContext *s, arg_rmrr *a)
2425     return require_rvv(s) &&
2426            require_rvf(s) &&
2427            vext_check_isa_ill(s) &&
2428            vext_check_ss(s, a->rd, a->rs2, a->vm) &&
2429            require_zve32f(s) &&
2430            require_zve64f(s);
2433 /* OPFVF without GVEC IR */
2434 #define GEN_OPFVF_TRANS(NAME, CHECK)                              \
2435 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)            \
2436 {                                                                 \
2437     if (CHECK(s, a)) {                                            \
2438         uint32_t data = 0;                                        \
2439         static gen_helper_opfvf *const fns[3] = {                 \
2440             gen_helper_##NAME##_h,                                \
2441             gen_helper_##NAME##_w,                                \
2442             gen_helper_##NAME##_d,                                \
2443         };                                                        \
2444         gen_set_rm(s, RISCV_FRM_DYN);                             \
2445         data = FIELD_DP32(data, VDATA, VM, a->vm);                \
2446         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);            \
2447         data = FIELD_DP32(data, VDATA, VTA, s->vta);              \
2448         data = FIELD_DP32(data, VDATA, VTA_ALL_1S,                \
2449                           s->cfg_vta_all_1s);                     \
2450         data = FIELD_DP32(data, VDATA, VMA, s->vma);              \
2451         return opfvf_trans(a->rd, a->rs1, a->rs2, data,           \
2452                            fns[s->sew - 1], s);                   \
2453     }                                                             \
2454     return false;                                                 \
2457 GEN_OPFVF_TRANS(vfadd_vf,  opfvf_check)
2458 GEN_OPFVF_TRANS(vfsub_vf,  opfvf_check)
2459 GEN_OPFVF_TRANS(vfrsub_vf,  opfvf_check)
2461 /* Vector Widening Floating-Point Add/Subtract Instructions */
2462 static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a)
2464     return require_rvv(s) &&
2465            require_scale_rvf(s) &&
2466            (s->sew != MO_8) &&
2467            vext_check_isa_ill(s) &&
2468            vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm) &&
2469            require_scale_zve32f(s) &&
2470            require_scale_zve64f(s);
2473 /* OPFVV with WIDEN */
2474 #define GEN_OPFVV_WIDEN_TRANS(NAME, CHECK)                       \
2475 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)           \
2476 {                                                                \
2477     if (CHECK(s, a)) {                                           \
2478         uint32_t data = 0;                                       \
2479         static gen_helper_gvec_4_ptr * const fns[2] = {          \
2480             gen_helper_##NAME##_h, gen_helper_##NAME##_w,        \
2481         };                                                       \
2482         TCGLabel *over = gen_new_label();                        \
2483         gen_set_rm(s, RISCV_FRM_DYN);                            \
2484         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);        \
2485         tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);\
2486                                                                  \
2487         data = FIELD_DP32(data, VDATA, VM, a->vm);               \
2488         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);           \
2489         data = FIELD_DP32(data, VDATA, VTA, s->vta);             \
2490         data = FIELD_DP32(data, VDATA, VMA, s->vma);             \
2491         tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),   \
2492                            vreg_ofs(s, a->rs1),                  \
2493                            vreg_ofs(s, a->rs2), cpu_env,         \
2494                            s->cfg_ptr->vlen / 8,                 \
2495                            s->cfg_ptr->vlen / 8, data,           \
2496                            fns[s->sew - 1]);                     \
2497         mark_vs_dirty(s);                                        \
2498         gen_set_label(over);                                     \
2499         return true;                                             \
2500     }                                                            \
2501     return false;                                                \
2504 GEN_OPFVV_WIDEN_TRANS(vfwadd_vv, opfvv_widen_check)
2505 GEN_OPFVV_WIDEN_TRANS(vfwsub_vv, opfvv_widen_check)
2507 static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a)
2509     return require_rvv(s) &&
2510            require_scale_rvf(s) &&
2511            (s->sew != MO_8) &&
2512            vext_check_isa_ill(s) &&
2513            vext_check_ds(s, a->rd, a->rs2, a->vm) &&
2514            require_scale_zve32f(s) &&
2515            require_scale_zve64f(s);
2518 /* OPFVF with WIDEN */
2519 #define GEN_OPFVF_WIDEN_TRANS(NAME)                              \
2520 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)           \
2521 {                                                                \
2522     if (opfvf_widen_check(s, a)) {                               \
2523         uint32_t data = 0;                                       \
2524         static gen_helper_opfvf *const fns[2] = {                \
2525             gen_helper_##NAME##_h, gen_helper_##NAME##_w,        \
2526         };                                                       \
2527         gen_set_rm(s, RISCV_FRM_DYN);                            \
2528         data = FIELD_DP32(data, VDATA, VM, a->vm);               \
2529         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);           \
2530         data = FIELD_DP32(data, VDATA, VTA, s->vta);             \
2531         data = FIELD_DP32(data, VDATA, VMA, s->vma);             \
2532         return opfvf_trans(a->rd, a->rs1, a->rs2, data,          \
2533                            fns[s->sew - 1], s);                  \
2534     }                                                            \
2535     return false;                                                \
2538 GEN_OPFVF_WIDEN_TRANS(vfwadd_vf)
2539 GEN_OPFVF_WIDEN_TRANS(vfwsub_vf)
2541 static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a)
2543     return require_rvv(s) &&
2544            require_scale_rvf(s) &&
2545            (s->sew != MO_8) &&
2546            vext_check_isa_ill(s) &&
2547            vext_check_dds(s, a->rd, a->rs1, a->rs2, a->vm) &&
2548            require_scale_zve32f(s) &&
2549            require_scale_zve64f(s);
2552 /* WIDEN OPFVV with WIDEN */
2553 #define GEN_OPFWV_WIDEN_TRANS(NAME)                                \
2554 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)             \
2555 {                                                                  \
2556     if (opfwv_widen_check(s, a)) {                                 \
2557         uint32_t data = 0;                                         \
2558         static gen_helper_gvec_4_ptr * const fns[2] = {            \
2559             gen_helper_##NAME##_h, gen_helper_##NAME##_w,          \
2560         };                                                         \
2561         TCGLabel *over = gen_new_label();                          \
2562         gen_set_rm(s, RISCV_FRM_DYN);                              \
2563         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
2564         tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
2565                                                                    \
2566         data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
2567         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
2568         data = FIELD_DP32(data, VDATA, VTA, s->vta);               \
2569         data = FIELD_DP32(data, VDATA, VMA, s->vma);               \
2570         tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
2571                            vreg_ofs(s, a->rs1),                    \
2572                            vreg_ofs(s, a->rs2), cpu_env,           \
2573                            s->cfg_ptr->vlen / 8,                   \
2574                            s->cfg_ptr->vlen / 8, data,             \
2575                            fns[s->sew - 1]);                       \
2576         mark_vs_dirty(s);                                          \
2577         gen_set_label(over);                                       \
2578         return true;                                               \
2579     }                                                              \
2580     return false;                                                  \
2583 GEN_OPFWV_WIDEN_TRANS(vfwadd_wv)
2584 GEN_OPFWV_WIDEN_TRANS(vfwsub_wv)
2586 static bool opfwf_widen_check(DisasContext *s, arg_rmrr *a)
2588     return require_rvv(s) &&
2589            require_scale_rvf(s) &&
2590            (s->sew != MO_8) &&
2591            vext_check_isa_ill(s) &&
2592            vext_check_dd(s, a->rd, a->rs2, a->vm) &&
2593            require_scale_zve32f(s) &&
2594            require_scale_zve64f(s);
2597 /* WIDEN OPFVF with WIDEN */
2598 #define GEN_OPFWF_WIDEN_TRANS(NAME)                              \
2599 static bool trans_##NAME(DisasContext *s, arg_rmrr *a)           \
2600 {                                                                \
2601     if (opfwf_widen_check(s, a)) {                               \
2602         uint32_t data = 0;                                       \
2603         static gen_helper_opfvf *const fns[2] = {                \
2604             gen_helper_##NAME##_h, gen_helper_##NAME##_w,        \
2605         };                                                       \
2606         gen_set_rm(s, RISCV_FRM_DYN);                            \
2607         data = FIELD_DP32(data, VDATA, VM, a->vm);               \
2608         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);           \
2609         data = FIELD_DP32(data, VDATA, VTA, s->vta);             \
2610         data = FIELD_DP32(data, VDATA, VMA, s->vma);             \
2611         return opfvf_trans(a->rd, a->rs1, a->rs2, data,          \
2612                            fns[s->sew - 1], s);                  \
2613     }                                                            \
2614     return false;                                                \
2617 GEN_OPFWF_WIDEN_TRANS(vfwadd_wf)
2618 GEN_OPFWF_WIDEN_TRANS(vfwsub_wf)
2620 /* Vector Single-Width Floating-Point Multiply/Divide Instructions */
2621 GEN_OPFVV_TRANS(vfmul_vv, opfvv_check)
2622 GEN_OPFVV_TRANS(vfdiv_vv, opfvv_check)
2623 GEN_OPFVF_TRANS(vfmul_vf,  opfvf_check)
2624 GEN_OPFVF_TRANS(vfdiv_vf,  opfvf_check)
2625 GEN_OPFVF_TRANS(vfrdiv_vf,  opfvf_check)
2627 /* Vector Widening Floating-Point Multiply */
2628 GEN_OPFVV_WIDEN_TRANS(vfwmul_vv, opfvv_widen_check)
2629 GEN_OPFVF_WIDEN_TRANS(vfwmul_vf)
2631 /* Vector Single-Width Floating-Point Fused Multiply-Add Instructions */
2632 GEN_OPFVV_TRANS(vfmacc_vv, opfvv_check)
2633 GEN_OPFVV_TRANS(vfnmacc_vv, opfvv_check)
2634 GEN_OPFVV_TRANS(vfmsac_vv, opfvv_check)
2635 GEN_OPFVV_TRANS(vfnmsac_vv, opfvv_check)
2636 GEN_OPFVV_TRANS(vfmadd_vv, opfvv_check)
2637 GEN_OPFVV_TRANS(vfnmadd_vv, opfvv_check)
2638 GEN_OPFVV_TRANS(vfmsub_vv, opfvv_check)
2639 GEN_OPFVV_TRANS(vfnmsub_vv, opfvv_check)
2640 GEN_OPFVF_TRANS(vfmacc_vf, opfvf_check)
2641 GEN_OPFVF_TRANS(vfnmacc_vf, opfvf_check)
2642 GEN_OPFVF_TRANS(vfmsac_vf, opfvf_check)
2643 GEN_OPFVF_TRANS(vfnmsac_vf, opfvf_check)
2644 GEN_OPFVF_TRANS(vfmadd_vf, opfvf_check)
2645 GEN_OPFVF_TRANS(vfnmadd_vf, opfvf_check)
2646 GEN_OPFVF_TRANS(vfmsub_vf, opfvf_check)
2647 GEN_OPFVF_TRANS(vfnmsub_vf, opfvf_check)
2649 /* Vector Widening Floating-Point Fused Multiply-Add Instructions */
2650 GEN_OPFVV_WIDEN_TRANS(vfwmacc_vv, opfvv_widen_check)
2651 GEN_OPFVV_WIDEN_TRANS(vfwnmacc_vv, opfvv_widen_check)
2652 GEN_OPFVV_WIDEN_TRANS(vfwmsac_vv, opfvv_widen_check)
2653 GEN_OPFVV_WIDEN_TRANS(vfwnmsac_vv, opfvv_widen_check)
2654 GEN_OPFVF_WIDEN_TRANS(vfwmacc_vf)
2655 GEN_OPFVF_WIDEN_TRANS(vfwnmacc_vf)
2656 GEN_OPFVF_WIDEN_TRANS(vfwmsac_vf)
2657 GEN_OPFVF_WIDEN_TRANS(vfwnmsac_vf)
2659 /* Vector Floating-Point Square-Root Instruction */
2662  * If the current SEW does not correspond to a supported IEEE floating-point
2663  * type, an illegal instruction exception is raised
2664  */
2665 static bool opfv_check(DisasContext *s, arg_rmr *a)
2667     return require_rvv(s) &&
2668            require_rvf(s) &&
2669            vext_check_isa_ill(s) &&
2670            /* OPFV instructions ignore vs1 check */
2671            vext_check_ss(s, a->rd, a->rs2, a->vm) &&
2672            require_zve32f(s) &&
2673            require_zve64f(s);
2676 static bool do_opfv(DisasContext *s, arg_rmr *a,
2677                     gen_helper_gvec_3_ptr *fn,
2678                     bool (*checkfn)(DisasContext *, arg_rmr *),
2679                     int rm)
2681     if (checkfn(s, a)) {
2682         if (rm != RISCV_FRM_DYN) {
2683             gen_set_rm(s, RISCV_FRM_DYN);
2684         }
2686         uint32_t data = 0;
2687         TCGLabel *over = gen_new_label();
2688         gen_set_rm(s, rm);
2689         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
2690         tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
2692         data = FIELD_DP32(data, VDATA, VM, a->vm);
2693         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
2694         data = FIELD_DP32(data, VDATA, VTA, s->vta);
2695         data = FIELD_DP32(data, VDATA, VMA, s->vma);
2696         tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
2697                            vreg_ofs(s, a->rs2), cpu_env,
2698                            s->cfg_ptr->vlen / 8,
2699                            s->cfg_ptr->vlen / 8, data, fn);
2700         mark_vs_dirty(s);
2701         gen_set_label(over);
2702         return true;
2703     }
2704     return false;
2707 #define GEN_OPFV_TRANS(NAME, CHECK, FRM)               \
2708 static bool trans_##NAME(DisasContext *s, arg_rmr *a)  \
2709 {                                                      \
2710     static gen_helper_gvec_3_ptr * const fns[3] = {    \
2711         gen_helper_##NAME##_h,                         \
2712         gen_helper_##NAME##_w,                         \
2713         gen_helper_##NAME##_d                          \
2714     };                                                 \
2715     return do_opfv(s, a, fns[s->sew - 1], CHECK, FRM); \
2718 GEN_OPFV_TRANS(vfsqrt_v, opfv_check, RISCV_FRM_DYN)
2719 GEN_OPFV_TRANS(vfrsqrt7_v, opfv_check, RISCV_FRM_DYN)
2720 GEN_OPFV_TRANS(vfrec7_v, opfv_check, RISCV_FRM_DYN)
2722 /* Vector Floating-Point MIN/MAX Instructions */
2723 GEN_OPFVV_TRANS(vfmin_vv, opfvv_check)
2724 GEN_OPFVV_TRANS(vfmax_vv, opfvv_check)
2725 GEN_OPFVF_TRANS(vfmin_vf, opfvf_check)
2726 GEN_OPFVF_TRANS(vfmax_vf, opfvf_check)
2728 /* Vector Floating-Point Sign-Injection Instructions */
2729 GEN_OPFVV_TRANS(vfsgnj_vv, opfvv_check)
2730 GEN_OPFVV_TRANS(vfsgnjn_vv, opfvv_check)
2731 GEN_OPFVV_TRANS(vfsgnjx_vv, opfvv_check)
2732 GEN_OPFVF_TRANS(vfsgnj_vf, opfvf_check)
2733 GEN_OPFVF_TRANS(vfsgnjn_vf, opfvf_check)
2734 GEN_OPFVF_TRANS(vfsgnjx_vf, opfvf_check)
2736 /* Vector Floating-Point Compare Instructions */
2737 static bool opfvv_cmp_check(DisasContext *s, arg_rmrr *a)
2739     return require_rvv(s) &&
2740            require_rvf(s) &&
2741            vext_check_isa_ill(s) &&
2742            vext_check_mss(s, a->rd, a->rs1, a->rs2) &&
2743            require_zve32f(s) &&
2744            require_zve64f(s);
2747 GEN_OPFVV_TRANS(vmfeq_vv, opfvv_cmp_check)
2748 GEN_OPFVV_TRANS(vmfne_vv, opfvv_cmp_check)
2749 GEN_OPFVV_TRANS(vmflt_vv, opfvv_cmp_check)
2750 GEN_OPFVV_TRANS(vmfle_vv, opfvv_cmp_check)
2752 static bool opfvf_cmp_check(DisasContext *s, arg_rmrr *a)
2754     return require_rvv(s) &&
2755            require_rvf(s) &&
2756            vext_check_isa_ill(s) &&
2757            vext_check_ms(s, a->rd, a->rs2) &&
2758            require_zve32f(s) &&
2759            require_zve64f(s);
2762 GEN_OPFVF_TRANS(vmfeq_vf, opfvf_cmp_check)
2763 GEN_OPFVF_TRANS(vmfne_vf, opfvf_cmp_check)
2764 GEN_OPFVF_TRANS(vmflt_vf, opfvf_cmp_check)
2765 GEN_OPFVF_TRANS(vmfle_vf, opfvf_cmp_check)
2766 GEN_OPFVF_TRANS(vmfgt_vf, opfvf_cmp_check)
2767 GEN_OPFVF_TRANS(vmfge_vf, opfvf_cmp_check)
2769 /* Vector Floating-Point Classify Instruction */
2770 GEN_OPFV_TRANS(vfclass_v, opfv_check, RISCV_FRM_DYN)
2772 /* Vector Floating-Point Merge Instruction */
2773 GEN_OPFVF_TRANS(vfmerge_vfm,  opfvf_check)
2775 static bool trans_vfmv_v_f(DisasContext *s, arg_vfmv_v_f *a)
2777     if (require_rvv(s) &&
2778         require_rvf(s) &&
2779         vext_check_isa_ill(s) &&
2780         require_align(a->rd, s->lmul) &&
2781         require_zve32f(s) &&
2782         require_zve64f(s)) {
2783         gen_set_rm(s, RISCV_FRM_DYN);
2785         TCGv_i64 t1;
2787         if (s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
2788             t1 = tcg_temp_new_i64();
2789             /* NaN-box f[rs1] */
2790             do_nanbox(s, t1, cpu_fpr[a->rs1]);
2792             tcg_gen_gvec_dup_i64(s->sew, vreg_ofs(s, a->rd),
2793                                  MAXSZ(s), MAXSZ(s), t1);
2794             mark_vs_dirty(s);
2795         } else {
2796             TCGv_ptr dest;
2797             TCGv_i32 desc;
2798             uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul);
2799             data = FIELD_DP32(data, VDATA, VTA, s->vta);
2800             data = FIELD_DP32(data, VDATA, VMA, s->vma);
2801             static gen_helper_vmv_vx * const fns[3] = {
2802                 gen_helper_vmv_v_x_h,
2803                 gen_helper_vmv_v_x_w,
2804                 gen_helper_vmv_v_x_d,
2805             };
2806             TCGLabel *over = gen_new_label();
2807             tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
2808             tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
2810             t1 = tcg_temp_new_i64();
2811             /* NaN-box f[rs1] */
2812             do_nanbox(s, t1, cpu_fpr[a->rs1]);
2814             dest = tcg_temp_new_ptr();
2815             desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
2816                                               s->cfg_ptr->vlen / 8, data));
2817             tcg_gen_addi_ptr(dest, cpu_env, vreg_ofs(s, a->rd));
2819             fns[s->sew - 1](dest, t1, cpu_env, desc);
2821             tcg_temp_free_ptr(dest);
2822             mark_vs_dirty(s);
2823             gen_set_label(over);
2824         }
2825         tcg_temp_free_i64(t1);
2826         return true;
2827     }
2828     return false;
2831 /* Single-Width Floating-Point/Integer Type-Convert Instructions */
2832 #define GEN_OPFV_CVT_TRANS(NAME, HELPER, FRM)               \
2833 static bool trans_##NAME(DisasContext *s, arg_rmr *a)       \
2834 {                                                           \
2835     static gen_helper_gvec_3_ptr * const fns[3] = {         \
2836         gen_helper_##HELPER##_h,                            \
2837         gen_helper_##HELPER##_w,                            \
2838         gen_helper_##HELPER##_d                             \
2839     };                                                      \
2840     return do_opfv(s, a, fns[s->sew - 1], opfv_check, FRM); \
2843 GEN_OPFV_CVT_TRANS(vfcvt_xu_f_v, vfcvt_xu_f_v, RISCV_FRM_DYN)
2844 GEN_OPFV_CVT_TRANS(vfcvt_x_f_v, vfcvt_x_f_v, RISCV_FRM_DYN)
2845 GEN_OPFV_CVT_TRANS(vfcvt_f_xu_v, vfcvt_f_xu_v, RISCV_FRM_DYN)
2846 GEN_OPFV_CVT_TRANS(vfcvt_f_x_v, vfcvt_f_x_v, RISCV_FRM_DYN)
2847 /* Reuse the helper functions from vfcvt.xu.f.v and vfcvt.x.f.v */
2848 GEN_OPFV_CVT_TRANS(vfcvt_rtz_xu_f_v, vfcvt_xu_f_v, RISCV_FRM_RTZ)
2849 GEN_OPFV_CVT_TRANS(vfcvt_rtz_x_f_v, vfcvt_x_f_v, RISCV_FRM_RTZ)
2851 /* Widening Floating-Point/Integer Type-Convert Instructions */
2854  * If the current SEW does not correspond to a supported IEEE floating-point
2855  * type, an illegal instruction exception is raised
2856  */
2857 static bool opfv_widen_check(DisasContext *s, arg_rmr *a)
2859     return require_rvv(s) &&
2860            vext_check_isa_ill(s) &&
2861            vext_check_ds(s, a->rd, a->rs2, a->vm);
2864 static bool opxfv_widen_check(DisasContext *s, arg_rmr *a)
2866     return opfv_widen_check(s, a) &&
2867            require_rvf(s) &&
2868            require_zve32f(s) &&
2869            require_zve64f(s);
2872 static bool opffv_widen_check(DisasContext *s, arg_rmr *a)
2874     return opfv_widen_check(s, a) &&
2875            require_scale_rvf(s) &&
2876            (s->sew != MO_8) &&
2877            require_scale_zve32f(s) &&
2878            require_scale_zve64f(s);
2881 #define GEN_OPFV_WIDEN_TRANS(NAME, CHECK, HELPER, FRM)             \
2882 static bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
2883 {                                                                  \
2884     if (CHECK(s, a)) {                                             \
2885         if (FRM != RISCV_FRM_DYN) {                                \
2886             gen_set_rm(s, RISCV_FRM_DYN);                          \
2887         }                                                          \
2888                                                                    \
2889         uint32_t data = 0;                                         \
2890         static gen_helper_gvec_3_ptr * const fns[2] = {            \
2891             gen_helper_##HELPER##_h,                               \
2892             gen_helper_##HELPER##_w,                               \
2893         };                                                         \
2894         TCGLabel *over = gen_new_label();                          \
2895         gen_set_rm(s, FRM);                                        \
2896         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
2897         tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
2898                                                                    \
2899         data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
2900         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
2901         data = FIELD_DP32(data, VDATA, VTA, s->vta);               \
2902         data = FIELD_DP32(data, VDATA, VMA, s->vma);               \
2903         tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
2904                            vreg_ofs(s, a->rs2), cpu_env,           \
2905                            s->cfg_ptr->vlen / 8,                   \
2906                            s->cfg_ptr->vlen / 8, data,             \
2907                            fns[s->sew - 1]);                       \
2908         mark_vs_dirty(s);                                          \
2909         gen_set_label(over);                                       \
2910         return true;                                               \
2911     }                                                              \
2912     return false;                                                  \
2915 GEN_OPFV_WIDEN_TRANS(vfwcvt_xu_f_v, opxfv_widen_check, vfwcvt_xu_f_v,
2916                      RISCV_FRM_DYN)
2917 GEN_OPFV_WIDEN_TRANS(vfwcvt_x_f_v, opxfv_widen_check, vfwcvt_x_f_v,
2918                      RISCV_FRM_DYN)
2919 GEN_OPFV_WIDEN_TRANS(vfwcvt_f_f_v, opffv_widen_check, vfwcvt_f_f_v,
2920                      RISCV_FRM_DYN)
2921 /* Reuse the helper functions from vfwcvt.xu.f.v and vfwcvt.x.f.v */
2922 GEN_OPFV_WIDEN_TRANS(vfwcvt_rtz_xu_f_v, opxfv_widen_check, vfwcvt_xu_f_v,
2923                      RISCV_FRM_RTZ)
2924 GEN_OPFV_WIDEN_TRANS(vfwcvt_rtz_x_f_v, opxfv_widen_check, vfwcvt_x_f_v,
2925                      RISCV_FRM_RTZ)
2927 static bool opfxv_widen_check(DisasContext *s, arg_rmr *a)
2929     return require_rvv(s) &&
2930            require_scale_rvf(s) &&
2931            vext_check_isa_ill(s) &&
2932            /* OPFV widening instructions ignore vs1 check */
2933            vext_check_ds(s, a->rd, a->rs2, a->vm) &&
2934            require_scale_zve32f(s) &&
2935            require_scale_zve64f(s);
2938 #define GEN_OPFXV_WIDEN_TRANS(NAME)                                \
2939 static bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
2940 {                                                                  \
2941     if (opfxv_widen_check(s, a)) {                                 \
2942         uint32_t data = 0;                                         \
2943         static gen_helper_gvec_3_ptr * const fns[3] = {            \
2944             gen_helper_##NAME##_b,                                 \
2945             gen_helper_##NAME##_h,                                 \
2946             gen_helper_##NAME##_w,                                 \
2947         };                                                         \
2948         TCGLabel *over = gen_new_label();                          \
2949         gen_set_rm(s, RISCV_FRM_DYN);                              \
2950         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
2951         tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
2952                                                                    \
2953         data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
2954         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
2955         data = FIELD_DP32(data, VDATA, VTA, s->vta);               \
2956         data = FIELD_DP32(data, VDATA, VMA, s->vma);               \
2957         tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
2958                            vreg_ofs(s, a->rs2), cpu_env,           \
2959                            s->cfg_ptr->vlen / 8,                   \
2960                            s->cfg_ptr->vlen / 8, data,             \
2961                            fns[s->sew]);                           \
2962         mark_vs_dirty(s);                                          \
2963         gen_set_label(over);                                       \
2964         return true;                                               \
2965     }                                                              \
2966     return false;                                                  \
2969 GEN_OPFXV_WIDEN_TRANS(vfwcvt_f_xu_v)
2970 GEN_OPFXV_WIDEN_TRANS(vfwcvt_f_x_v)
2972 /* Narrowing Floating-Point/Integer Type-Convert Instructions */
2975  * If the current SEW does not correspond to a supported IEEE floating-point
2976  * type, an illegal instruction exception is raised
2977  */
2978 static bool opfv_narrow_check(DisasContext *s, arg_rmr *a)
2980     return require_rvv(s) &&
2981            vext_check_isa_ill(s) &&
2982            /* OPFV narrowing instructions ignore vs1 check */
2983            vext_check_sd(s, a->rd, a->rs2, a->vm);
2986 static bool opfxv_narrow_check(DisasContext *s, arg_rmr *a)
2988     return opfv_narrow_check(s, a) &&
2989            require_rvf(s) &&
2990            (s->sew != MO_64) &&
2991            require_zve32f(s) &&
2992            require_zve64f(s);
2995 static bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
2997     return opfv_narrow_check(s, a) &&
2998            require_scale_rvf(s) &&
2999            (s->sew != MO_8) &&
3000            require_scale_zve32f(s) &&
3001            require_scale_zve64f(s);
3004 #define GEN_OPFV_NARROW_TRANS(NAME, CHECK, HELPER, FRM)            \
3005 static bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
3006 {                                                                  \
3007     if (CHECK(s, a)) {                                             \
3008         if (FRM != RISCV_FRM_DYN) {                                \
3009             gen_set_rm(s, RISCV_FRM_DYN);                          \
3010         }                                                          \
3011                                                                    \
3012         uint32_t data = 0;                                         \
3013         static gen_helper_gvec_3_ptr * const fns[2] = {            \
3014             gen_helper_##HELPER##_h,                               \
3015             gen_helper_##HELPER##_w,                               \
3016         };                                                         \
3017         TCGLabel *over = gen_new_label();                          \
3018         gen_set_rm(s, FRM);                                        \
3019         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
3020         tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
3021                                                                    \
3022         data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
3023         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
3024         data = FIELD_DP32(data, VDATA, VTA, s->vta);               \
3025         data = FIELD_DP32(data, VDATA, VMA, s->vma);               \
3026         tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
3027                            vreg_ofs(s, a->rs2), cpu_env,           \
3028                            s->cfg_ptr->vlen / 8,                   \
3029                            s->cfg_ptr->vlen / 8, data,             \
3030                            fns[s->sew - 1]);                       \
3031         mark_vs_dirty(s);                                          \
3032         gen_set_label(over);                                       \
3033         return true;                                               \
3034     }                                                              \
3035     return false;                                                  \
3038 GEN_OPFV_NARROW_TRANS(vfncvt_f_xu_w, opfxv_narrow_check, vfncvt_f_xu_w,
3039                       RISCV_FRM_DYN)
3040 GEN_OPFV_NARROW_TRANS(vfncvt_f_x_w, opfxv_narrow_check, vfncvt_f_x_w,
3041                       RISCV_FRM_DYN)
3042 GEN_OPFV_NARROW_TRANS(vfncvt_f_f_w, opffv_narrow_check, vfncvt_f_f_w,
3043                       RISCV_FRM_DYN)
3044 /* Reuse the helper function from vfncvt.f.f.w */
3045 GEN_OPFV_NARROW_TRANS(vfncvt_rod_f_f_w, opffv_narrow_check, vfncvt_f_f_w,
3046                       RISCV_FRM_ROD)
3048 static bool opxfv_narrow_check(DisasContext *s, arg_rmr *a)
3050     return require_rvv(s) &&
3051            require_scale_rvf(s) &&
3052            vext_check_isa_ill(s) &&
3053            /* OPFV narrowing instructions ignore vs1 check */
3054            vext_check_sd(s, a->rd, a->rs2, a->vm) &&
3055            require_scale_zve32f(s) &&
3056            require_scale_zve64f(s);
3059 #define GEN_OPXFV_NARROW_TRANS(NAME, HELPER, FRM)                  \
3060 static bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
3061 {                                                                  \
3062     if (opxfv_narrow_check(s, a)) {                                \
3063         if (FRM != RISCV_FRM_DYN) {                                \
3064             gen_set_rm(s, RISCV_FRM_DYN);                          \
3065         }                                                          \
3066                                                                    \
3067         uint32_t data = 0;                                         \
3068         static gen_helper_gvec_3_ptr * const fns[3] = {            \
3069             gen_helper_##HELPER##_b,                               \
3070             gen_helper_##HELPER##_h,                               \
3071             gen_helper_##HELPER##_w,                               \
3072         };                                                         \
3073         TCGLabel *over = gen_new_label();                          \
3074         gen_set_rm(s, FRM);                                        \
3075         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
3076         tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
3077                                                                    \
3078         data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
3079         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
3080         data = FIELD_DP32(data, VDATA, VTA, s->vta);               \
3081         data = FIELD_DP32(data, VDATA, VMA, s->vma);               \
3082         tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
3083                            vreg_ofs(s, a->rs2), cpu_env,           \
3084                            s->cfg_ptr->vlen / 8,                   \
3085                            s->cfg_ptr->vlen / 8, data,             \
3086                            fns[s->sew]);                           \
3087         mark_vs_dirty(s);                                          \
3088         gen_set_label(over);                                       \
3089         return true;                                               \
3090     }                                                              \
3091     return false;                                                  \
3094 GEN_OPXFV_NARROW_TRANS(vfncvt_xu_f_w, vfncvt_xu_f_w, RISCV_FRM_DYN)
3095 GEN_OPXFV_NARROW_TRANS(vfncvt_x_f_w, vfncvt_x_f_w, RISCV_FRM_DYN)
3096 /* Reuse the helper functions from vfncvt.xu.f.w and vfncvt.x.f.w */
3097 GEN_OPXFV_NARROW_TRANS(vfncvt_rtz_xu_f_w, vfncvt_xu_f_w, RISCV_FRM_RTZ)
3098 GEN_OPXFV_NARROW_TRANS(vfncvt_rtz_x_f_w, vfncvt_x_f_w, RISCV_FRM_RTZ)
3101  *** Vector Reduction Operations
3102  */
3103 /* Vector Single-Width Integer Reduction Instructions */
3104 static bool reduction_check(DisasContext *s, arg_rmrr *a)
3106     return require_rvv(s) &&
3107            vext_check_isa_ill(s) &&
3108            vext_check_reduction(s, a->rs2);
3111 GEN_OPIVV_TRANS(vredsum_vs, reduction_check)
3112 GEN_OPIVV_TRANS(vredmaxu_vs, reduction_check)
3113 GEN_OPIVV_TRANS(vredmax_vs, reduction_check)
3114 GEN_OPIVV_TRANS(vredminu_vs, reduction_check)
3115 GEN_OPIVV_TRANS(vredmin_vs, reduction_check)
3116 GEN_OPIVV_TRANS(vredand_vs, reduction_check)
3117 GEN_OPIVV_TRANS(vredor_vs, reduction_check)
3118 GEN_OPIVV_TRANS(vredxor_vs, reduction_check)
3120 /* Vector Widening Integer Reduction Instructions */
3121 static bool reduction_widen_check(DisasContext *s, arg_rmrr *a)
3123     return reduction_check(s, a) && (s->sew < MO_64) &&
3124            ((s->sew + 1) <= (s->cfg_ptr->elen >> 4));
3127 GEN_OPIVV_WIDEN_TRANS(vwredsum_vs, reduction_widen_check)
3128 GEN_OPIVV_WIDEN_TRANS(vwredsumu_vs, reduction_widen_check)
3130 /* Vector Single-Width Floating-Point Reduction Instructions */
3131 static bool freduction_check(DisasContext *s, arg_rmrr *a)
3133     return reduction_check(s, a) &&
3134            require_rvf(s) &&
3135            require_zve32f(s) &&
3136            require_zve64f(s);
3139 GEN_OPFVV_TRANS(vfredsum_vs, freduction_check)
3140 GEN_OPFVV_TRANS(vfredmax_vs, freduction_check)
3141 GEN_OPFVV_TRANS(vfredmin_vs, freduction_check)
3143 /* Vector Widening Floating-Point Reduction Instructions */
3144 static bool freduction_widen_check(DisasContext *s, arg_rmrr *a)
3146     return reduction_widen_check(s, a) &&
3147            require_scale_rvf(s) &&
3148            (s->sew != MO_8);
3151 GEN_OPFVV_WIDEN_TRANS(vfwredsum_vs, freduction_widen_check)
3154  *** Vector Mask Operations
3155  */
3157 /* Vector Mask-Register Logical Instructions */
3158 #define GEN_MM_TRANS(NAME)                                         \
3159 static bool trans_##NAME(DisasContext *s, arg_r *a)                \
3160 {                                                                  \
3161     if (require_rvv(s) &&                                          \
3162         vext_check_isa_ill(s)) {                                   \
3163         uint32_t data = 0;                                         \
3164         gen_helper_gvec_4_ptr *fn = gen_helper_##NAME;             \
3165         TCGLabel *over = gen_new_label();                          \
3166         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
3167         tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
3168                                                                    \
3169         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
3170         data =                                                     \
3171             FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);\
3172         tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),     \
3173                            vreg_ofs(s, a->rs1),                    \
3174                            vreg_ofs(s, a->rs2), cpu_env,           \
3175                            s->cfg_ptr->vlen / 8,                   \
3176                            s->cfg_ptr->vlen / 8, data, fn);        \
3177         mark_vs_dirty(s);                                          \
3178         gen_set_label(over);                                       \
3179         return true;                                               \
3180     }                                                              \
3181     return false;                                                  \
3184 GEN_MM_TRANS(vmand_mm)
3185 GEN_MM_TRANS(vmnand_mm)
3186 GEN_MM_TRANS(vmandn_mm)
3187 GEN_MM_TRANS(vmxor_mm)
3188 GEN_MM_TRANS(vmor_mm)
3189 GEN_MM_TRANS(vmnor_mm)
3190 GEN_MM_TRANS(vmorn_mm)
3191 GEN_MM_TRANS(vmxnor_mm)
3193 /* Vector count population in mask vcpop */
3194 static bool trans_vcpop_m(DisasContext *s, arg_rmr *a)
3196     if (require_rvv(s) &&
3197         vext_check_isa_ill(s) &&
3198         s->vstart == 0) {
3199         TCGv_ptr src2, mask;
3200         TCGv dst;
3201         TCGv_i32 desc;
3202         uint32_t data = 0;
3203         data = FIELD_DP32(data, VDATA, VM, a->vm);
3204         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
3206         mask = tcg_temp_new_ptr();
3207         src2 = tcg_temp_new_ptr();
3208         dst = dest_gpr(s, a->rd);
3209         desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
3210                                           s->cfg_ptr->vlen / 8, data));
3212         tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, a->rs2));
3213         tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
3215         gen_helper_vcpop_m(dst, mask, src2, cpu_env, desc);
3216         gen_set_gpr(s, a->rd, dst);
3218         tcg_temp_free_ptr(mask);
3219         tcg_temp_free_ptr(src2);
3221         return true;
3222     }
3223     return false;
3226 /* vmfirst find-first-set mask bit */
3227 static bool trans_vfirst_m(DisasContext *s, arg_rmr *a)
3229     if (require_rvv(s) &&
3230         vext_check_isa_ill(s) &&
3231         s->vstart == 0) {
3232         TCGv_ptr src2, mask;
3233         TCGv dst;
3234         TCGv_i32 desc;
3235         uint32_t data = 0;
3236         data = FIELD_DP32(data, VDATA, VM, a->vm);
3237         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
3239         mask = tcg_temp_new_ptr();
3240         src2 = tcg_temp_new_ptr();
3241         dst = dest_gpr(s, a->rd);
3242         desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8,
3243                                           s->cfg_ptr->vlen / 8, data));
3245         tcg_gen_addi_ptr(src2, cpu_env, vreg_ofs(s, a->rs2));
3246         tcg_gen_addi_ptr(mask, cpu_env, vreg_ofs(s, 0));
3248         gen_helper_vfirst_m(dst, mask, src2, cpu_env, desc);
3249         gen_set_gpr(s, a->rd, dst);
3251         tcg_temp_free_ptr(mask);
3252         tcg_temp_free_ptr(src2);
3253         return true;
3254     }
3255     return false;
3258 /* vmsbf.m set-before-first mask bit */
3259 /* vmsif.m set-includ-first mask bit */
3260 /* vmsof.m set-only-first mask bit */
3261 #define GEN_M_TRANS(NAME)                                          \
3262 static bool trans_##NAME(DisasContext *s, arg_rmr *a)              \
3263 {                                                                  \
3264     if (require_rvv(s) &&                                          \
3265         vext_check_isa_ill(s) &&                                   \
3266         require_vm(a->vm, a->rd) &&                                \
3267         (a->rd != a->rs2) &&                                       \
3268         (s->vstart == 0)) {                                        \
3269         uint32_t data = 0;                                         \
3270         gen_helper_gvec_3_ptr *fn = gen_helper_##NAME;             \
3271         TCGLabel *over = gen_new_label();                          \
3272         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);          \
3273                                                                    \
3274         data = FIELD_DP32(data, VDATA, VM, a->vm);                 \
3275         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);             \
3276         data =                                                     \
3277             FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);\
3278         data = FIELD_DP32(data, VDATA, VMA, s->vma);               \
3279         tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd),                     \
3280                            vreg_ofs(s, 0), vreg_ofs(s, a->rs2),    \
3281                            cpu_env, s->cfg_ptr->vlen / 8,          \
3282                            s->cfg_ptr->vlen / 8,                   \
3283                            data, fn);                              \
3284         mark_vs_dirty(s);                                          \
3285         gen_set_label(over);                                       \
3286         return true;                                               \
3287     }                                                              \
3288     return false;                                                  \
3291 GEN_M_TRANS(vmsbf_m)
3292 GEN_M_TRANS(vmsif_m)
3293 GEN_M_TRANS(vmsof_m)
3296  * Vector Iota Instruction
3298  * 1. The destination register cannot overlap the source register.
3299  * 2. If masked, cannot overlap the mask register ('v0').
3300  * 3. An illegal instruction exception is raised if vstart is non-zero.
3301  */
3302 static bool trans_viota_m(DisasContext *s, arg_viota_m *a)
3304     if (require_rvv(s) &&
3305         vext_check_isa_ill(s) &&
3306         !is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs2, 1) &&
3307         require_vm(a->vm, a->rd) &&
3308         require_align(a->rd, s->lmul) &&
3309         (s->vstart == 0)) {
3310         uint32_t data = 0;
3311         TCGLabel *over = gen_new_label();
3312         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
3314         data = FIELD_DP32(data, VDATA, VM, a->vm);
3315         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
3316         data = FIELD_DP32(data, VDATA, VTA, s->vta);
3317         data = FIELD_DP32(data, VDATA, VMA, s->vma);
3318         static gen_helper_gvec_3_ptr * const fns[4] = {
3319             gen_helper_viota_m_b, gen_helper_viota_m_h,
3320             gen_helper_viota_m_w, gen_helper_viota_m_d,
3321         };
3322         tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
3323                            vreg_ofs(s, a->rs2), cpu_env,
3324                            s->cfg_ptr->vlen / 8,
3325                            s->cfg_ptr->vlen / 8, data, fns[s->sew]);
3326         mark_vs_dirty(s);
3327         gen_set_label(over);
3328         return true;
3329     }
3330     return false;
3333 /* Vector Element Index Instruction */
3334 static bool trans_vid_v(DisasContext *s, arg_vid_v *a)
3336     if (require_rvv(s) &&
3337         vext_check_isa_ill(s) &&
3338         require_align(a->rd, s->lmul) &&
3339         require_vm(a->vm, a->rd)) {
3340         uint32_t data = 0;
3341         TCGLabel *over = gen_new_label();
3342         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
3343         tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
3345         data = FIELD_DP32(data, VDATA, VM, a->vm);
3346         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
3347         data = FIELD_DP32(data, VDATA, VTA, s->vta);
3348         data = FIELD_DP32(data, VDATA, VMA, s->vma);
3349         static gen_helper_gvec_2_ptr * const fns[4] = {
3350             gen_helper_vid_v_b, gen_helper_vid_v_h,
3351             gen_helper_vid_v_w, gen_helper_vid_v_d,
3352         };
3353         tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
3354                            cpu_env, s->cfg_ptr->vlen / 8,
3355                            s->cfg_ptr->vlen / 8,
3356                            data, fns[s->sew]);
3357         mark_vs_dirty(s);
3358         gen_set_label(over);
3359         return true;
3360     }
3361     return false;
3365  *** Vector Permutation Instructions
3366  */
3368 static void load_element(TCGv_i64 dest, TCGv_ptr base,
3369                          int ofs, int sew, bool sign)
3371     switch (sew) {
3372     case MO_8:
3373         if (!sign) {
3374             tcg_gen_ld8u_i64(dest, base, ofs);
3375         } else {
3376             tcg_gen_ld8s_i64(dest, base, ofs);
3377         }
3378         break;
3379     case MO_16:
3380         if (!sign) {
3381             tcg_gen_ld16u_i64(dest, base, ofs);
3382         } else {
3383             tcg_gen_ld16s_i64(dest, base, ofs);
3384         }
3385         break;
3386     case MO_32:
3387         if (!sign) {
3388             tcg_gen_ld32u_i64(dest, base, ofs);
3389         } else {
3390             tcg_gen_ld32s_i64(dest, base, ofs);
3391         }
3392         break;
3393     case MO_64:
3394         tcg_gen_ld_i64(dest, base, ofs);
3395         break;
3396     default:
3397         g_assert_not_reached();
3398         break;
3399     }
3402 /* offset of the idx element with base regsiter r */
3403 static uint32_t endian_ofs(DisasContext *s, int r, int idx)
3405 #if HOST_BIG_ENDIAN
3406     return vreg_ofs(s, r) + ((idx ^ (7 >> s->sew)) << s->sew);
3407 #else
3408     return vreg_ofs(s, r) + (idx << s->sew);
3409 #endif
3412 /* adjust the index according to the endian */
3413 static void endian_adjust(TCGv_i32 ofs, int sew)
3415 #if HOST_BIG_ENDIAN
3416     tcg_gen_xori_i32(ofs, ofs, 7 >> sew);
3417 #endif
3420 /* Load idx >= VLMAX ? 0 : vreg[idx] */
3421 static void vec_element_loadx(DisasContext *s, TCGv_i64 dest,
3422                               int vreg, TCGv idx, int vlmax)
3424     TCGv_i32 ofs = tcg_temp_new_i32();
3425     TCGv_ptr base = tcg_temp_new_ptr();
3426     TCGv_i64 t_idx = tcg_temp_new_i64();
3427     TCGv_i64 t_vlmax, t_zero;
3429     /*
3430      * Mask the index to the length so that we do
3431      * not produce an out-of-range load.
3432      */
3433     tcg_gen_trunc_tl_i32(ofs, idx);
3434     tcg_gen_andi_i32(ofs, ofs, vlmax - 1);
3436     /* Convert the index to an offset. */
3437     endian_adjust(ofs, s->sew);
3438     tcg_gen_shli_i32(ofs, ofs, s->sew);
3440     /* Convert the index to a pointer. */
3441     tcg_gen_ext_i32_ptr(base, ofs);
3442     tcg_gen_add_ptr(base, base, cpu_env);
3444     /* Perform the load. */
3445     load_element(dest, base,
3446                  vreg_ofs(s, vreg), s->sew, false);
3447     tcg_temp_free_ptr(base);
3448     tcg_temp_free_i32(ofs);
3450     /* Flush out-of-range indexing to zero.  */
3451     t_vlmax = tcg_constant_i64(vlmax);
3452     t_zero = tcg_constant_i64(0);
3453     tcg_gen_extu_tl_i64(t_idx, idx);
3455     tcg_gen_movcond_i64(TCG_COND_LTU, dest, t_idx,
3456                         t_vlmax, dest, t_zero);
3458     tcg_temp_free_i64(t_idx);
3461 static void vec_element_loadi(DisasContext *s, TCGv_i64 dest,
3462                               int vreg, int idx, bool sign)
3464     load_element(dest, cpu_env, endian_ofs(s, vreg, idx), s->sew, sign);
3467 /* Integer Scalar Move Instruction */
3469 static void store_element(TCGv_i64 val, TCGv_ptr base,
3470                           int ofs, int sew)
3472     switch (sew) {
3473     case MO_8:
3474         tcg_gen_st8_i64(val, base, ofs);
3475         break;
3476     case MO_16:
3477         tcg_gen_st16_i64(val, base, ofs);
3478         break;
3479     case MO_32:
3480         tcg_gen_st32_i64(val, base, ofs);
3481         break;
3482     case MO_64:
3483         tcg_gen_st_i64(val, base, ofs);
3484         break;
3485     default:
3486         g_assert_not_reached();
3487         break;
3488     }
3492  * Store vreg[idx] = val.
3493  * The index must be in range of VLMAX.
3494  */
3495 static void vec_element_storei(DisasContext *s, int vreg,
3496                                int idx, TCGv_i64 val)
3498     store_element(val, cpu_env, endian_ofs(s, vreg, idx), s->sew);
3501 /* vmv.x.s rd, vs2 # x[rd] = vs2[0] */
3502 static bool trans_vmv_x_s(DisasContext *s, arg_vmv_x_s *a)
3504     if (require_rvv(s) &&
3505         vext_check_isa_ill(s)) {
3506         TCGv_i64 t1;
3507         TCGv dest;
3509         t1 = tcg_temp_new_i64();
3510         dest = tcg_temp_new();
3511         /*
3512          * load vreg and sign-extend to 64 bits,
3513          * then truncate to XLEN bits before storing to gpr.
3514          */
3515         vec_element_loadi(s, t1, a->rs2, 0, true);
3516         tcg_gen_trunc_i64_tl(dest, t1);
3517         gen_set_gpr(s, a->rd, dest);
3518         tcg_temp_free_i64(t1);
3519         tcg_temp_free(dest);
3521         return true;
3522     }
3523     return false;
3526 /* vmv.s.x vd, rs1 # vd[0] = rs1 */
3527 static bool trans_vmv_s_x(DisasContext *s, arg_vmv_s_x *a)
3529     if (require_rvv(s) &&
3530         vext_check_isa_ill(s)) {
3531         /* This instruction ignores LMUL and vector register groups */
3532         TCGv_i64 t1;
3533         TCGv s1;
3534         TCGLabel *over = gen_new_label();
3536         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
3537         tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
3539         t1 = tcg_temp_new_i64();
3541         /*
3542          * load gpr and sign-extend to 64 bits,
3543          * then truncate to SEW bits when storing to vreg.
3544          */
3545         s1 = get_gpr(s, a->rs1, EXT_NONE);
3546         tcg_gen_ext_tl_i64(t1, s1);
3547         vec_element_storei(s, a->rd, 0, t1);
3548         tcg_temp_free_i64(t1);
3549         mark_vs_dirty(s);
3550         gen_set_label(over);
3551         return true;
3552     }
3553     return false;
3556 /* Floating-Point Scalar Move Instructions */
3557 static bool trans_vfmv_f_s(DisasContext *s, arg_vfmv_f_s *a)
3559     if (require_rvv(s) &&
3560         require_rvf(s) &&
3561         vext_check_isa_ill(s) &&
3562         require_zve32f(s) &&
3563         require_zve64f(s)) {
3564         gen_set_rm(s, RISCV_FRM_DYN);
3566         unsigned int ofs = (8 << s->sew);
3567         unsigned int len = 64 - ofs;
3568         TCGv_i64 t_nan;
3570         vec_element_loadi(s, cpu_fpr[a->rd], a->rs2, 0, false);
3571         /* NaN-box f[rd] as necessary for SEW */
3572         if (len) {
3573             t_nan = tcg_constant_i64(UINT64_MAX);
3574             tcg_gen_deposit_i64(cpu_fpr[a->rd], cpu_fpr[a->rd],
3575                                 t_nan, ofs, len);
3576         }
3578         mark_fs_dirty(s);
3579         return true;
3580     }
3581     return false;
3584 /* vfmv.s.f vd, rs1 # vd[0] = rs1 (vs2=0) */
3585 static bool trans_vfmv_s_f(DisasContext *s, arg_vfmv_s_f *a)
3587     if (require_rvv(s) &&
3588         require_rvf(s) &&
3589         vext_check_isa_ill(s) &&
3590         require_zve32f(s) &&
3591         require_zve64f(s)) {
3592         gen_set_rm(s, RISCV_FRM_DYN);
3594         /* The instructions ignore LMUL and vector register group. */
3595         TCGv_i64 t1;
3596         TCGLabel *over = gen_new_label();
3598         /* if vl == 0 or vstart >= vl, skip vector register write back */
3599         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
3600         tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
3602         /* NaN-box f[rs1] */
3603         t1 = tcg_temp_new_i64();
3604         do_nanbox(s, t1, cpu_fpr[a->rs1]);
3606         vec_element_storei(s, a->rd, 0, t1);
3607         tcg_temp_free_i64(t1);
3608         mark_vs_dirty(s);
3609         gen_set_label(over);
3610         return true;
3611     }
3612     return false;
3615 /* Vector Slide Instructions */
3616 static bool slideup_check(DisasContext *s, arg_rmrr *a)
3618     return require_rvv(s) &&
3619            vext_check_isa_ill(s) &&
3620            vext_check_slide(s, a->rd, a->rs2, a->vm, true);
3623 GEN_OPIVX_TRANS(vslideup_vx, slideup_check)
3624 GEN_OPIVX_TRANS(vslide1up_vx, slideup_check)
3625 GEN_OPIVI_TRANS(vslideup_vi, IMM_ZX, vslideup_vx, slideup_check)
3627 static bool slidedown_check(DisasContext *s, arg_rmrr *a)
3629     return require_rvv(s) &&
3630            vext_check_isa_ill(s) &&
3631            vext_check_slide(s, a->rd, a->rs2, a->vm, false);
3634 GEN_OPIVX_TRANS(vslidedown_vx, slidedown_check)
3635 GEN_OPIVX_TRANS(vslide1down_vx, slidedown_check)
3636 GEN_OPIVI_TRANS(vslidedown_vi, IMM_ZX, vslidedown_vx, slidedown_check)
3638 /* Vector Floating-Point Slide Instructions */
3639 static bool fslideup_check(DisasContext *s, arg_rmrr *a)
3641     return slideup_check(s, a) &&
3642            require_rvf(s) &&
3643            require_zve32f(s) &&
3644            require_zve64f(s);
3647 static bool fslidedown_check(DisasContext *s, arg_rmrr *a)
3649     return slidedown_check(s, a) &&
3650            require_rvf(s) &&
3651            require_zve32f(s) &&
3652            require_zve64f(s);
3655 GEN_OPFVF_TRANS(vfslide1up_vf, fslideup_check)
3656 GEN_OPFVF_TRANS(vfslide1down_vf, fslidedown_check)
3658 /* Vector Register Gather Instruction */
3659 static bool vrgather_vv_check(DisasContext *s, arg_rmrr *a)
3661     return require_rvv(s) &&
3662            vext_check_isa_ill(s) &&
3663            require_align(a->rd, s->lmul) &&
3664            require_align(a->rs1, s->lmul) &&
3665            require_align(a->rs2, s->lmul) &&
3666            (a->rd != a->rs2 && a->rd != a->rs1) &&
3667            require_vm(a->vm, a->rd);
3670 static bool vrgatherei16_vv_check(DisasContext *s, arg_rmrr *a)
3672     int8_t emul = MO_16 - s->sew + s->lmul;
3673     return require_rvv(s) &&
3674            vext_check_isa_ill(s) &&
3675            (emul >= -3 && emul <= 3) &&
3676            require_align(a->rd, s->lmul) &&
3677            require_align(a->rs1, emul) &&
3678            require_align(a->rs2, s->lmul) &&
3679            (a->rd != a->rs2 && a->rd != a->rs1) &&
3680            !is_overlapped(a->rd, 1 << MAX(s->lmul, 0),
3681                           a->rs1, 1 << MAX(emul, 0)) &&
3682            !is_overlapped(a->rd, 1 << MAX(s->lmul, 0),
3683                           a->rs2, 1 << MAX(s->lmul, 0)) &&
3684            require_vm(a->vm, a->rd);
3687 GEN_OPIVV_TRANS(vrgather_vv, vrgather_vv_check)
3688 GEN_OPIVV_TRANS(vrgatherei16_vv, vrgatherei16_vv_check)
3690 static bool vrgather_vx_check(DisasContext *s, arg_rmrr *a)
3692     return require_rvv(s) &&
3693            vext_check_isa_ill(s) &&
3694            require_align(a->rd, s->lmul) &&
3695            require_align(a->rs2, s->lmul) &&
3696            (a->rd != a->rs2) &&
3697            require_vm(a->vm, a->rd);
3700 /* vrgather.vx vd, vs2, rs1, vm # vd[i] = (x[rs1] >= VLMAX) ? 0 : vs2[rs1] */
3701 static bool trans_vrgather_vx(DisasContext *s, arg_rmrr *a)
3703     if (!vrgather_vx_check(s, a)) {
3704         return false;
3705     }
3707     if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
3708         int scale = s->lmul - (s->sew + 3);
3709         int vlmax = s->cfg_ptr->vlen >> -scale;
3710         TCGv_i64 dest = tcg_temp_new_i64();
3712         if (a->rs1 == 0) {
3713             vec_element_loadi(s, dest, a->rs2, 0, false);
3714         } else {
3715             vec_element_loadx(s, dest, a->rs2, cpu_gpr[a->rs1], vlmax);
3716         }
3718         tcg_gen_gvec_dup_i64(s->sew, vreg_ofs(s, a->rd),
3719                              MAXSZ(s), MAXSZ(s), dest);
3720         tcg_temp_free_i64(dest);
3721         mark_vs_dirty(s);
3722     } else {
3723         static gen_helper_opivx * const fns[4] = {
3724             gen_helper_vrgather_vx_b, gen_helper_vrgather_vx_h,
3725             gen_helper_vrgather_vx_w, gen_helper_vrgather_vx_d
3726         };
3727         return opivx_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew], s);
3728     }
3729     return true;
3732 /* vrgather.vi vd, vs2, imm, vm # vd[i] = (imm >= VLMAX) ? 0 : vs2[imm] */
3733 static bool trans_vrgather_vi(DisasContext *s, arg_rmrr *a)
3735     if (!vrgather_vx_check(s, a)) {
3736         return false;
3737     }
3739     if (a->vm && s->vl_eq_vlmax && !(s->vta && s->lmul < 0)) {
3740         int scale = s->lmul - (s->sew + 3);
3741         int vlmax = s->cfg_ptr->vlen >> -scale;
3742         if (a->rs1 >= vlmax) {
3743             tcg_gen_gvec_dup_imm(MO_64, vreg_ofs(s, a->rd),
3744                                  MAXSZ(s), MAXSZ(s), 0);
3745         } else {
3746             tcg_gen_gvec_dup_mem(s->sew, vreg_ofs(s, a->rd),
3747                                  endian_ofs(s, a->rs2, a->rs1),
3748                                  MAXSZ(s), MAXSZ(s));
3749         }
3750         mark_vs_dirty(s);
3751     } else {
3752         static gen_helper_opivx * const fns[4] = {
3753             gen_helper_vrgather_vx_b, gen_helper_vrgather_vx_h,
3754             gen_helper_vrgather_vx_w, gen_helper_vrgather_vx_d
3755         };
3756         return opivi_trans(a->rd, a->rs1, a->rs2, a->vm, fns[s->sew],
3757                            s, IMM_ZX);
3758     }
3759     return true;
3763  * Vector Compress Instruction
3765  * The destination vector register group cannot overlap the
3766  * source vector register group or the source mask register.
3767  */
3768 static bool vcompress_vm_check(DisasContext *s, arg_r *a)
3770     return require_rvv(s) &&
3771            vext_check_isa_ill(s) &&
3772            require_align(a->rd, s->lmul) &&
3773            require_align(a->rs2, s->lmul) &&
3774            (a->rd != a->rs2) &&
3775            !is_overlapped(a->rd, 1 << MAX(s->lmul, 0), a->rs1, 1) &&
3776            (s->vstart == 0);
3779 static bool trans_vcompress_vm(DisasContext *s, arg_r *a)
3781     if (vcompress_vm_check(s, a)) {
3782         uint32_t data = 0;
3783         static gen_helper_gvec_4_ptr * const fns[4] = {
3784             gen_helper_vcompress_vm_b, gen_helper_vcompress_vm_h,
3785             gen_helper_vcompress_vm_w, gen_helper_vcompress_vm_d,
3786         };
3787         TCGLabel *over = gen_new_label();
3788         tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
3790         data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
3791         data = FIELD_DP32(data, VDATA, VTA, s->vta);
3792         tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
3793                            vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2),
3794                            cpu_env, s->cfg_ptr->vlen / 8,
3795                            s->cfg_ptr->vlen / 8, data,
3796                            fns[s->sew]);
3797         mark_vs_dirty(s);
3798         gen_set_label(over);
3799         return true;
3800     }
3801     return false;
3805  * Whole Vector Register Move Instructions ignore vtype and vl setting.
3806  * Thus, we don't need to check vill bit. (Section 16.6)
3807  */
3808 #define GEN_VMV_WHOLE_TRANS(NAME, LEN)                             \
3809 static bool trans_##NAME(DisasContext *s, arg_##NAME * a)               \
3810 {                                                                       \
3811     if (require_rvv(s) &&                                               \
3812         QEMU_IS_ALIGNED(a->rd, LEN) &&                                  \
3813         QEMU_IS_ALIGNED(a->rs2, LEN)) {                                 \
3814         uint32_t maxsz = (s->cfg_ptr->vlen >> 3) * LEN;                 \
3815         if (s->vstart == 0) {                                           \
3816             /* EEW = 8 */                                               \
3817             tcg_gen_gvec_mov(MO_8, vreg_ofs(s, a->rd),                  \
3818                              vreg_ofs(s, a->rs2), maxsz, maxsz);        \
3819             mark_vs_dirty(s);                                           \
3820         } else {                                                        \
3821             TCGLabel *over = gen_new_label();                           \
3822             tcg_gen_brcondi_tl(TCG_COND_GEU, cpu_vstart, maxsz, over);  \
3823             tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2), \
3824                                cpu_env, maxsz, maxsz, 0, gen_helper_vmvr_v); \
3825             mark_vs_dirty(s);                                           \
3826             gen_set_label(over);                                        \
3827         }                                                               \
3828         return true;                                                    \
3829     }                                                                   \
3830     return false;                                                       \
3833 GEN_VMV_WHOLE_TRANS(vmv1r_v, 1)
3834 GEN_VMV_WHOLE_TRANS(vmv2r_v, 2)
3835 GEN_VMV_WHOLE_TRANS(vmv4r_v, 4)
3836 GEN_VMV_WHOLE_TRANS(vmv8r_v, 8)
3838 static bool int_ext_check(DisasContext *s, arg_rmr *a, uint8_t div)
3840     uint8_t from = (s->sew + 3) - div;
3841     bool ret = require_rvv(s) &&
3842         (from >= 3 && from <= 8) &&
3843         (a->rd != a->rs2) &&
3844         require_align(a->rd, s->lmul) &&
3845         require_align(a->rs2, s->lmul - div) &&
3846         require_vm(a->vm, a->rd) &&
3847         require_noover(a->rd, s->lmul, a->rs2, s->lmul - div);
3848     return ret;
3851 static bool int_ext_op(DisasContext *s, arg_rmr *a, uint8_t seq)
3853     uint32_t data = 0;
3854     gen_helper_gvec_3_ptr *fn;
3855     TCGLabel *over = gen_new_label();
3856     tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
3857     tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
3859     static gen_helper_gvec_3_ptr * const fns[6][4] = {
3860         {
3861             NULL, gen_helper_vzext_vf2_h,
3862             gen_helper_vzext_vf2_w, gen_helper_vzext_vf2_d
3863         },
3864         {
3865             NULL, NULL,
3866             gen_helper_vzext_vf4_w, gen_helper_vzext_vf4_d,
3867         },
3868         {
3869             NULL, NULL,
3870             NULL, gen_helper_vzext_vf8_d
3871         },
3872         {
3873             NULL, gen_helper_vsext_vf2_h,
3874             gen_helper_vsext_vf2_w, gen_helper_vsext_vf2_d
3875         },
3876         {
3877             NULL, NULL,
3878             gen_helper_vsext_vf4_w, gen_helper_vsext_vf4_d,
3879         },
3880         {
3881             NULL, NULL,
3882             NULL, gen_helper_vsext_vf8_d
3883         }
3884     };
3886     fn = fns[seq][s->sew];
3887     if (fn == NULL) {
3888         return false;
3889     }
3891     data = FIELD_DP32(data, VDATA, VM, a->vm);
3892     data = FIELD_DP32(data, VDATA, LMUL, s->lmul);
3893     data = FIELD_DP32(data, VDATA, VTA, s->vta);
3895     tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0),
3896                        vreg_ofs(s, a->rs2), cpu_env,
3897                        s->cfg_ptr->vlen / 8,
3898                        s->cfg_ptr->vlen / 8, data, fn);
3900     mark_vs_dirty(s);
3901     gen_set_label(over);
3902     return true;
3905 /* Vector Integer Extension */
3906 #define GEN_INT_EXT_TRANS(NAME, DIV, SEQ)             \
3907 static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
3908 {                                                     \
3909     if (int_ext_check(s, a, DIV)) {                   \
3910         return int_ext_op(s, a, SEQ);                 \
3911     }                                                 \
3912     return false;                                     \
3915 GEN_INT_EXT_TRANS(vzext_vf2, 1, 0)
3916 GEN_INT_EXT_TRANS(vzext_vf4, 2, 1)
3917 GEN_INT_EXT_TRANS(vzext_vf8, 3, 2)
3918 GEN_INT_EXT_TRANS(vsext_vf2, 1, 3)
3919 GEN_INT_EXT_TRANS(vsext_vf4, 2, 4)
3920 GEN_INT_EXT_TRANS(vsext_vf8, 3, 5)