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