target/riscv: vector_helper: Fixup local variables shadowing
[qemu/ar7.git] / target / riscv / vector_helper.c
blobcba02c13203a6ad4705c41c74065431cbba23d2f
1 /*
2 * RISC-V Vector Extension Helpers for QEMU.
4 * Copyright (c) 2020 T-Head Semiconductor Co., Ltd. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2 or later, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
20 #include "qemu/host-utils.h"
21 #include "qemu/bitops.h"
22 #include "cpu.h"
23 #include "exec/memop.h"
24 #include "exec/exec-all.h"
25 #include "exec/cpu_ldst.h"
26 #include "exec/helper-proto.h"
27 #include "fpu/softfloat.h"
28 #include "tcg/tcg-gvec-desc.h"
29 #include "internals.h"
30 #include "vector_internals.h"
31 #include <math.h>
33 target_ulong HELPER(vsetvl)(CPURISCVState *env, target_ulong s1,
34 target_ulong s2)
36 int vlmax, vl;
37 RISCVCPU *cpu = env_archcpu(env);
38 uint64_t lmul = FIELD_EX64(s2, VTYPE, VLMUL);
39 uint16_t sew = 8 << FIELD_EX64(s2, VTYPE, VSEW);
40 uint8_t ediv = FIELD_EX64(s2, VTYPE, VEDIV);
41 int xlen = riscv_cpu_xlen(env);
42 bool vill = (s2 >> (xlen - 1)) & 0x1;
43 target_ulong reserved = s2 &
44 MAKE_64BIT_MASK(R_VTYPE_RESERVED_SHIFT,
45 xlen - 1 - R_VTYPE_RESERVED_SHIFT);
47 if (lmul & 4) {
48 /* Fractional LMUL - check LMUL * VLEN >= SEW */
49 if (lmul == 4 ||
50 cpu->cfg.vlen >> (8 - lmul) < sew) {
51 vill = true;
55 if ((sew > cpu->cfg.elen) || vill || (ediv != 0) || (reserved != 0)) {
56 /* only set vill bit. */
57 env->vill = 1;
58 env->vtype = 0;
59 env->vl = 0;
60 env->vstart = 0;
61 return 0;
64 vlmax = vext_get_vlmax(cpu, s2);
65 if (s1 <= vlmax) {
66 vl = s1;
67 } else {
68 vl = vlmax;
70 env->vl = vl;
71 env->vtype = s2;
72 env->vstart = 0;
73 env->vill = 0;
74 return vl;
78 * Get the maximum number of elements can be operated.
80 * log2_esz: log2 of element size in bytes.
82 static inline uint32_t vext_max_elems(uint32_t desc, uint32_t log2_esz)
85 * As simd_desc support at most 2048 bytes, the max vlen is 1024 bits.
86 * so vlen in bytes (vlenb) is encoded as maxsz.
88 uint32_t vlenb = simd_maxsz(desc);
90 /* Return VLMAX */
91 int scale = vext_lmul(desc) - log2_esz;
92 return scale < 0 ? vlenb >> -scale : vlenb << scale;
95 static inline target_ulong adjust_addr(CPURISCVState *env, target_ulong addr)
97 return (addr & ~env->cur_pmmask) | env->cur_pmbase;
101 * This function checks watchpoint before real load operation.
103 * In softmmu mode, the TLB API probe_access is enough for watchpoint check.
104 * In user mode, there is no watchpoint support now.
106 * It will trigger an exception if there is no mapping in TLB
107 * and page table walk can't fill the TLB entry. Then the guest
108 * software can return here after process the exception or never return.
110 static void probe_pages(CPURISCVState *env, target_ulong addr,
111 target_ulong len, uintptr_t ra,
112 MMUAccessType access_type)
114 target_ulong pagelen = -(addr | TARGET_PAGE_MASK);
115 target_ulong curlen = MIN(pagelen, len);
117 probe_access(env, adjust_addr(env, addr), curlen, access_type,
118 cpu_mmu_index(env, false), ra);
119 if (len > curlen) {
120 addr += curlen;
121 curlen = len - curlen;
122 probe_access(env, adjust_addr(env, addr), curlen, access_type,
123 cpu_mmu_index(env, false), ra);
127 static inline void vext_set_elem_mask(void *v0, int index,
128 uint8_t value)
130 int idx = index / 64;
131 int pos = index % 64;
132 uint64_t old = ((uint64_t *)v0)[idx];
133 ((uint64_t *)v0)[idx] = deposit64(old, pos, 1, value);
136 /* elements operations for load and store */
137 typedef void vext_ldst_elem_fn(CPURISCVState *env, abi_ptr addr,
138 uint32_t idx, void *vd, uintptr_t retaddr);
140 #define GEN_VEXT_LD_ELEM(NAME, ETYPE, H, LDSUF) \
141 static void NAME(CPURISCVState *env, abi_ptr addr, \
142 uint32_t idx, void *vd, uintptr_t retaddr)\
144 ETYPE *cur = ((ETYPE *)vd + H(idx)); \
145 *cur = cpu_##LDSUF##_data_ra(env, addr, retaddr); \
148 GEN_VEXT_LD_ELEM(lde_b, int8_t, H1, ldsb)
149 GEN_VEXT_LD_ELEM(lde_h, int16_t, H2, ldsw)
150 GEN_VEXT_LD_ELEM(lde_w, int32_t, H4, ldl)
151 GEN_VEXT_LD_ELEM(lde_d, int64_t, H8, ldq)
153 #define GEN_VEXT_ST_ELEM(NAME, ETYPE, H, STSUF) \
154 static void NAME(CPURISCVState *env, abi_ptr addr, \
155 uint32_t idx, void *vd, uintptr_t retaddr)\
157 ETYPE data = *((ETYPE *)vd + H(idx)); \
158 cpu_##STSUF##_data_ra(env, addr, data, retaddr); \
161 GEN_VEXT_ST_ELEM(ste_b, int8_t, H1, stb)
162 GEN_VEXT_ST_ELEM(ste_h, int16_t, H2, stw)
163 GEN_VEXT_ST_ELEM(ste_w, int32_t, H4, stl)
164 GEN_VEXT_ST_ELEM(ste_d, int64_t, H8, stq)
166 static void vext_set_tail_elems_1s(target_ulong vl, void *vd,
167 uint32_t desc, uint32_t nf,
168 uint32_t esz, uint32_t max_elems)
170 uint32_t vta = vext_vta(desc);
171 int k;
173 if (vta == 0) {
174 return;
177 for (k = 0; k < nf; ++k) {
178 vext_set_elems_1s(vd, vta, (k * max_elems + vl) * esz,
179 (k * max_elems + max_elems) * esz);
184 * stride: access vector element from strided memory
186 static void
187 vext_ldst_stride(void *vd, void *v0, target_ulong base,
188 target_ulong stride, CPURISCVState *env,
189 uint32_t desc, uint32_t vm,
190 vext_ldst_elem_fn *ldst_elem,
191 uint32_t log2_esz, uintptr_t ra)
193 uint32_t i, k;
194 uint32_t nf = vext_nf(desc);
195 uint32_t max_elems = vext_max_elems(desc, log2_esz);
196 uint32_t esz = 1 << log2_esz;
197 uint32_t vma = vext_vma(desc);
199 for (i = env->vstart; i < env->vl; i++, env->vstart++) {
200 k = 0;
201 while (k < nf) {
202 if (!vm && !vext_elem_mask(v0, i)) {
203 /* set masked-off elements to 1s */
204 vext_set_elems_1s(vd, vma, (i + k * max_elems) * esz,
205 (i + k * max_elems + 1) * esz);
206 k++;
207 continue;
209 target_ulong addr = base + stride * i + (k << log2_esz);
210 ldst_elem(env, adjust_addr(env, addr), i + k * max_elems, vd, ra);
211 k++;
214 env->vstart = 0;
216 vext_set_tail_elems_1s(env->vl, vd, desc, nf, esz, max_elems);
219 #define GEN_VEXT_LD_STRIDE(NAME, ETYPE, LOAD_FN) \
220 void HELPER(NAME)(void *vd, void * v0, target_ulong base, \
221 target_ulong stride, CPURISCVState *env, \
222 uint32_t desc) \
224 uint32_t vm = vext_vm(desc); \
225 vext_ldst_stride(vd, v0, base, stride, env, desc, vm, LOAD_FN, \
226 ctzl(sizeof(ETYPE)), GETPC()); \
229 GEN_VEXT_LD_STRIDE(vlse8_v, int8_t, lde_b)
230 GEN_VEXT_LD_STRIDE(vlse16_v, int16_t, lde_h)
231 GEN_VEXT_LD_STRIDE(vlse32_v, int32_t, lde_w)
232 GEN_VEXT_LD_STRIDE(vlse64_v, int64_t, lde_d)
234 #define GEN_VEXT_ST_STRIDE(NAME, ETYPE, STORE_FN) \
235 void HELPER(NAME)(void *vd, void *v0, target_ulong base, \
236 target_ulong stride, CPURISCVState *env, \
237 uint32_t desc) \
239 uint32_t vm = vext_vm(desc); \
240 vext_ldst_stride(vd, v0, base, stride, env, desc, vm, STORE_FN, \
241 ctzl(sizeof(ETYPE)), GETPC()); \
244 GEN_VEXT_ST_STRIDE(vsse8_v, int8_t, ste_b)
245 GEN_VEXT_ST_STRIDE(vsse16_v, int16_t, ste_h)
246 GEN_VEXT_ST_STRIDE(vsse32_v, int32_t, ste_w)
247 GEN_VEXT_ST_STRIDE(vsse64_v, int64_t, ste_d)
250 * unit-stride: access elements stored contiguously in memory
253 /* unmasked unit-stride load and store operation */
254 static void
255 vext_ldst_us(void *vd, target_ulong base, CPURISCVState *env, uint32_t desc,
256 vext_ldst_elem_fn *ldst_elem, uint32_t log2_esz, uint32_t evl,
257 uintptr_t ra)
259 uint32_t i, k;
260 uint32_t nf = vext_nf(desc);
261 uint32_t max_elems = vext_max_elems(desc, log2_esz);
262 uint32_t esz = 1 << log2_esz;
264 /* load bytes from guest memory */
265 for (i = env->vstart; i < evl; i++, env->vstart++) {
266 k = 0;
267 while (k < nf) {
268 target_ulong addr = base + ((i * nf + k) << log2_esz);
269 ldst_elem(env, adjust_addr(env, addr), i + k * max_elems, vd, ra);
270 k++;
273 env->vstart = 0;
275 vext_set_tail_elems_1s(evl, vd, desc, nf, esz, max_elems);
279 * masked unit-stride load and store operation will be a special case of
280 * stride, stride = NF * sizeof (ETYPE)
283 #define GEN_VEXT_LD_US(NAME, ETYPE, LOAD_FN) \
284 void HELPER(NAME##_mask)(void *vd, void *v0, target_ulong base, \
285 CPURISCVState *env, uint32_t desc) \
287 uint32_t stride = vext_nf(desc) << ctzl(sizeof(ETYPE)); \
288 vext_ldst_stride(vd, v0, base, stride, env, desc, false, LOAD_FN, \
289 ctzl(sizeof(ETYPE)), GETPC()); \
292 void HELPER(NAME)(void *vd, void *v0, target_ulong base, \
293 CPURISCVState *env, uint32_t desc) \
295 vext_ldst_us(vd, base, env, desc, LOAD_FN, \
296 ctzl(sizeof(ETYPE)), env->vl, GETPC()); \
299 GEN_VEXT_LD_US(vle8_v, int8_t, lde_b)
300 GEN_VEXT_LD_US(vle16_v, int16_t, lde_h)
301 GEN_VEXT_LD_US(vle32_v, int32_t, lde_w)
302 GEN_VEXT_LD_US(vle64_v, int64_t, lde_d)
304 #define GEN_VEXT_ST_US(NAME, ETYPE, STORE_FN) \
305 void HELPER(NAME##_mask)(void *vd, void *v0, target_ulong base, \
306 CPURISCVState *env, uint32_t desc) \
308 uint32_t stride = vext_nf(desc) << ctzl(sizeof(ETYPE)); \
309 vext_ldst_stride(vd, v0, base, stride, env, desc, false, STORE_FN, \
310 ctzl(sizeof(ETYPE)), GETPC()); \
313 void HELPER(NAME)(void *vd, void *v0, target_ulong base, \
314 CPURISCVState *env, uint32_t desc) \
316 vext_ldst_us(vd, base, env, desc, STORE_FN, \
317 ctzl(sizeof(ETYPE)), env->vl, GETPC()); \
320 GEN_VEXT_ST_US(vse8_v, int8_t, ste_b)
321 GEN_VEXT_ST_US(vse16_v, int16_t, ste_h)
322 GEN_VEXT_ST_US(vse32_v, int32_t, ste_w)
323 GEN_VEXT_ST_US(vse64_v, int64_t, ste_d)
326 * unit stride mask load and store, EEW = 1
328 void HELPER(vlm_v)(void *vd, void *v0, target_ulong base,
329 CPURISCVState *env, uint32_t desc)
331 /* evl = ceil(vl/8) */
332 uint8_t evl = (env->vl + 7) >> 3;
333 vext_ldst_us(vd, base, env, desc, lde_b,
334 0, evl, GETPC());
337 void HELPER(vsm_v)(void *vd, void *v0, target_ulong base,
338 CPURISCVState *env, uint32_t desc)
340 /* evl = ceil(vl/8) */
341 uint8_t evl = (env->vl + 7) >> 3;
342 vext_ldst_us(vd, base, env, desc, ste_b,
343 0, evl, GETPC());
347 * index: access vector element from indexed memory
349 typedef target_ulong vext_get_index_addr(target_ulong base,
350 uint32_t idx, void *vs2);
352 #define GEN_VEXT_GET_INDEX_ADDR(NAME, ETYPE, H) \
353 static target_ulong NAME(target_ulong base, \
354 uint32_t idx, void *vs2) \
356 return (base + *((ETYPE *)vs2 + H(idx))); \
359 GEN_VEXT_GET_INDEX_ADDR(idx_b, uint8_t, H1)
360 GEN_VEXT_GET_INDEX_ADDR(idx_h, uint16_t, H2)
361 GEN_VEXT_GET_INDEX_ADDR(idx_w, uint32_t, H4)
362 GEN_VEXT_GET_INDEX_ADDR(idx_d, uint64_t, H8)
364 static inline void
365 vext_ldst_index(void *vd, void *v0, target_ulong base,
366 void *vs2, CPURISCVState *env, uint32_t desc,
367 vext_get_index_addr get_index_addr,
368 vext_ldst_elem_fn *ldst_elem,
369 uint32_t log2_esz, uintptr_t ra)
371 uint32_t i, k;
372 uint32_t nf = vext_nf(desc);
373 uint32_t vm = vext_vm(desc);
374 uint32_t max_elems = vext_max_elems(desc, log2_esz);
375 uint32_t esz = 1 << log2_esz;
376 uint32_t vma = vext_vma(desc);
378 /* load bytes from guest memory */
379 for (i = env->vstart; i < env->vl; i++, env->vstart++) {
380 k = 0;
381 while (k < nf) {
382 if (!vm && !vext_elem_mask(v0, i)) {
383 /* set masked-off elements to 1s */
384 vext_set_elems_1s(vd, vma, (i + k * max_elems) * esz,
385 (i + k * max_elems + 1) * esz);
386 k++;
387 continue;
389 abi_ptr addr = get_index_addr(base, i, vs2) + (k << log2_esz);
390 ldst_elem(env, adjust_addr(env, addr), i + k * max_elems, vd, ra);
391 k++;
394 env->vstart = 0;
396 vext_set_tail_elems_1s(env->vl, vd, desc, nf, esz, max_elems);
399 #define GEN_VEXT_LD_INDEX(NAME, ETYPE, INDEX_FN, LOAD_FN) \
400 void HELPER(NAME)(void *vd, void *v0, target_ulong base, \
401 void *vs2, CPURISCVState *env, uint32_t desc) \
403 vext_ldst_index(vd, v0, base, vs2, env, desc, INDEX_FN, \
404 LOAD_FN, ctzl(sizeof(ETYPE)), GETPC()); \
407 GEN_VEXT_LD_INDEX(vlxei8_8_v, int8_t, idx_b, lde_b)
408 GEN_VEXT_LD_INDEX(vlxei8_16_v, int16_t, idx_b, lde_h)
409 GEN_VEXT_LD_INDEX(vlxei8_32_v, int32_t, idx_b, lde_w)
410 GEN_VEXT_LD_INDEX(vlxei8_64_v, int64_t, idx_b, lde_d)
411 GEN_VEXT_LD_INDEX(vlxei16_8_v, int8_t, idx_h, lde_b)
412 GEN_VEXT_LD_INDEX(vlxei16_16_v, int16_t, idx_h, lde_h)
413 GEN_VEXT_LD_INDEX(vlxei16_32_v, int32_t, idx_h, lde_w)
414 GEN_VEXT_LD_INDEX(vlxei16_64_v, int64_t, idx_h, lde_d)
415 GEN_VEXT_LD_INDEX(vlxei32_8_v, int8_t, idx_w, lde_b)
416 GEN_VEXT_LD_INDEX(vlxei32_16_v, int16_t, idx_w, lde_h)
417 GEN_VEXT_LD_INDEX(vlxei32_32_v, int32_t, idx_w, lde_w)
418 GEN_VEXT_LD_INDEX(vlxei32_64_v, int64_t, idx_w, lde_d)
419 GEN_VEXT_LD_INDEX(vlxei64_8_v, int8_t, idx_d, lde_b)
420 GEN_VEXT_LD_INDEX(vlxei64_16_v, int16_t, idx_d, lde_h)
421 GEN_VEXT_LD_INDEX(vlxei64_32_v, int32_t, idx_d, lde_w)
422 GEN_VEXT_LD_INDEX(vlxei64_64_v, int64_t, idx_d, lde_d)
424 #define GEN_VEXT_ST_INDEX(NAME, ETYPE, INDEX_FN, STORE_FN) \
425 void HELPER(NAME)(void *vd, void *v0, target_ulong base, \
426 void *vs2, CPURISCVState *env, uint32_t desc) \
428 vext_ldst_index(vd, v0, base, vs2, env, desc, INDEX_FN, \
429 STORE_FN, ctzl(sizeof(ETYPE)), \
430 GETPC()); \
433 GEN_VEXT_ST_INDEX(vsxei8_8_v, int8_t, idx_b, ste_b)
434 GEN_VEXT_ST_INDEX(vsxei8_16_v, int16_t, idx_b, ste_h)
435 GEN_VEXT_ST_INDEX(vsxei8_32_v, int32_t, idx_b, ste_w)
436 GEN_VEXT_ST_INDEX(vsxei8_64_v, int64_t, idx_b, ste_d)
437 GEN_VEXT_ST_INDEX(vsxei16_8_v, int8_t, idx_h, ste_b)
438 GEN_VEXT_ST_INDEX(vsxei16_16_v, int16_t, idx_h, ste_h)
439 GEN_VEXT_ST_INDEX(vsxei16_32_v, int32_t, idx_h, ste_w)
440 GEN_VEXT_ST_INDEX(vsxei16_64_v, int64_t, idx_h, ste_d)
441 GEN_VEXT_ST_INDEX(vsxei32_8_v, int8_t, idx_w, ste_b)
442 GEN_VEXT_ST_INDEX(vsxei32_16_v, int16_t, idx_w, ste_h)
443 GEN_VEXT_ST_INDEX(vsxei32_32_v, int32_t, idx_w, ste_w)
444 GEN_VEXT_ST_INDEX(vsxei32_64_v, int64_t, idx_w, ste_d)
445 GEN_VEXT_ST_INDEX(vsxei64_8_v, int8_t, idx_d, ste_b)
446 GEN_VEXT_ST_INDEX(vsxei64_16_v, int16_t, idx_d, ste_h)
447 GEN_VEXT_ST_INDEX(vsxei64_32_v, int32_t, idx_d, ste_w)
448 GEN_VEXT_ST_INDEX(vsxei64_64_v, int64_t, idx_d, ste_d)
451 * unit-stride fault-only-fisrt load instructions
453 static inline void
454 vext_ldff(void *vd, void *v0, target_ulong base,
455 CPURISCVState *env, uint32_t desc,
456 vext_ldst_elem_fn *ldst_elem,
457 uint32_t log2_esz, uintptr_t ra)
459 void *host;
460 uint32_t i, k, vl = 0;
461 uint32_t nf = vext_nf(desc);
462 uint32_t vm = vext_vm(desc);
463 uint32_t max_elems = vext_max_elems(desc, log2_esz);
464 uint32_t esz = 1 << log2_esz;
465 uint32_t vma = vext_vma(desc);
466 target_ulong addr, offset, remain;
468 /* probe every access */
469 for (i = env->vstart; i < env->vl; i++) {
470 if (!vm && !vext_elem_mask(v0, i)) {
471 continue;
473 addr = adjust_addr(env, base + i * (nf << log2_esz));
474 if (i == 0) {
475 probe_pages(env, addr, nf << log2_esz, ra, MMU_DATA_LOAD);
476 } else {
477 /* if it triggers an exception, no need to check watchpoint */
478 remain = nf << log2_esz;
479 while (remain > 0) {
480 offset = -(addr | TARGET_PAGE_MASK);
481 host = tlb_vaddr_to_host(env, addr, MMU_DATA_LOAD,
482 cpu_mmu_index(env, false));
483 if (host) {
484 #ifdef CONFIG_USER_ONLY
485 if (!page_check_range(addr, offset, PAGE_READ)) {
486 vl = i;
487 goto ProbeSuccess;
489 #else
490 probe_pages(env, addr, offset, ra, MMU_DATA_LOAD);
491 #endif
492 } else {
493 vl = i;
494 goto ProbeSuccess;
496 if (remain <= offset) {
497 break;
499 remain -= offset;
500 addr = adjust_addr(env, addr + offset);
504 ProbeSuccess:
505 /* load bytes from guest memory */
506 if (vl != 0) {
507 env->vl = vl;
509 for (i = env->vstart; i < env->vl; i++) {
510 k = 0;
511 while (k < nf) {
512 if (!vm && !vext_elem_mask(v0, i)) {
513 /* set masked-off elements to 1s */
514 vext_set_elems_1s(vd, vma, (i + k * max_elems) * esz,
515 (i + k * max_elems + 1) * esz);
516 k++;
517 continue;
519 addr = base + ((i * nf + k) << log2_esz);
520 ldst_elem(env, adjust_addr(env, addr), i + k * max_elems, vd, ra);
521 k++;
524 env->vstart = 0;
526 vext_set_tail_elems_1s(env->vl, vd, desc, nf, esz, max_elems);
529 #define GEN_VEXT_LDFF(NAME, ETYPE, LOAD_FN) \
530 void HELPER(NAME)(void *vd, void *v0, target_ulong base, \
531 CPURISCVState *env, uint32_t desc) \
533 vext_ldff(vd, v0, base, env, desc, LOAD_FN, \
534 ctzl(sizeof(ETYPE)), GETPC()); \
537 GEN_VEXT_LDFF(vle8ff_v, int8_t, lde_b)
538 GEN_VEXT_LDFF(vle16ff_v, int16_t, lde_h)
539 GEN_VEXT_LDFF(vle32ff_v, int32_t, lde_w)
540 GEN_VEXT_LDFF(vle64ff_v, int64_t, lde_d)
542 #define DO_SWAP(N, M) (M)
543 #define DO_AND(N, M) (N & M)
544 #define DO_XOR(N, M) (N ^ M)
545 #define DO_OR(N, M) (N | M)
546 #define DO_ADD(N, M) (N + M)
548 /* Signed min/max */
549 #define DO_MAX(N, M) ((N) >= (M) ? (N) : (M))
550 #define DO_MIN(N, M) ((N) >= (M) ? (M) : (N))
553 * load and store whole register instructions
555 static void
556 vext_ldst_whole(void *vd, target_ulong base, CPURISCVState *env, uint32_t desc,
557 vext_ldst_elem_fn *ldst_elem, uint32_t log2_esz, uintptr_t ra)
559 uint32_t i, k, off, pos;
560 uint32_t nf = vext_nf(desc);
561 uint32_t vlenb = riscv_cpu_cfg(env)->vlen >> 3;
562 uint32_t max_elems = vlenb >> log2_esz;
564 k = env->vstart / max_elems;
565 off = env->vstart % max_elems;
567 if (off) {
568 /* load/store rest of elements of current segment pointed by vstart */
569 for (pos = off; pos < max_elems; pos++, env->vstart++) {
570 target_ulong addr = base + ((pos + k * max_elems) << log2_esz);
571 ldst_elem(env, adjust_addr(env, addr), pos + k * max_elems, vd,
572 ra);
574 k++;
577 /* load/store elements for rest of segments */
578 for (; k < nf; k++) {
579 for (i = 0; i < max_elems; i++, env->vstart++) {
580 target_ulong addr = base + ((i + k * max_elems) << log2_esz);
581 ldst_elem(env, adjust_addr(env, addr), i + k * max_elems, vd, ra);
585 env->vstart = 0;
588 #define GEN_VEXT_LD_WHOLE(NAME, ETYPE, LOAD_FN) \
589 void HELPER(NAME)(void *vd, target_ulong base, \
590 CPURISCVState *env, uint32_t desc) \
592 vext_ldst_whole(vd, base, env, desc, LOAD_FN, \
593 ctzl(sizeof(ETYPE)), GETPC()); \
596 GEN_VEXT_LD_WHOLE(vl1re8_v, int8_t, lde_b)
597 GEN_VEXT_LD_WHOLE(vl1re16_v, int16_t, lde_h)
598 GEN_VEXT_LD_WHOLE(vl1re32_v, int32_t, lde_w)
599 GEN_VEXT_LD_WHOLE(vl1re64_v, int64_t, lde_d)
600 GEN_VEXT_LD_WHOLE(vl2re8_v, int8_t, lde_b)
601 GEN_VEXT_LD_WHOLE(vl2re16_v, int16_t, lde_h)
602 GEN_VEXT_LD_WHOLE(vl2re32_v, int32_t, lde_w)
603 GEN_VEXT_LD_WHOLE(vl2re64_v, int64_t, lde_d)
604 GEN_VEXT_LD_WHOLE(vl4re8_v, int8_t, lde_b)
605 GEN_VEXT_LD_WHOLE(vl4re16_v, int16_t, lde_h)
606 GEN_VEXT_LD_WHOLE(vl4re32_v, int32_t, lde_w)
607 GEN_VEXT_LD_WHOLE(vl4re64_v, int64_t, lde_d)
608 GEN_VEXT_LD_WHOLE(vl8re8_v, int8_t, lde_b)
609 GEN_VEXT_LD_WHOLE(vl8re16_v, int16_t, lde_h)
610 GEN_VEXT_LD_WHOLE(vl8re32_v, int32_t, lde_w)
611 GEN_VEXT_LD_WHOLE(vl8re64_v, int64_t, lde_d)
613 #define GEN_VEXT_ST_WHOLE(NAME, ETYPE, STORE_FN) \
614 void HELPER(NAME)(void *vd, target_ulong base, \
615 CPURISCVState *env, uint32_t desc) \
617 vext_ldst_whole(vd, base, env, desc, STORE_FN, \
618 ctzl(sizeof(ETYPE)), GETPC()); \
621 GEN_VEXT_ST_WHOLE(vs1r_v, int8_t, ste_b)
622 GEN_VEXT_ST_WHOLE(vs2r_v, int8_t, ste_b)
623 GEN_VEXT_ST_WHOLE(vs4r_v, int8_t, ste_b)
624 GEN_VEXT_ST_WHOLE(vs8r_v, int8_t, ste_b)
627 * Vector Integer Arithmetic Instructions
630 /* (TD, T1, T2, TX1, TX2) */
631 #define OP_SSS_B int8_t, int8_t, int8_t, int8_t, int8_t
632 #define OP_SSS_H int16_t, int16_t, int16_t, int16_t, int16_t
633 #define OP_SSS_W int32_t, int32_t, int32_t, int32_t, int32_t
634 #define OP_SSS_D int64_t, int64_t, int64_t, int64_t, int64_t
635 #define OP_SUS_B int8_t, uint8_t, int8_t, uint8_t, int8_t
636 #define OP_SUS_H int16_t, uint16_t, int16_t, uint16_t, int16_t
637 #define OP_SUS_W int32_t, uint32_t, int32_t, uint32_t, int32_t
638 #define OP_SUS_D int64_t, uint64_t, int64_t, uint64_t, int64_t
639 #define WOP_SSS_B int16_t, int8_t, int8_t, int16_t, int16_t
640 #define WOP_SSS_H int32_t, int16_t, int16_t, int32_t, int32_t
641 #define WOP_SSS_W int64_t, int32_t, int32_t, int64_t, int64_t
642 #define WOP_SUS_B int16_t, uint8_t, int8_t, uint16_t, int16_t
643 #define WOP_SUS_H int32_t, uint16_t, int16_t, uint32_t, int32_t
644 #define WOP_SUS_W int64_t, uint32_t, int32_t, uint64_t, int64_t
645 #define WOP_SSU_B int16_t, int8_t, uint8_t, int16_t, uint16_t
646 #define WOP_SSU_H int32_t, int16_t, uint16_t, int32_t, uint32_t
647 #define WOP_SSU_W int64_t, int32_t, uint32_t, int64_t, uint64_t
648 #define NOP_SSS_B int8_t, int8_t, int16_t, int8_t, int16_t
649 #define NOP_SSS_H int16_t, int16_t, int32_t, int16_t, int32_t
650 #define NOP_SSS_W int32_t, int32_t, int64_t, int32_t, int64_t
651 #define NOP_UUU_B uint8_t, uint8_t, uint16_t, uint8_t, uint16_t
652 #define NOP_UUU_H uint16_t, uint16_t, uint32_t, uint16_t, uint32_t
653 #define NOP_UUU_W uint32_t, uint32_t, uint64_t, uint32_t, uint64_t
655 #define DO_SUB(N, M) (N - M)
656 #define DO_RSUB(N, M) (M - N)
658 RVVCALL(OPIVV2, vadd_vv_b, OP_SSS_B, H1, H1, H1, DO_ADD)
659 RVVCALL(OPIVV2, vadd_vv_h, OP_SSS_H, H2, H2, H2, DO_ADD)
660 RVVCALL(OPIVV2, vadd_vv_w, OP_SSS_W, H4, H4, H4, DO_ADD)
661 RVVCALL(OPIVV2, vadd_vv_d, OP_SSS_D, H8, H8, H8, DO_ADD)
662 RVVCALL(OPIVV2, vsub_vv_b, OP_SSS_B, H1, H1, H1, DO_SUB)
663 RVVCALL(OPIVV2, vsub_vv_h, OP_SSS_H, H2, H2, H2, DO_SUB)
664 RVVCALL(OPIVV2, vsub_vv_w, OP_SSS_W, H4, H4, H4, DO_SUB)
665 RVVCALL(OPIVV2, vsub_vv_d, OP_SSS_D, H8, H8, H8, DO_SUB)
667 GEN_VEXT_VV(vadd_vv_b, 1)
668 GEN_VEXT_VV(vadd_vv_h, 2)
669 GEN_VEXT_VV(vadd_vv_w, 4)
670 GEN_VEXT_VV(vadd_vv_d, 8)
671 GEN_VEXT_VV(vsub_vv_b, 1)
672 GEN_VEXT_VV(vsub_vv_h, 2)
673 GEN_VEXT_VV(vsub_vv_w, 4)
674 GEN_VEXT_VV(vsub_vv_d, 8)
677 RVVCALL(OPIVX2, vadd_vx_b, OP_SSS_B, H1, H1, DO_ADD)
678 RVVCALL(OPIVX2, vadd_vx_h, OP_SSS_H, H2, H2, DO_ADD)
679 RVVCALL(OPIVX2, vadd_vx_w, OP_SSS_W, H4, H4, DO_ADD)
680 RVVCALL(OPIVX2, vadd_vx_d, OP_SSS_D, H8, H8, DO_ADD)
681 RVVCALL(OPIVX2, vsub_vx_b, OP_SSS_B, H1, H1, DO_SUB)
682 RVVCALL(OPIVX2, vsub_vx_h, OP_SSS_H, H2, H2, DO_SUB)
683 RVVCALL(OPIVX2, vsub_vx_w, OP_SSS_W, H4, H4, DO_SUB)
684 RVVCALL(OPIVX2, vsub_vx_d, OP_SSS_D, H8, H8, DO_SUB)
685 RVVCALL(OPIVX2, vrsub_vx_b, OP_SSS_B, H1, H1, DO_RSUB)
686 RVVCALL(OPIVX2, vrsub_vx_h, OP_SSS_H, H2, H2, DO_RSUB)
687 RVVCALL(OPIVX2, vrsub_vx_w, OP_SSS_W, H4, H4, DO_RSUB)
688 RVVCALL(OPIVX2, vrsub_vx_d, OP_SSS_D, H8, H8, DO_RSUB)
690 GEN_VEXT_VX(vadd_vx_b, 1)
691 GEN_VEXT_VX(vadd_vx_h, 2)
692 GEN_VEXT_VX(vadd_vx_w, 4)
693 GEN_VEXT_VX(vadd_vx_d, 8)
694 GEN_VEXT_VX(vsub_vx_b, 1)
695 GEN_VEXT_VX(vsub_vx_h, 2)
696 GEN_VEXT_VX(vsub_vx_w, 4)
697 GEN_VEXT_VX(vsub_vx_d, 8)
698 GEN_VEXT_VX(vrsub_vx_b, 1)
699 GEN_VEXT_VX(vrsub_vx_h, 2)
700 GEN_VEXT_VX(vrsub_vx_w, 4)
701 GEN_VEXT_VX(vrsub_vx_d, 8)
703 void HELPER(vec_rsubs8)(void *d, void *a, uint64_t b, uint32_t desc)
705 intptr_t oprsz = simd_oprsz(desc);
706 intptr_t i;
708 for (i = 0; i < oprsz; i += sizeof(uint8_t)) {
709 *(uint8_t *)(d + i) = (uint8_t)b - *(uint8_t *)(a + i);
713 void HELPER(vec_rsubs16)(void *d, void *a, uint64_t b, uint32_t desc)
715 intptr_t oprsz = simd_oprsz(desc);
716 intptr_t i;
718 for (i = 0; i < oprsz; i += sizeof(uint16_t)) {
719 *(uint16_t *)(d + i) = (uint16_t)b - *(uint16_t *)(a + i);
723 void HELPER(vec_rsubs32)(void *d, void *a, uint64_t b, uint32_t desc)
725 intptr_t oprsz = simd_oprsz(desc);
726 intptr_t i;
728 for (i = 0; i < oprsz; i += sizeof(uint32_t)) {
729 *(uint32_t *)(d + i) = (uint32_t)b - *(uint32_t *)(a + i);
733 void HELPER(vec_rsubs64)(void *d, void *a, uint64_t b, uint32_t desc)
735 intptr_t oprsz = simd_oprsz(desc);
736 intptr_t i;
738 for (i = 0; i < oprsz; i += sizeof(uint64_t)) {
739 *(uint64_t *)(d + i) = b - *(uint64_t *)(a + i);
743 /* Vector Widening Integer Add/Subtract */
744 #define WOP_UUU_B uint16_t, uint8_t, uint8_t, uint16_t, uint16_t
745 #define WOP_UUU_H uint32_t, uint16_t, uint16_t, uint32_t, uint32_t
746 #define WOP_UUU_W uint64_t, uint32_t, uint32_t, uint64_t, uint64_t
747 #define WOP_SSS_B int16_t, int8_t, int8_t, int16_t, int16_t
748 #define WOP_SSS_H int32_t, int16_t, int16_t, int32_t, int32_t
749 #define WOP_SSS_W int64_t, int32_t, int32_t, int64_t, int64_t
750 #define WOP_WUUU_B uint16_t, uint8_t, uint16_t, uint16_t, uint16_t
751 #define WOP_WUUU_H uint32_t, uint16_t, uint32_t, uint32_t, uint32_t
752 #define WOP_WUUU_W uint64_t, uint32_t, uint64_t, uint64_t, uint64_t
753 #define WOP_WSSS_B int16_t, int8_t, int16_t, int16_t, int16_t
754 #define WOP_WSSS_H int32_t, int16_t, int32_t, int32_t, int32_t
755 #define WOP_WSSS_W int64_t, int32_t, int64_t, int64_t, int64_t
756 RVVCALL(OPIVV2, vwaddu_vv_b, WOP_UUU_B, H2, H1, H1, DO_ADD)
757 RVVCALL(OPIVV2, vwaddu_vv_h, WOP_UUU_H, H4, H2, H2, DO_ADD)
758 RVVCALL(OPIVV2, vwaddu_vv_w, WOP_UUU_W, H8, H4, H4, DO_ADD)
759 RVVCALL(OPIVV2, vwsubu_vv_b, WOP_UUU_B, H2, H1, H1, DO_SUB)
760 RVVCALL(OPIVV2, vwsubu_vv_h, WOP_UUU_H, H4, H2, H2, DO_SUB)
761 RVVCALL(OPIVV2, vwsubu_vv_w, WOP_UUU_W, H8, H4, H4, DO_SUB)
762 RVVCALL(OPIVV2, vwadd_vv_b, WOP_SSS_B, H2, H1, H1, DO_ADD)
763 RVVCALL(OPIVV2, vwadd_vv_h, WOP_SSS_H, H4, H2, H2, DO_ADD)
764 RVVCALL(OPIVV2, vwadd_vv_w, WOP_SSS_W, H8, H4, H4, DO_ADD)
765 RVVCALL(OPIVV2, vwsub_vv_b, WOP_SSS_B, H2, H1, H1, DO_SUB)
766 RVVCALL(OPIVV2, vwsub_vv_h, WOP_SSS_H, H4, H2, H2, DO_SUB)
767 RVVCALL(OPIVV2, vwsub_vv_w, WOP_SSS_W, H8, H4, H4, DO_SUB)
768 RVVCALL(OPIVV2, vwaddu_wv_b, WOP_WUUU_B, H2, H1, H1, DO_ADD)
769 RVVCALL(OPIVV2, vwaddu_wv_h, WOP_WUUU_H, H4, H2, H2, DO_ADD)
770 RVVCALL(OPIVV2, vwaddu_wv_w, WOP_WUUU_W, H8, H4, H4, DO_ADD)
771 RVVCALL(OPIVV2, vwsubu_wv_b, WOP_WUUU_B, H2, H1, H1, DO_SUB)
772 RVVCALL(OPIVV2, vwsubu_wv_h, WOP_WUUU_H, H4, H2, H2, DO_SUB)
773 RVVCALL(OPIVV2, vwsubu_wv_w, WOP_WUUU_W, H8, H4, H4, DO_SUB)
774 RVVCALL(OPIVV2, vwadd_wv_b, WOP_WSSS_B, H2, H1, H1, DO_ADD)
775 RVVCALL(OPIVV2, vwadd_wv_h, WOP_WSSS_H, H4, H2, H2, DO_ADD)
776 RVVCALL(OPIVV2, vwadd_wv_w, WOP_WSSS_W, H8, H4, H4, DO_ADD)
777 RVVCALL(OPIVV2, vwsub_wv_b, WOP_WSSS_B, H2, H1, H1, DO_SUB)
778 RVVCALL(OPIVV2, vwsub_wv_h, WOP_WSSS_H, H4, H2, H2, DO_SUB)
779 RVVCALL(OPIVV2, vwsub_wv_w, WOP_WSSS_W, H8, H4, H4, DO_SUB)
780 GEN_VEXT_VV(vwaddu_vv_b, 2)
781 GEN_VEXT_VV(vwaddu_vv_h, 4)
782 GEN_VEXT_VV(vwaddu_vv_w, 8)
783 GEN_VEXT_VV(vwsubu_vv_b, 2)
784 GEN_VEXT_VV(vwsubu_vv_h, 4)
785 GEN_VEXT_VV(vwsubu_vv_w, 8)
786 GEN_VEXT_VV(vwadd_vv_b, 2)
787 GEN_VEXT_VV(vwadd_vv_h, 4)
788 GEN_VEXT_VV(vwadd_vv_w, 8)
789 GEN_VEXT_VV(vwsub_vv_b, 2)
790 GEN_VEXT_VV(vwsub_vv_h, 4)
791 GEN_VEXT_VV(vwsub_vv_w, 8)
792 GEN_VEXT_VV(vwaddu_wv_b, 2)
793 GEN_VEXT_VV(vwaddu_wv_h, 4)
794 GEN_VEXT_VV(vwaddu_wv_w, 8)
795 GEN_VEXT_VV(vwsubu_wv_b, 2)
796 GEN_VEXT_VV(vwsubu_wv_h, 4)
797 GEN_VEXT_VV(vwsubu_wv_w, 8)
798 GEN_VEXT_VV(vwadd_wv_b, 2)
799 GEN_VEXT_VV(vwadd_wv_h, 4)
800 GEN_VEXT_VV(vwadd_wv_w, 8)
801 GEN_VEXT_VV(vwsub_wv_b, 2)
802 GEN_VEXT_VV(vwsub_wv_h, 4)
803 GEN_VEXT_VV(vwsub_wv_w, 8)
805 RVVCALL(OPIVX2, vwaddu_vx_b, WOP_UUU_B, H2, H1, DO_ADD)
806 RVVCALL(OPIVX2, vwaddu_vx_h, WOP_UUU_H, H4, H2, DO_ADD)
807 RVVCALL(OPIVX2, vwaddu_vx_w, WOP_UUU_W, H8, H4, DO_ADD)
808 RVVCALL(OPIVX2, vwsubu_vx_b, WOP_UUU_B, H2, H1, DO_SUB)
809 RVVCALL(OPIVX2, vwsubu_vx_h, WOP_UUU_H, H4, H2, DO_SUB)
810 RVVCALL(OPIVX2, vwsubu_vx_w, WOP_UUU_W, H8, H4, DO_SUB)
811 RVVCALL(OPIVX2, vwadd_vx_b, WOP_SSS_B, H2, H1, DO_ADD)
812 RVVCALL(OPIVX2, vwadd_vx_h, WOP_SSS_H, H4, H2, DO_ADD)
813 RVVCALL(OPIVX2, vwadd_vx_w, WOP_SSS_W, H8, H4, DO_ADD)
814 RVVCALL(OPIVX2, vwsub_vx_b, WOP_SSS_B, H2, H1, DO_SUB)
815 RVVCALL(OPIVX2, vwsub_vx_h, WOP_SSS_H, H4, H2, DO_SUB)
816 RVVCALL(OPIVX2, vwsub_vx_w, WOP_SSS_W, H8, H4, DO_SUB)
817 RVVCALL(OPIVX2, vwaddu_wx_b, WOP_WUUU_B, H2, H1, DO_ADD)
818 RVVCALL(OPIVX2, vwaddu_wx_h, WOP_WUUU_H, H4, H2, DO_ADD)
819 RVVCALL(OPIVX2, vwaddu_wx_w, WOP_WUUU_W, H8, H4, DO_ADD)
820 RVVCALL(OPIVX2, vwsubu_wx_b, WOP_WUUU_B, H2, H1, DO_SUB)
821 RVVCALL(OPIVX2, vwsubu_wx_h, WOP_WUUU_H, H4, H2, DO_SUB)
822 RVVCALL(OPIVX2, vwsubu_wx_w, WOP_WUUU_W, H8, H4, DO_SUB)
823 RVVCALL(OPIVX2, vwadd_wx_b, WOP_WSSS_B, H2, H1, DO_ADD)
824 RVVCALL(OPIVX2, vwadd_wx_h, WOP_WSSS_H, H4, H2, DO_ADD)
825 RVVCALL(OPIVX2, vwadd_wx_w, WOP_WSSS_W, H8, H4, DO_ADD)
826 RVVCALL(OPIVX2, vwsub_wx_b, WOP_WSSS_B, H2, H1, DO_SUB)
827 RVVCALL(OPIVX2, vwsub_wx_h, WOP_WSSS_H, H4, H2, DO_SUB)
828 RVVCALL(OPIVX2, vwsub_wx_w, WOP_WSSS_W, H8, H4, DO_SUB)
829 GEN_VEXT_VX(vwaddu_vx_b, 2)
830 GEN_VEXT_VX(vwaddu_vx_h, 4)
831 GEN_VEXT_VX(vwaddu_vx_w, 8)
832 GEN_VEXT_VX(vwsubu_vx_b, 2)
833 GEN_VEXT_VX(vwsubu_vx_h, 4)
834 GEN_VEXT_VX(vwsubu_vx_w, 8)
835 GEN_VEXT_VX(vwadd_vx_b, 2)
836 GEN_VEXT_VX(vwadd_vx_h, 4)
837 GEN_VEXT_VX(vwadd_vx_w, 8)
838 GEN_VEXT_VX(vwsub_vx_b, 2)
839 GEN_VEXT_VX(vwsub_vx_h, 4)
840 GEN_VEXT_VX(vwsub_vx_w, 8)
841 GEN_VEXT_VX(vwaddu_wx_b, 2)
842 GEN_VEXT_VX(vwaddu_wx_h, 4)
843 GEN_VEXT_VX(vwaddu_wx_w, 8)
844 GEN_VEXT_VX(vwsubu_wx_b, 2)
845 GEN_VEXT_VX(vwsubu_wx_h, 4)
846 GEN_VEXT_VX(vwsubu_wx_w, 8)
847 GEN_VEXT_VX(vwadd_wx_b, 2)
848 GEN_VEXT_VX(vwadd_wx_h, 4)
849 GEN_VEXT_VX(vwadd_wx_w, 8)
850 GEN_VEXT_VX(vwsub_wx_b, 2)
851 GEN_VEXT_VX(vwsub_wx_h, 4)
852 GEN_VEXT_VX(vwsub_wx_w, 8)
854 /* Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions */
855 #define DO_VADC(N, M, C) (N + M + C)
856 #define DO_VSBC(N, M, C) (N - M - C)
858 #define GEN_VEXT_VADC_VVM(NAME, ETYPE, H, DO_OP) \
859 void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
860 CPURISCVState *env, uint32_t desc) \
862 uint32_t vl = env->vl; \
863 uint32_t esz = sizeof(ETYPE); \
864 uint32_t total_elems = \
865 vext_get_total_elems(env, desc, esz); \
866 uint32_t vta = vext_vta(desc); \
867 uint32_t i; \
869 for (i = env->vstart; i < vl; i++) { \
870 ETYPE s1 = *((ETYPE *)vs1 + H(i)); \
871 ETYPE s2 = *((ETYPE *)vs2 + H(i)); \
872 ETYPE carry = vext_elem_mask(v0, i); \
874 *((ETYPE *)vd + H(i)) = DO_OP(s2, s1, carry); \
876 env->vstart = 0; \
877 /* set tail elements to 1s */ \
878 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
881 GEN_VEXT_VADC_VVM(vadc_vvm_b, uint8_t, H1, DO_VADC)
882 GEN_VEXT_VADC_VVM(vadc_vvm_h, uint16_t, H2, DO_VADC)
883 GEN_VEXT_VADC_VVM(vadc_vvm_w, uint32_t, H4, DO_VADC)
884 GEN_VEXT_VADC_VVM(vadc_vvm_d, uint64_t, H8, DO_VADC)
886 GEN_VEXT_VADC_VVM(vsbc_vvm_b, uint8_t, H1, DO_VSBC)
887 GEN_VEXT_VADC_VVM(vsbc_vvm_h, uint16_t, H2, DO_VSBC)
888 GEN_VEXT_VADC_VVM(vsbc_vvm_w, uint32_t, H4, DO_VSBC)
889 GEN_VEXT_VADC_VVM(vsbc_vvm_d, uint64_t, H8, DO_VSBC)
891 #define GEN_VEXT_VADC_VXM(NAME, ETYPE, H, DO_OP) \
892 void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \
893 CPURISCVState *env, uint32_t desc) \
895 uint32_t vl = env->vl; \
896 uint32_t esz = sizeof(ETYPE); \
897 uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
898 uint32_t vta = vext_vta(desc); \
899 uint32_t i; \
901 for (i = env->vstart; i < vl; i++) { \
902 ETYPE s2 = *((ETYPE *)vs2 + H(i)); \
903 ETYPE carry = vext_elem_mask(v0, i); \
905 *((ETYPE *)vd + H(i)) = DO_OP(s2, (ETYPE)(target_long)s1, carry);\
907 env->vstart = 0; \
908 /* set tail elements to 1s */ \
909 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
912 GEN_VEXT_VADC_VXM(vadc_vxm_b, uint8_t, H1, DO_VADC)
913 GEN_VEXT_VADC_VXM(vadc_vxm_h, uint16_t, H2, DO_VADC)
914 GEN_VEXT_VADC_VXM(vadc_vxm_w, uint32_t, H4, DO_VADC)
915 GEN_VEXT_VADC_VXM(vadc_vxm_d, uint64_t, H8, DO_VADC)
917 GEN_VEXT_VADC_VXM(vsbc_vxm_b, uint8_t, H1, DO_VSBC)
918 GEN_VEXT_VADC_VXM(vsbc_vxm_h, uint16_t, H2, DO_VSBC)
919 GEN_VEXT_VADC_VXM(vsbc_vxm_w, uint32_t, H4, DO_VSBC)
920 GEN_VEXT_VADC_VXM(vsbc_vxm_d, uint64_t, H8, DO_VSBC)
922 #define DO_MADC(N, M, C) (C ? (__typeof(N))(N + M + 1) <= N : \
923 (__typeof(N))(N + M) < N)
924 #define DO_MSBC(N, M, C) (C ? N <= M : N < M)
926 #define GEN_VEXT_VMADC_VVM(NAME, ETYPE, H, DO_OP) \
927 void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
928 CPURISCVState *env, uint32_t desc) \
930 uint32_t vl = env->vl; \
931 uint32_t vm = vext_vm(desc); \
932 uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
933 uint32_t vta_all_1s = vext_vta_all_1s(desc); \
934 uint32_t i; \
936 for (i = env->vstart; i < vl; i++) { \
937 ETYPE s1 = *((ETYPE *)vs1 + H(i)); \
938 ETYPE s2 = *((ETYPE *)vs2 + H(i)); \
939 ETYPE carry = !vm && vext_elem_mask(v0, i); \
940 vext_set_elem_mask(vd, i, DO_OP(s2, s1, carry)); \
942 env->vstart = 0; \
944 * mask destination register are always tail-agnostic
945 * set tail elements to 1s
946 */ \
947 if (vta_all_1s) { \
948 for (; i < total_elems; i++) { \
949 vext_set_elem_mask(vd, i, 1); \
954 GEN_VEXT_VMADC_VVM(vmadc_vvm_b, uint8_t, H1, DO_MADC)
955 GEN_VEXT_VMADC_VVM(vmadc_vvm_h, uint16_t, H2, DO_MADC)
956 GEN_VEXT_VMADC_VVM(vmadc_vvm_w, uint32_t, H4, DO_MADC)
957 GEN_VEXT_VMADC_VVM(vmadc_vvm_d, uint64_t, H8, DO_MADC)
959 GEN_VEXT_VMADC_VVM(vmsbc_vvm_b, uint8_t, H1, DO_MSBC)
960 GEN_VEXT_VMADC_VVM(vmsbc_vvm_h, uint16_t, H2, DO_MSBC)
961 GEN_VEXT_VMADC_VVM(vmsbc_vvm_w, uint32_t, H4, DO_MSBC)
962 GEN_VEXT_VMADC_VVM(vmsbc_vvm_d, uint64_t, H8, DO_MSBC)
964 #define GEN_VEXT_VMADC_VXM(NAME, ETYPE, H, DO_OP) \
965 void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \
966 void *vs2, CPURISCVState *env, uint32_t desc) \
968 uint32_t vl = env->vl; \
969 uint32_t vm = vext_vm(desc); \
970 uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
971 uint32_t vta_all_1s = vext_vta_all_1s(desc); \
972 uint32_t i; \
974 for (i = env->vstart; i < vl; i++) { \
975 ETYPE s2 = *((ETYPE *)vs2 + H(i)); \
976 ETYPE carry = !vm && vext_elem_mask(v0, i); \
977 vext_set_elem_mask(vd, i, \
978 DO_OP(s2, (ETYPE)(target_long)s1, carry)); \
980 env->vstart = 0; \
982 * mask destination register are always tail-agnostic
983 * set tail elements to 1s
984 */ \
985 if (vta_all_1s) { \
986 for (; i < total_elems; i++) { \
987 vext_set_elem_mask(vd, i, 1); \
992 GEN_VEXT_VMADC_VXM(vmadc_vxm_b, uint8_t, H1, DO_MADC)
993 GEN_VEXT_VMADC_VXM(vmadc_vxm_h, uint16_t, H2, DO_MADC)
994 GEN_VEXT_VMADC_VXM(vmadc_vxm_w, uint32_t, H4, DO_MADC)
995 GEN_VEXT_VMADC_VXM(vmadc_vxm_d, uint64_t, H8, DO_MADC)
997 GEN_VEXT_VMADC_VXM(vmsbc_vxm_b, uint8_t, H1, DO_MSBC)
998 GEN_VEXT_VMADC_VXM(vmsbc_vxm_h, uint16_t, H2, DO_MSBC)
999 GEN_VEXT_VMADC_VXM(vmsbc_vxm_w, uint32_t, H4, DO_MSBC)
1000 GEN_VEXT_VMADC_VXM(vmsbc_vxm_d, uint64_t, H8, DO_MSBC)
1002 /* Vector Bitwise Logical Instructions */
1003 RVVCALL(OPIVV2, vand_vv_b, OP_SSS_B, H1, H1, H1, DO_AND)
1004 RVVCALL(OPIVV2, vand_vv_h, OP_SSS_H, H2, H2, H2, DO_AND)
1005 RVVCALL(OPIVV2, vand_vv_w, OP_SSS_W, H4, H4, H4, DO_AND)
1006 RVVCALL(OPIVV2, vand_vv_d, OP_SSS_D, H8, H8, H8, DO_AND)
1007 RVVCALL(OPIVV2, vor_vv_b, OP_SSS_B, H1, H1, H1, DO_OR)
1008 RVVCALL(OPIVV2, vor_vv_h, OP_SSS_H, H2, H2, H2, DO_OR)
1009 RVVCALL(OPIVV2, vor_vv_w, OP_SSS_W, H4, H4, H4, DO_OR)
1010 RVVCALL(OPIVV2, vor_vv_d, OP_SSS_D, H8, H8, H8, DO_OR)
1011 RVVCALL(OPIVV2, vxor_vv_b, OP_SSS_B, H1, H1, H1, DO_XOR)
1012 RVVCALL(OPIVV2, vxor_vv_h, OP_SSS_H, H2, H2, H2, DO_XOR)
1013 RVVCALL(OPIVV2, vxor_vv_w, OP_SSS_W, H4, H4, H4, DO_XOR)
1014 RVVCALL(OPIVV2, vxor_vv_d, OP_SSS_D, H8, H8, H8, DO_XOR)
1015 GEN_VEXT_VV(vand_vv_b, 1)
1016 GEN_VEXT_VV(vand_vv_h, 2)
1017 GEN_VEXT_VV(vand_vv_w, 4)
1018 GEN_VEXT_VV(vand_vv_d, 8)
1019 GEN_VEXT_VV(vor_vv_b, 1)
1020 GEN_VEXT_VV(vor_vv_h, 2)
1021 GEN_VEXT_VV(vor_vv_w, 4)
1022 GEN_VEXT_VV(vor_vv_d, 8)
1023 GEN_VEXT_VV(vxor_vv_b, 1)
1024 GEN_VEXT_VV(vxor_vv_h, 2)
1025 GEN_VEXT_VV(vxor_vv_w, 4)
1026 GEN_VEXT_VV(vxor_vv_d, 8)
1028 RVVCALL(OPIVX2, vand_vx_b, OP_SSS_B, H1, H1, DO_AND)
1029 RVVCALL(OPIVX2, vand_vx_h, OP_SSS_H, H2, H2, DO_AND)
1030 RVVCALL(OPIVX2, vand_vx_w, OP_SSS_W, H4, H4, DO_AND)
1031 RVVCALL(OPIVX2, vand_vx_d, OP_SSS_D, H8, H8, DO_AND)
1032 RVVCALL(OPIVX2, vor_vx_b, OP_SSS_B, H1, H1, DO_OR)
1033 RVVCALL(OPIVX2, vor_vx_h, OP_SSS_H, H2, H2, DO_OR)
1034 RVVCALL(OPIVX2, vor_vx_w, OP_SSS_W, H4, H4, DO_OR)
1035 RVVCALL(OPIVX2, vor_vx_d, OP_SSS_D, H8, H8, DO_OR)
1036 RVVCALL(OPIVX2, vxor_vx_b, OP_SSS_B, H1, H1, DO_XOR)
1037 RVVCALL(OPIVX2, vxor_vx_h, OP_SSS_H, H2, H2, DO_XOR)
1038 RVVCALL(OPIVX2, vxor_vx_w, OP_SSS_W, H4, H4, DO_XOR)
1039 RVVCALL(OPIVX2, vxor_vx_d, OP_SSS_D, H8, H8, DO_XOR)
1040 GEN_VEXT_VX(vand_vx_b, 1)
1041 GEN_VEXT_VX(vand_vx_h, 2)
1042 GEN_VEXT_VX(vand_vx_w, 4)
1043 GEN_VEXT_VX(vand_vx_d, 8)
1044 GEN_VEXT_VX(vor_vx_b, 1)
1045 GEN_VEXT_VX(vor_vx_h, 2)
1046 GEN_VEXT_VX(vor_vx_w, 4)
1047 GEN_VEXT_VX(vor_vx_d, 8)
1048 GEN_VEXT_VX(vxor_vx_b, 1)
1049 GEN_VEXT_VX(vxor_vx_h, 2)
1050 GEN_VEXT_VX(vxor_vx_w, 4)
1051 GEN_VEXT_VX(vxor_vx_d, 8)
1053 /* Vector Single-Width Bit Shift Instructions */
1054 #define DO_SLL(N, M) (N << (M))
1055 #define DO_SRL(N, M) (N >> (M))
1057 /* generate the helpers for shift instructions with two vector operators */
1058 #define GEN_VEXT_SHIFT_VV(NAME, TS1, TS2, HS1, HS2, OP, MASK) \
1059 void HELPER(NAME)(void *vd, void *v0, void *vs1, \
1060 void *vs2, CPURISCVState *env, uint32_t desc) \
1062 uint32_t vm = vext_vm(desc); \
1063 uint32_t vl = env->vl; \
1064 uint32_t esz = sizeof(TS1); \
1065 uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
1066 uint32_t vta = vext_vta(desc); \
1067 uint32_t vma = vext_vma(desc); \
1068 uint32_t i; \
1070 for (i = env->vstart; i < vl; i++) { \
1071 if (!vm && !vext_elem_mask(v0, i)) { \
1072 /* set masked-off elements to 1s */ \
1073 vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \
1074 continue; \
1076 TS1 s1 = *((TS1 *)vs1 + HS1(i)); \
1077 TS2 s2 = *((TS2 *)vs2 + HS2(i)); \
1078 *((TS1 *)vd + HS1(i)) = OP(s2, s1 & MASK); \
1080 env->vstart = 0; \
1081 /* set tail elements to 1s */ \
1082 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
1085 GEN_VEXT_SHIFT_VV(vsll_vv_b, uint8_t, uint8_t, H1, H1, DO_SLL, 0x7)
1086 GEN_VEXT_SHIFT_VV(vsll_vv_h, uint16_t, uint16_t, H2, H2, DO_SLL, 0xf)
1087 GEN_VEXT_SHIFT_VV(vsll_vv_w, uint32_t, uint32_t, H4, H4, DO_SLL, 0x1f)
1088 GEN_VEXT_SHIFT_VV(vsll_vv_d, uint64_t, uint64_t, H8, H8, DO_SLL, 0x3f)
1090 GEN_VEXT_SHIFT_VV(vsrl_vv_b, uint8_t, uint8_t, H1, H1, DO_SRL, 0x7)
1091 GEN_VEXT_SHIFT_VV(vsrl_vv_h, uint16_t, uint16_t, H2, H2, DO_SRL, 0xf)
1092 GEN_VEXT_SHIFT_VV(vsrl_vv_w, uint32_t, uint32_t, H4, H4, DO_SRL, 0x1f)
1093 GEN_VEXT_SHIFT_VV(vsrl_vv_d, uint64_t, uint64_t, H8, H8, DO_SRL, 0x3f)
1095 GEN_VEXT_SHIFT_VV(vsra_vv_b, uint8_t, int8_t, H1, H1, DO_SRL, 0x7)
1096 GEN_VEXT_SHIFT_VV(vsra_vv_h, uint16_t, int16_t, H2, H2, DO_SRL, 0xf)
1097 GEN_VEXT_SHIFT_VV(vsra_vv_w, uint32_t, int32_t, H4, H4, DO_SRL, 0x1f)
1098 GEN_VEXT_SHIFT_VV(vsra_vv_d, uint64_t, int64_t, H8, H8, DO_SRL, 0x3f)
1101 * generate the helpers for shift instructions with one vector and one scalar
1103 #define GEN_VEXT_SHIFT_VX(NAME, TD, TS2, HD, HS2, OP, MASK) \
1104 void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \
1105 void *vs2, CPURISCVState *env, \
1106 uint32_t desc) \
1108 uint32_t vm = vext_vm(desc); \
1109 uint32_t vl = env->vl; \
1110 uint32_t esz = sizeof(TD); \
1111 uint32_t total_elems = \
1112 vext_get_total_elems(env, desc, esz); \
1113 uint32_t vta = vext_vta(desc); \
1114 uint32_t vma = vext_vma(desc); \
1115 uint32_t i; \
1117 for (i = env->vstart; i < vl; i++) { \
1118 if (!vm && !vext_elem_mask(v0, i)) { \
1119 /* set masked-off elements to 1s */ \
1120 vext_set_elems_1s(vd, vma, i * esz, \
1121 (i + 1) * esz); \
1122 continue; \
1124 TS2 s2 = *((TS2 *)vs2 + HS2(i)); \
1125 *((TD *)vd + HD(i)) = OP(s2, s1 & MASK); \
1127 env->vstart = 0; \
1128 /* set tail elements to 1s */ \
1129 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);\
1132 GEN_VEXT_SHIFT_VX(vsll_vx_b, uint8_t, int8_t, H1, H1, DO_SLL, 0x7)
1133 GEN_VEXT_SHIFT_VX(vsll_vx_h, uint16_t, int16_t, H2, H2, DO_SLL, 0xf)
1134 GEN_VEXT_SHIFT_VX(vsll_vx_w, uint32_t, int32_t, H4, H4, DO_SLL, 0x1f)
1135 GEN_VEXT_SHIFT_VX(vsll_vx_d, uint64_t, int64_t, H8, H8, DO_SLL, 0x3f)
1137 GEN_VEXT_SHIFT_VX(vsrl_vx_b, uint8_t, uint8_t, H1, H1, DO_SRL, 0x7)
1138 GEN_VEXT_SHIFT_VX(vsrl_vx_h, uint16_t, uint16_t, H2, H2, DO_SRL, 0xf)
1139 GEN_VEXT_SHIFT_VX(vsrl_vx_w, uint32_t, uint32_t, H4, H4, DO_SRL, 0x1f)
1140 GEN_VEXT_SHIFT_VX(vsrl_vx_d, uint64_t, uint64_t, H8, H8, DO_SRL, 0x3f)
1142 GEN_VEXT_SHIFT_VX(vsra_vx_b, int8_t, int8_t, H1, H1, DO_SRL, 0x7)
1143 GEN_VEXT_SHIFT_VX(vsra_vx_h, int16_t, int16_t, H2, H2, DO_SRL, 0xf)
1144 GEN_VEXT_SHIFT_VX(vsra_vx_w, int32_t, int32_t, H4, H4, DO_SRL, 0x1f)
1145 GEN_VEXT_SHIFT_VX(vsra_vx_d, int64_t, int64_t, H8, H8, DO_SRL, 0x3f)
1147 /* Vector Narrowing Integer Right Shift Instructions */
1148 GEN_VEXT_SHIFT_VV(vnsrl_wv_b, uint8_t, uint16_t, H1, H2, DO_SRL, 0xf)
1149 GEN_VEXT_SHIFT_VV(vnsrl_wv_h, uint16_t, uint32_t, H2, H4, DO_SRL, 0x1f)
1150 GEN_VEXT_SHIFT_VV(vnsrl_wv_w, uint32_t, uint64_t, H4, H8, DO_SRL, 0x3f)
1151 GEN_VEXT_SHIFT_VV(vnsra_wv_b, uint8_t, int16_t, H1, H2, DO_SRL, 0xf)
1152 GEN_VEXT_SHIFT_VV(vnsra_wv_h, uint16_t, int32_t, H2, H4, DO_SRL, 0x1f)
1153 GEN_VEXT_SHIFT_VV(vnsra_wv_w, uint32_t, int64_t, H4, H8, DO_SRL, 0x3f)
1154 GEN_VEXT_SHIFT_VX(vnsrl_wx_b, uint8_t, uint16_t, H1, H2, DO_SRL, 0xf)
1155 GEN_VEXT_SHIFT_VX(vnsrl_wx_h, uint16_t, uint32_t, H2, H4, DO_SRL, 0x1f)
1156 GEN_VEXT_SHIFT_VX(vnsrl_wx_w, uint32_t, uint64_t, H4, H8, DO_SRL, 0x3f)
1157 GEN_VEXT_SHIFT_VX(vnsra_wx_b, int8_t, int16_t, H1, H2, DO_SRL, 0xf)
1158 GEN_VEXT_SHIFT_VX(vnsra_wx_h, int16_t, int32_t, H2, H4, DO_SRL, 0x1f)
1159 GEN_VEXT_SHIFT_VX(vnsra_wx_w, int32_t, int64_t, H4, H8, DO_SRL, 0x3f)
1161 /* Vector Integer Comparison Instructions */
1162 #define DO_MSEQ(N, M) (N == M)
1163 #define DO_MSNE(N, M) (N != M)
1164 #define DO_MSLT(N, M) (N < M)
1165 #define DO_MSLE(N, M) (N <= M)
1166 #define DO_MSGT(N, M) (N > M)
1168 #define GEN_VEXT_CMP_VV(NAME, ETYPE, H, DO_OP) \
1169 void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
1170 CPURISCVState *env, uint32_t desc) \
1172 uint32_t vm = vext_vm(desc); \
1173 uint32_t vl = env->vl; \
1174 uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
1175 uint32_t vta_all_1s = vext_vta_all_1s(desc); \
1176 uint32_t vma = vext_vma(desc); \
1177 uint32_t i; \
1179 for (i = env->vstart; i < vl; i++) { \
1180 ETYPE s1 = *((ETYPE *)vs1 + H(i)); \
1181 ETYPE s2 = *((ETYPE *)vs2 + H(i)); \
1182 if (!vm && !vext_elem_mask(v0, i)) { \
1183 /* set masked-off elements to 1s */ \
1184 if (vma) { \
1185 vext_set_elem_mask(vd, i, 1); \
1187 continue; \
1189 vext_set_elem_mask(vd, i, DO_OP(s2, s1)); \
1191 env->vstart = 0; \
1193 * mask destination register are always tail-agnostic
1194 * set tail elements to 1s
1195 */ \
1196 if (vta_all_1s) { \
1197 for (; i < total_elems; i++) { \
1198 vext_set_elem_mask(vd, i, 1); \
1203 GEN_VEXT_CMP_VV(vmseq_vv_b, uint8_t, H1, DO_MSEQ)
1204 GEN_VEXT_CMP_VV(vmseq_vv_h, uint16_t, H2, DO_MSEQ)
1205 GEN_VEXT_CMP_VV(vmseq_vv_w, uint32_t, H4, DO_MSEQ)
1206 GEN_VEXT_CMP_VV(vmseq_vv_d, uint64_t, H8, DO_MSEQ)
1208 GEN_VEXT_CMP_VV(vmsne_vv_b, uint8_t, H1, DO_MSNE)
1209 GEN_VEXT_CMP_VV(vmsne_vv_h, uint16_t, H2, DO_MSNE)
1210 GEN_VEXT_CMP_VV(vmsne_vv_w, uint32_t, H4, DO_MSNE)
1211 GEN_VEXT_CMP_VV(vmsne_vv_d, uint64_t, H8, DO_MSNE)
1213 GEN_VEXT_CMP_VV(vmsltu_vv_b, uint8_t, H1, DO_MSLT)
1214 GEN_VEXT_CMP_VV(vmsltu_vv_h, uint16_t, H2, DO_MSLT)
1215 GEN_VEXT_CMP_VV(vmsltu_vv_w, uint32_t, H4, DO_MSLT)
1216 GEN_VEXT_CMP_VV(vmsltu_vv_d, uint64_t, H8, DO_MSLT)
1218 GEN_VEXT_CMP_VV(vmslt_vv_b, int8_t, H1, DO_MSLT)
1219 GEN_VEXT_CMP_VV(vmslt_vv_h, int16_t, H2, DO_MSLT)
1220 GEN_VEXT_CMP_VV(vmslt_vv_w, int32_t, H4, DO_MSLT)
1221 GEN_VEXT_CMP_VV(vmslt_vv_d, int64_t, H8, DO_MSLT)
1223 GEN_VEXT_CMP_VV(vmsleu_vv_b, uint8_t, H1, DO_MSLE)
1224 GEN_VEXT_CMP_VV(vmsleu_vv_h, uint16_t, H2, DO_MSLE)
1225 GEN_VEXT_CMP_VV(vmsleu_vv_w, uint32_t, H4, DO_MSLE)
1226 GEN_VEXT_CMP_VV(vmsleu_vv_d, uint64_t, H8, DO_MSLE)
1228 GEN_VEXT_CMP_VV(vmsle_vv_b, int8_t, H1, DO_MSLE)
1229 GEN_VEXT_CMP_VV(vmsle_vv_h, int16_t, H2, DO_MSLE)
1230 GEN_VEXT_CMP_VV(vmsle_vv_w, int32_t, H4, DO_MSLE)
1231 GEN_VEXT_CMP_VV(vmsle_vv_d, int64_t, H8, DO_MSLE)
1233 #define GEN_VEXT_CMP_VX(NAME, ETYPE, H, DO_OP) \
1234 void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \
1235 CPURISCVState *env, uint32_t desc) \
1237 uint32_t vm = vext_vm(desc); \
1238 uint32_t vl = env->vl; \
1239 uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
1240 uint32_t vta_all_1s = vext_vta_all_1s(desc); \
1241 uint32_t vma = vext_vma(desc); \
1242 uint32_t i; \
1244 for (i = env->vstart; i < vl; i++) { \
1245 ETYPE s2 = *((ETYPE *)vs2 + H(i)); \
1246 if (!vm && !vext_elem_mask(v0, i)) { \
1247 /* set masked-off elements to 1s */ \
1248 if (vma) { \
1249 vext_set_elem_mask(vd, i, 1); \
1251 continue; \
1253 vext_set_elem_mask(vd, i, \
1254 DO_OP(s2, (ETYPE)(target_long)s1)); \
1256 env->vstart = 0; \
1258 * mask destination register are always tail-agnostic
1259 * set tail elements to 1s
1260 */ \
1261 if (vta_all_1s) { \
1262 for (; i < total_elems; i++) { \
1263 vext_set_elem_mask(vd, i, 1); \
1268 GEN_VEXT_CMP_VX(vmseq_vx_b, uint8_t, H1, DO_MSEQ)
1269 GEN_VEXT_CMP_VX(vmseq_vx_h, uint16_t, H2, DO_MSEQ)
1270 GEN_VEXT_CMP_VX(vmseq_vx_w, uint32_t, H4, DO_MSEQ)
1271 GEN_VEXT_CMP_VX(vmseq_vx_d, uint64_t, H8, DO_MSEQ)
1273 GEN_VEXT_CMP_VX(vmsne_vx_b, uint8_t, H1, DO_MSNE)
1274 GEN_VEXT_CMP_VX(vmsne_vx_h, uint16_t, H2, DO_MSNE)
1275 GEN_VEXT_CMP_VX(vmsne_vx_w, uint32_t, H4, DO_MSNE)
1276 GEN_VEXT_CMP_VX(vmsne_vx_d, uint64_t, H8, DO_MSNE)
1278 GEN_VEXT_CMP_VX(vmsltu_vx_b, uint8_t, H1, DO_MSLT)
1279 GEN_VEXT_CMP_VX(vmsltu_vx_h, uint16_t, H2, DO_MSLT)
1280 GEN_VEXT_CMP_VX(vmsltu_vx_w, uint32_t, H4, DO_MSLT)
1281 GEN_VEXT_CMP_VX(vmsltu_vx_d, uint64_t, H8, DO_MSLT)
1283 GEN_VEXT_CMP_VX(vmslt_vx_b, int8_t, H1, DO_MSLT)
1284 GEN_VEXT_CMP_VX(vmslt_vx_h, int16_t, H2, DO_MSLT)
1285 GEN_VEXT_CMP_VX(vmslt_vx_w, int32_t, H4, DO_MSLT)
1286 GEN_VEXT_CMP_VX(vmslt_vx_d, int64_t, H8, DO_MSLT)
1288 GEN_VEXT_CMP_VX(vmsleu_vx_b, uint8_t, H1, DO_MSLE)
1289 GEN_VEXT_CMP_VX(vmsleu_vx_h, uint16_t, H2, DO_MSLE)
1290 GEN_VEXT_CMP_VX(vmsleu_vx_w, uint32_t, H4, DO_MSLE)
1291 GEN_VEXT_CMP_VX(vmsleu_vx_d, uint64_t, H8, DO_MSLE)
1293 GEN_VEXT_CMP_VX(vmsle_vx_b, int8_t, H1, DO_MSLE)
1294 GEN_VEXT_CMP_VX(vmsle_vx_h, int16_t, H2, DO_MSLE)
1295 GEN_VEXT_CMP_VX(vmsle_vx_w, int32_t, H4, DO_MSLE)
1296 GEN_VEXT_CMP_VX(vmsle_vx_d, int64_t, H8, DO_MSLE)
1298 GEN_VEXT_CMP_VX(vmsgtu_vx_b, uint8_t, H1, DO_MSGT)
1299 GEN_VEXT_CMP_VX(vmsgtu_vx_h, uint16_t, H2, DO_MSGT)
1300 GEN_VEXT_CMP_VX(vmsgtu_vx_w, uint32_t, H4, DO_MSGT)
1301 GEN_VEXT_CMP_VX(vmsgtu_vx_d, uint64_t, H8, DO_MSGT)
1303 GEN_VEXT_CMP_VX(vmsgt_vx_b, int8_t, H1, DO_MSGT)
1304 GEN_VEXT_CMP_VX(vmsgt_vx_h, int16_t, H2, DO_MSGT)
1305 GEN_VEXT_CMP_VX(vmsgt_vx_w, int32_t, H4, DO_MSGT)
1306 GEN_VEXT_CMP_VX(vmsgt_vx_d, int64_t, H8, DO_MSGT)
1308 /* Vector Integer Min/Max Instructions */
1309 RVVCALL(OPIVV2, vminu_vv_b, OP_UUU_B, H1, H1, H1, DO_MIN)
1310 RVVCALL(OPIVV2, vminu_vv_h, OP_UUU_H, H2, H2, H2, DO_MIN)
1311 RVVCALL(OPIVV2, vminu_vv_w, OP_UUU_W, H4, H4, H4, DO_MIN)
1312 RVVCALL(OPIVV2, vminu_vv_d, OP_UUU_D, H8, H8, H8, DO_MIN)
1313 RVVCALL(OPIVV2, vmin_vv_b, OP_SSS_B, H1, H1, H1, DO_MIN)
1314 RVVCALL(OPIVV2, vmin_vv_h, OP_SSS_H, H2, H2, H2, DO_MIN)
1315 RVVCALL(OPIVV2, vmin_vv_w, OP_SSS_W, H4, H4, H4, DO_MIN)
1316 RVVCALL(OPIVV2, vmin_vv_d, OP_SSS_D, H8, H8, H8, DO_MIN)
1317 RVVCALL(OPIVV2, vmaxu_vv_b, OP_UUU_B, H1, H1, H1, DO_MAX)
1318 RVVCALL(OPIVV2, vmaxu_vv_h, OP_UUU_H, H2, H2, H2, DO_MAX)
1319 RVVCALL(OPIVV2, vmaxu_vv_w, OP_UUU_W, H4, H4, H4, DO_MAX)
1320 RVVCALL(OPIVV2, vmaxu_vv_d, OP_UUU_D, H8, H8, H8, DO_MAX)
1321 RVVCALL(OPIVV2, vmax_vv_b, OP_SSS_B, H1, H1, H1, DO_MAX)
1322 RVVCALL(OPIVV2, vmax_vv_h, OP_SSS_H, H2, H2, H2, DO_MAX)
1323 RVVCALL(OPIVV2, vmax_vv_w, OP_SSS_W, H4, H4, H4, DO_MAX)
1324 RVVCALL(OPIVV2, vmax_vv_d, OP_SSS_D, H8, H8, H8, DO_MAX)
1325 GEN_VEXT_VV(vminu_vv_b, 1)
1326 GEN_VEXT_VV(vminu_vv_h, 2)
1327 GEN_VEXT_VV(vminu_vv_w, 4)
1328 GEN_VEXT_VV(vminu_vv_d, 8)
1329 GEN_VEXT_VV(vmin_vv_b, 1)
1330 GEN_VEXT_VV(vmin_vv_h, 2)
1331 GEN_VEXT_VV(vmin_vv_w, 4)
1332 GEN_VEXT_VV(vmin_vv_d, 8)
1333 GEN_VEXT_VV(vmaxu_vv_b, 1)
1334 GEN_VEXT_VV(vmaxu_vv_h, 2)
1335 GEN_VEXT_VV(vmaxu_vv_w, 4)
1336 GEN_VEXT_VV(vmaxu_vv_d, 8)
1337 GEN_VEXT_VV(vmax_vv_b, 1)
1338 GEN_VEXT_VV(vmax_vv_h, 2)
1339 GEN_VEXT_VV(vmax_vv_w, 4)
1340 GEN_VEXT_VV(vmax_vv_d, 8)
1342 RVVCALL(OPIVX2, vminu_vx_b, OP_UUU_B, H1, H1, DO_MIN)
1343 RVVCALL(OPIVX2, vminu_vx_h, OP_UUU_H, H2, H2, DO_MIN)
1344 RVVCALL(OPIVX2, vminu_vx_w, OP_UUU_W, H4, H4, DO_MIN)
1345 RVVCALL(OPIVX2, vminu_vx_d, OP_UUU_D, H8, H8, DO_MIN)
1346 RVVCALL(OPIVX2, vmin_vx_b, OP_SSS_B, H1, H1, DO_MIN)
1347 RVVCALL(OPIVX2, vmin_vx_h, OP_SSS_H, H2, H2, DO_MIN)
1348 RVVCALL(OPIVX2, vmin_vx_w, OP_SSS_W, H4, H4, DO_MIN)
1349 RVVCALL(OPIVX2, vmin_vx_d, OP_SSS_D, H8, H8, DO_MIN)
1350 RVVCALL(OPIVX2, vmaxu_vx_b, OP_UUU_B, H1, H1, DO_MAX)
1351 RVVCALL(OPIVX2, vmaxu_vx_h, OP_UUU_H, H2, H2, DO_MAX)
1352 RVVCALL(OPIVX2, vmaxu_vx_w, OP_UUU_W, H4, H4, DO_MAX)
1353 RVVCALL(OPIVX2, vmaxu_vx_d, OP_UUU_D, H8, H8, DO_MAX)
1354 RVVCALL(OPIVX2, vmax_vx_b, OP_SSS_B, H1, H1, DO_MAX)
1355 RVVCALL(OPIVX2, vmax_vx_h, OP_SSS_H, H2, H2, DO_MAX)
1356 RVVCALL(OPIVX2, vmax_vx_w, OP_SSS_W, H4, H4, DO_MAX)
1357 RVVCALL(OPIVX2, vmax_vx_d, OP_SSS_D, H8, H8, DO_MAX)
1358 GEN_VEXT_VX(vminu_vx_b, 1)
1359 GEN_VEXT_VX(vminu_vx_h, 2)
1360 GEN_VEXT_VX(vminu_vx_w, 4)
1361 GEN_VEXT_VX(vminu_vx_d, 8)
1362 GEN_VEXT_VX(vmin_vx_b, 1)
1363 GEN_VEXT_VX(vmin_vx_h, 2)
1364 GEN_VEXT_VX(vmin_vx_w, 4)
1365 GEN_VEXT_VX(vmin_vx_d, 8)
1366 GEN_VEXT_VX(vmaxu_vx_b, 1)
1367 GEN_VEXT_VX(vmaxu_vx_h, 2)
1368 GEN_VEXT_VX(vmaxu_vx_w, 4)
1369 GEN_VEXT_VX(vmaxu_vx_d, 8)
1370 GEN_VEXT_VX(vmax_vx_b, 1)
1371 GEN_VEXT_VX(vmax_vx_h, 2)
1372 GEN_VEXT_VX(vmax_vx_w, 4)
1373 GEN_VEXT_VX(vmax_vx_d, 8)
1375 /* Vector Single-Width Integer Multiply Instructions */
1376 #define DO_MUL(N, M) (N * M)
1377 RVVCALL(OPIVV2, vmul_vv_b, OP_SSS_B, H1, H1, H1, DO_MUL)
1378 RVVCALL(OPIVV2, vmul_vv_h, OP_SSS_H, H2, H2, H2, DO_MUL)
1379 RVVCALL(OPIVV2, vmul_vv_w, OP_SSS_W, H4, H4, H4, DO_MUL)
1380 RVVCALL(OPIVV2, vmul_vv_d, OP_SSS_D, H8, H8, H8, DO_MUL)
1381 GEN_VEXT_VV(vmul_vv_b, 1)
1382 GEN_VEXT_VV(vmul_vv_h, 2)
1383 GEN_VEXT_VV(vmul_vv_w, 4)
1384 GEN_VEXT_VV(vmul_vv_d, 8)
1386 static int8_t do_mulh_b(int8_t s2, int8_t s1)
1388 return (int16_t)s2 * (int16_t)s1 >> 8;
1391 static int16_t do_mulh_h(int16_t s2, int16_t s1)
1393 return (int32_t)s2 * (int32_t)s1 >> 16;
1396 static int32_t do_mulh_w(int32_t s2, int32_t s1)
1398 return (int64_t)s2 * (int64_t)s1 >> 32;
1401 static int64_t do_mulh_d(int64_t s2, int64_t s1)
1403 uint64_t hi_64, lo_64;
1405 muls64(&lo_64, &hi_64, s1, s2);
1406 return hi_64;
1409 static uint8_t do_mulhu_b(uint8_t s2, uint8_t s1)
1411 return (uint16_t)s2 * (uint16_t)s1 >> 8;
1414 static uint16_t do_mulhu_h(uint16_t s2, uint16_t s1)
1416 return (uint32_t)s2 * (uint32_t)s1 >> 16;
1419 static uint32_t do_mulhu_w(uint32_t s2, uint32_t s1)
1421 return (uint64_t)s2 * (uint64_t)s1 >> 32;
1424 static uint64_t do_mulhu_d(uint64_t s2, uint64_t s1)
1426 uint64_t hi_64, lo_64;
1428 mulu64(&lo_64, &hi_64, s2, s1);
1429 return hi_64;
1432 static int8_t do_mulhsu_b(int8_t s2, uint8_t s1)
1434 return (int16_t)s2 * (uint16_t)s1 >> 8;
1437 static int16_t do_mulhsu_h(int16_t s2, uint16_t s1)
1439 return (int32_t)s2 * (uint32_t)s1 >> 16;
1442 static int32_t do_mulhsu_w(int32_t s2, uint32_t s1)
1444 return (int64_t)s2 * (uint64_t)s1 >> 32;
1448 * Let A = signed operand,
1449 * B = unsigned operand
1450 * P = mulu64(A, B), unsigned product
1452 * LET X = 2 ** 64 - A, 2's complement of A
1453 * SP = signed product
1454 * THEN
1455 * IF A < 0
1456 * SP = -X * B
1457 * = -(2 ** 64 - A) * B
1458 * = A * B - 2 ** 64 * B
1459 * = P - 2 ** 64 * B
1460 * ELSE
1461 * SP = P
1462 * THEN
1463 * HI_P -= (A < 0 ? B : 0)
1466 static int64_t do_mulhsu_d(int64_t s2, uint64_t s1)
1468 uint64_t hi_64, lo_64;
1470 mulu64(&lo_64, &hi_64, s2, s1);
1472 hi_64 -= s2 < 0 ? s1 : 0;
1473 return hi_64;
1476 RVVCALL(OPIVV2, vmulh_vv_b, OP_SSS_B, H1, H1, H1, do_mulh_b)
1477 RVVCALL(OPIVV2, vmulh_vv_h, OP_SSS_H, H2, H2, H2, do_mulh_h)
1478 RVVCALL(OPIVV2, vmulh_vv_w, OP_SSS_W, H4, H4, H4, do_mulh_w)
1479 RVVCALL(OPIVV2, vmulh_vv_d, OP_SSS_D, H8, H8, H8, do_mulh_d)
1480 RVVCALL(OPIVV2, vmulhu_vv_b, OP_UUU_B, H1, H1, H1, do_mulhu_b)
1481 RVVCALL(OPIVV2, vmulhu_vv_h, OP_UUU_H, H2, H2, H2, do_mulhu_h)
1482 RVVCALL(OPIVV2, vmulhu_vv_w, OP_UUU_W, H4, H4, H4, do_mulhu_w)
1483 RVVCALL(OPIVV2, vmulhu_vv_d, OP_UUU_D, H8, H8, H8, do_mulhu_d)
1484 RVVCALL(OPIVV2, vmulhsu_vv_b, OP_SUS_B, H1, H1, H1, do_mulhsu_b)
1485 RVVCALL(OPIVV2, vmulhsu_vv_h, OP_SUS_H, H2, H2, H2, do_mulhsu_h)
1486 RVVCALL(OPIVV2, vmulhsu_vv_w, OP_SUS_W, H4, H4, H4, do_mulhsu_w)
1487 RVVCALL(OPIVV2, vmulhsu_vv_d, OP_SUS_D, H8, H8, H8, do_mulhsu_d)
1488 GEN_VEXT_VV(vmulh_vv_b, 1)
1489 GEN_VEXT_VV(vmulh_vv_h, 2)
1490 GEN_VEXT_VV(vmulh_vv_w, 4)
1491 GEN_VEXT_VV(vmulh_vv_d, 8)
1492 GEN_VEXT_VV(vmulhu_vv_b, 1)
1493 GEN_VEXT_VV(vmulhu_vv_h, 2)
1494 GEN_VEXT_VV(vmulhu_vv_w, 4)
1495 GEN_VEXT_VV(vmulhu_vv_d, 8)
1496 GEN_VEXT_VV(vmulhsu_vv_b, 1)
1497 GEN_VEXT_VV(vmulhsu_vv_h, 2)
1498 GEN_VEXT_VV(vmulhsu_vv_w, 4)
1499 GEN_VEXT_VV(vmulhsu_vv_d, 8)
1501 RVVCALL(OPIVX2, vmul_vx_b, OP_SSS_B, H1, H1, DO_MUL)
1502 RVVCALL(OPIVX2, vmul_vx_h, OP_SSS_H, H2, H2, DO_MUL)
1503 RVVCALL(OPIVX2, vmul_vx_w, OP_SSS_W, H4, H4, DO_MUL)
1504 RVVCALL(OPIVX2, vmul_vx_d, OP_SSS_D, H8, H8, DO_MUL)
1505 RVVCALL(OPIVX2, vmulh_vx_b, OP_SSS_B, H1, H1, do_mulh_b)
1506 RVVCALL(OPIVX2, vmulh_vx_h, OP_SSS_H, H2, H2, do_mulh_h)
1507 RVVCALL(OPIVX2, vmulh_vx_w, OP_SSS_W, H4, H4, do_mulh_w)
1508 RVVCALL(OPIVX2, vmulh_vx_d, OP_SSS_D, H8, H8, do_mulh_d)
1509 RVVCALL(OPIVX2, vmulhu_vx_b, OP_UUU_B, H1, H1, do_mulhu_b)
1510 RVVCALL(OPIVX2, vmulhu_vx_h, OP_UUU_H, H2, H2, do_mulhu_h)
1511 RVVCALL(OPIVX2, vmulhu_vx_w, OP_UUU_W, H4, H4, do_mulhu_w)
1512 RVVCALL(OPIVX2, vmulhu_vx_d, OP_UUU_D, H8, H8, do_mulhu_d)
1513 RVVCALL(OPIVX2, vmulhsu_vx_b, OP_SUS_B, H1, H1, do_mulhsu_b)
1514 RVVCALL(OPIVX2, vmulhsu_vx_h, OP_SUS_H, H2, H2, do_mulhsu_h)
1515 RVVCALL(OPIVX2, vmulhsu_vx_w, OP_SUS_W, H4, H4, do_mulhsu_w)
1516 RVVCALL(OPIVX2, vmulhsu_vx_d, OP_SUS_D, H8, H8, do_mulhsu_d)
1517 GEN_VEXT_VX(vmul_vx_b, 1)
1518 GEN_VEXT_VX(vmul_vx_h, 2)
1519 GEN_VEXT_VX(vmul_vx_w, 4)
1520 GEN_VEXT_VX(vmul_vx_d, 8)
1521 GEN_VEXT_VX(vmulh_vx_b, 1)
1522 GEN_VEXT_VX(vmulh_vx_h, 2)
1523 GEN_VEXT_VX(vmulh_vx_w, 4)
1524 GEN_VEXT_VX(vmulh_vx_d, 8)
1525 GEN_VEXT_VX(vmulhu_vx_b, 1)
1526 GEN_VEXT_VX(vmulhu_vx_h, 2)
1527 GEN_VEXT_VX(vmulhu_vx_w, 4)
1528 GEN_VEXT_VX(vmulhu_vx_d, 8)
1529 GEN_VEXT_VX(vmulhsu_vx_b, 1)
1530 GEN_VEXT_VX(vmulhsu_vx_h, 2)
1531 GEN_VEXT_VX(vmulhsu_vx_w, 4)
1532 GEN_VEXT_VX(vmulhsu_vx_d, 8)
1534 /* Vector Integer Divide Instructions */
1535 #define DO_DIVU(N, M) (unlikely(M == 0) ? (__typeof(N))(-1) : N / M)
1536 #define DO_REMU(N, M) (unlikely(M == 0) ? N : N % M)
1537 #define DO_DIV(N, M) (unlikely(M == 0) ? (__typeof(N))(-1) : \
1538 unlikely((N == -N) && (M == (__typeof(N))(-1))) ? N : N / M)
1539 #define DO_REM(N, M) (unlikely(M == 0) ? N : \
1540 unlikely((N == -N) && (M == (__typeof(N))(-1))) ? 0 : N % M)
1542 RVVCALL(OPIVV2, vdivu_vv_b, OP_UUU_B, H1, H1, H1, DO_DIVU)
1543 RVVCALL(OPIVV2, vdivu_vv_h, OP_UUU_H, H2, H2, H2, DO_DIVU)
1544 RVVCALL(OPIVV2, vdivu_vv_w, OP_UUU_W, H4, H4, H4, DO_DIVU)
1545 RVVCALL(OPIVV2, vdivu_vv_d, OP_UUU_D, H8, H8, H8, DO_DIVU)
1546 RVVCALL(OPIVV2, vdiv_vv_b, OP_SSS_B, H1, H1, H1, DO_DIV)
1547 RVVCALL(OPIVV2, vdiv_vv_h, OP_SSS_H, H2, H2, H2, DO_DIV)
1548 RVVCALL(OPIVV2, vdiv_vv_w, OP_SSS_W, H4, H4, H4, DO_DIV)
1549 RVVCALL(OPIVV2, vdiv_vv_d, OP_SSS_D, H8, H8, H8, DO_DIV)
1550 RVVCALL(OPIVV2, vremu_vv_b, OP_UUU_B, H1, H1, H1, DO_REMU)
1551 RVVCALL(OPIVV2, vremu_vv_h, OP_UUU_H, H2, H2, H2, DO_REMU)
1552 RVVCALL(OPIVV2, vremu_vv_w, OP_UUU_W, H4, H4, H4, DO_REMU)
1553 RVVCALL(OPIVV2, vremu_vv_d, OP_UUU_D, H8, H8, H8, DO_REMU)
1554 RVVCALL(OPIVV2, vrem_vv_b, OP_SSS_B, H1, H1, H1, DO_REM)
1555 RVVCALL(OPIVV2, vrem_vv_h, OP_SSS_H, H2, H2, H2, DO_REM)
1556 RVVCALL(OPIVV2, vrem_vv_w, OP_SSS_W, H4, H4, H4, DO_REM)
1557 RVVCALL(OPIVV2, vrem_vv_d, OP_SSS_D, H8, H8, H8, DO_REM)
1558 GEN_VEXT_VV(vdivu_vv_b, 1)
1559 GEN_VEXT_VV(vdivu_vv_h, 2)
1560 GEN_VEXT_VV(vdivu_vv_w, 4)
1561 GEN_VEXT_VV(vdivu_vv_d, 8)
1562 GEN_VEXT_VV(vdiv_vv_b, 1)
1563 GEN_VEXT_VV(vdiv_vv_h, 2)
1564 GEN_VEXT_VV(vdiv_vv_w, 4)
1565 GEN_VEXT_VV(vdiv_vv_d, 8)
1566 GEN_VEXT_VV(vremu_vv_b, 1)
1567 GEN_VEXT_VV(vremu_vv_h, 2)
1568 GEN_VEXT_VV(vremu_vv_w, 4)
1569 GEN_VEXT_VV(vremu_vv_d, 8)
1570 GEN_VEXT_VV(vrem_vv_b, 1)
1571 GEN_VEXT_VV(vrem_vv_h, 2)
1572 GEN_VEXT_VV(vrem_vv_w, 4)
1573 GEN_VEXT_VV(vrem_vv_d, 8)
1575 RVVCALL(OPIVX2, vdivu_vx_b, OP_UUU_B, H1, H1, DO_DIVU)
1576 RVVCALL(OPIVX2, vdivu_vx_h, OP_UUU_H, H2, H2, DO_DIVU)
1577 RVVCALL(OPIVX2, vdivu_vx_w, OP_UUU_W, H4, H4, DO_DIVU)
1578 RVVCALL(OPIVX2, vdivu_vx_d, OP_UUU_D, H8, H8, DO_DIVU)
1579 RVVCALL(OPIVX2, vdiv_vx_b, OP_SSS_B, H1, H1, DO_DIV)
1580 RVVCALL(OPIVX2, vdiv_vx_h, OP_SSS_H, H2, H2, DO_DIV)
1581 RVVCALL(OPIVX2, vdiv_vx_w, OP_SSS_W, H4, H4, DO_DIV)
1582 RVVCALL(OPIVX2, vdiv_vx_d, OP_SSS_D, H8, H8, DO_DIV)
1583 RVVCALL(OPIVX2, vremu_vx_b, OP_UUU_B, H1, H1, DO_REMU)
1584 RVVCALL(OPIVX2, vremu_vx_h, OP_UUU_H, H2, H2, DO_REMU)
1585 RVVCALL(OPIVX2, vremu_vx_w, OP_UUU_W, H4, H4, DO_REMU)
1586 RVVCALL(OPIVX2, vremu_vx_d, OP_UUU_D, H8, H8, DO_REMU)
1587 RVVCALL(OPIVX2, vrem_vx_b, OP_SSS_B, H1, H1, DO_REM)
1588 RVVCALL(OPIVX2, vrem_vx_h, OP_SSS_H, H2, H2, DO_REM)
1589 RVVCALL(OPIVX2, vrem_vx_w, OP_SSS_W, H4, H4, DO_REM)
1590 RVVCALL(OPIVX2, vrem_vx_d, OP_SSS_D, H8, H8, DO_REM)
1591 GEN_VEXT_VX(vdivu_vx_b, 1)
1592 GEN_VEXT_VX(vdivu_vx_h, 2)
1593 GEN_VEXT_VX(vdivu_vx_w, 4)
1594 GEN_VEXT_VX(vdivu_vx_d, 8)
1595 GEN_VEXT_VX(vdiv_vx_b, 1)
1596 GEN_VEXT_VX(vdiv_vx_h, 2)
1597 GEN_VEXT_VX(vdiv_vx_w, 4)
1598 GEN_VEXT_VX(vdiv_vx_d, 8)
1599 GEN_VEXT_VX(vremu_vx_b, 1)
1600 GEN_VEXT_VX(vremu_vx_h, 2)
1601 GEN_VEXT_VX(vremu_vx_w, 4)
1602 GEN_VEXT_VX(vremu_vx_d, 8)
1603 GEN_VEXT_VX(vrem_vx_b, 1)
1604 GEN_VEXT_VX(vrem_vx_h, 2)
1605 GEN_VEXT_VX(vrem_vx_w, 4)
1606 GEN_VEXT_VX(vrem_vx_d, 8)
1608 /* Vector Widening Integer Multiply Instructions */
1609 RVVCALL(OPIVV2, vwmul_vv_b, WOP_SSS_B, H2, H1, H1, DO_MUL)
1610 RVVCALL(OPIVV2, vwmul_vv_h, WOP_SSS_H, H4, H2, H2, DO_MUL)
1611 RVVCALL(OPIVV2, vwmul_vv_w, WOP_SSS_W, H8, H4, H4, DO_MUL)
1612 RVVCALL(OPIVV2, vwmulu_vv_b, WOP_UUU_B, H2, H1, H1, DO_MUL)
1613 RVVCALL(OPIVV2, vwmulu_vv_h, WOP_UUU_H, H4, H2, H2, DO_MUL)
1614 RVVCALL(OPIVV2, vwmulu_vv_w, WOP_UUU_W, H8, H4, H4, DO_MUL)
1615 RVVCALL(OPIVV2, vwmulsu_vv_b, WOP_SUS_B, H2, H1, H1, DO_MUL)
1616 RVVCALL(OPIVV2, vwmulsu_vv_h, WOP_SUS_H, H4, H2, H2, DO_MUL)
1617 RVVCALL(OPIVV2, vwmulsu_vv_w, WOP_SUS_W, H8, H4, H4, DO_MUL)
1618 GEN_VEXT_VV(vwmul_vv_b, 2)
1619 GEN_VEXT_VV(vwmul_vv_h, 4)
1620 GEN_VEXT_VV(vwmul_vv_w, 8)
1621 GEN_VEXT_VV(vwmulu_vv_b, 2)
1622 GEN_VEXT_VV(vwmulu_vv_h, 4)
1623 GEN_VEXT_VV(vwmulu_vv_w, 8)
1624 GEN_VEXT_VV(vwmulsu_vv_b, 2)
1625 GEN_VEXT_VV(vwmulsu_vv_h, 4)
1626 GEN_VEXT_VV(vwmulsu_vv_w, 8)
1628 RVVCALL(OPIVX2, vwmul_vx_b, WOP_SSS_B, H2, H1, DO_MUL)
1629 RVVCALL(OPIVX2, vwmul_vx_h, WOP_SSS_H, H4, H2, DO_MUL)
1630 RVVCALL(OPIVX2, vwmul_vx_w, WOP_SSS_W, H8, H4, DO_MUL)
1631 RVVCALL(OPIVX2, vwmulu_vx_b, WOP_UUU_B, H2, H1, DO_MUL)
1632 RVVCALL(OPIVX2, vwmulu_vx_h, WOP_UUU_H, H4, H2, DO_MUL)
1633 RVVCALL(OPIVX2, vwmulu_vx_w, WOP_UUU_W, H8, H4, DO_MUL)
1634 RVVCALL(OPIVX2, vwmulsu_vx_b, WOP_SUS_B, H2, H1, DO_MUL)
1635 RVVCALL(OPIVX2, vwmulsu_vx_h, WOP_SUS_H, H4, H2, DO_MUL)
1636 RVVCALL(OPIVX2, vwmulsu_vx_w, WOP_SUS_W, H8, H4, DO_MUL)
1637 GEN_VEXT_VX(vwmul_vx_b, 2)
1638 GEN_VEXT_VX(vwmul_vx_h, 4)
1639 GEN_VEXT_VX(vwmul_vx_w, 8)
1640 GEN_VEXT_VX(vwmulu_vx_b, 2)
1641 GEN_VEXT_VX(vwmulu_vx_h, 4)
1642 GEN_VEXT_VX(vwmulu_vx_w, 8)
1643 GEN_VEXT_VX(vwmulsu_vx_b, 2)
1644 GEN_VEXT_VX(vwmulsu_vx_h, 4)
1645 GEN_VEXT_VX(vwmulsu_vx_w, 8)
1647 /* Vector Single-Width Integer Multiply-Add Instructions */
1648 #define OPIVV3(NAME, TD, T1, T2, TX1, TX2, HD, HS1, HS2, OP) \
1649 static void do_##NAME(void *vd, void *vs1, void *vs2, int i) \
1651 TX1 s1 = *((T1 *)vs1 + HS1(i)); \
1652 TX2 s2 = *((T2 *)vs2 + HS2(i)); \
1653 TD d = *((TD *)vd + HD(i)); \
1654 *((TD *)vd + HD(i)) = OP(s2, s1, d); \
1657 #define DO_MACC(N, M, D) (M * N + D)
1658 #define DO_NMSAC(N, M, D) (-(M * N) + D)
1659 #define DO_MADD(N, M, D) (M * D + N)
1660 #define DO_NMSUB(N, M, D) (-(M * D) + N)
1661 RVVCALL(OPIVV3, vmacc_vv_b, OP_SSS_B, H1, H1, H1, DO_MACC)
1662 RVVCALL(OPIVV3, vmacc_vv_h, OP_SSS_H, H2, H2, H2, DO_MACC)
1663 RVVCALL(OPIVV3, vmacc_vv_w, OP_SSS_W, H4, H4, H4, DO_MACC)
1664 RVVCALL(OPIVV3, vmacc_vv_d, OP_SSS_D, H8, H8, H8, DO_MACC)
1665 RVVCALL(OPIVV3, vnmsac_vv_b, OP_SSS_B, H1, H1, H1, DO_NMSAC)
1666 RVVCALL(OPIVV3, vnmsac_vv_h, OP_SSS_H, H2, H2, H2, DO_NMSAC)
1667 RVVCALL(OPIVV3, vnmsac_vv_w, OP_SSS_W, H4, H4, H4, DO_NMSAC)
1668 RVVCALL(OPIVV3, vnmsac_vv_d, OP_SSS_D, H8, H8, H8, DO_NMSAC)
1669 RVVCALL(OPIVV3, vmadd_vv_b, OP_SSS_B, H1, H1, H1, DO_MADD)
1670 RVVCALL(OPIVV3, vmadd_vv_h, OP_SSS_H, H2, H2, H2, DO_MADD)
1671 RVVCALL(OPIVV3, vmadd_vv_w, OP_SSS_W, H4, H4, H4, DO_MADD)
1672 RVVCALL(OPIVV3, vmadd_vv_d, OP_SSS_D, H8, H8, H8, DO_MADD)
1673 RVVCALL(OPIVV3, vnmsub_vv_b, OP_SSS_B, H1, H1, H1, DO_NMSUB)
1674 RVVCALL(OPIVV3, vnmsub_vv_h, OP_SSS_H, H2, H2, H2, DO_NMSUB)
1675 RVVCALL(OPIVV3, vnmsub_vv_w, OP_SSS_W, H4, H4, H4, DO_NMSUB)
1676 RVVCALL(OPIVV3, vnmsub_vv_d, OP_SSS_D, H8, H8, H8, DO_NMSUB)
1677 GEN_VEXT_VV(vmacc_vv_b, 1)
1678 GEN_VEXT_VV(vmacc_vv_h, 2)
1679 GEN_VEXT_VV(vmacc_vv_w, 4)
1680 GEN_VEXT_VV(vmacc_vv_d, 8)
1681 GEN_VEXT_VV(vnmsac_vv_b, 1)
1682 GEN_VEXT_VV(vnmsac_vv_h, 2)
1683 GEN_VEXT_VV(vnmsac_vv_w, 4)
1684 GEN_VEXT_VV(vnmsac_vv_d, 8)
1685 GEN_VEXT_VV(vmadd_vv_b, 1)
1686 GEN_VEXT_VV(vmadd_vv_h, 2)
1687 GEN_VEXT_VV(vmadd_vv_w, 4)
1688 GEN_VEXT_VV(vmadd_vv_d, 8)
1689 GEN_VEXT_VV(vnmsub_vv_b, 1)
1690 GEN_VEXT_VV(vnmsub_vv_h, 2)
1691 GEN_VEXT_VV(vnmsub_vv_w, 4)
1692 GEN_VEXT_VV(vnmsub_vv_d, 8)
1694 #define OPIVX3(NAME, TD, T1, T2, TX1, TX2, HD, HS2, OP) \
1695 static void do_##NAME(void *vd, target_long s1, void *vs2, int i) \
1697 TX2 s2 = *((T2 *)vs2 + HS2(i)); \
1698 TD d = *((TD *)vd + HD(i)); \
1699 *((TD *)vd + HD(i)) = OP(s2, (TX1)(T1)s1, d); \
1702 RVVCALL(OPIVX3, vmacc_vx_b, OP_SSS_B, H1, H1, DO_MACC)
1703 RVVCALL(OPIVX3, vmacc_vx_h, OP_SSS_H, H2, H2, DO_MACC)
1704 RVVCALL(OPIVX3, vmacc_vx_w, OP_SSS_W, H4, H4, DO_MACC)
1705 RVVCALL(OPIVX3, vmacc_vx_d, OP_SSS_D, H8, H8, DO_MACC)
1706 RVVCALL(OPIVX3, vnmsac_vx_b, OP_SSS_B, H1, H1, DO_NMSAC)
1707 RVVCALL(OPIVX3, vnmsac_vx_h, OP_SSS_H, H2, H2, DO_NMSAC)
1708 RVVCALL(OPIVX3, vnmsac_vx_w, OP_SSS_W, H4, H4, DO_NMSAC)
1709 RVVCALL(OPIVX3, vnmsac_vx_d, OP_SSS_D, H8, H8, DO_NMSAC)
1710 RVVCALL(OPIVX3, vmadd_vx_b, OP_SSS_B, H1, H1, DO_MADD)
1711 RVVCALL(OPIVX3, vmadd_vx_h, OP_SSS_H, H2, H2, DO_MADD)
1712 RVVCALL(OPIVX3, vmadd_vx_w, OP_SSS_W, H4, H4, DO_MADD)
1713 RVVCALL(OPIVX3, vmadd_vx_d, OP_SSS_D, H8, H8, DO_MADD)
1714 RVVCALL(OPIVX3, vnmsub_vx_b, OP_SSS_B, H1, H1, DO_NMSUB)
1715 RVVCALL(OPIVX3, vnmsub_vx_h, OP_SSS_H, H2, H2, DO_NMSUB)
1716 RVVCALL(OPIVX3, vnmsub_vx_w, OP_SSS_W, H4, H4, DO_NMSUB)
1717 RVVCALL(OPIVX3, vnmsub_vx_d, OP_SSS_D, H8, H8, DO_NMSUB)
1718 GEN_VEXT_VX(vmacc_vx_b, 1)
1719 GEN_VEXT_VX(vmacc_vx_h, 2)
1720 GEN_VEXT_VX(vmacc_vx_w, 4)
1721 GEN_VEXT_VX(vmacc_vx_d, 8)
1722 GEN_VEXT_VX(vnmsac_vx_b, 1)
1723 GEN_VEXT_VX(vnmsac_vx_h, 2)
1724 GEN_VEXT_VX(vnmsac_vx_w, 4)
1725 GEN_VEXT_VX(vnmsac_vx_d, 8)
1726 GEN_VEXT_VX(vmadd_vx_b, 1)
1727 GEN_VEXT_VX(vmadd_vx_h, 2)
1728 GEN_VEXT_VX(vmadd_vx_w, 4)
1729 GEN_VEXT_VX(vmadd_vx_d, 8)
1730 GEN_VEXT_VX(vnmsub_vx_b, 1)
1731 GEN_VEXT_VX(vnmsub_vx_h, 2)
1732 GEN_VEXT_VX(vnmsub_vx_w, 4)
1733 GEN_VEXT_VX(vnmsub_vx_d, 8)
1735 /* Vector Widening Integer Multiply-Add Instructions */
1736 RVVCALL(OPIVV3, vwmaccu_vv_b, WOP_UUU_B, H2, H1, H1, DO_MACC)
1737 RVVCALL(OPIVV3, vwmaccu_vv_h, WOP_UUU_H, H4, H2, H2, DO_MACC)
1738 RVVCALL(OPIVV3, vwmaccu_vv_w, WOP_UUU_W, H8, H4, H4, DO_MACC)
1739 RVVCALL(OPIVV3, vwmacc_vv_b, WOP_SSS_B, H2, H1, H1, DO_MACC)
1740 RVVCALL(OPIVV3, vwmacc_vv_h, WOP_SSS_H, H4, H2, H2, DO_MACC)
1741 RVVCALL(OPIVV3, vwmacc_vv_w, WOP_SSS_W, H8, H4, H4, DO_MACC)
1742 RVVCALL(OPIVV3, vwmaccsu_vv_b, WOP_SSU_B, H2, H1, H1, DO_MACC)
1743 RVVCALL(OPIVV3, vwmaccsu_vv_h, WOP_SSU_H, H4, H2, H2, DO_MACC)
1744 RVVCALL(OPIVV3, vwmaccsu_vv_w, WOP_SSU_W, H8, H4, H4, DO_MACC)
1745 GEN_VEXT_VV(vwmaccu_vv_b, 2)
1746 GEN_VEXT_VV(vwmaccu_vv_h, 4)
1747 GEN_VEXT_VV(vwmaccu_vv_w, 8)
1748 GEN_VEXT_VV(vwmacc_vv_b, 2)
1749 GEN_VEXT_VV(vwmacc_vv_h, 4)
1750 GEN_VEXT_VV(vwmacc_vv_w, 8)
1751 GEN_VEXT_VV(vwmaccsu_vv_b, 2)
1752 GEN_VEXT_VV(vwmaccsu_vv_h, 4)
1753 GEN_VEXT_VV(vwmaccsu_vv_w, 8)
1755 RVVCALL(OPIVX3, vwmaccu_vx_b, WOP_UUU_B, H2, H1, DO_MACC)
1756 RVVCALL(OPIVX3, vwmaccu_vx_h, WOP_UUU_H, H4, H2, DO_MACC)
1757 RVVCALL(OPIVX3, vwmaccu_vx_w, WOP_UUU_W, H8, H4, DO_MACC)
1758 RVVCALL(OPIVX3, vwmacc_vx_b, WOP_SSS_B, H2, H1, DO_MACC)
1759 RVVCALL(OPIVX3, vwmacc_vx_h, WOP_SSS_H, H4, H2, DO_MACC)
1760 RVVCALL(OPIVX3, vwmacc_vx_w, WOP_SSS_W, H8, H4, DO_MACC)
1761 RVVCALL(OPIVX3, vwmaccsu_vx_b, WOP_SSU_B, H2, H1, DO_MACC)
1762 RVVCALL(OPIVX3, vwmaccsu_vx_h, WOP_SSU_H, H4, H2, DO_MACC)
1763 RVVCALL(OPIVX3, vwmaccsu_vx_w, WOP_SSU_W, H8, H4, DO_MACC)
1764 RVVCALL(OPIVX3, vwmaccus_vx_b, WOP_SUS_B, H2, H1, DO_MACC)
1765 RVVCALL(OPIVX3, vwmaccus_vx_h, WOP_SUS_H, H4, H2, DO_MACC)
1766 RVVCALL(OPIVX3, vwmaccus_vx_w, WOP_SUS_W, H8, H4, DO_MACC)
1767 GEN_VEXT_VX(vwmaccu_vx_b, 2)
1768 GEN_VEXT_VX(vwmaccu_vx_h, 4)
1769 GEN_VEXT_VX(vwmaccu_vx_w, 8)
1770 GEN_VEXT_VX(vwmacc_vx_b, 2)
1771 GEN_VEXT_VX(vwmacc_vx_h, 4)
1772 GEN_VEXT_VX(vwmacc_vx_w, 8)
1773 GEN_VEXT_VX(vwmaccsu_vx_b, 2)
1774 GEN_VEXT_VX(vwmaccsu_vx_h, 4)
1775 GEN_VEXT_VX(vwmaccsu_vx_w, 8)
1776 GEN_VEXT_VX(vwmaccus_vx_b, 2)
1777 GEN_VEXT_VX(vwmaccus_vx_h, 4)
1778 GEN_VEXT_VX(vwmaccus_vx_w, 8)
1780 /* Vector Integer Merge and Move Instructions */
1781 #define GEN_VEXT_VMV_VV(NAME, ETYPE, H) \
1782 void HELPER(NAME)(void *vd, void *vs1, CPURISCVState *env, \
1783 uint32_t desc) \
1785 uint32_t vl = env->vl; \
1786 uint32_t esz = sizeof(ETYPE); \
1787 uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
1788 uint32_t vta = vext_vta(desc); \
1789 uint32_t i; \
1791 for (i = env->vstart; i < vl; i++) { \
1792 ETYPE s1 = *((ETYPE *)vs1 + H(i)); \
1793 *((ETYPE *)vd + H(i)) = s1; \
1795 env->vstart = 0; \
1796 /* set tail elements to 1s */ \
1797 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
1800 GEN_VEXT_VMV_VV(vmv_v_v_b, int8_t, H1)
1801 GEN_VEXT_VMV_VV(vmv_v_v_h, int16_t, H2)
1802 GEN_VEXT_VMV_VV(vmv_v_v_w, int32_t, H4)
1803 GEN_VEXT_VMV_VV(vmv_v_v_d, int64_t, H8)
1805 #define GEN_VEXT_VMV_VX(NAME, ETYPE, H) \
1806 void HELPER(NAME)(void *vd, uint64_t s1, CPURISCVState *env, \
1807 uint32_t desc) \
1809 uint32_t vl = env->vl; \
1810 uint32_t esz = sizeof(ETYPE); \
1811 uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
1812 uint32_t vta = vext_vta(desc); \
1813 uint32_t i; \
1815 for (i = env->vstart; i < vl; i++) { \
1816 *((ETYPE *)vd + H(i)) = (ETYPE)s1; \
1818 env->vstart = 0; \
1819 /* set tail elements to 1s */ \
1820 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
1823 GEN_VEXT_VMV_VX(vmv_v_x_b, int8_t, H1)
1824 GEN_VEXT_VMV_VX(vmv_v_x_h, int16_t, H2)
1825 GEN_VEXT_VMV_VX(vmv_v_x_w, int32_t, H4)
1826 GEN_VEXT_VMV_VX(vmv_v_x_d, int64_t, H8)
1828 #define GEN_VEXT_VMERGE_VV(NAME, ETYPE, H) \
1829 void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
1830 CPURISCVState *env, uint32_t desc) \
1832 uint32_t vl = env->vl; \
1833 uint32_t esz = sizeof(ETYPE); \
1834 uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
1835 uint32_t vta = vext_vta(desc); \
1836 uint32_t i; \
1838 for (i = env->vstart; i < vl; i++) { \
1839 ETYPE *vt = (!vext_elem_mask(v0, i) ? vs2 : vs1); \
1840 *((ETYPE *)vd + H(i)) = *(vt + H(i)); \
1842 env->vstart = 0; \
1843 /* set tail elements to 1s */ \
1844 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
1847 GEN_VEXT_VMERGE_VV(vmerge_vvm_b, int8_t, H1)
1848 GEN_VEXT_VMERGE_VV(vmerge_vvm_h, int16_t, H2)
1849 GEN_VEXT_VMERGE_VV(vmerge_vvm_w, int32_t, H4)
1850 GEN_VEXT_VMERGE_VV(vmerge_vvm_d, int64_t, H8)
1852 #define GEN_VEXT_VMERGE_VX(NAME, ETYPE, H) \
1853 void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \
1854 void *vs2, CPURISCVState *env, uint32_t desc) \
1856 uint32_t vl = env->vl; \
1857 uint32_t esz = sizeof(ETYPE); \
1858 uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
1859 uint32_t vta = vext_vta(desc); \
1860 uint32_t i; \
1862 for (i = env->vstart; i < vl; i++) { \
1863 ETYPE s2 = *((ETYPE *)vs2 + H(i)); \
1864 ETYPE d = (!vext_elem_mask(v0, i) ? s2 : \
1865 (ETYPE)(target_long)s1); \
1866 *((ETYPE *)vd + H(i)) = d; \
1868 env->vstart = 0; \
1869 /* set tail elements to 1s */ \
1870 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
1873 GEN_VEXT_VMERGE_VX(vmerge_vxm_b, int8_t, H1)
1874 GEN_VEXT_VMERGE_VX(vmerge_vxm_h, int16_t, H2)
1875 GEN_VEXT_VMERGE_VX(vmerge_vxm_w, int32_t, H4)
1876 GEN_VEXT_VMERGE_VX(vmerge_vxm_d, int64_t, H8)
1879 * Vector Fixed-Point Arithmetic Instructions
1882 /* Vector Single-Width Saturating Add and Subtract */
1885 * As fixed point instructions probably have round mode and saturation,
1886 * define common macros for fixed point here.
1888 typedef void opivv2_rm_fn(void *vd, void *vs1, void *vs2, int i,
1889 CPURISCVState *env, int vxrm);
1891 #define OPIVV2_RM(NAME, TD, T1, T2, TX1, TX2, HD, HS1, HS2, OP) \
1892 static inline void \
1893 do_##NAME(void *vd, void *vs1, void *vs2, int i, \
1894 CPURISCVState *env, int vxrm) \
1896 TX1 s1 = *((T1 *)vs1 + HS1(i)); \
1897 TX2 s2 = *((T2 *)vs2 + HS2(i)); \
1898 *((TD *)vd + HD(i)) = OP(env, vxrm, s2, s1); \
1901 static inline void
1902 vext_vv_rm_1(void *vd, void *v0, void *vs1, void *vs2,
1903 CPURISCVState *env,
1904 uint32_t vl, uint32_t vm, int vxrm,
1905 opivv2_rm_fn *fn, uint32_t vma, uint32_t esz)
1907 for (uint32_t i = env->vstart; i < vl; i++) {
1908 if (!vm && !vext_elem_mask(v0, i)) {
1909 /* set masked-off elements to 1s */
1910 vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz);
1911 continue;
1913 fn(vd, vs1, vs2, i, env, vxrm);
1915 env->vstart = 0;
1918 static inline void
1919 vext_vv_rm_2(void *vd, void *v0, void *vs1, void *vs2,
1920 CPURISCVState *env,
1921 uint32_t desc,
1922 opivv2_rm_fn *fn, uint32_t esz)
1924 uint32_t vm = vext_vm(desc);
1925 uint32_t vl = env->vl;
1926 uint32_t total_elems = vext_get_total_elems(env, desc, esz);
1927 uint32_t vta = vext_vta(desc);
1928 uint32_t vma = vext_vma(desc);
1930 switch (env->vxrm) {
1931 case 0: /* rnu */
1932 vext_vv_rm_1(vd, v0, vs1, vs2,
1933 env, vl, vm, 0, fn, vma, esz);
1934 break;
1935 case 1: /* rne */
1936 vext_vv_rm_1(vd, v0, vs1, vs2,
1937 env, vl, vm, 1, fn, vma, esz);
1938 break;
1939 case 2: /* rdn */
1940 vext_vv_rm_1(vd, v0, vs1, vs2,
1941 env, vl, vm, 2, fn, vma, esz);
1942 break;
1943 default: /* rod */
1944 vext_vv_rm_1(vd, v0, vs1, vs2,
1945 env, vl, vm, 3, fn, vma, esz);
1946 break;
1948 /* set tail elements to 1s */
1949 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);
1952 /* generate helpers for fixed point instructions with OPIVV format */
1953 #define GEN_VEXT_VV_RM(NAME, ESZ) \
1954 void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
1955 CPURISCVState *env, uint32_t desc) \
1957 vext_vv_rm_2(vd, v0, vs1, vs2, env, desc, \
1958 do_##NAME, ESZ); \
1961 static inline uint8_t saddu8(CPURISCVState *env, int vxrm, uint8_t a,
1962 uint8_t b)
1964 uint8_t res = a + b;
1965 if (res < a) {
1966 res = UINT8_MAX;
1967 env->vxsat = 0x1;
1969 return res;
1972 static inline uint16_t saddu16(CPURISCVState *env, int vxrm, uint16_t a,
1973 uint16_t b)
1975 uint16_t res = a + b;
1976 if (res < a) {
1977 res = UINT16_MAX;
1978 env->vxsat = 0x1;
1980 return res;
1983 static inline uint32_t saddu32(CPURISCVState *env, int vxrm, uint32_t a,
1984 uint32_t b)
1986 uint32_t res = a + b;
1987 if (res < a) {
1988 res = UINT32_MAX;
1989 env->vxsat = 0x1;
1991 return res;
1994 static inline uint64_t saddu64(CPURISCVState *env, int vxrm, uint64_t a,
1995 uint64_t b)
1997 uint64_t res = a + b;
1998 if (res < a) {
1999 res = UINT64_MAX;
2000 env->vxsat = 0x1;
2002 return res;
2005 RVVCALL(OPIVV2_RM, vsaddu_vv_b, OP_UUU_B, H1, H1, H1, saddu8)
2006 RVVCALL(OPIVV2_RM, vsaddu_vv_h, OP_UUU_H, H2, H2, H2, saddu16)
2007 RVVCALL(OPIVV2_RM, vsaddu_vv_w, OP_UUU_W, H4, H4, H4, saddu32)
2008 RVVCALL(OPIVV2_RM, vsaddu_vv_d, OP_UUU_D, H8, H8, H8, saddu64)
2009 GEN_VEXT_VV_RM(vsaddu_vv_b, 1)
2010 GEN_VEXT_VV_RM(vsaddu_vv_h, 2)
2011 GEN_VEXT_VV_RM(vsaddu_vv_w, 4)
2012 GEN_VEXT_VV_RM(vsaddu_vv_d, 8)
2014 typedef void opivx2_rm_fn(void *vd, target_long s1, void *vs2, int i,
2015 CPURISCVState *env, int vxrm);
2017 #define OPIVX2_RM(NAME, TD, T1, T2, TX1, TX2, HD, HS2, OP) \
2018 static inline void \
2019 do_##NAME(void *vd, target_long s1, void *vs2, int i, \
2020 CPURISCVState *env, int vxrm) \
2022 TX2 s2 = *((T2 *)vs2 + HS2(i)); \
2023 *((TD *)vd + HD(i)) = OP(env, vxrm, s2, (TX1)(T1)s1); \
2026 static inline void
2027 vext_vx_rm_1(void *vd, void *v0, target_long s1, void *vs2,
2028 CPURISCVState *env,
2029 uint32_t vl, uint32_t vm, int vxrm,
2030 opivx2_rm_fn *fn, uint32_t vma, uint32_t esz)
2032 for (uint32_t i = env->vstart; i < vl; i++) {
2033 if (!vm && !vext_elem_mask(v0, i)) {
2034 /* set masked-off elements to 1s */
2035 vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz);
2036 continue;
2038 fn(vd, s1, vs2, i, env, vxrm);
2040 env->vstart = 0;
2043 static inline void
2044 vext_vx_rm_2(void *vd, void *v0, target_long s1, void *vs2,
2045 CPURISCVState *env,
2046 uint32_t desc,
2047 opivx2_rm_fn *fn, uint32_t esz)
2049 uint32_t vm = vext_vm(desc);
2050 uint32_t vl = env->vl;
2051 uint32_t total_elems = vext_get_total_elems(env, desc, esz);
2052 uint32_t vta = vext_vta(desc);
2053 uint32_t vma = vext_vma(desc);
2055 switch (env->vxrm) {
2056 case 0: /* rnu */
2057 vext_vx_rm_1(vd, v0, s1, vs2,
2058 env, vl, vm, 0, fn, vma, esz);
2059 break;
2060 case 1: /* rne */
2061 vext_vx_rm_1(vd, v0, s1, vs2,
2062 env, vl, vm, 1, fn, vma, esz);
2063 break;
2064 case 2: /* rdn */
2065 vext_vx_rm_1(vd, v0, s1, vs2,
2066 env, vl, vm, 2, fn, vma, esz);
2067 break;
2068 default: /* rod */
2069 vext_vx_rm_1(vd, v0, s1, vs2,
2070 env, vl, vm, 3, fn, vma, esz);
2071 break;
2073 /* set tail elements to 1s */
2074 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);
2077 /* generate helpers for fixed point instructions with OPIVX format */
2078 #define GEN_VEXT_VX_RM(NAME, ESZ) \
2079 void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \
2080 void *vs2, CPURISCVState *env, \
2081 uint32_t desc) \
2083 vext_vx_rm_2(vd, v0, s1, vs2, env, desc, \
2084 do_##NAME, ESZ); \
2087 RVVCALL(OPIVX2_RM, vsaddu_vx_b, OP_UUU_B, H1, H1, saddu8)
2088 RVVCALL(OPIVX2_RM, vsaddu_vx_h, OP_UUU_H, H2, H2, saddu16)
2089 RVVCALL(OPIVX2_RM, vsaddu_vx_w, OP_UUU_W, H4, H4, saddu32)
2090 RVVCALL(OPIVX2_RM, vsaddu_vx_d, OP_UUU_D, H8, H8, saddu64)
2091 GEN_VEXT_VX_RM(vsaddu_vx_b, 1)
2092 GEN_VEXT_VX_RM(vsaddu_vx_h, 2)
2093 GEN_VEXT_VX_RM(vsaddu_vx_w, 4)
2094 GEN_VEXT_VX_RM(vsaddu_vx_d, 8)
2096 static inline int8_t sadd8(CPURISCVState *env, int vxrm, int8_t a, int8_t b)
2098 int8_t res = a + b;
2099 if ((res ^ a) & (res ^ b) & INT8_MIN) {
2100 res = a > 0 ? INT8_MAX : INT8_MIN;
2101 env->vxsat = 0x1;
2103 return res;
2106 static inline int16_t sadd16(CPURISCVState *env, int vxrm, int16_t a,
2107 int16_t b)
2109 int16_t res = a + b;
2110 if ((res ^ a) & (res ^ b) & INT16_MIN) {
2111 res = a > 0 ? INT16_MAX : INT16_MIN;
2112 env->vxsat = 0x1;
2114 return res;
2117 static inline int32_t sadd32(CPURISCVState *env, int vxrm, int32_t a,
2118 int32_t b)
2120 int32_t res = a + b;
2121 if ((res ^ a) & (res ^ b) & INT32_MIN) {
2122 res = a > 0 ? INT32_MAX : INT32_MIN;
2123 env->vxsat = 0x1;
2125 return res;
2128 static inline int64_t sadd64(CPURISCVState *env, int vxrm, int64_t a,
2129 int64_t b)
2131 int64_t res = a + b;
2132 if ((res ^ a) & (res ^ b) & INT64_MIN) {
2133 res = a > 0 ? INT64_MAX : INT64_MIN;
2134 env->vxsat = 0x1;
2136 return res;
2139 RVVCALL(OPIVV2_RM, vsadd_vv_b, OP_SSS_B, H1, H1, H1, sadd8)
2140 RVVCALL(OPIVV2_RM, vsadd_vv_h, OP_SSS_H, H2, H2, H2, sadd16)
2141 RVVCALL(OPIVV2_RM, vsadd_vv_w, OP_SSS_W, H4, H4, H4, sadd32)
2142 RVVCALL(OPIVV2_RM, vsadd_vv_d, OP_SSS_D, H8, H8, H8, sadd64)
2143 GEN_VEXT_VV_RM(vsadd_vv_b, 1)
2144 GEN_VEXT_VV_RM(vsadd_vv_h, 2)
2145 GEN_VEXT_VV_RM(vsadd_vv_w, 4)
2146 GEN_VEXT_VV_RM(vsadd_vv_d, 8)
2148 RVVCALL(OPIVX2_RM, vsadd_vx_b, OP_SSS_B, H1, H1, sadd8)
2149 RVVCALL(OPIVX2_RM, vsadd_vx_h, OP_SSS_H, H2, H2, sadd16)
2150 RVVCALL(OPIVX2_RM, vsadd_vx_w, OP_SSS_W, H4, H4, sadd32)
2151 RVVCALL(OPIVX2_RM, vsadd_vx_d, OP_SSS_D, H8, H8, sadd64)
2152 GEN_VEXT_VX_RM(vsadd_vx_b, 1)
2153 GEN_VEXT_VX_RM(vsadd_vx_h, 2)
2154 GEN_VEXT_VX_RM(vsadd_vx_w, 4)
2155 GEN_VEXT_VX_RM(vsadd_vx_d, 8)
2157 static inline uint8_t ssubu8(CPURISCVState *env, int vxrm, uint8_t a,
2158 uint8_t b)
2160 uint8_t res = a - b;
2161 if (res > a) {
2162 res = 0;
2163 env->vxsat = 0x1;
2165 return res;
2168 static inline uint16_t ssubu16(CPURISCVState *env, int vxrm, uint16_t a,
2169 uint16_t b)
2171 uint16_t res = a - b;
2172 if (res > a) {
2173 res = 0;
2174 env->vxsat = 0x1;
2176 return res;
2179 static inline uint32_t ssubu32(CPURISCVState *env, int vxrm, uint32_t a,
2180 uint32_t b)
2182 uint32_t res = a - b;
2183 if (res > a) {
2184 res = 0;
2185 env->vxsat = 0x1;
2187 return res;
2190 static inline uint64_t ssubu64(CPURISCVState *env, int vxrm, uint64_t a,
2191 uint64_t b)
2193 uint64_t res = a - b;
2194 if (res > a) {
2195 res = 0;
2196 env->vxsat = 0x1;
2198 return res;
2201 RVVCALL(OPIVV2_RM, vssubu_vv_b, OP_UUU_B, H1, H1, H1, ssubu8)
2202 RVVCALL(OPIVV2_RM, vssubu_vv_h, OP_UUU_H, H2, H2, H2, ssubu16)
2203 RVVCALL(OPIVV2_RM, vssubu_vv_w, OP_UUU_W, H4, H4, H4, ssubu32)
2204 RVVCALL(OPIVV2_RM, vssubu_vv_d, OP_UUU_D, H8, H8, H8, ssubu64)
2205 GEN_VEXT_VV_RM(vssubu_vv_b, 1)
2206 GEN_VEXT_VV_RM(vssubu_vv_h, 2)
2207 GEN_VEXT_VV_RM(vssubu_vv_w, 4)
2208 GEN_VEXT_VV_RM(vssubu_vv_d, 8)
2210 RVVCALL(OPIVX2_RM, vssubu_vx_b, OP_UUU_B, H1, H1, ssubu8)
2211 RVVCALL(OPIVX2_RM, vssubu_vx_h, OP_UUU_H, H2, H2, ssubu16)
2212 RVVCALL(OPIVX2_RM, vssubu_vx_w, OP_UUU_W, H4, H4, ssubu32)
2213 RVVCALL(OPIVX2_RM, vssubu_vx_d, OP_UUU_D, H8, H8, ssubu64)
2214 GEN_VEXT_VX_RM(vssubu_vx_b, 1)
2215 GEN_VEXT_VX_RM(vssubu_vx_h, 2)
2216 GEN_VEXT_VX_RM(vssubu_vx_w, 4)
2217 GEN_VEXT_VX_RM(vssubu_vx_d, 8)
2219 static inline int8_t ssub8(CPURISCVState *env, int vxrm, int8_t a, int8_t b)
2221 int8_t res = a - b;
2222 if ((res ^ a) & (a ^ b) & INT8_MIN) {
2223 res = a >= 0 ? INT8_MAX : INT8_MIN;
2224 env->vxsat = 0x1;
2226 return res;
2229 static inline int16_t ssub16(CPURISCVState *env, int vxrm, int16_t a,
2230 int16_t b)
2232 int16_t res = a - b;
2233 if ((res ^ a) & (a ^ b) & INT16_MIN) {
2234 res = a >= 0 ? INT16_MAX : INT16_MIN;
2235 env->vxsat = 0x1;
2237 return res;
2240 static inline int32_t ssub32(CPURISCVState *env, int vxrm, int32_t a,
2241 int32_t b)
2243 int32_t res = a - b;
2244 if ((res ^ a) & (a ^ b) & INT32_MIN) {
2245 res = a >= 0 ? INT32_MAX : INT32_MIN;
2246 env->vxsat = 0x1;
2248 return res;
2251 static inline int64_t ssub64(CPURISCVState *env, int vxrm, int64_t a,
2252 int64_t b)
2254 int64_t res = a - b;
2255 if ((res ^ a) & (a ^ b) & INT64_MIN) {
2256 res = a >= 0 ? INT64_MAX : INT64_MIN;
2257 env->vxsat = 0x1;
2259 return res;
2262 RVVCALL(OPIVV2_RM, vssub_vv_b, OP_SSS_B, H1, H1, H1, ssub8)
2263 RVVCALL(OPIVV2_RM, vssub_vv_h, OP_SSS_H, H2, H2, H2, ssub16)
2264 RVVCALL(OPIVV2_RM, vssub_vv_w, OP_SSS_W, H4, H4, H4, ssub32)
2265 RVVCALL(OPIVV2_RM, vssub_vv_d, OP_SSS_D, H8, H8, H8, ssub64)
2266 GEN_VEXT_VV_RM(vssub_vv_b, 1)
2267 GEN_VEXT_VV_RM(vssub_vv_h, 2)
2268 GEN_VEXT_VV_RM(vssub_vv_w, 4)
2269 GEN_VEXT_VV_RM(vssub_vv_d, 8)
2271 RVVCALL(OPIVX2_RM, vssub_vx_b, OP_SSS_B, H1, H1, ssub8)
2272 RVVCALL(OPIVX2_RM, vssub_vx_h, OP_SSS_H, H2, H2, ssub16)
2273 RVVCALL(OPIVX2_RM, vssub_vx_w, OP_SSS_W, H4, H4, ssub32)
2274 RVVCALL(OPIVX2_RM, vssub_vx_d, OP_SSS_D, H8, H8, ssub64)
2275 GEN_VEXT_VX_RM(vssub_vx_b, 1)
2276 GEN_VEXT_VX_RM(vssub_vx_h, 2)
2277 GEN_VEXT_VX_RM(vssub_vx_w, 4)
2278 GEN_VEXT_VX_RM(vssub_vx_d, 8)
2280 /* Vector Single-Width Averaging Add and Subtract */
2281 static inline uint8_t get_round(int vxrm, uint64_t v, uint8_t shift)
2283 uint8_t d = extract64(v, shift, 1);
2284 uint8_t d1;
2285 uint64_t D1, D2;
2287 if (shift == 0 || shift > 64) {
2288 return 0;
2291 d1 = extract64(v, shift - 1, 1);
2292 D1 = extract64(v, 0, shift);
2293 if (vxrm == 0) { /* round-to-nearest-up (add +0.5 LSB) */
2294 return d1;
2295 } else if (vxrm == 1) { /* round-to-nearest-even */
2296 if (shift > 1) {
2297 D2 = extract64(v, 0, shift - 1);
2298 return d1 & ((D2 != 0) | d);
2299 } else {
2300 return d1 & d;
2302 } else if (vxrm == 3) { /* round-to-odd (OR bits into LSB, aka "jam") */
2303 return !d & (D1 != 0);
2305 return 0; /* round-down (truncate) */
2308 static inline int32_t aadd32(CPURISCVState *env, int vxrm, int32_t a,
2309 int32_t b)
2311 int64_t res = (int64_t)a + b;
2312 uint8_t round = get_round(vxrm, res, 1);
2314 return (res >> 1) + round;
2317 static inline int64_t aadd64(CPURISCVState *env, int vxrm, int64_t a,
2318 int64_t b)
2320 int64_t res = a + b;
2321 uint8_t round = get_round(vxrm, res, 1);
2322 int64_t over = (res ^ a) & (res ^ b) & INT64_MIN;
2324 /* With signed overflow, bit 64 is inverse of bit 63. */
2325 return ((res >> 1) ^ over) + round;
2328 RVVCALL(OPIVV2_RM, vaadd_vv_b, OP_SSS_B, H1, H1, H1, aadd32)
2329 RVVCALL(OPIVV2_RM, vaadd_vv_h, OP_SSS_H, H2, H2, H2, aadd32)
2330 RVVCALL(OPIVV2_RM, vaadd_vv_w, OP_SSS_W, H4, H4, H4, aadd32)
2331 RVVCALL(OPIVV2_RM, vaadd_vv_d, OP_SSS_D, H8, H8, H8, aadd64)
2332 GEN_VEXT_VV_RM(vaadd_vv_b, 1)
2333 GEN_VEXT_VV_RM(vaadd_vv_h, 2)
2334 GEN_VEXT_VV_RM(vaadd_vv_w, 4)
2335 GEN_VEXT_VV_RM(vaadd_vv_d, 8)
2337 RVVCALL(OPIVX2_RM, vaadd_vx_b, OP_SSS_B, H1, H1, aadd32)
2338 RVVCALL(OPIVX2_RM, vaadd_vx_h, OP_SSS_H, H2, H2, aadd32)
2339 RVVCALL(OPIVX2_RM, vaadd_vx_w, OP_SSS_W, H4, H4, aadd32)
2340 RVVCALL(OPIVX2_RM, vaadd_vx_d, OP_SSS_D, H8, H8, aadd64)
2341 GEN_VEXT_VX_RM(vaadd_vx_b, 1)
2342 GEN_VEXT_VX_RM(vaadd_vx_h, 2)
2343 GEN_VEXT_VX_RM(vaadd_vx_w, 4)
2344 GEN_VEXT_VX_RM(vaadd_vx_d, 8)
2346 static inline uint32_t aaddu32(CPURISCVState *env, int vxrm,
2347 uint32_t a, uint32_t b)
2349 uint64_t res = (uint64_t)a + b;
2350 uint8_t round = get_round(vxrm, res, 1);
2352 return (res >> 1) + round;
2355 static inline uint64_t aaddu64(CPURISCVState *env, int vxrm,
2356 uint64_t a, uint64_t b)
2358 uint64_t res = a + b;
2359 uint8_t round = get_round(vxrm, res, 1);
2360 uint64_t over = (uint64_t)(res < a) << 63;
2362 return ((res >> 1) | over) + round;
2365 RVVCALL(OPIVV2_RM, vaaddu_vv_b, OP_UUU_B, H1, H1, H1, aaddu32)
2366 RVVCALL(OPIVV2_RM, vaaddu_vv_h, OP_UUU_H, H2, H2, H2, aaddu32)
2367 RVVCALL(OPIVV2_RM, vaaddu_vv_w, OP_UUU_W, H4, H4, H4, aaddu32)
2368 RVVCALL(OPIVV2_RM, vaaddu_vv_d, OP_UUU_D, H8, H8, H8, aaddu64)
2369 GEN_VEXT_VV_RM(vaaddu_vv_b, 1)
2370 GEN_VEXT_VV_RM(vaaddu_vv_h, 2)
2371 GEN_VEXT_VV_RM(vaaddu_vv_w, 4)
2372 GEN_VEXT_VV_RM(vaaddu_vv_d, 8)
2374 RVVCALL(OPIVX2_RM, vaaddu_vx_b, OP_UUU_B, H1, H1, aaddu32)
2375 RVVCALL(OPIVX2_RM, vaaddu_vx_h, OP_UUU_H, H2, H2, aaddu32)
2376 RVVCALL(OPIVX2_RM, vaaddu_vx_w, OP_UUU_W, H4, H4, aaddu32)
2377 RVVCALL(OPIVX2_RM, vaaddu_vx_d, OP_UUU_D, H8, H8, aaddu64)
2378 GEN_VEXT_VX_RM(vaaddu_vx_b, 1)
2379 GEN_VEXT_VX_RM(vaaddu_vx_h, 2)
2380 GEN_VEXT_VX_RM(vaaddu_vx_w, 4)
2381 GEN_VEXT_VX_RM(vaaddu_vx_d, 8)
2383 static inline int32_t asub32(CPURISCVState *env, int vxrm, int32_t a,
2384 int32_t b)
2386 int64_t res = (int64_t)a - b;
2387 uint8_t round = get_round(vxrm, res, 1);
2389 return (res >> 1) + round;
2392 static inline int64_t asub64(CPURISCVState *env, int vxrm, int64_t a,
2393 int64_t b)
2395 int64_t res = (int64_t)a - b;
2396 uint8_t round = get_round(vxrm, res, 1);
2397 int64_t over = (res ^ a) & (a ^ b) & INT64_MIN;
2399 /* With signed overflow, bit 64 is inverse of bit 63. */
2400 return ((res >> 1) ^ over) + round;
2403 RVVCALL(OPIVV2_RM, vasub_vv_b, OP_SSS_B, H1, H1, H1, asub32)
2404 RVVCALL(OPIVV2_RM, vasub_vv_h, OP_SSS_H, H2, H2, H2, asub32)
2405 RVVCALL(OPIVV2_RM, vasub_vv_w, OP_SSS_W, H4, H4, H4, asub32)
2406 RVVCALL(OPIVV2_RM, vasub_vv_d, OP_SSS_D, H8, H8, H8, asub64)
2407 GEN_VEXT_VV_RM(vasub_vv_b, 1)
2408 GEN_VEXT_VV_RM(vasub_vv_h, 2)
2409 GEN_VEXT_VV_RM(vasub_vv_w, 4)
2410 GEN_VEXT_VV_RM(vasub_vv_d, 8)
2412 RVVCALL(OPIVX2_RM, vasub_vx_b, OP_SSS_B, H1, H1, asub32)
2413 RVVCALL(OPIVX2_RM, vasub_vx_h, OP_SSS_H, H2, H2, asub32)
2414 RVVCALL(OPIVX2_RM, vasub_vx_w, OP_SSS_W, H4, H4, asub32)
2415 RVVCALL(OPIVX2_RM, vasub_vx_d, OP_SSS_D, H8, H8, asub64)
2416 GEN_VEXT_VX_RM(vasub_vx_b, 1)
2417 GEN_VEXT_VX_RM(vasub_vx_h, 2)
2418 GEN_VEXT_VX_RM(vasub_vx_w, 4)
2419 GEN_VEXT_VX_RM(vasub_vx_d, 8)
2421 static inline uint32_t asubu32(CPURISCVState *env, int vxrm,
2422 uint32_t a, uint32_t b)
2424 int64_t res = (int64_t)a - b;
2425 uint8_t round = get_round(vxrm, res, 1);
2427 return (res >> 1) + round;
2430 static inline uint64_t asubu64(CPURISCVState *env, int vxrm,
2431 uint64_t a, uint64_t b)
2433 uint64_t res = (uint64_t)a - b;
2434 uint8_t round = get_round(vxrm, res, 1);
2435 uint64_t over = (uint64_t)(res > a) << 63;
2437 return ((res >> 1) | over) + round;
2440 RVVCALL(OPIVV2_RM, vasubu_vv_b, OP_UUU_B, H1, H1, H1, asubu32)
2441 RVVCALL(OPIVV2_RM, vasubu_vv_h, OP_UUU_H, H2, H2, H2, asubu32)
2442 RVVCALL(OPIVV2_RM, vasubu_vv_w, OP_UUU_W, H4, H4, H4, asubu32)
2443 RVVCALL(OPIVV2_RM, vasubu_vv_d, OP_UUU_D, H8, H8, H8, asubu64)
2444 GEN_VEXT_VV_RM(vasubu_vv_b, 1)
2445 GEN_VEXT_VV_RM(vasubu_vv_h, 2)
2446 GEN_VEXT_VV_RM(vasubu_vv_w, 4)
2447 GEN_VEXT_VV_RM(vasubu_vv_d, 8)
2449 RVVCALL(OPIVX2_RM, vasubu_vx_b, OP_UUU_B, H1, H1, asubu32)
2450 RVVCALL(OPIVX2_RM, vasubu_vx_h, OP_UUU_H, H2, H2, asubu32)
2451 RVVCALL(OPIVX2_RM, vasubu_vx_w, OP_UUU_W, H4, H4, asubu32)
2452 RVVCALL(OPIVX2_RM, vasubu_vx_d, OP_UUU_D, H8, H8, asubu64)
2453 GEN_VEXT_VX_RM(vasubu_vx_b, 1)
2454 GEN_VEXT_VX_RM(vasubu_vx_h, 2)
2455 GEN_VEXT_VX_RM(vasubu_vx_w, 4)
2456 GEN_VEXT_VX_RM(vasubu_vx_d, 8)
2458 /* Vector Single-Width Fractional Multiply with Rounding and Saturation */
2459 static inline int8_t vsmul8(CPURISCVState *env, int vxrm, int8_t a, int8_t b)
2461 uint8_t round;
2462 int16_t res;
2464 res = (int16_t)a * (int16_t)b;
2465 round = get_round(vxrm, res, 7);
2466 res = (res >> 7) + round;
2468 if (res > INT8_MAX) {
2469 env->vxsat = 0x1;
2470 return INT8_MAX;
2471 } else if (res < INT8_MIN) {
2472 env->vxsat = 0x1;
2473 return INT8_MIN;
2474 } else {
2475 return res;
2479 static int16_t vsmul16(CPURISCVState *env, int vxrm, int16_t a, int16_t b)
2481 uint8_t round;
2482 int32_t res;
2484 res = (int32_t)a * (int32_t)b;
2485 round = get_round(vxrm, res, 15);
2486 res = (res >> 15) + round;
2488 if (res > INT16_MAX) {
2489 env->vxsat = 0x1;
2490 return INT16_MAX;
2491 } else if (res < INT16_MIN) {
2492 env->vxsat = 0x1;
2493 return INT16_MIN;
2494 } else {
2495 return res;
2499 static int32_t vsmul32(CPURISCVState *env, int vxrm, int32_t a, int32_t b)
2501 uint8_t round;
2502 int64_t res;
2504 res = (int64_t)a * (int64_t)b;
2505 round = get_round(vxrm, res, 31);
2506 res = (res >> 31) + round;
2508 if (res > INT32_MAX) {
2509 env->vxsat = 0x1;
2510 return INT32_MAX;
2511 } else if (res < INT32_MIN) {
2512 env->vxsat = 0x1;
2513 return INT32_MIN;
2514 } else {
2515 return res;
2519 static int64_t vsmul64(CPURISCVState *env, int vxrm, int64_t a, int64_t b)
2521 uint8_t round;
2522 uint64_t hi_64, lo_64;
2523 int64_t res;
2525 if (a == INT64_MIN && b == INT64_MIN) {
2526 env->vxsat = 1;
2527 return INT64_MAX;
2530 muls64(&lo_64, &hi_64, a, b);
2531 round = get_round(vxrm, lo_64, 63);
2533 * Cannot overflow, as there are always
2534 * 2 sign bits after multiply.
2536 res = (hi_64 << 1) | (lo_64 >> 63);
2537 if (round) {
2538 if (res == INT64_MAX) {
2539 env->vxsat = 1;
2540 } else {
2541 res += 1;
2544 return res;
2547 RVVCALL(OPIVV2_RM, vsmul_vv_b, OP_SSS_B, H1, H1, H1, vsmul8)
2548 RVVCALL(OPIVV2_RM, vsmul_vv_h, OP_SSS_H, H2, H2, H2, vsmul16)
2549 RVVCALL(OPIVV2_RM, vsmul_vv_w, OP_SSS_W, H4, H4, H4, vsmul32)
2550 RVVCALL(OPIVV2_RM, vsmul_vv_d, OP_SSS_D, H8, H8, H8, vsmul64)
2551 GEN_VEXT_VV_RM(vsmul_vv_b, 1)
2552 GEN_VEXT_VV_RM(vsmul_vv_h, 2)
2553 GEN_VEXT_VV_RM(vsmul_vv_w, 4)
2554 GEN_VEXT_VV_RM(vsmul_vv_d, 8)
2556 RVVCALL(OPIVX2_RM, vsmul_vx_b, OP_SSS_B, H1, H1, vsmul8)
2557 RVVCALL(OPIVX2_RM, vsmul_vx_h, OP_SSS_H, H2, H2, vsmul16)
2558 RVVCALL(OPIVX2_RM, vsmul_vx_w, OP_SSS_W, H4, H4, vsmul32)
2559 RVVCALL(OPIVX2_RM, vsmul_vx_d, OP_SSS_D, H8, H8, vsmul64)
2560 GEN_VEXT_VX_RM(vsmul_vx_b, 1)
2561 GEN_VEXT_VX_RM(vsmul_vx_h, 2)
2562 GEN_VEXT_VX_RM(vsmul_vx_w, 4)
2563 GEN_VEXT_VX_RM(vsmul_vx_d, 8)
2565 /* Vector Single-Width Scaling Shift Instructions */
2566 static inline uint8_t
2567 vssrl8(CPURISCVState *env, int vxrm, uint8_t a, uint8_t b)
2569 uint8_t round, shift = b & 0x7;
2570 uint8_t res;
2572 round = get_round(vxrm, a, shift);
2573 res = (a >> shift) + round;
2574 return res;
2576 static inline uint16_t
2577 vssrl16(CPURISCVState *env, int vxrm, uint16_t a, uint16_t b)
2579 uint8_t round, shift = b & 0xf;
2581 round = get_round(vxrm, a, shift);
2582 return (a >> shift) + round;
2584 static inline uint32_t
2585 vssrl32(CPURISCVState *env, int vxrm, uint32_t a, uint32_t b)
2587 uint8_t round, shift = b & 0x1f;
2589 round = get_round(vxrm, a, shift);
2590 return (a >> shift) + round;
2592 static inline uint64_t
2593 vssrl64(CPURISCVState *env, int vxrm, uint64_t a, uint64_t b)
2595 uint8_t round, shift = b & 0x3f;
2597 round = get_round(vxrm, a, shift);
2598 return (a >> shift) + round;
2600 RVVCALL(OPIVV2_RM, vssrl_vv_b, OP_UUU_B, H1, H1, H1, vssrl8)
2601 RVVCALL(OPIVV2_RM, vssrl_vv_h, OP_UUU_H, H2, H2, H2, vssrl16)
2602 RVVCALL(OPIVV2_RM, vssrl_vv_w, OP_UUU_W, H4, H4, H4, vssrl32)
2603 RVVCALL(OPIVV2_RM, vssrl_vv_d, OP_UUU_D, H8, H8, H8, vssrl64)
2604 GEN_VEXT_VV_RM(vssrl_vv_b, 1)
2605 GEN_VEXT_VV_RM(vssrl_vv_h, 2)
2606 GEN_VEXT_VV_RM(vssrl_vv_w, 4)
2607 GEN_VEXT_VV_RM(vssrl_vv_d, 8)
2609 RVVCALL(OPIVX2_RM, vssrl_vx_b, OP_UUU_B, H1, H1, vssrl8)
2610 RVVCALL(OPIVX2_RM, vssrl_vx_h, OP_UUU_H, H2, H2, vssrl16)
2611 RVVCALL(OPIVX2_RM, vssrl_vx_w, OP_UUU_W, H4, H4, vssrl32)
2612 RVVCALL(OPIVX2_RM, vssrl_vx_d, OP_UUU_D, H8, H8, vssrl64)
2613 GEN_VEXT_VX_RM(vssrl_vx_b, 1)
2614 GEN_VEXT_VX_RM(vssrl_vx_h, 2)
2615 GEN_VEXT_VX_RM(vssrl_vx_w, 4)
2616 GEN_VEXT_VX_RM(vssrl_vx_d, 8)
2618 static inline int8_t
2619 vssra8(CPURISCVState *env, int vxrm, int8_t a, int8_t b)
2621 uint8_t round, shift = b & 0x7;
2623 round = get_round(vxrm, a, shift);
2624 return (a >> shift) + round;
2626 static inline int16_t
2627 vssra16(CPURISCVState *env, int vxrm, int16_t a, int16_t b)
2629 uint8_t round, shift = b & 0xf;
2631 round = get_round(vxrm, a, shift);
2632 return (a >> shift) + round;
2634 static inline int32_t
2635 vssra32(CPURISCVState *env, int vxrm, int32_t a, int32_t b)
2637 uint8_t round, shift = b & 0x1f;
2639 round = get_round(vxrm, a, shift);
2640 return (a >> shift) + round;
2642 static inline int64_t
2643 vssra64(CPURISCVState *env, int vxrm, int64_t a, int64_t b)
2645 uint8_t round, shift = b & 0x3f;
2647 round = get_round(vxrm, a, shift);
2648 return (a >> shift) + round;
2651 RVVCALL(OPIVV2_RM, vssra_vv_b, OP_SSS_B, H1, H1, H1, vssra8)
2652 RVVCALL(OPIVV2_RM, vssra_vv_h, OP_SSS_H, H2, H2, H2, vssra16)
2653 RVVCALL(OPIVV2_RM, vssra_vv_w, OP_SSS_W, H4, H4, H4, vssra32)
2654 RVVCALL(OPIVV2_RM, vssra_vv_d, OP_SSS_D, H8, H8, H8, vssra64)
2655 GEN_VEXT_VV_RM(vssra_vv_b, 1)
2656 GEN_VEXT_VV_RM(vssra_vv_h, 2)
2657 GEN_VEXT_VV_RM(vssra_vv_w, 4)
2658 GEN_VEXT_VV_RM(vssra_vv_d, 8)
2660 RVVCALL(OPIVX2_RM, vssra_vx_b, OP_SSS_B, H1, H1, vssra8)
2661 RVVCALL(OPIVX2_RM, vssra_vx_h, OP_SSS_H, H2, H2, vssra16)
2662 RVVCALL(OPIVX2_RM, vssra_vx_w, OP_SSS_W, H4, H4, vssra32)
2663 RVVCALL(OPIVX2_RM, vssra_vx_d, OP_SSS_D, H8, H8, vssra64)
2664 GEN_VEXT_VX_RM(vssra_vx_b, 1)
2665 GEN_VEXT_VX_RM(vssra_vx_h, 2)
2666 GEN_VEXT_VX_RM(vssra_vx_w, 4)
2667 GEN_VEXT_VX_RM(vssra_vx_d, 8)
2669 /* Vector Narrowing Fixed-Point Clip Instructions */
2670 static inline int8_t
2671 vnclip8(CPURISCVState *env, int vxrm, int16_t a, int8_t b)
2673 uint8_t round, shift = b & 0xf;
2674 int16_t res;
2676 round = get_round(vxrm, a, shift);
2677 res = (a >> shift) + round;
2678 if (res > INT8_MAX) {
2679 env->vxsat = 0x1;
2680 return INT8_MAX;
2681 } else if (res < INT8_MIN) {
2682 env->vxsat = 0x1;
2683 return INT8_MIN;
2684 } else {
2685 return res;
2689 static inline int16_t
2690 vnclip16(CPURISCVState *env, int vxrm, int32_t a, int16_t b)
2692 uint8_t round, shift = b & 0x1f;
2693 int32_t res;
2695 round = get_round(vxrm, a, shift);
2696 res = (a >> shift) + round;
2697 if (res > INT16_MAX) {
2698 env->vxsat = 0x1;
2699 return INT16_MAX;
2700 } else if (res < INT16_MIN) {
2701 env->vxsat = 0x1;
2702 return INT16_MIN;
2703 } else {
2704 return res;
2708 static inline int32_t
2709 vnclip32(CPURISCVState *env, int vxrm, int64_t a, int32_t b)
2711 uint8_t round, shift = b & 0x3f;
2712 int64_t res;
2714 round = get_round(vxrm, a, shift);
2715 res = (a >> shift) + round;
2716 if (res > INT32_MAX) {
2717 env->vxsat = 0x1;
2718 return INT32_MAX;
2719 } else if (res < INT32_MIN) {
2720 env->vxsat = 0x1;
2721 return INT32_MIN;
2722 } else {
2723 return res;
2727 RVVCALL(OPIVV2_RM, vnclip_wv_b, NOP_SSS_B, H1, H2, H1, vnclip8)
2728 RVVCALL(OPIVV2_RM, vnclip_wv_h, NOP_SSS_H, H2, H4, H2, vnclip16)
2729 RVVCALL(OPIVV2_RM, vnclip_wv_w, NOP_SSS_W, H4, H8, H4, vnclip32)
2730 GEN_VEXT_VV_RM(vnclip_wv_b, 1)
2731 GEN_VEXT_VV_RM(vnclip_wv_h, 2)
2732 GEN_VEXT_VV_RM(vnclip_wv_w, 4)
2734 RVVCALL(OPIVX2_RM, vnclip_wx_b, NOP_SSS_B, H1, H2, vnclip8)
2735 RVVCALL(OPIVX2_RM, vnclip_wx_h, NOP_SSS_H, H2, H4, vnclip16)
2736 RVVCALL(OPIVX2_RM, vnclip_wx_w, NOP_SSS_W, H4, H8, vnclip32)
2737 GEN_VEXT_VX_RM(vnclip_wx_b, 1)
2738 GEN_VEXT_VX_RM(vnclip_wx_h, 2)
2739 GEN_VEXT_VX_RM(vnclip_wx_w, 4)
2741 static inline uint8_t
2742 vnclipu8(CPURISCVState *env, int vxrm, uint16_t a, uint8_t b)
2744 uint8_t round, shift = b & 0xf;
2745 uint16_t res;
2747 round = get_round(vxrm, a, shift);
2748 res = (a >> shift) + round;
2749 if (res > UINT8_MAX) {
2750 env->vxsat = 0x1;
2751 return UINT8_MAX;
2752 } else {
2753 return res;
2757 static inline uint16_t
2758 vnclipu16(CPURISCVState *env, int vxrm, uint32_t a, uint16_t b)
2760 uint8_t round, shift = b & 0x1f;
2761 uint32_t res;
2763 round = get_round(vxrm, a, shift);
2764 res = (a >> shift) + round;
2765 if (res > UINT16_MAX) {
2766 env->vxsat = 0x1;
2767 return UINT16_MAX;
2768 } else {
2769 return res;
2773 static inline uint32_t
2774 vnclipu32(CPURISCVState *env, int vxrm, uint64_t a, uint32_t b)
2776 uint8_t round, shift = b & 0x3f;
2777 uint64_t res;
2779 round = get_round(vxrm, a, shift);
2780 res = (a >> shift) + round;
2781 if (res > UINT32_MAX) {
2782 env->vxsat = 0x1;
2783 return UINT32_MAX;
2784 } else {
2785 return res;
2789 RVVCALL(OPIVV2_RM, vnclipu_wv_b, NOP_UUU_B, H1, H2, H1, vnclipu8)
2790 RVVCALL(OPIVV2_RM, vnclipu_wv_h, NOP_UUU_H, H2, H4, H2, vnclipu16)
2791 RVVCALL(OPIVV2_RM, vnclipu_wv_w, NOP_UUU_W, H4, H8, H4, vnclipu32)
2792 GEN_VEXT_VV_RM(vnclipu_wv_b, 1)
2793 GEN_VEXT_VV_RM(vnclipu_wv_h, 2)
2794 GEN_VEXT_VV_RM(vnclipu_wv_w, 4)
2796 RVVCALL(OPIVX2_RM, vnclipu_wx_b, NOP_UUU_B, H1, H2, vnclipu8)
2797 RVVCALL(OPIVX2_RM, vnclipu_wx_h, NOP_UUU_H, H2, H4, vnclipu16)
2798 RVVCALL(OPIVX2_RM, vnclipu_wx_w, NOP_UUU_W, H4, H8, vnclipu32)
2799 GEN_VEXT_VX_RM(vnclipu_wx_b, 1)
2800 GEN_VEXT_VX_RM(vnclipu_wx_h, 2)
2801 GEN_VEXT_VX_RM(vnclipu_wx_w, 4)
2804 * Vector Float Point Arithmetic Instructions
2806 /* Vector Single-Width Floating-Point Add/Subtract Instructions */
2807 #define OPFVV2(NAME, TD, T1, T2, TX1, TX2, HD, HS1, HS2, OP) \
2808 static void do_##NAME(void *vd, void *vs1, void *vs2, int i, \
2809 CPURISCVState *env) \
2811 TX1 s1 = *((T1 *)vs1 + HS1(i)); \
2812 TX2 s2 = *((T2 *)vs2 + HS2(i)); \
2813 *((TD *)vd + HD(i)) = OP(s2, s1, &env->fp_status); \
2816 #define GEN_VEXT_VV_ENV(NAME, ESZ) \
2817 void HELPER(NAME)(void *vd, void *v0, void *vs1, \
2818 void *vs2, CPURISCVState *env, \
2819 uint32_t desc) \
2821 uint32_t vm = vext_vm(desc); \
2822 uint32_t vl = env->vl; \
2823 uint32_t total_elems = \
2824 vext_get_total_elems(env, desc, ESZ); \
2825 uint32_t vta = vext_vta(desc); \
2826 uint32_t vma = vext_vma(desc); \
2827 uint32_t i; \
2829 for (i = env->vstart; i < vl; i++) { \
2830 if (!vm && !vext_elem_mask(v0, i)) { \
2831 /* set masked-off elements to 1s */ \
2832 vext_set_elems_1s(vd, vma, i * ESZ, \
2833 (i + 1) * ESZ); \
2834 continue; \
2836 do_##NAME(vd, vs1, vs2, i, env); \
2838 env->vstart = 0; \
2839 /* set tail elements to 1s */ \
2840 vext_set_elems_1s(vd, vta, vl * ESZ, \
2841 total_elems * ESZ); \
2844 RVVCALL(OPFVV2, vfadd_vv_h, OP_UUU_H, H2, H2, H2, float16_add)
2845 RVVCALL(OPFVV2, vfadd_vv_w, OP_UUU_W, H4, H4, H4, float32_add)
2846 RVVCALL(OPFVV2, vfadd_vv_d, OP_UUU_D, H8, H8, H8, float64_add)
2847 GEN_VEXT_VV_ENV(vfadd_vv_h, 2)
2848 GEN_VEXT_VV_ENV(vfadd_vv_w, 4)
2849 GEN_VEXT_VV_ENV(vfadd_vv_d, 8)
2851 #define OPFVF2(NAME, TD, T1, T2, TX1, TX2, HD, HS2, OP) \
2852 static void do_##NAME(void *vd, uint64_t s1, void *vs2, int i, \
2853 CPURISCVState *env) \
2855 TX2 s2 = *((T2 *)vs2 + HS2(i)); \
2856 *((TD *)vd + HD(i)) = OP(s2, (TX1)(T1)s1, &env->fp_status);\
2859 #define GEN_VEXT_VF(NAME, ESZ) \
2860 void HELPER(NAME)(void *vd, void *v0, uint64_t s1, \
2861 void *vs2, CPURISCVState *env, \
2862 uint32_t desc) \
2864 uint32_t vm = vext_vm(desc); \
2865 uint32_t vl = env->vl; \
2866 uint32_t total_elems = \
2867 vext_get_total_elems(env, desc, ESZ); \
2868 uint32_t vta = vext_vta(desc); \
2869 uint32_t vma = vext_vma(desc); \
2870 uint32_t i; \
2872 for (i = env->vstart; i < vl; i++) { \
2873 if (!vm && !vext_elem_mask(v0, i)) { \
2874 /* set masked-off elements to 1s */ \
2875 vext_set_elems_1s(vd, vma, i * ESZ, \
2876 (i + 1) * ESZ); \
2877 continue; \
2879 do_##NAME(vd, s1, vs2, i, env); \
2881 env->vstart = 0; \
2882 /* set tail elements to 1s */ \
2883 vext_set_elems_1s(vd, vta, vl * ESZ, \
2884 total_elems * ESZ); \
2887 RVVCALL(OPFVF2, vfadd_vf_h, OP_UUU_H, H2, H2, float16_add)
2888 RVVCALL(OPFVF2, vfadd_vf_w, OP_UUU_W, H4, H4, float32_add)
2889 RVVCALL(OPFVF2, vfadd_vf_d, OP_UUU_D, H8, H8, float64_add)
2890 GEN_VEXT_VF(vfadd_vf_h, 2)
2891 GEN_VEXT_VF(vfadd_vf_w, 4)
2892 GEN_VEXT_VF(vfadd_vf_d, 8)
2894 RVVCALL(OPFVV2, vfsub_vv_h, OP_UUU_H, H2, H2, H2, float16_sub)
2895 RVVCALL(OPFVV2, vfsub_vv_w, OP_UUU_W, H4, H4, H4, float32_sub)
2896 RVVCALL(OPFVV2, vfsub_vv_d, OP_UUU_D, H8, H8, H8, float64_sub)
2897 GEN_VEXT_VV_ENV(vfsub_vv_h, 2)
2898 GEN_VEXT_VV_ENV(vfsub_vv_w, 4)
2899 GEN_VEXT_VV_ENV(vfsub_vv_d, 8)
2900 RVVCALL(OPFVF2, vfsub_vf_h, OP_UUU_H, H2, H2, float16_sub)
2901 RVVCALL(OPFVF2, vfsub_vf_w, OP_UUU_W, H4, H4, float32_sub)
2902 RVVCALL(OPFVF2, vfsub_vf_d, OP_UUU_D, H8, H8, float64_sub)
2903 GEN_VEXT_VF(vfsub_vf_h, 2)
2904 GEN_VEXT_VF(vfsub_vf_w, 4)
2905 GEN_VEXT_VF(vfsub_vf_d, 8)
2907 static uint16_t float16_rsub(uint16_t a, uint16_t b, float_status *s)
2909 return float16_sub(b, a, s);
2912 static uint32_t float32_rsub(uint32_t a, uint32_t b, float_status *s)
2914 return float32_sub(b, a, s);
2917 static uint64_t float64_rsub(uint64_t a, uint64_t b, float_status *s)
2919 return float64_sub(b, a, s);
2922 RVVCALL(OPFVF2, vfrsub_vf_h, OP_UUU_H, H2, H2, float16_rsub)
2923 RVVCALL(OPFVF2, vfrsub_vf_w, OP_UUU_W, H4, H4, float32_rsub)
2924 RVVCALL(OPFVF2, vfrsub_vf_d, OP_UUU_D, H8, H8, float64_rsub)
2925 GEN_VEXT_VF(vfrsub_vf_h, 2)
2926 GEN_VEXT_VF(vfrsub_vf_w, 4)
2927 GEN_VEXT_VF(vfrsub_vf_d, 8)
2929 /* Vector Widening Floating-Point Add/Subtract Instructions */
2930 static uint32_t vfwadd16(uint16_t a, uint16_t b, float_status *s)
2932 return float32_add(float16_to_float32(a, true, s),
2933 float16_to_float32(b, true, s), s);
2936 static uint64_t vfwadd32(uint32_t a, uint32_t b, float_status *s)
2938 return float64_add(float32_to_float64(a, s),
2939 float32_to_float64(b, s), s);
2943 RVVCALL(OPFVV2, vfwadd_vv_h, WOP_UUU_H, H4, H2, H2, vfwadd16)
2944 RVVCALL(OPFVV2, vfwadd_vv_w, WOP_UUU_W, H8, H4, H4, vfwadd32)
2945 GEN_VEXT_VV_ENV(vfwadd_vv_h, 4)
2946 GEN_VEXT_VV_ENV(vfwadd_vv_w, 8)
2947 RVVCALL(OPFVF2, vfwadd_vf_h, WOP_UUU_H, H4, H2, vfwadd16)
2948 RVVCALL(OPFVF2, vfwadd_vf_w, WOP_UUU_W, H8, H4, vfwadd32)
2949 GEN_VEXT_VF(vfwadd_vf_h, 4)
2950 GEN_VEXT_VF(vfwadd_vf_w, 8)
2952 static uint32_t vfwsub16(uint16_t a, uint16_t b, float_status *s)
2954 return float32_sub(float16_to_float32(a, true, s),
2955 float16_to_float32(b, true, s), s);
2958 static uint64_t vfwsub32(uint32_t a, uint32_t b, float_status *s)
2960 return float64_sub(float32_to_float64(a, s),
2961 float32_to_float64(b, s), s);
2965 RVVCALL(OPFVV2, vfwsub_vv_h, WOP_UUU_H, H4, H2, H2, vfwsub16)
2966 RVVCALL(OPFVV2, vfwsub_vv_w, WOP_UUU_W, H8, H4, H4, vfwsub32)
2967 GEN_VEXT_VV_ENV(vfwsub_vv_h, 4)
2968 GEN_VEXT_VV_ENV(vfwsub_vv_w, 8)
2969 RVVCALL(OPFVF2, vfwsub_vf_h, WOP_UUU_H, H4, H2, vfwsub16)
2970 RVVCALL(OPFVF2, vfwsub_vf_w, WOP_UUU_W, H8, H4, vfwsub32)
2971 GEN_VEXT_VF(vfwsub_vf_h, 4)
2972 GEN_VEXT_VF(vfwsub_vf_w, 8)
2974 static uint32_t vfwaddw16(uint32_t a, uint16_t b, float_status *s)
2976 return float32_add(a, float16_to_float32(b, true, s), s);
2979 static uint64_t vfwaddw32(uint64_t a, uint32_t b, float_status *s)
2981 return float64_add(a, float32_to_float64(b, s), s);
2984 RVVCALL(OPFVV2, vfwadd_wv_h, WOP_WUUU_H, H4, H2, H2, vfwaddw16)
2985 RVVCALL(OPFVV2, vfwadd_wv_w, WOP_WUUU_W, H8, H4, H4, vfwaddw32)
2986 GEN_VEXT_VV_ENV(vfwadd_wv_h, 4)
2987 GEN_VEXT_VV_ENV(vfwadd_wv_w, 8)
2988 RVVCALL(OPFVF2, vfwadd_wf_h, WOP_WUUU_H, H4, H2, vfwaddw16)
2989 RVVCALL(OPFVF2, vfwadd_wf_w, WOP_WUUU_W, H8, H4, vfwaddw32)
2990 GEN_VEXT_VF(vfwadd_wf_h, 4)
2991 GEN_VEXT_VF(vfwadd_wf_w, 8)
2993 static uint32_t vfwsubw16(uint32_t a, uint16_t b, float_status *s)
2995 return float32_sub(a, float16_to_float32(b, true, s), s);
2998 static uint64_t vfwsubw32(uint64_t a, uint32_t b, float_status *s)
3000 return float64_sub(a, float32_to_float64(b, s), s);
3003 RVVCALL(OPFVV2, vfwsub_wv_h, WOP_WUUU_H, H4, H2, H2, vfwsubw16)
3004 RVVCALL(OPFVV2, vfwsub_wv_w, WOP_WUUU_W, H8, H4, H4, vfwsubw32)
3005 GEN_VEXT_VV_ENV(vfwsub_wv_h, 4)
3006 GEN_VEXT_VV_ENV(vfwsub_wv_w, 8)
3007 RVVCALL(OPFVF2, vfwsub_wf_h, WOP_WUUU_H, H4, H2, vfwsubw16)
3008 RVVCALL(OPFVF2, vfwsub_wf_w, WOP_WUUU_W, H8, H4, vfwsubw32)
3009 GEN_VEXT_VF(vfwsub_wf_h, 4)
3010 GEN_VEXT_VF(vfwsub_wf_w, 8)
3012 /* Vector Single-Width Floating-Point Multiply/Divide Instructions */
3013 RVVCALL(OPFVV2, vfmul_vv_h, OP_UUU_H, H2, H2, H2, float16_mul)
3014 RVVCALL(OPFVV2, vfmul_vv_w, OP_UUU_W, H4, H4, H4, float32_mul)
3015 RVVCALL(OPFVV2, vfmul_vv_d, OP_UUU_D, H8, H8, H8, float64_mul)
3016 GEN_VEXT_VV_ENV(vfmul_vv_h, 2)
3017 GEN_VEXT_VV_ENV(vfmul_vv_w, 4)
3018 GEN_VEXT_VV_ENV(vfmul_vv_d, 8)
3019 RVVCALL(OPFVF2, vfmul_vf_h, OP_UUU_H, H2, H2, float16_mul)
3020 RVVCALL(OPFVF2, vfmul_vf_w, OP_UUU_W, H4, H4, float32_mul)
3021 RVVCALL(OPFVF2, vfmul_vf_d, OP_UUU_D, H8, H8, float64_mul)
3022 GEN_VEXT_VF(vfmul_vf_h, 2)
3023 GEN_VEXT_VF(vfmul_vf_w, 4)
3024 GEN_VEXT_VF(vfmul_vf_d, 8)
3026 RVVCALL(OPFVV2, vfdiv_vv_h, OP_UUU_H, H2, H2, H2, float16_div)
3027 RVVCALL(OPFVV2, vfdiv_vv_w, OP_UUU_W, H4, H4, H4, float32_div)
3028 RVVCALL(OPFVV2, vfdiv_vv_d, OP_UUU_D, H8, H8, H8, float64_div)
3029 GEN_VEXT_VV_ENV(vfdiv_vv_h, 2)
3030 GEN_VEXT_VV_ENV(vfdiv_vv_w, 4)
3031 GEN_VEXT_VV_ENV(vfdiv_vv_d, 8)
3032 RVVCALL(OPFVF2, vfdiv_vf_h, OP_UUU_H, H2, H2, float16_div)
3033 RVVCALL(OPFVF2, vfdiv_vf_w, OP_UUU_W, H4, H4, float32_div)
3034 RVVCALL(OPFVF2, vfdiv_vf_d, OP_UUU_D, H8, H8, float64_div)
3035 GEN_VEXT_VF(vfdiv_vf_h, 2)
3036 GEN_VEXT_VF(vfdiv_vf_w, 4)
3037 GEN_VEXT_VF(vfdiv_vf_d, 8)
3039 static uint16_t float16_rdiv(uint16_t a, uint16_t b, float_status *s)
3041 return float16_div(b, a, s);
3044 static uint32_t float32_rdiv(uint32_t a, uint32_t b, float_status *s)
3046 return float32_div(b, a, s);
3049 static uint64_t float64_rdiv(uint64_t a, uint64_t b, float_status *s)
3051 return float64_div(b, a, s);
3054 RVVCALL(OPFVF2, vfrdiv_vf_h, OP_UUU_H, H2, H2, float16_rdiv)
3055 RVVCALL(OPFVF2, vfrdiv_vf_w, OP_UUU_W, H4, H4, float32_rdiv)
3056 RVVCALL(OPFVF2, vfrdiv_vf_d, OP_UUU_D, H8, H8, float64_rdiv)
3057 GEN_VEXT_VF(vfrdiv_vf_h, 2)
3058 GEN_VEXT_VF(vfrdiv_vf_w, 4)
3059 GEN_VEXT_VF(vfrdiv_vf_d, 8)
3061 /* Vector Widening Floating-Point Multiply */
3062 static uint32_t vfwmul16(uint16_t a, uint16_t b, float_status *s)
3064 return float32_mul(float16_to_float32(a, true, s),
3065 float16_to_float32(b, true, s), s);
3068 static uint64_t vfwmul32(uint32_t a, uint32_t b, float_status *s)
3070 return float64_mul(float32_to_float64(a, s),
3071 float32_to_float64(b, s), s);
3074 RVVCALL(OPFVV2, vfwmul_vv_h, WOP_UUU_H, H4, H2, H2, vfwmul16)
3075 RVVCALL(OPFVV2, vfwmul_vv_w, WOP_UUU_W, H8, H4, H4, vfwmul32)
3076 GEN_VEXT_VV_ENV(vfwmul_vv_h, 4)
3077 GEN_VEXT_VV_ENV(vfwmul_vv_w, 8)
3078 RVVCALL(OPFVF2, vfwmul_vf_h, WOP_UUU_H, H4, H2, vfwmul16)
3079 RVVCALL(OPFVF2, vfwmul_vf_w, WOP_UUU_W, H8, H4, vfwmul32)
3080 GEN_VEXT_VF(vfwmul_vf_h, 4)
3081 GEN_VEXT_VF(vfwmul_vf_w, 8)
3083 /* Vector Single-Width Floating-Point Fused Multiply-Add Instructions */
3084 #define OPFVV3(NAME, TD, T1, T2, TX1, TX2, HD, HS1, HS2, OP) \
3085 static void do_##NAME(void *vd, void *vs1, void *vs2, int i, \
3086 CPURISCVState *env) \
3088 TX1 s1 = *((T1 *)vs1 + HS1(i)); \
3089 TX2 s2 = *((T2 *)vs2 + HS2(i)); \
3090 TD d = *((TD *)vd + HD(i)); \
3091 *((TD *)vd + HD(i)) = OP(s2, s1, d, &env->fp_status); \
3094 static uint16_t fmacc16(uint16_t a, uint16_t b, uint16_t d, float_status *s)
3096 return float16_muladd(a, b, d, 0, s);
3099 static uint32_t fmacc32(uint32_t a, uint32_t b, uint32_t d, float_status *s)
3101 return float32_muladd(a, b, d, 0, s);
3104 static uint64_t fmacc64(uint64_t a, uint64_t b, uint64_t d, float_status *s)
3106 return float64_muladd(a, b, d, 0, s);
3109 RVVCALL(OPFVV3, vfmacc_vv_h, OP_UUU_H, H2, H2, H2, fmacc16)
3110 RVVCALL(OPFVV3, vfmacc_vv_w, OP_UUU_W, H4, H4, H4, fmacc32)
3111 RVVCALL(OPFVV3, vfmacc_vv_d, OP_UUU_D, H8, H8, H8, fmacc64)
3112 GEN_VEXT_VV_ENV(vfmacc_vv_h, 2)
3113 GEN_VEXT_VV_ENV(vfmacc_vv_w, 4)
3114 GEN_VEXT_VV_ENV(vfmacc_vv_d, 8)
3116 #define OPFVF3(NAME, TD, T1, T2, TX1, TX2, HD, HS2, OP) \
3117 static void do_##NAME(void *vd, uint64_t s1, void *vs2, int i, \
3118 CPURISCVState *env) \
3120 TX2 s2 = *((T2 *)vs2 + HS2(i)); \
3121 TD d = *((TD *)vd + HD(i)); \
3122 *((TD *)vd + HD(i)) = OP(s2, (TX1)(T1)s1, d, &env->fp_status);\
3125 RVVCALL(OPFVF3, vfmacc_vf_h, OP_UUU_H, H2, H2, fmacc16)
3126 RVVCALL(OPFVF3, vfmacc_vf_w, OP_UUU_W, H4, H4, fmacc32)
3127 RVVCALL(OPFVF3, vfmacc_vf_d, OP_UUU_D, H8, H8, fmacc64)
3128 GEN_VEXT_VF(vfmacc_vf_h, 2)
3129 GEN_VEXT_VF(vfmacc_vf_w, 4)
3130 GEN_VEXT_VF(vfmacc_vf_d, 8)
3132 static uint16_t fnmacc16(uint16_t a, uint16_t b, uint16_t d, float_status *s)
3134 return float16_muladd(a, b, d, float_muladd_negate_c |
3135 float_muladd_negate_product, s);
3138 static uint32_t fnmacc32(uint32_t a, uint32_t b, uint32_t d, float_status *s)
3140 return float32_muladd(a, b, d, float_muladd_negate_c |
3141 float_muladd_negate_product, s);
3144 static uint64_t fnmacc64(uint64_t a, uint64_t b, uint64_t d, float_status *s)
3146 return float64_muladd(a, b, d, float_muladd_negate_c |
3147 float_muladd_negate_product, s);
3150 RVVCALL(OPFVV3, vfnmacc_vv_h, OP_UUU_H, H2, H2, H2, fnmacc16)
3151 RVVCALL(OPFVV3, vfnmacc_vv_w, OP_UUU_W, H4, H4, H4, fnmacc32)
3152 RVVCALL(OPFVV3, vfnmacc_vv_d, OP_UUU_D, H8, H8, H8, fnmacc64)
3153 GEN_VEXT_VV_ENV(vfnmacc_vv_h, 2)
3154 GEN_VEXT_VV_ENV(vfnmacc_vv_w, 4)
3155 GEN_VEXT_VV_ENV(vfnmacc_vv_d, 8)
3156 RVVCALL(OPFVF3, vfnmacc_vf_h, OP_UUU_H, H2, H2, fnmacc16)
3157 RVVCALL(OPFVF3, vfnmacc_vf_w, OP_UUU_W, H4, H4, fnmacc32)
3158 RVVCALL(OPFVF3, vfnmacc_vf_d, OP_UUU_D, H8, H8, fnmacc64)
3159 GEN_VEXT_VF(vfnmacc_vf_h, 2)
3160 GEN_VEXT_VF(vfnmacc_vf_w, 4)
3161 GEN_VEXT_VF(vfnmacc_vf_d, 8)
3163 static uint16_t fmsac16(uint16_t a, uint16_t b, uint16_t d, float_status *s)
3165 return float16_muladd(a, b, d, float_muladd_negate_c, s);
3168 static uint32_t fmsac32(uint32_t a, uint32_t b, uint32_t d, float_status *s)
3170 return float32_muladd(a, b, d, float_muladd_negate_c, s);
3173 static uint64_t fmsac64(uint64_t a, uint64_t b, uint64_t d, float_status *s)
3175 return float64_muladd(a, b, d, float_muladd_negate_c, s);
3178 RVVCALL(OPFVV3, vfmsac_vv_h, OP_UUU_H, H2, H2, H2, fmsac16)
3179 RVVCALL(OPFVV3, vfmsac_vv_w, OP_UUU_W, H4, H4, H4, fmsac32)
3180 RVVCALL(OPFVV3, vfmsac_vv_d, OP_UUU_D, H8, H8, H8, fmsac64)
3181 GEN_VEXT_VV_ENV(vfmsac_vv_h, 2)
3182 GEN_VEXT_VV_ENV(vfmsac_vv_w, 4)
3183 GEN_VEXT_VV_ENV(vfmsac_vv_d, 8)
3184 RVVCALL(OPFVF3, vfmsac_vf_h, OP_UUU_H, H2, H2, fmsac16)
3185 RVVCALL(OPFVF3, vfmsac_vf_w, OP_UUU_W, H4, H4, fmsac32)
3186 RVVCALL(OPFVF3, vfmsac_vf_d, OP_UUU_D, H8, H8, fmsac64)
3187 GEN_VEXT_VF(vfmsac_vf_h, 2)
3188 GEN_VEXT_VF(vfmsac_vf_w, 4)
3189 GEN_VEXT_VF(vfmsac_vf_d, 8)
3191 static uint16_t fnmsac16(uint16_t a, uint16_t b, uint16_t d, float_status *s)
3193 return float16_muladd(a, b, d, float_muladd_negate_product, s);
3196 static uint32_t fnmsac32(uint32_t a, uint32_t b, uint32_t d, float_status *s)
3198 return float32_muladd(a, b, d, float_muladd_negate_product, s);
3201 static uint64_t fnmsac64(uint64_t a, uint64_t b, uint64_t d, float_status *s)
3203 return float64_muladd(a, b, d, float_muladd_negate_product, s);
3206 RVVCALL(OPFVV3, vfnmsac_vv_h, OP_UUU_H, H2, H2, H2, fnmsac16)
3207 RVVCALL(OPFVV3, vfnmsac_vv_w, OP_UUU_W, H4, H4, H4, fnmsac32)
3208 RVVCALL(OPFVV3, vfnmsac_vv_d, OP_UUU_D, H8, H8, H8, fnmsac64)
3209 GEN_VEXT_VV_ENV(vfnmsac_vv_h, 2)
3210 GEN_VEXT_VV_ENV(vfnmsac_vv_w, 4)
3211 GEN_VEXT_VV_ENV(vfnmsac_vv_d, 8)
3212 RVVCALL(OPFVF3, vfnmsac_vf_h, OP_UUU_H, H2, H2, fnmsac16)
3213 RVVCALL(OPFVF3, vfnmsac_vf_w, OP_UUU_W, H4, H4, fnmsac32)
3214 RVVCALL(OPFVF3, vfnmsac_vf_d, OP_UUU_D, H8, H8, fnmsac64)
3215 GEN_VEXT_VF(vfnmsac_vf_h, 2)
3216 GEN_VEXT_VF(vfnmsac_vf_w, 4)
3217 GEN_VEXT_VF(vfnmsac_vf_d, 8)
3219 static uint16_t fmadd16(uint16_t a, uint16_t b, uint16_t d, float_status *s)
3221 return float16_muladd(d, b, a, 0, s);
3224 static uint32_t fmadd32(uint32_t a, uint32_t b, uint32_t d, float_status *s)
3226 return float32_muladd(d, b, a, 0, s);
3229 static uint64_t fmadd64(uint64_t a, uint64_t b, uint64_t d, float_status *s)
3231 return float64_muladd(d, b, a, 0, s);
3234 RVVCALL(OPFVV3, vfmadd_vv_h, OP_UUU_H, H2, H2, H2, fmadd16)
3235 RVVCALL(OPFVV3, vfmadd_vv_w, OP_UUU_W, H4, H4, H4, fmadd32)
3236 RVVCALL(OPFVV3, vfmadd_vv_d, OP_UUU_D, H8, H8, H8, fmadd64)
3237 GEN_VEXT_VV_ENV(vfmadd_vv_h, 2)
3238 GEN_VEXT_VV_ENV(vfmadd_vv_w, 4)
3239 GEN_VEXT_VV_ENV(vfmadd_vv_d, 8)
3240 RVVCALL(OPFVF3, vfmadd_vf_h, OP_UUU_H, H2, H2, fmadd16)
3241 RVVCALL(OPFVF3, vfmadd_vf_w, OP_UUU_W, H4, H4, fmadd32)
3242 RVVCALL(OPFVF3, vfmadd_vf_d, OP_UUU_D, H8, H8, fmadd64)
3243 GEN_VEXT_VF(vfmadd_vf_h, 2)
3244 GEN_VEXT_VF(vfmadd_vf_w, 4)
3245 GEN_VEXT_VF(vfmadd_vf_d, 8)
3247 static uint16_t fnmadd16(uint16_t a, uint16_t b, uint16_t d, float_status *s)
3249 return float16_muladd(d, b, a, float_muladd_negate_c |
3250 float_muladd_negate_product, s);
3253 static uint32_t fnmadd32(uint32_t a, uint32_t b, uint32_t d, float_status *s)
3255 return float32_muladd(d, b, a, float_muladd_negate_c |
3256 float_muladd_negate_product, s);
3259 static uint64_t fnmadd64(uint64_t a, uint64_t b, uint64_t d, float_status *s)
3261 return float64_muladd(d, b, a, float_muladd_negate_c |
3262 float_muladd_negate_product, s);
3265 RVVCALL(OPFVV3, vfnmadd_vv_h, OP_UUU_H, H2, H2, H2, fnmadd16)
3266 RVVCALL(OPFVV3, vfnmadd_vv_w, OP_UUU_W, H4, H4, H4, fnmadd32)
3267 RVVCALL(OPFVV3, vfnmadd_vv_d, OP_UUU_D, H8, H8, H8, fnmadd64)
3268 GEN_VEXT_VV_ENV(vfnmadd_vv_h, 2)
3269 GEN_VEXT_VV_ENV(vfnmadd_vv_w, 4)
3270 GEN_VEXT_VV_ENV(vfnmadd_vv_d, 8)
3271 RVVCALL(OPFVF3, vfnmadd_vf_h, OP_UUU_H, H2, H2, fnmadd16)
3272 RVVCALL(OPFVF3, vfnmadd_vf_w, OP_UUU_W, H4, H4, fnmadd32)
3273 RVVCALL(OPFVF3, vfnmadd_vf_d, OP_UUU_D, H8, H8, fnmadd64)
3274 GEN_VEXT_VF(vfnmadd_vf_h, 2)
3275 GEN_VEXT_VF(vfnmadd_vf_w, 4)
3276 GEN_VEXT_VF(vfnmadd_vf_d, 8)
3278 static uint16_t fmsub16(uint16_t a, uint16_t b, uint16_t d, float_status *s)
3280 return float16_muladd(d, b, a, float_muladd_negate_c, s);
3283 static uint32_t fmsub32(uint32_t a, uint32_t b, uint32_t d, float_status *s)
3285 return float32_muladd(d, b, a, float_muladd_negate_c, s);
3288 static uint64_t fmsub64(uint64_t a, uint64_t b, uint64_t d, float_status *s)
3290 return float64_muladd(d, b, a, float_muladd_negate_c, s);
3293 RVVCALL(OPFVV3, vfmsub_vv_h, OP_UUU_H, H2, H2, H2, fmsub16)
3294 RVVCALL(OPFVV3, vfmsub_vv_w, OP_UUU_W, H4, H4, H4, fmsub32)
3295 RVVCALL(OPFVV3, vfmsub_vv_d, OP_UUU_D, H8, H8, H8, fmsub64)
3296 GEN_VEXT_VV_ENV(vfmsub_vv_h, 2)
3297 GEN_VEXT_VV_ENV(vfmsub_vv_w, 4)
3298 GEN_VEXT_VV_ENV(vfmsub_vv_d, 8)
3299 RVVCALL(OPFVF3, vfmsub_vf_h, OP_UUU_H, H2, H2, fmsub16)
3300 RVVCALL(OPFVF3, vfmsub_vf_w, OP_UUU_W, H4, H4, fmsub32)
3301 RVVCALL(OPFVF3, vfmsub_vf_d, OP_UUU_D, H8, H8, fmsub64)
3302 GEN_VEXT_VF(vfmsub_vf_h, 2)
3303 GEN_VEXT_VF(vfmsub_vf_w, 4)
3304 GEN_VEXT_VF(vfmsub_vf_d, 8)
3306 static uint16_t fnmsub16(uint16_t a, uint16_t b, uint16_t d, float_status *s)
3308 return float16_muladd(d, b, a, float_muladd_negate_product, s);
3311 static uint32_t fnmsub32(uint32_t a, uint32_t b, uint32_t d, float_status *s)
3313 return float32_muladd(d, b, a, float_muladd_negate_product, s);
3316 static uint64_t fnmsub64(uint64_t a, uint64_t b, uint64_t d, float_status *s)
3318 return float64_muladd(d, b, a, float_muladd_negate_product, s);
3321 RVVCALL(OPFVV3, vfnmsub_vv_h, OP_UUU_H, H2, H2, H2, fnmsub16)
3322 RVVCALL(OPFVV3, vfnmsub_vv_w, OP_UUU_W, H4, H4, H4, fnmsub32)
3323 RVVCALL(OPFVV3, vfnmsub_vv_d, OP_UUU_D, H8, H8, H8, fnmsub64)
3324 GEN_VEXT_VV_ENV(vfnmsub_vv_h, 2)
3325 GEN_VEXT_VV_ENV(vfnmsub_vv_w, 4)
3326 GEN_VEXT_VV_ENV(vfnmsub_vv_d, 8)
3327 RVVCALL(OPFVF3, vfnmsub_vf_h, OP_UUU_H, H2, H2, fnmsub16)
3328 RVVCALL(OPFVF3, vfnmsub_vf_w, OP_UUU_W, H4, H4, fnmsub32)
3329 RVVCALL(OPFVF3, vfnmsub_vf_d, OP_UUU_D, H8, H8, fnmsub64)
3330 GEN_VEXT_VF(vfnmsub_vf_h, 2)
3331 GEN_VEXT_VF(vfnmsub_vf_w, 4)
3332 GEN_VEXT_VF(vfnmsub_vf_d, 8)
3334 /* Vector Widening Floating-Point Fused Multiply-Add Instructions */
3335 static uint32_t fwmacc16(uint16_t a, uint16_t b, uint32_t d, float_status *s)
3337 return float32_muladd(float16_to_float32(a, true, s),
3338 float16_to_float32(b, true, s), d, 0, s);
3341 static uint64_t fwmacc32(uint32_t a, uint32_t b, uint64_t d, float_status *s)
3343 return float64_muladd(float32_to_float64(a, s),
3344 float32_to_float64(b, s), d, 0, s);
3347 RVVCALL(OPFVV3, vfwmacc_vv_h, WOP_UUU_H, H4, H2, H2, fwmacc16)
3348 RVVCALL(OPFVV3, vfwmacc_vv_w, WOP_UUU_W, H8, H4, H4, fwmacc32)
3349 GEN_VEXT_VV_ENV(vfwmacc_vv_h, 4)
3350 GEN_VEXT_VV_ENV(vfwmacc_vv_w, 8)
3351 RVVCALL(OPFVF3, vfwmacc_vf_h, WOP_UUU_H, H4, H2, fwmacc16)
3352 RVVCALL(OPFVF3, vfwmacc_vf_w, WOP_UUU_W, H8, H4, fwmacc32)
3353 GEN_VEXT_VF(vfwmacc_vf_h, 4)
3354 GEN_VEXT_VF(vfwmacc_vf_w, 8)
3356 static uint32_t fwmaccbf16(uint16_t a, uint16_t b, uint32_t d, float_status *s)
3358 return float32_muladd(bfloat16_to_float32(a, s),
3359 bfloat16_to_float32(b, s), d, 0, s);
3362 RVVCALL(OPFVV3, vfwmaccbf16_vv, WOP_UUU_H, H4, H2, H2, fwmaccbf16)
3363 GEN_VEXT_VV_ENV(vfwmaccbf16_vv, 4)
3364 RVVCALL(OPFVF3, vfwmaccbf16_vf, WOP_UUU_H, H4, H2, fwmacc16)
3365 GEN_VEXT_VF(vfwmaccbf16_vf, 4)
3367 static uint32_t fwnmacc16(uint16_t a, uint16_t b, uint32_t d, float_status *s)
3369 return float32_muladd(float16_to_float32(a, true, s),
3370 float16_to_float32(b, true, s), d,
3371 float_muladd_negate_c | float_muladd_negate_product,
3375 static uint64_t fwnmacc32(uint32_t a, uint32_t b, uint64_t d, float_status *s)
3377 return float64_muladd(float32_to_float64(a, s), float32_to_float64(b, s),
3378 d, float_muladd_negate_c |
3379 float_muladd_negate_product, s);
3382 RVVCALL(OPFVV3, vfwnmacc_vv_h, WOP_UUU_H, H4, H2, H2, fwnmacc16)
3383 RVVCALL(OPFVV3, vfwnmacc_vv_w, WOP_UUU_W, H8, H4, H4, fwnmacc32)
3384 GEN_VEXT_VV_ENV(vfwnmacc_vv_h, 4)
3385 GEN_VEXT_VV_ENV(vfwnmacc_vv_w, 8)
3386 RVVCALL(OPFVF3, vfwnmacc_vf_h, WOP_UUU_H, H4, H2, fwnmacc16)
3387 RVVCALL(OPFVF3, vfwnmacc_vf_w, WOP_UUU_W, H8, H4, fwnmacc32)
3388 GEN_VEXT_VF(vfwnmacc_vf_h, 4)
3389 GEN_VEXT_VF(vfwnmacc_vf_w, 8)
3391 static uint32_t fwmsac16(uint16_t a, uint16_t b, uint32_t d, float_status *s)
3393 return float32_muladd(float16_to_float32(a, true, s),
3394 float16_to_float32(b, true, s), d,
3395 float_muladd_negate_c, s);
3398 static uint64_t fwmsac32(uint32_t a, uint32_t b, uint64_t d, float_status *s)
3400 return float64_muladd(float32_to_float64(a, s),
3401 float32_to_float64(b, s), d,
3402 float_muladd_negate_c, s);
3405 RVVCALL(OPFVV3, vfwmsac_vv_h, WOP_UUU_H, H4, H2, H2, fwmsac16)
3406 RVVCALL(OPFVV3, vfwmsac_vv_w, WOP_UUU_W, H8, H4, H4, fwmsac32)
3407 GEN_VEXT_VV_ENV(vfwmsac_vv_h, 4)
3408 GEN_VEXT_VV_ENV(vfwmsac_vv_w, 8)
3409 RVVCALL(OPFVF3, vfwmsac_vf_h, WOP_UUU_H, H4, H2, fwmsac16)
3410 RVVCALL(OPFVF3, vfwmsac_vf_w, WOP_UUU_W, H8, H4, fwmsac32)
3411 GEN_VEXT_VF(vfwmsac_vf_h, 4)
3412 GEN_VEXT_VF(vfwmsac_vf_w, 8)
3414 static uint32_t fwnmsac16(uint16_t a, uint16_t b, uint32_t d, float_status *s)
3416 return float32_muladd(float16_to_float32(a, true, s),
3417 float16_to_float32(b, true, s), d,
3418 float_muladd_negate_product, s);
3421 static uint64_t fwnmsac32(uint32_t a, uint32_t b, uint64_t d, float_status *s)
3423 return float64_muladd(float32_to_float64(a, s),
3424 float32_to_float64(b, s), d,
3425 float_muladd_negate_product, s);
3428 RVVCALL(OPFVV3, vfwnmsac_vv_h, WOP_UUU_H, H4, H2, H2, fwnmsac16)
3429 RVVCALL(OPFVV3, vfwnmsac_vv_w, WOP_UUU_W, H8, H4, H4, fwnmsac32)
3430 GEN_VEXT_VV_ENV(vfwnmsac_vv_h, 4)
3431 GEN_VEXT_VV_ENV(vfwnmsac_vv_w, 8)
3432 RVVCALL(OPFVF3, vfwnmsac_vf_h, WOP_UUU_H, H4, H2, fwnmsac16)
3433 RVVCALL(OPFVF3, vfwnmsac_vf_w, WOP_UUU_W, H8, H4, fwnmsac32)
3434 GEN_VEXT_VF(vfwnmsac_vf_h, 4)
3435 GEN_VEXT_VF(vfwnmsac_vf_w, 8)
3437 /* Vector Floating-Point Square-Root Instruction */
3438 #define OPFVV1(NAME, TD, T2, TX2, HD, HS2, OP) \
3439 static void do_##NAME(void *vd, void *vs2, int i, \
3440 CPURISCVState *env) \
3442 TX2 s2 = *((T2 *)vs2 + HS2(i)); \
3443 *((TD *)vd + HD(i)) = OP(s2, &env->fp_status); \
3446 #define GEN_VEXT_V_ENV(NAME, ESZ) \
3447 void HELPER(NAME)(void *vd, void *v0, void *vs2, \
3448 CPURISCVState *env, uint32_t desc) \
3450 uint32_t vm = vext_vm(desc); \
3451 uint32_t vl = env->vl; \
3452 uint32_t total_elems = \
3453 vext_get_total_elems(env, desc, ESZ); \
3454 uint32_t vta = vext_vta(desc); \
3455 uint32_t vma = vext_vma(desc); \
3456 uint32_t i; \
3458 if (vl == 0) { \
3459 return; \
3461 for (i = env->vstart; i < vl; i++) { \
3462 if (!vm && !vext_elem_mask(v0, i)) { \
3463 /* set masked-off elements to 1s */ \
3464 vext_set_elems_1s(vd, vma, i * ESZ, \
3465 (i + 1) * ESZ); \
3466 continue; \
3468 do_##NAME(vd, vs2, i, env); \
3470 env->vstart = 0; \
3471 vext_set_elems_1s(vd, vta, vl * ESZ, \
3472 total_elems * ESZ); \
3475 RVVCALL(OPFVV1, vfsqrt_v_h, OP_UU_H, H2, H2, float16_sqrt)
3476 RVVCALL(OPFVV1, vfsqrt_v_w, OP_UU_W, H4, H4, float32_sqrt)
3477 RVVCALL(OPFVV1, vfsqrt_v_d, OP_UU_D, H8, H8, float64_sqrt)
3478 GEN_VEXT_V_ENV(vfsqrt_v_h, 2)
3479 GEN_VEXT_V_ENV(vfsqrt_v_w, 4)
3480 GEN_VEXT_V_ENV(vfsqrt_v_d, 8)
3483 * Vector Floating-Point Reciprocal Square-Root Estimate Instruction
3485 * Adapted from riscv-v-spec recip.c:
3486 * https://github.com/riscv/riscv-v-spec/blob/master/recip.c
3488 static uint64_t frsqrt7(uint64_t f, int exp_size, int frac_size)
3490 uint64_t sign = extract64(f, frac_size + exp_size, 1);
3491 uint64_t exp = extract64(f, frac_size, exp_size);
3492 uint64_t frac = extract64(f, 0, frac_size);
3494 const uint8_t lookup_table[] = {
3495 52, 51, 50, 48, 47, 46, 44, 43,
3496 42, 41, 40, 39, 38, 36, 35, 34,
3497 33, 32, 31, 30, 30, 29, 28, 27,
3498 26, 25, 24, 23, 23, 22, 21, 20,
3499 19, 19, 18, 17, 16, 16, 15, 14,
3500 14, 13, 12, 12, 11, 10, 10, 9,
3501 9, 8, 7, 7, 6, 6, 5, 4,
3502 4, 3, 3, 2, 2, 1, 1, 0,
3503 127, 125, 123, 121, 119, 118, 116, 114,
3504 113, 111, 109, 108, 106, 105, 103, 102,
3505 100, 99, 97, 96, 95, 93, 92, 91,
3506 90, 88, 87, 86, 85, 84, 83, 82,
3507 80, 79, 78, 77, 76, 75, 74, 73,
3508 72, 71, 70, 70, 69, 68, 67, 66,
3509 65, 64, 63, 63, 62, 61, 60, 59,
3510 59, 58, 57, 56, 56, 55, 54, 53
3512 const int precision = 7;
3514 if (exp == 0 && frac != 0) { /* subnormal */
3515 /* Normalize the subnormal. */
3516 while (extract64(frac, frac_size - 1, 1) == 0) {
3517 exp--;
3518 frac <<= 1;
3521 frac = (frac << 1) & MAKE_64BIT_MASK(0, frac_size);
3524 int idx = ((exp & 1) << (precision - 1)) |
3525 (frac >> (frac_size - precision + 1));
3526 uint64_t out_frac = (uint64_t)(lookup_table[idx]) <<
3527 (frac_size - precision);
3528 uint64_t out_exp = (3 * MAKE_64BIT_MASK(0, exp_size - 1) + ~exp) / 2;
3530 uint64_t val = 0;
3531 val = deposit64(val, 0, frac_size, out_frac);
3532 val = deposit64(val, frac_size, exp_size, out_exp);
3533 val = deposit64(val, frac_size + exp_size, 1, sign);
3534 return val;
3537 static float16 frsqrt7_h(float16 f, float_status *s)
3539 int exp_size = 5, frac_size = 10;
3540 bool sign = float16_is_neg(f);
3543 * frsqrt7(sNaN) = canonical NaN
3544 * frsqrt7(-inf) = canonical NaN
3545 * frsqrt7(-normal) = canonical NaN
3546 * frsqrt7(-subnormal) = canonical NaN
3548 if (float16_is_signaling_nan(f, s) ||
3549 (float16_is_infinity(f) && sign) ||
3550 (float16_is_normal(f) && sign) ||
3551 (float16_is_zero_or_denormal(f) && !float16_is_zero(f) && sign)) {
3552 s->float_exception_flags |= float_flag_invalid;
3553 return float16_default_nan(s);
3556 /* frsqrt7(qNaN) = canonical NaN */
3557 if (float16_is_quiet_nan(f, s)) {
3558 return float16_default_nan(s);
3561 /* frsqrt7(+-0) = +-inf */
3562 if (float16_is_zero(f)) {
3563 s->float_exception_flags |= float_flag_divbyzero;
3564 return float16_set_sign(float16_infinity, sign);
3567 /* frsqrt7(+inf) = +0 */
3568 if (float16_is_infinity(f) && !sign) {
3569 return float16_set_sign(float16_zero, sign);
3572 /* +normal, +subnormal */
3573 uint64_t val = frsqrt7(f, exp_size, frac_size);
3574 return make_float16(val);
3577 static float32 frsqrt7_s(float32 f, float_status *s)
3579 int exp_size = 8, frac_size = 23;
3580 bool sign = float32_is_neg(f);
3583 * frsqrt7(sNaN) = canonical NaN
3584 * frsqrt7(-inf) = canonical NaN
3585 * frsqrt7(-normal) = canonical NaN
3586 * frsqrt7(-subnormal) = canonical NaN
3588 if (float32_is_signaling_nan(f, s) ||
3589 (float32_is_infinity(f) && sign) ||
3590 (float32_is_normal(f) && sign) ||
3591 (float32_is_zero_or_denormal(f) && !float32_is_zero(f) && sign)) {
3592 s->float_exception_flags |= float_flag_invalid;
3593 return float32_default_nan(s);
3596 /* frsqrt7(qNaN) = canonical NaN */
3597 if (float32_is_quiet_nan(f, s)) {
3598 return float32_default_nan(s);
3601 /* frsqrt7(+-0) = +-inf */
3602 if (float32_is_zero(f)) {
3603 s->float_exception_flags |= float_flag_divbyzero;
3604 return float32_set_sign(float32_infinity, sign);
3607 /* frsqrt7(+inf) = +0 */
3608 if (float32_is_infinity(f) && !sign) {
3609 return float32_set_sign(float32_zero, sign);
3612 /* +normal, +subnormal */
3613 uint64_t val = frsqrt7(f, exp_size, frac_size);
3614 return make_float32(val);
3617 static float64 frsqrt7_d(float64 f, float_status *s)
3619 int exp_size = 11, frac_size = 52;
3620 bool sign = float64_is_neg(f);
3623 * frsqrt7(sNaN) = canonical NaN
3624 * frsqrt7(-inf) = canonical NaN
3625 * frsqrt7(-normal) = canonical NaN
3626 * frsqrt7(-subnormal) = canonical NaN
3628 if (float64_is_signaling_nan(f, s) ||
3629 (float64_is_infinity(f) && sign) ||
3630 (float64_is_normal(f) && sign) ||
3631 (float64_is_zero_or_denormal(f) && !float64_is_zero(f) && sign)) {
3632 s->float_exception_flags |= float_flag_invalid;
3633 return float64_default_nan(s);
3636 /* frsqrt7(qNaN) = canonical NaN */
3637 if (float64_is_quiet_nan(f, s)) {
3638 return float64_default_nan(s);
3641 /* frsqrt7(+-0) = +-inf */
3642 if (float64_is_zero(f)) {
3643 s->float_exception_flags |= float_flag_divbyzero;
3644 return float64_set_sign(float64_infinity, sign);
3647 /* frsqrt7(+inf) = +0 */
3648 if (float64_is_infinity(f) && !sign) {
3649 return float64_set_sign(float64_zero, sign);
3652 /* +normal, +subnormal */
3653 uint64_t val = frsqrt7(f, exp_size, frac_size);
3654 return make_float64(val);
3657 RVVCALL(OPFVV1, vfrsqrt7_v_h, OP_UU_H, H2, H2, frsqrt7_h)
3658 RVVCALL(OPFVV1, vfrsqrt7_v_w, OP_UU_W, H4, H4, frsqrt7_s)
3659 RVVCALL(OPFVV1, vfrsqrt7_v_d, OP_UU_D, H8, H8, frsqrt7_d)
3660 GEN_VEXT_V_ENV(vfrsqrt7_v_h, 2)
3661 GEN_VEXT_V_ENV(vfrsqrt7_v_w, 4)
3662 GEN_VEXT_V_ENV(vfrsqrt7_v_d, 8)
3665 * Vector Floating-Point Reciprocal Estimate Instruction
3667 * Adapted from riscv-v-spec recip.c:
3668 * https://github.com/riscv/riscv-v-spec/blob/master/recip.c
3670 static uint64_t frec7(uint64_t f, int exp_size, int frac_size,
3671 float_status *s)
3673 uint64_t sign = extract64(f, frac_size + exp_size, 1);
3674 uint64_t exp = extract64(f, frac_size, exp_size);
3675 uint64_t frac = extract64(f, 0, frac_size);
3677 const uint8_t lookup_table[] = {
3678 127, 125, 123, 121, 119, 117, 116, 114,
3679 112, 110, 109, 107, 105, 104, 102, 100,
3680 99, 97, 96, 94, 93, 91, 90, 88,
3681 87, 85, 84, 83, 81, 80, 79, 77,
3682 76, 75, 74, 72, 71, 70, 69, 68,
3683 66, 65, 64, 63, 62, 61, 60, 59,
3684 58, 57, 56, 55, 54, 53, 52, 51,
3685 50, 49, 48, 47, 46, 45, 44, 43,
3686 42, 41, 40, 40, 39, 38, 37, 36,
3687 35, 35, 34, 33, 32, 31, 31, 30,
3688 29, 28, 28, 27, 26, 25, 25, 24,
3689 23, 23, 22, 21, 21, 20, 19, 19,
3690 18, 17, 17, 16, 15, 15, 14, 14,
3691 13, 12, 12, 11, 11, 10, 9, 9,
3692 8, 8, 7, 7, 6, 5, 5, 4,
3693 4, 3, 3, 2, 2, 1, 1, 0
3695 const int precision = 7;
3697 if (exp == 0 && frac != 0) { /* subnormal */
3698 /* Normalize the subnormal. */
3699 while (extract64(frac, frac_size - 1, 1) == 0) {
3700 exp--;
3701 frac <<= 1;
3704 frac = (frac << 1) & MAKE_64BIT_MASK(0, frac_size);
3706 if (exp != 0 && exp != UINT64_MAX) {
3708 * Overflow to inf or max value of same sign,
3709 * depending on sign and rounding mode.
3711 s->float_exception_flags |= (float_flag_inexact |
3712 float_flag_overflow);
3714 if ((s->float_rounding_mode == float_round_to_zero) ||
3715 ((s->float_rounding_mode == float_round_down) && !sign) ||
3716 ((s->float_rounding_mode == float_round_up) && sign)) {
3717 /* Return greatest/negative finite value. */
3718 return (sign << (exp_size + frac_size)) |
3719 (MAKE_64BIT_MASK(frac_size, exp_size) - 1);
3720 } else {
3721 /* Return +-inf. */
3722 return (sign << (exp_size + frac_size)) |
3723 MAKE_64BIT_MASK(frac_size, exp_size);
3728 int idx = frac >> (frac_size - precision);
3729 uint64_t out_frac = (uint64_t)(lookup_table[idx]) <<
3730 (frac_size - precision);
3731 uint64_t out_exp = 2 * MAKE_64BIT_MASK(0, exp_size - 1) + ~exp;
3733 if (out_exp == 0 || out_exp == UINT64_MAX) {
3735 * The result is subnormal, but don't raise the underflow exception,
3736 * because there's no additional loss of precision.
3738 out_frac = (out_frac >> 1) | MAKE_64BIT_MASK(frac_size - 1, 1);
3739 if (out_exp == UINT64_MAX) {
3740 out_frac >>= 1;
3741 out_exp = 0;
3745 uint64_t val = 0;
3746 val = deposit64(val, 0, frac_size, out_frac);
3747 val = deposit64(val, frac_size, exp_size, out_exp);
3748 val = deposit64(val, frac_size + exp_size, 1, sign);
3749 return val;
3752 static float16 frec7_h(float16 f, float_status *s)
3754 int exp_size = 5, frac_size = 10;
3755 bool sign = float16_is_neg(f);
3757 /* frec7(+-inf) = +-0 */
3758 if (float16_is_infinity(f)) {
3759 return float16_set_sign(float16_zero, sign);
3762 /* frec7(+-0) = +-inf */
3763 if (float16_is_zero(f)) {
3764 s->float_exception_flags |= float_flag_divbyzero;
3765 return float16_set_sign(float16_infinity, sign);
3768 /* frec7(sNaN) = canonical NaN */
3769 if (float16_is_signaling_nan(f, s)) {
3770 s->float_exception_flags |= float_flag_invalid;
3771 return float16_default_nan(s);
3774 /* frec7(qNaN) = canonical NaN */
3775 if (float16_is_quiet_nan(f, s)) {
3776 return float16_default_nan(s);
3779 /* +-normal, +-subnormal */
3780 uint64_t val = frec7(f, exp_size, frac_size, s);
3781 return make_float16(val);
3784 static float32 frec7_s(float32 f, float_status *s)
3786 int exp_size = 8, frac_size = 23;
3787 bool sign = float32_is_neg(f);
3789 /* frec7(+-inf) = +-0 */
3790 if (float32_is_infinity(f)) {
3791 return float32_set_sign(float32_zero, sign);
3794 /* frec7(+-0) = +-inf */
3795 if (float32_is_zero(f)) {
3796 s->float_exception_flags |= float_flag_divbyzero;
3797 return float32_set_sign(float32_infinity, sign);
3800 /* frec7(sNaN) = canonical NaN */
3801 if (float32_is_signaling_nan(f, s)) {
3802 s->float_exception_flags |= float_flag_invalid;
3803 return float32_default_nan(s);
3806 /* frec7(qNaN) = canonical NaN */
3807 if (float32_is_quiet_nan(f, s)) {
3808 return float32_default_nan(s);
3811 /* +-normal, +-subnormal */
3812 uint64_t val = frec7(f, exp_size, frac_size, s);
3813 return make_float32(val);
3816 static float64 frec7_d(float64 f, float_status *s)
3818 int exp_size = 11, frac_size = 52;
3819 bool sign = float64_is_neg(f);
3821 /* frec7(+-inf) = +-0 */
3822 if (float64_is_infinity(f)) {
3823 return float64_set_sign(float64_zero, sign);
3826 /* frec7(+-0) = +-inf */
3827 if (float64_is_zero(f)) {
3828 s->float_exception_flags |= float_flag_divbyzero;
3829 return float64_set_sign(float64_infinity, sign);
3832 /* frec7(sNaN) = canonical NaN */
3833 if (float64_is_signaling_nan(f, s)) {
3834 s->float_exception_flags |= float_flag_invalid;
3835 return float64_default_nan(s);
3838 /* frec7(qNaN) = canonical NaN */
3839 if (float64_is_quiet_nan(f, s)) {
3840 return float64_default_nan(s);
3843 /* +-normal, +-subnormal */
3844 uint64_t val = frec7(f, exp_size, frac_size, s);
3845 return make_float64(val);
3848 RVVCALL(OPFVV1, vfrec7_v_h, OP_UU_H, H2, H2, frec7_h)
3849 RVVCALL(OPFVV1, vfrec7_v_w, OP_UU_W, H4, H4, frec7_s)
3850 RVVCALL(OPFVV1, vfrec7_v_d, OP_UU_D, H8, H8, frec7_d)
3851 GEN_VEXT_V_ENV(vfrec7_v_h, 2)
3852 GEN_VEXT_V_ENV(vfrec7_v_w, 4)
3853 GEN_VEXT_V_ENV(vfrec7_v_d, 8)
3855 /* Vector Floating-Point MIN/MAX Instructions */
3856 RVVCALL(OPFVV2, vfmin_vv_h, OP_UUU_H, H2, H2, H2, float16_minimum_number)
3857 RVVCALL(OPFVV2, vfmin_vv_w, OP_UUU_W, H4, H4, H4, float32_minimum_number)
3858 RVVCALL(OPFVV2, vfmin_vv_d, OP_UUU_D, H8, H8, H8, float64_minimum_number)
3859 GEN_VEXT_VV_ENV(vfmin_vv_h, 2)
3860 GEN_VEXT_VV_ENV(vfmin_vv_w, 4)
3861 GEN_VEXT_VV_ENV(vfmin_vv_d, 8)
3862 RVVCALL(OPFVF2, vfmin_vf_h, OP_UUU_H, H2, H2, float16_minimum_number)
3863 RVVCALL(OPFVF2, vfmin_vf_w, OP_UUU_W, H4, H4, float32_minimum_number)
3864 RVVCALL(OPFVF2, vfmin_vf_d, OP_UUU_D, H8, H8, float64_minimum_number)
3865 GEN_VEXT_VF(vfmin_vf_h, 2)
3866 GEN_VEXT_VF(vfmin_vf_w, 4)
3867 GEN_VEXT_VF(vfmin_vf_d, 8)
3869 RVVCALL(OPFVV2, vfmax_vv_h, OP_UUU_H, H2, H2, H2, float16_maximum_number)
3870 RVVCALL(OPFVV2, vfmax_vv_w, OP_UUU_W, H4, H4, H4, float32_maximum_number)
3871 RVVCALL(OPFVV2, vfmax_vv_d, OP_UUU_D, H8, H8, H8, float64_maximum_number)
3872 GEN_VEXT_VV_ENV(vfmax_vv_h, 2)
3873 GEN_VEXT_VV_ENV(vfmax_vv_w, 4)
3874 GEN_VEXT_VV_ENV(vfmax_vv_d, 8)
3875 RVVCALL(OPFVF2, vfmax_vf_h, OP_UUU_H, H2, H2, float16_maximum_number)
3876 RVVCALL(OPFVF2, vfmax_vf_w, OP_UUU_W, H4, H4, float32_maximum_number)
3877 RVVCALL(OPFVF2, vfmax_vf_d, OP_UUU_D, H8, H8, float64_maximum_number)
3878 GEN_VEXT_VF(vfmax_vf_h, 2)
3879 GEN_VEXT_VF(vfmax_vf_w, 4)
3880 GEN_VEXT_VF(vfmax_vf_d, 8)
3882 /* Vector Floating-Point Sign-Injection Instructions */
3883 static uint16_t fsgnj16(uint16_t a, uint16_t b, float_status *s)
3885 return deposit64(b, 0, 15, a);
3888 static uint32_t fsgnj32(uint32_t a, uint32_t b, float_status *s)
3890 return deposit64(b, 0, 31, a);
3893 static uint64_t fsgnj64(uint64_t a, uint64_t b, float_status *s)
3895 return deposit64(b, 0, 63, a);
3898 RVVCALL(OPFVV2, vfsgnj_vv_h, OP_UUU_H, H2, H2, H2, fsgnj16)
3899 RVVCALL(OPFVV2, vfsgnj_vv_w, OP_UUU_W, H4, H4, H4, fsgnj32)
3900 RVVCALL(OPFVV2, vfsgnj_vv_d, OP_UUU_D, H8, H8, H8, fsgnj64)
3901 GEN_VEXT_VV_ENV(vfsgnj_vv_h, 2)
3902 GEN_VEXT_VV_ENV(vfsgnj_vv_w, 4)
3903 GEN_VEXT_VV_ENV(vfsgnj_vv_d, 8)
3904 RVVCALL(OPFVF2, vfsgnj_vf_h, OP_UUU_H, H2, H2, fsgnj16)
3905 RVVCALL(OPFVF2, vfsgnj_vf_w, OP_UUU_W, H4, H4, fsgnj32)
3906 RVVCALL(OPFVF2, vfsgnj_vf_d, OP_UUU_D, H8, H8, fsgnj64)
3907 GEN_VEXT_VF(vfsgnj_vf_h, 2)
3908 GEN_VEXT_VF(vfsgnj_vf_w, 4)
3909 GEN_VEXT_VF(vfsgnj_vf_d, 8)
3911 static uint16_t fsgnjn16(uint16_t a, uint16_t b, float_status *s)
3913 return deposit64(~b, 0, 15, a);
3916 static uint32_t fsgnjn32(uint32_t a, uint32_t b, float_status *s)
3918 return deposit64(~b, 0, 31, a);
3921 static uint64_t fsgnjn64(uint64_t a, uint64_t b, float_status *s)
3923 return deposit64(~b, 0, 63, a);
3926 RVVCALL(OPFVV2, vfsgnjn_vv_h, OP_UUU_H, H2, H2, H2, fsgnjn16)
3927 RVVCALL(OPFVV2, vfsgnjn_vv_w, OP_UUU_W, H4, H4, H4, fsgnjn32)
3928 RVVCALL(OPFVV2, vfsgnjn_vv_d, OP_UUU_D, H8, H8, H8, fsgnjn64)
3929 GEN_VEXT_VV_ENV(vfsgnjn_vv_h, 2)
3930 GEN_VEXT_VV_ENV(vfsgnjn_vv_w, 4)
3931 GEN_VEXT_VV_ENV(vfsgnjn_vv_d, 8)
3932 RVVCALL(OPFVF2, vfsgnjn_vf_h, OP_UUU_H, H2, H2, fsgnjn16)
3933 RVVCALL(OPFVF2, vfsgnjn_vf_w, OP_UUU_W, H4, H4, fsgnjn32)
3934 RVVCALL(OPFVF2, vfsgnjn_vf_d, OP_UUU_D, H8, H8, fsgnjn64)
3935 GEN_VEXT_VF(vfsgnjn_vf_h, 2)
3936 GEN_VEXT_VF(vfsgnjn_vf_w, 4)
3937 GEN_VEXT_VF(vfsgnjn_vf_d, 8)
3939 static uint16_t fsgnjx16(uint16_t a, uint16_t b, float_status *s)
3941 return deposit64(b ^ a, 0, 15, a);
3944 static uint32_t fsgnjx32(uint32_t a, uint32_t b, float_status *s)
3946 return deposit64(b ^ a, 0, 31, a);
3949 static uint64_t fsgnjx64(uint64_t a, uint64_t b, float_status *s)
3951 return deposit64(b ^ a, 0, 63, a);
3954 RVVCALL(OPFVV2, vfsgnjx_vv_h, OP_UUU_H, H2, H2, H2, fsgnjx16)
3955 RVVCALL(OPFVV2, vfsgnjx_vv_w, OP_UUU_W, H4, H4, H4, fsgnjx32)
3956 RVVCALL(OPFVV2, vfsgnjx_vv_d, OP_UUU_D, H8, H8, H8, fsgnjx64)
3957 GEN_VEXT_VV_ENV(vfsgnjx_vv_h, 2)
3958 GEN_VEXT_VV_ENV(vfsgnjx_vv_w, 4)
3959 GEN_VEXT_VV_ENV(vfsgnjx_vv_d, 8)
3960 RVVCALL(OPFVF2, vfsgnjx_vf_h, OP_UUU_H, H2, H2, fsgnjx16)
3961 RVVCALL(OPFVF2, vfsgnjx_vf_w, OP_UUU_W, H4, H4, fsgnjx32)
3962 RVVCALL(OPFVF2, vfsgnjx_vf_d, OP_UUU_D, H8, H8, fsgnjx64)
3963 GEN_VEXT_VF(vfsgnjx_vf_h, 2)
3964 GEN_VEXT_VF(vfsgnjx_vf_w, 4)
3965 GEN_VEXT_VF(vfsgnjx_vf_d, 8)
3967 /* Vector Floating-Point Compare Instructions */
3968 #define GEN_VEXT_CMP_VV_ENV(NAME, ETYPE, H, DO_OP) \
3969 void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
3970 CPURISCVState *env, uint32_t desc) \
3972 uint32_t vm = vext_vm(desc); \
3973 uint32_t vl = env->vl; \
3974 uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
3975 uint32_t vta_all_1s = vext_vta_all_1s(desc); \
3976 uint32_t vma = vext_vma(desc); \
3977 uint32_t i; \
3979 for (i = env->vstart; i < vl; i++) { \
3980 ETYPE s1 = *((ETYPE *)vs1 + H(i)); \
3981 ETYPE s2 = *((ETYPE *)vs2 + H(i)); \
3982 if (!vm && !vext_elem_mask(v0, i)) { \
3983 /* set masked-off elements to 1s */ \
3984 if (vma) { \
3985 vext_set_elem_mask(vd, i, 1); \
3987 continue; \
3989 vext_set_elem_mask(vd, i, \
3990 DO_OP(s2, s1, &env->fp_status)); \
3992 env->vstart = 0; \
3994 * mask destination register are always tail-agnostic
3995 * set tail elements to 1s
3996 */ \
3997 if (vta_all_1s) { \
3998 for (; i < total_elems; i++) { \
3999 vext_set_elem_mask(vd, i, 1); \
4004 GEN_VEXT_CMP_VV_ENV(vmfeq_vv_h, uint16_t, H2, float16_eq_quiet)
4005 GEN_VEXT_CMP_VV_ENV(vmfeq_vv_w, uint32_t, H4, float32_eq_quiet)
4006 GEN_VEXT_CMP_VV_ENV(vmfeq_vv_d, uint64_t, H8, float64_eq_quiet)
4008 #define GEN_VEXT_CMP_VF(NAME, ETYPE, H, DO_OP) \
4009 void HELPER(NAME)(void *vd, void *v0, uint64_t s1, void *vs2, \
4010 CPURISCVState *env, uint32_t desc) \
4012 uint32_t vm = vext_vm(desc); \
4013 uint32_t vl = env->vl; \
4014 uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
4015 uint32_t vta_all_1s = vext_vta_all_1s(desc); \
4016 uint32_t vma = vext_vma(desc); \
4017 uint32_t i; \
4019 for (i = env->vstart; i < vl; i++) { \
4020 ETYPE s2 = *((ETYPE *)vs2 + H(i)); \
4021 if (!vm && !vext_elem_mask(v0, i)) { \
4022 /* set masked-off elements to 1s */ \
4023 if (vma) { \
4024 vext_set_elem_mask(vd, i, 1); \
4026 continue; \
4028 vext_set_elem_mask(vd, i, \
4029 DO_OP(s2, (ETYPE)s1, &env->fp_status)); \
4031 env->vstart = 0; \
4033 * mask destination register are always tail-agnostic
4034 * set tail elements to 1s
4035 */ \
4036 if (vta_all_1s) { \
4037 for (; i < total_elems; i++) { \
4038 vext_set_elem_mask(vd, i, 1); \
4043 GEN_VEXT_CMP_VF(vmfeq_vf_h, uint16_t, H2, float16_eq_quiet)
4044 GEN_VEXT_CMP_VF(vmfeq_vf_w, uint32_t, H4, float32_eq_quiet)
4045 GEN_VEXT_CMP_VF(vmfeq_vf_d, uint64_t, H8, float64_eq_quiet)
4047 static bool vmfne16(uint16_t a, uint16_t b, float_status *s)
4049 FloatRelation compare = float16_compare_quiet(a, b, s);
4050 return compare != float_relation_equal;
4053 static bool vmfne32(uint32_t a, uint32_t b, float_status *s)
4055 FloatRelation compare = float32_compare_quiet(a, b, s);
4056 return compare != float_relation_equal;
4059 static bool vmfne64(uint64_t a, uint64_t b, float_status *s)
4061 FloatRelation compare = float64_compare_quiet(a, b, s);
4062 return compare != float_relation_equal;
4065 GEN_VEXT_CMP_VV_ENV(vmfne_vv_h, uint16_t, H2, vmfne16)
4066 GEN_VEXT_CMP_VV_ENV(vmfne_vv_w, uint32_t, H4, vmfne32)
4067 GEN_VEXT_CMP_VV_ENV(vmfne_vv_d, uint64_t, H8, vmfne64)
4068 GEN_VEXT_CMP_VF(vmfne_vf_h, uint16_t, H2, vmfne16)
4069 GEN_VEXT_CMP_VF(vmfne_vf_w, uint32_t, H4, vmfne32)
4070 GEN_VEXT_CMP_VF(vmfne_vf_d, uint64_t, H8, vmfne64)
4072 GEN_VEXT_CMP_VV_ENV(vmflt_vv_h, uint16_t, H2, float16_lt)
4073 GEN_VEXT_CMP_VV_ENV(vmflt_vv_w, uint32_t, H4, float32_lt)
4074 GEN_VEXT_CMP_VV_ENV(vmflt_vv_d, uint64_t, H8, float64_lt)
4075 GEN_VEXT_CMP_VF(vmflt_vf_h, uint16_t, H2, float16_lt)
4076 GEN_VEXT_CMP_VF(vmflt_vf_w, uint32_t, H4, float32_lt)
4077 GEN_VEXT_CMP_VF(vmflt_vf_d, uint64_t, H8, float64_lt)
4079 GEN_VEXT_CMP_VV_ENV(vmfle_vv_h, uint16_t, H2, float16_le)
4080 GEN_VEXT_CMP_VV_ENV(vmfle_vv_w, uint32_t, H4, float32_le)
4081 GEN_VEXT_CMP_VV_ENV(vmfle_vv_d, uint64_t, H8, float64_le)
4082 GEN_VEXT_CMP_VF(vmfle_vf_h, uint16_t, H2, float16_le)
4083 GEN_VEXT_CMP_VF(vmfle_vf_w, uint32_t, H4, float32_le)
4084 GEN_VEXT_CMP_VF(vmfle_vf_d, uint64_t, H8, float64_le)
4086 static bool vmfgt16(uint16_t a, uint16_t b, float_status *s)
4088 FloatRelation compare = float16_compare(a, b, s);
4089 return compare == float_relation_greater;
4092 static bool vmfgt32(uint32_t a, uint32_t b, float_status *s)
4094 FloatRelation compare = float32_compare(a, b, s);
4095 return compare == float_relation_greater;
4098 static bool vmfgt64(uint64_t a, uint64_t b, float_status *s)
4100 FloatRelation compare = float64_compare(a, b, s);
4101 return compare == float_relation_greater;
4104 GEN_VEXT_CMP_VF(vmfgt_vf_h, uint16_t, H2, vmfgt16)
4105 GEN_VEXT_CMP_VF(vmfgt_vf_w, uint32_t, H4, vmfgt32)
4106 GEN_VEXT_CMP_VF(vmfgt_vf_d, uint64_t, H8, vmfgt64)
4108 static bool vmfge16(uint16_t a, uint16_t b, float_status *s)
4110 FloatRelation compare = float16_compare(a, b, s);
4111 return compare == float_relation_greater ||
4112 compare == float_relation_equal;
4115 static bool vmfge32(uint32_t a, uint32_t b, float_status *s)
4117 FloatRelation compare = float32_compare(a, b, s);
4118 return compare == float_relation_greater ||
4119 compare == float_relation_equal;
4122 static bool vmfge64(uint64_t a, uint64_t b, float_status *s)
4124 FloatRelation compare = float64_compare(a, b, s);
4125 return compare == float_relation_greater ||
4126 compare == float_relation_equal;
4129 GEN_VEXT_CMP_VF(vmfge_vf_h, uint16_t, H2, vmfge16)
4130 GEN_VEXT_CMP_VF(vmfge_vf_w, uint32_t, H4, vmfge32)
4131 GEN_VEXT_CMP_VF(vmfge_vf_d, uint64_t, H8, vmfge64)
4133 /* Vector Floating-Point Classify Instruction */
4134 target_ulong fclass_h(uint64_t frs1)
4136 float16 f = frs1;
4137 bool sign = float16_is_neg(f);
4139 if (float16_is_infinity(f)) {
4140 return sign ? 1 << 0 : 1 << 7;
4141 } else if (float16_is_zero(f)) {
4142 return sign ? 1 << 3 : 1 << 4;
4143 } else if (float16_is_zero_or_denormal(f)) {
4144 return sign ? 1 << 2 : 1 << 5;
4145 } else if (float16_is_any_nan(f)) {
4146 float_status s = { }; /* for snan_bit_is_one */
4147 return float16_is_quiet_nan(f, &s) ? 1 << 9 : 1 << 8;
4148 } else {
4149 return sign ? 1 << 1 : 1 << 6;
4153 target_ulong fclass_s(uint64_t frs1)
4155 float32 f = frs1;
4156 bool sign = float32_is_neg(f);
4158 if (float32_is_infinity(f)) {
4159 return sign ? 1 << 0 : 1 << 7;
4160 } else if (float32_is_zero(f)) {
4161 return sign ? 1 << 3 : 1 << 4;
4162 } else if (float32_is_zero_or_denormal(f)) {
4163 return sign ? 1 << 2 : 1 << 5;
4164 } else if (float32_is_any_nan(f)) {
4165 float_status s = { }; /* for snan_bit_is_one */
4166 return float32_is_quiet_nan(f, &s) ? 1 << 9 : 1 << 8;
4167 } else {
4168 return sign ? 1 << 1 : 1 << 6;
4172 target_ulong fclass_d(uint64_t frs1)
4174 float64 f = frs1;
4175 bool sign = float64_is_neg(f);
4177 if (float64_is_infinity(f)) {
4178 return sign ? 1 << 0 : 1 << 7;
4179 } else if (float64_is_zero(f)) {
4180 return sign ? 1 << 3 : 1 << 4;
4181 } else if (float64_is_zero_or_denormal(f)) {
4182 return sign ? 1 << 2 : 1 << 5;
4183 } else if (float64_is_any_nan(f)) {
4184 float_status s = { }; /* for snan_bit_is_one */
4185 return float64_is_quiet_nan(f, &s) ? 1 << 9 : 1 << 8;
4186 } else {
4187 return sign ? 1 << 1 : 1 << 6;
4191 RVVCALL(OPIVV1, vfclass_v_h, OP_UU_H, H2, H2, fclass_h)
4192 RVVCALL(OPIVV1, vfclass_v_w, OP_UU_W, H4, H4, fclass_s)
4193 RVVCALL(OPIVV1, vfclass_v_d, OP_UU_D, H8, H8, fclass_d)
4194 GEN_VEXT_V(vfclass_v_h, 2)
4195 GEN_VEXT_V(vfclass_v_w, 4)
4196 GEN_VEXT_V(vfclass_v_d, 8)
4198 /* Vector Floating-Point Merge Instruction */
4200 #define GEN_VFMERGE_VF(NAME, ETYPE, H) \
4201 void HELPER(NAME)(void *vd, void *v0, uint64_t s1, void *vs2, \
4202 CPURISCVState *env, uint32_t desc) \
4204 uint32_t vm = vext_vm(desc); \
4205 uint32_t vl = env->vl; \
4206 uint32_t esz = sizeof(ETYPE); \
4207 uint32_t total_elems = \
4208 vext_get_total_elems(env, desc, esz); \
4209 uint32_t vta = vext_vta(desc); \
4210 uint32_t i; \
4212 for (i = env->vstart; i < vl; i++) { \
4213 ETYPE s2 = *((ETYPE *)vs2 + H(i)); \
4214 *((ETYPE *)vd + H(i)) = \
4215 (!vm && !vext_elem_mask(v0, i) ? s2 : s1); \
4217 env->vstart = 0; \
4218 /* set tail elements to 1s */ \
4219 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
4222 GEN_VFMERGE_VF(vfmerge_vfm_h, int16_t, H2)
4223 GEN_VFMERGE_VF(vfmerge_vfm_w, int32_t, H4)
4224 GEN_VFMERGE_VF(vfmerge_vfm_d, int64_t, H8)
4226 /* Single-Width Floating-Point/Integer Type-Convert Instructions */
4227 /* vfcvt.xu.f.v vd, vs2, vm # Convert float to unsigned integer. */
4228 RVVCALL(OPFVV1, vfcvt_xu_f_v_h, OP_UU_H, H2, H2, float16_to_uint16)
4229 RVVCALL(OPFVV1, vfcvt_xu_f_v_w, OP_UU_W, H4, H4, float32_to_uint32)
4230 RVVCALL(OPFVV1, vfcvt_xu_f_v_d, OP_UU_D, H8, H8, float64_to_uint64)
4231 GEN_VEXT_V_ENV(vfcvt_xu_f_v_h, 2)
4232 GEN_VEXT_V_ENV(vfcvt_xu_f_v_w, 4)
4233 GEN_VEXT_V_ENV(vfcvt_xu_f_v_d, 8)
4235 /* vfcvt.x.f.v vd, vs2, vm # Convert float to signed integer. */
4236 RVVCALL(OPFVV1, vfcvt_x_f_v_h, OP_UU_H, H2, H2, float16_to_int16)
4237 RVVCALL(OPFVV1, vfcvt_x_f_v_w, OP_UU_W, H4, H4, float32_to_int32)
4238 RVVCALL(OPFVV1, vfcvt_x_f_v_d, OP_UU_D, H8, H8, float64_to_int64)
4239 GEN_VEXT_V_ENV(vfcvt_x_f_v_h, 2)
4240 GEN_VEXT_V_ENV(vfcvt_x_f_v_w, 4)
4241 GEN_VEXT_V_ENV(vfcvt_x_f_v_d, 8)
4243 /* vfcvt.f.xu.v vd, vs2, vm # Convert unsigned integer to float. */
4244 RVVCALL(OPFVV1, vfcvt_f_xu_v_h, OP_UU_H, H2, H2, uint16_to_float16)
4245 RVVCALL(OPFVV1, vfcvt_f_xu_v_w, OP_UU_W, H4, H4, uint32_to_float32)
4246 RVVCALL(OPFVV1, vfcvt_f_xu_v_d, OP_UU_D, H8, H8, uint64_to_float64)
4247 GEN_VEXT_V_ENV(vfcvt_f_xu_v_h, 2)
4248 GEN_VEXT_V_ENV(vfcvt_f_xu_v_w, 4)
4249 GEN_VEXT_V_ENV(vfcvt_f_xu_v_d, 8)
4251 /* vfcvt.f.x.v vd, vs2, vm # Convert integer to float. */
4252 RVVCALL(OPFVV1, vfcvt_f_x_v_h, OP_UU_H, H2, H2, int16_to_float16)
4253 RVVCALL(OPFVV1, vfcvt_f_x_v_w, OP_UU_W, H4, H4, int32_to_float32)
4254 RVVCALL(OPFVV1, vfcvt_f_x_v_d, OP_UU_D, H8, H8, int64_to_float64)
4255 GEN_VEXT_V_ENV(vfcvt_f_x_v_h, 2)
4256 GEN_VEXT_V_ENV(vfcvt_f_x_v_w, 4)
4257 GEN_VEXT_V_ENV(vfcvt_f_x_v_d, 8)
4259 /* Widening Floating-Point/Integer Type-Convert Instructions */
4260 /* (TD, T2, TX2) */
4261 #define WOP_UU_B uint16_t, uint8_t, uint8_t
4262 #define WOP_UU_H uint32_t, uint16_t, uint16_t
4263 #define WOP_UU_W uint64_t, uint32_t, uint32_t
4265 * vfwcvt.xu.f.v vd, vs2, vm # Convert float to double-width unsigned integer.
4267 RVVCALL(OPFVV1, vfwcvt_xu_f_v_h, WOP_UU_H, H4, H2, float16_to_uint32)
4268 RVVCALL(OPFVV1, vfwcvt_xu_f_v_w, WOP_UU_W, H8, H4, float32_to_uint64)
4269 GEN_VEXT_V_ENV(vfwcvt_xu_f_v_h, 4)
4270 GEN_VEXT_V_ENV(vfwcvt_xu_f_v_w, 8)
4272 /* vfwcvt.x.f.v vd, vs2, vm # Convert float to double-width signed integer. */
4273 RVVCALL(OPFVV1, vfwcvt_x_f_v_h, WOP_UU_H, H4, H2, float16_to_int32)
4274 RVVCALL(OPFVV1, vfwcvt_x_f_v_w, WOP_UU_W, H8, H4, float32_to_int64)
4275 GEN_VEXT_V_ENV(vfwcvt_x_f_v_h, 4)
4276 GEN_VEXT_V_ENV(vfwcvt_x_f_v_w, 8)
4279 * vfwcvt.f.xu.v vd, vs2, vm # Convert unsigned integer to double-width float.
4281 RVVCALL(OPFVV1, vfwcvt_f_xu_v_b, WOP_UU_B, H2, H1, uint8_to_float16)
4282 RVVCALL(OPFVV1, vfwcvt_f_xu_v_h, WOP_UU_H, H4, H2, uint16_to_float32)
4283 RVVCALL(OPFVV1, vfwcvt_f_xu_v_w, WOP_UU_W, H8, H4, uint32_to_float64)
4284 GEN_VEXT_V_ENV(vfwcvt_f_xu_v_b, 2)
4285 GEN_VEXT_V_ENV(vfwcvt_f_xu_v_h, 4)
4286 GEN_VEXT_V_ENV(vfwcvt_f_xu_v_w, 8)
4288 /* vfwcvt.f.x.v vd, vs2, vm # Convert integer to double-width float. */
4289 RVVCALL(OPFVV1, vfwcvt_f_x_v_b, WOP_UU_B, H2, H1, int8_to_float16)
4290 RVVCALL(OPFVV1, vfwcvt_f_x_v_h, WOP_UU_H, H4, H2, int16_to_float32)
4291 RVVCALL(OPFVV1, vfwcvt_f_x_v_w, WOP_UU_W, H8, H4, int32_to_float64)
4292 GEN_VEXT_V_ENV(vfwcvt_f_x_v_b, 2)
4293 GEN_VEXT_V_ENV(vfwcvt_f_x_v_h, 4)
4294 GEN_VEXT_V_ENV(vfwcvt_f_x_v_w, 8)
4297 * vfwcvt.f.f.v vd, vs2, vm # Convert single-width float to double-width float.
4299 static uint32_t vfwcvtffv16(uint16_t a, float_status *s)
4301 return float16_to_float32(a, true, s);
4304 RVVCALL(OPFVV1, vfwcvt_f_f_v_h, WOP_UU_H, H4, H2, vfwcvtffv16)
4305 RVVCALL(OPFVV1, vfwcvt_f_f_v_w, WOP_UU_W, H8, H4, float32_to_float64)
4306 GEN_VEXT_V_ENV(vfwcvt_f_f_v_h, 4)
4307 GEN_VEXT_V_ENV(vfwcvt_f_f_v_w, 8)
4309 RVVCALL(OPFVV1, vfwcvtbf16_f_f_v, WOP_UU_H, H4, H2, bfloat16_to_float32)
4310 GEN_VEXT_V_ENV(vfwcvtbf16_f_f_v, 4)
4312 /* Narrowing Floating-Point/Integer Type-Convert Instructions */
4313 /* (TD, T2, TX2) */
4314 #define NOP_UU_B uint8_t, uint16_t, uint32_t
4315 #define NOP_UU_H uint16_t, uint32_t, uint32_t
4316 #define NOP_UU_W uint32_t, uint64_t, uint64_t
4317 /* vfncvt.xu.f.v vd, vs2, vm # Convert float to unsigned integer. */
4318 RVVCALL(OPFVV1, vfncvt_xu_f_w_b, NOP_UU_B, H1, H2, float16_to_uint8)
4319 RVVCALL(OPFVV1, vfncvt_xu_f_w_h, NOP_UU_H, H2, H4, float32_to_uint16)
4320 RVVCALL(OPFVV1, vfncvt_xu_f_w_w, NOP_UU_W, H4, H8, float64_to_uint32)
4321 GEN_VEXT_V_ENV(vfncvt_xu_f_w_b, 1)
4322 GEN_VEXT_V_ENV(vfncvt_xu_f_w_h, 2)
4323 GEN_VEXT_V_ENV(vfncvt_xu_f_w_w, 4)
4325 /* vfncvt.x.f.v vd, vs2, vm # Convert double-width float to signed integer. */
4326 RVVCALL(OPFVV1, vfncvt_x_f_w_b, NOP_UU_B, H1, H2, float16_to_int8)
4327 RVVCALL(OPFVV1, vfncvt_x_f_w_h, NOP_UU_H, H2, H4, float32_to_int16)
4328 RVVCALL(OPFVV1, vfncvt_x_f_w_w, NOP_UU_W, H4, H8, float64_to_int32)
4329 GEN_VEXT_V_ENV(vfncvt_x_f_w_b, 1)
4330 GEN_VEXT_V_ENV(vfncvt_x_f_w_h, 2)
4331 GEN_VEXT_V_ENV(vfncvt_x_f_w_w, 4)
4334 * vfncvt.f.xu.v vd, vs2, vm # Convert double-width unsigned integer to float.
4336 RVVCALL(OPFVV1, vfncvt_f_xu_w_h, NOP_UU_H, H2, H4, uint32_to_float16)
4337 RVVCALL(OPFVV1, vfncvt_f_xu_w_w, NOP_UU_W, H4, H8, uint64_to_float32)
4338 GEN_VEXT_V_ENV(vfncvt_f_xu_w_h, 2)
4339 GEN_VEXT_V_ENV(vfncvt_f_xu_w_w, 4)
4341 /* vfncvt.f.x.v vd, vs2, vm # Convert double-width integer to float. */
4342 RVVCALL(OPFVV1, vfncvt_f_x_w_h, NOP_UU_H, H2, H4, int32_to_float16)
4343 RVVCALL(OPFVV1, vfncvt_f_x_w_w, NOP_UU_W, H4, H8, int64_to_float32)
4344 GEN_VEXT_V_ENV(vfncvt_f_x_w_h, 2)
4345 GEN_VEXT_V_ENV(vfncvt_f_x_w_w, 4)
4347 /* vfncvt.f.f.v vd, vs2, vm # Convert double float to single-width float. */
4348 static uint16_t vfncvtffv16(uint32_t a, float_status *s)
4350 return float32_to_float16(a, true, s);
4353 RVVCALL(OPFVV1, vfncvt_f_f_w_h, NOP_UU_H, H2, H4, vfncvtffv16)
4354 RVVCALL(OPFVV1, vfncvt_f_f_w_w, NOP_UU_W, H4, H8, float64_to_float32)
4355 GEN_VEXT_V_ENV(vfncvt_f_f_w_h, 2)
4356 GEN_VEXT_V_ENV(vfncvt_f_f_w_w, 4)
4358 RVVCALL(OPFVV1, vfncvtbf16_f_f_w, NOP_UU_H, H2, H4, float32_to_bfloat16)
4359 GEN_VEXT_V_ENV(vfncvtbf16_f_f_w, 2)
4362 * Vector Reduction Operations
4364 /* Vector Single-Width Integer Reduction Instructions */
4365 #define GEN_VEXT_RED(NAME, TD, TS2, HD, HS2, OP) \
4366 void HELPER(NAME)(void *vd, void *v0, void *vs1, \
4367 void *vs2, CPURISCVState *env, \
4368 uint32_t desc) \
4370 uint32_t vm = vext_vm(desc); \
4371 uint32_t vl = env->vl; \
4372 uint32_t esz = sizeof(TD); \
4373 uint32_t vlenb = simd_maxsz(desc); \
4374 uint32_t vta = vext_vta(desc); \
4375 uint32_t i; \
4376 TD s1 = *((TD *)vs1 + HD(0)); \
4378 for (i = env->vstart; i < vl; i++) { \
4379 TS2 s2 = *((TS2 *)vs2 + HS2(i)); \
4380 if (!vm && !vext_elem_mask(v0, i)) { \
4381 continue; \
4383 s1 = OP(s1, (TD)s2); \
4385 *((TD *)vd + HD(0)) = s1; \
4386 env->vstart = 0; \
4387 /* set tail elements to 1s */ \
4388 vext_set_elems_1s(vd, vta, esz, vlenb); \
4391 /* vd[0] = sum(vs1[0], vs2[*]) */
4392 GEN_VEXT_RED(vredsum_vs_b, int8_t, int8_t, H1, H1, DO_ADD)
4393 GEN_VEXT_RED(vredsum_vs_h, int16_t, int16_t, H2, H2, DO_ADD)
4394 GEN_VEXT_RED(vredsum_vs_w, int32_t, int32_t, H4, H4, DO_ADD)
4395 GEN_VEXT_RED(vredsum_vs_d, int64_t, int64_t, H8, H8, DO_ADD)
4397 /* vd[0] = maxu(vs1[0], vs2[*]) */
4398 GEN_VEXT_RED(vredmaxu_vs_b, uint8_t, uint8_t, H1, H1, DO_MAX)
4399 GEN_VEXT_RED(vredmaxu_vs_h, uint16_t, uint16_t, H2, H2, DO_MAX)
4400 GEN_VEXT_RED(vredmaxu_vs_w, uint32_t, uint32_t, H4, H4, DO_MAX)
4401 GEN_VEXT_RED(vredmaxu_vs_d, uint64_t, uint64_t, H8, H8, DO_MAX)
4403 /* vd[0] = max(vs1[0], vs2[*]) */
4404 GEN_VEXT_RED(vredmax_vs_b, int8_t, int8_t, H1, H1, DO_MAX)
4405 GEN_VEXT_RED(vredmax_vs_h, int16_t, int16_t, H2, H2, DO_MAX)
4406 GEN_VEXT_RED(vredmax_vs_w, int32_t, int32_t, H4, H4, DO_MAX)
4407 GEN_VEXT_RED(vredmax_vs_d, int64_t, int64_t, H8, H8, DO_MAX)
4409 /* vd[0] = minu(vs1[0], vs2[*]) */
4410 GEN_VEXT_RED(vredminu_vs_b, uint8_t, uint8_t, H1, H1, DO_MIN)
4411 GEN_VEXT_RED(vredminu_vs_h, uint16_t, uint16_t, H2, H2, DO_MIN)
4412 GEN_VEXT_RED(vredminu_vs_w, uint32_t, uint32_t, H4, H4, DO_MIN)
4413 GEN_VEXT_RED(vredminu_vs_d, uint64_t, uint64_t, H8, H8, DO_MIN)
4415 /* vd[0] = min(vs1[0], vs2[*]) */
4416 GEN_VEXT_RED(vredmin_vs_b, int8_t, int8_t, H1, H1, DO_MIN)
4417 GEN_VEXT_RED(vredmin_vs_h, int16_t, int16_t, H2, H2, DO_MIN)
4418 GEN_VEXT_RED(vredmin_vs_w, int32_t, int32_t, H4, H4, DO_MIN)
4419 GEN_VEXT_RED(vredmin_vs_d, int64_t, int64_t, H8, H8, DO_MIN)
4421 /* vd[0] = and(vs1[0], vs2[*]) */
4422 GEN_VEXT_RED(vredand_vs_b, int8_t, int8_t, H1, H1, DO_AND)
4423 GEN_VEXT_RED(vredand_vs_h, int16_t, int16_t, H2, H2, DO_AND)
4424 GEN_VEXT_RED(vredand_vs_w, int32_t, int32_t, H4, H4, DO_AND)
4425 GEN_VEXT_RED(vredand_vs_d, int64_t, int64_t, H8, H8, DO_AND)
4427 /* vd[0] = or(vs1[0], vs2[*]) */
4428 GEN_VEXT_RED(vredor_vs_b, int8_t, int8_t, H1, H1, DO_OR)
4429 GEN_VEXT_RED(vredor_vs_h, int16_t, int16_t, H2, H2, DO_OR)
4430 GEN_VEXT_RED(vredor_vs_w, int32_t, int32_t, H4, H4, DO_OR)
4431 GEN_VEXT_RED(vredor_vs_d, int64_t, int64_t, H8, H8, DO_OR)
4433 /* vd[0] = xor(vs1[0], vs2[*]) */
4434 GEN_VEXT_RED(vredxor_vs_b, int8_t, int8_t, H1, H1, DO_XOR)
4435 GEN_VEXT_RED(vredxor_vs_h, int16_t, int16_t, H2, H2, DO_XOR)
4436 GEN_VEXT_RED(vredxor_vs_w, int32_t, int32_t, H4, H4, DO_XOR)
4437 GEN_VEXT_RED(vredxor_vs_d, int64_t, int64_t, H8, H8, DO_XOR)
4439 /* Vector Widening Integer Reduction Instructions */
4440 /* signed sum reduction into double-width accumulator */
4441 GEN_VEXT_RED(vwredsum_vs_b, int16_t, int8_t, H2, H1, DO_ADD)
4442 GEN_VEXT_RED(vwredsum_vs_h, int32_t, int16_t, H4, H2, DO_ADD)
4443 GEN_VEXT_RED(vwredsum_vs_w, int64_t, int32_t, H8, H4, DO_ADD)
4445 /* Unsigned sum reduction into double-width accumulator */
4446 GEN_VEXT_RED(vwredsumu_vs_b, uint16_t, uint8_t, H2, H1, DO_ADD)
4447 GEN_VEXT_RED(vwredsumu_vs_h, uint32_t, uint16_t, H4, H2, DO_ADD)
4448 GEN_VEXT_RED(vwredsumu_vs_w, uint64_t, uint32_t, H8, H4, DO_ADD)
4450 /* Vector Single-Width Floating-Point Reduction Instructions */
4451 #define GEN_VEXT_FRED(NAME, TD, TS2, HD, HS2, OP) \
4452 void HELPER(NAME)(void *vd, void *v0, void *vs1, \
4453 void *vs2, CPURISCVState *env, \
4454 uint32_t desc) \
4456 uint32_t vm = vext_vm(desc); \
4457 uint32_t vl = env->vl; \
4458 uint32_t esz = sizeof(TD); \
4459 uint32_t vlenb = simd_maxsz(desc); \
4460 uint32_t vta = vext_vta(desc); \
4461 uint32_t i; \
4462 TD s1 = *((TD *)vs1 + HD(0)); \
4464 for (i = env->vstart; i < vl; i++) { \
4465 TS2 s2 = *((TS2 *)vs2 + HS2(i)); \
4466 if (!vm && !vext_elem_mask(v0, i)) { \
4467 continue; \
4469 s1 = OP(s1, (TD)s2, &env->fp_status); \
4471 *((TD *)vd + HD(0)) = s1; \
4472 env->vstart = 0; \
4473 /* set tail elements to 1s */ \
4474 vext_set_elems_1s(vd, vta, esz, vlenb); \
4477 /* Unordered sum */
4478 GEN_VEXT_FRED(vfredusum_vs_h, uint16_t, uint16_t, H2, H2, float16_add)
4479 GEN_VEXT_FRED(vfredusum_vs_w, uint32_t, uint32_t, H4, H4, float32_add)
4480 GEN_VEXT_FRED(vfredusum_vs_d, uint64_t, uint64_t, H8, H8, float64_add)
4482 /* Ordered sum */
4483 GEN_VEXT_FRED(vfredosum_vs_h, uint16_t, uint16_t, H2, H2, float16_add)
4484 GEN_VEXT_FRED(vfredosum_vs_w, uint32_t, uint32_t, H4, H4, float32_add)
4485 GEN_VEXT_FRED(vfredosum_vs_d, uint64_t, uint64_t, H8, H8, float64_add)
4487 /* Maximum value */
4488 GEN_VEXT_FRED(vfredmax_vs_h, uint16_t, uint16_t, H2, H2,
4489 float16_maximum_number)
4490 GEN_VEXT_FRED(vfredmax_vs_w, uint32_t, uint32_t, H4, H4,
4491 float32_maximum_number)
4492 GEN_VEXT_FRED(vfredmax_vs_d, uint64_t, uint64_t, H8, H8,
4493 float64_maximum_number)
4495 /* Minimum value */
4496 GEN_VEXT_FRED(vfredmin_vs_h, uint16_t, uint16_t, H2, H2,
4497 float16_minimum_number)
4498 GEN_VEXT_FRED(vfredmin_vs_w, uint32_t, uint32_t, H4, H4,
4499 float32_minimum_number)
4500 GEN_VEXT_FRED(vfredmin_vs_d, uint64_t, uint64_t, H8, H8,
4501 float64_minimum_number)
4503 /* Vector Widening Floating-Point Add Instructions */
4504 static uint32_t fwadd16(uint32_t a, uint16_t b, float_status *s)
4506 return float32_add(a, float16_to_float32(b, true, s), s);
4509 static uint64_t fwadd32(uint64_t a, uint32_t b, float_status *s)
4511 return float64_add(a, float32_to_float64(b, s), s);
4514 /* Vector Widening Floating-Point Reduction Instructions */
4515 /* Ordered/unordered reduce 2*SEW = 2*SEW + sum(promote(SEW)) */
4516 GEN_VEXT_FRED(vfwredusum_vs_h, uint32_t, uint16_t, H4, H2, fwadd16)
4517 GEN_VEXT_FRED(vfwredusum_vs_w, uint64_t, uint32_t, H8, H4, fwadd32)
4518 GEN_VEXT_FRED(vfwredosum_vs_h, uint32_t, uint16_t, H4, H2, fwadd16)
4519 GEN_VEXT_FRED(vfwredosum_vs_w, uint64_t, uint32_t, H8, H4, fwadd32)
4522 * Vector Mask Operations
4524 /* Vector Mask-Register Logical Instructions */
4525 #define GEN_VEXT_MASK_VV(NAME, OP) \
4526 void HELPER(NAME)(void *vd, void *v0, void *vs1, \
4527 void *vs2, CPURISCVState *env, \
4528 uint32_t desc) \
4530 uint32_t vl = env->vl; \
4531 uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
4532 uint32_t vta_all_1s = vext_vta_all_1s(desc); \
4533 uint32_t i; \
4534 int a, b; \
4536 for (i = env->vstart; i < vl; i++) { \
4537 a = vext_elem_mask(vs1, i); \
4538 b = vext_elem_mask(vs2, i); \
4539 vext_set_elem_mask(vd, i, OP(b, a)); \
4541 env->vstart = 0; \
4543 * mask destination register are always tail-agnostic
4544 * set tail elements to 1s
4545 */ \
4546 if (vta_all_1s) { \
4547 for (; i < total_elems; i++) { \
4548 vext_set_elem_mask(vd, i, 1); \
4553 #define DO_NAND(N, M) (!(N & M))
4554 #define DO_ANDNOT(N, M) (N & !M)
4555 #define DO_NOR(N, M) (!(N | M))
4556 #define DO_ORNOT(N, M) (N | !M)
4557 #define DO_XNOR(N, M) (!(N ^ M))
4559 GEN_VEXT_MASK_VV(vmand_mm, DO_AND)
4560 GEN_VEXT_MASK_VV(vmnand_mm, DO_NAND)
4561 GEN_VEXT_MASK_VV(vmandn_mm, DO_ANDNOT)
4562 GEN_VEXT_MASK_VV(vmxor_mm, DO_XOR)
4563 GEN_VEXT_MASK_VV(vmor_mm, DO_OR)
4564 GEN_VEXT_MASK_VV(vmnor_mm, DO_NOR)
4565 GEN_VEXT_MASK_VV(vmorn_mm, DO_ORNOT)
4566 GEN_VEXT_MASK_VV(vmxnor_mm, DO_XNOR)
4568 /* Vector count population in mask vcpop */
4569 target_ulong HELPER(vcpop_m)(void *v0, void *vs2, CPURISCVState *env,
4570 uint32_t desc)
4572 target_ulong cnt = 0;
4573 uint32_t vm = vext_vm(desc);
4574 uint32_t vl = env->vl;
4575 int i;
4577 for (i = env->vstart; i < vl; i++) {
4578 if (vm || vext_elem_mask(v0, i)) {
4579 if (vext_elem_mask(vs2, i)) {
4580 cnt++;
4584 env->vstart = 0;
4585 return cnt;
4588 /* vfirst find-first-set mask bit */
4589 target_ulong HELPER(vfirst_m)(void *v0, void *vs2, CPURISCVState *env,
4590 uint32_t desc)
4592 uint32_t vm = vext_vm(desc);
4593 uint32_t vl = env->vl;
4594 int i;
4596 for (i = env->vstart; i < vl; i++) {
4597 if (vm || vext_elem_mask(v0, i)) {
4598 if (vext_elem_mask(vs2, i)) {
4599 return i;
4603 env->vstart = 0;
4604 return -1LL;
4607 enum set_mask_type {
4608 ONLY_FIRST = 1,
4609 INCLUDE_FIRST,
4610 BEFORE_FIRST,
4613 static void vmsetm(void *vd, void *v0, void *vs2, CPURISCVState *env,
4614 uint32_t desc, enum set_mask_type type)
4616 uint32_t vm = vext_vm(desc);
4617 uint32_t vl = env->vl;
4618 uint32_t total_elems = riscv_cpu_cfg(env)->vlen;
4619 uint32_t vta_all_1s = vext_vta_all_1s(desc);
4620 uint32_t vma = vext_vma(desc);
4621 int i;
4622 bool first_mask_bit = false;
4624 for (i = env->vstart; i < vl; i++) {
4625 if (!vm && !vext_elem_mask(v0, i)) {
4626 /* set masked-off elements to 1s */
4627 if (vma) {
4628 vext_set_elem_mask(vd, i, 1);
4630 continue;
4632 /* write a zero to all following active elements */
4633 if (first_mask_bit) {
4634 vext_set_elem_mask(vd, i, 0);
4635 continue;
4637 if (vext_elem_mask(vs2, i)) {
4638 first_mask_bit = true;
4639 if (type == BEFORE_FIRST) {
4640 vext_set_elem_mask(vd, i, 0);
4641 } else {
4642 vext_set_elem_mask(vd, i, 1);
4644 } else {
4645 if (type == ONLY_FIRST) {
4646 vext_set_elem_mask(vd, i, 0);
4647 } else {
4648 vext_set_elem_mask(vd, i, 1);
4652 env->vstart = 0;
4654 * mask destination register are always tail-agnostic
4655 * set tail elements to 1s
4657 if (vta_all_1s) {
4658 for (; i < total_elems; i++) {
4659 vext_set_elem_mask(vd, i, 1);
4664 void HELPER(vmsbf_m)(void *vd, void *v0, void *vs2, CPURISCVState *env,
4665 uint32_t desc)
4667 vmsetm(vd, v0, vs2, env, desc, BEFORE_FIRST);
4670 void HELPER(vmsif_m)(void *vd, void *v0, void *vs2, CPURISCVState *env,
4671 uint32_t desc)
4673 vmsetm(vd, v0, vs2, env, desc, INCLUDE_FIRST);
4676 void HELPER(vmsof_m)(void *vd, void *v0, void *vs2, CPURISCVState *env,
4677 uint32_t desc)
4679 vmsetm(vd, v0, vs2, env, desc, ONLY_FIRST);
4682 /* Vector Iota Instruction */
4683 #define GEN_VEXT_VIOTA_M(NAME, ETYPE, H) \
4684 void HELPER(NAME)(void *vd, void *v0, void *vs2, CPURISCVState *env, \
4685 uint32_t desc) \
4687 uint32_t vm = vext_vm(desc); \
4688 uint32_t vl = env->vl; \
4689 uint32_t esz = sizeof(ETYPE); \
4690 uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
4691 uint32_t vta = vext_vta(desc); \
4692 uint32_t vma = vext_vma(desc); \
4693 uint32_t sum = 0; \
4694 int i; \
4696 for (i = env->vstart; i < vl; i++) { \
4697 if (!vm && !vext_elem_mask(v0, i)) { \
4698 /* set masked-off elements to 1s */ \
4699 vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \
4700 continue; \
4702 *((ETYPE *)vd + H(i)) = sum; \
4703 if (vext_elem_mask(vs2, i)) { \
4704 sum++; \
4707 env->vstart = 0; \
4708 /* set tail elements to 1s */ \
4709 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
4712 GEN_VEXT_VIOTA_M(viota_m_b, uint8_t, H1)
4713 GEN_VEXT_VIOTA_M(viota_m_h, uint16_t, H2)
4714 GEN_VEXT_VIOTA_M(viota_m_w, uint32_t, H4)
4715 GEN_VEXT_VIOTA_M(viota_m_d, uint64_t, H8)
4717 /* Vector Element Index Instruction */
4718 #define GEN_VEXT_VID_V(NAME, ETYPE, H) \
4719 void HELPER(NAME)(void *vd, void *v0, CPURISCVState *env, uint32_t desc) \
4721 uint32_t vm = vext_vm(desc); \
4722 uint32_t vl = env->vl; \
4723 uint32_t esz = sizeof(ETYPE); \
4724 uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
4725 uint32_t vta = vext_vta(desc); \
4726 uint32_t vma = vext_vma(desc); \
4727 int i; \
4729 for (i = env->vstart; i < vl; i++) { \
4730 if (!vm && !vext_elem_mask(v0, i)) { \
4731 /* set masked-off elements to 1s */ \
4732 vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \
4733 continue; \
4735 *((ETYPE *)vd + H(i)) = i; \
4737 env->vstart = 0; \
4738 /* set tail elements to 1s */ \
4739 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
4742 GEN_VEXT_VID_V(vid_v_b, uint8_t, H1)
4743 GEN_VEXT_VID_V(vid_v_h, uint16_t, H2)
4744 GEN_VEXT_VID_V(vid_v_w, uint32_t, H4)
4745 GEN_VEXT_VID_V(vid_v_d, uint64_t, H8)
4748 * Vector Permutation Instructions
4751 /* Vector Slide Instructions */
4752 #define GEN_VEXT_VSLIDEUP_VX(NAME, ETYPE, H) \
4753 void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \
4754 CPURISCVState *env, uint32_t desc) \
4756 uint32_t vm = vext_vm(desc); \
4757 uint32_t vl = env->vl; \
4758 uint32_t esz = sizeof(ETYPE); \
4759 uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
4760 uint32_t vta = vext_vta(desc); \
4761 uint32_t vma = vext_vma(desc); \
4762 target_ulong offset = s1, i_min, i; \
4764 i_min = MAX(env->vstart, offset); \
4765 for (i = i_min; i < vl; i++) { \
4766 if (!vm && !vext_elem_mask(v0, i)) { \
4767 /* set masked-off elements to 1s */ \
4768 vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \
4769 continue; \
4771 *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(i - offset)); \
4773 /* set tail elements to 1s */ \
4774 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
4777 /* vslideup.vx vd, vs2, rs1, vm # vd[i+rs1] = vs2[i] */
4778 GEN_VEXT_VSLIDEUP_VX(vslideup_vx_b, uint8_t, H1)
4779 GEN_VEXT_VSLIDEUP_VX(vslideup_vx_h, uint16_t, H2)
4780 GEN_VEXT_VSLIDEUP_VX(vslideup_vx_w, uint32_t, H4)
4781 GEN_VEXT_VSLIDEUP_VX(vslideup_vx_d, uint64_t, H8)
4783 #define GEN_VEXT_VSLIDEDOWN_VX(NAME, ETYPE, H) \
4784 void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \
4785 CPURISCVState *env, uint32_t desc) \
4787 uint32_t vlmax = vext_max_elems(desc, ctzl(sizeof(ETYPE))); \
4788 uint32_t vm = vext_vm(desc); \
4789 uint32_t vl = env->vl; \
4790 uint32_t esz = sizeof(ETYPE); \
4791 uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
4792 uint32_t vta = vext_vta(desc); \
4793 uint32_t vma = vext_vma(desc); \
4794 target_ulong i_max, i_min, i; \
4796 i_min = MIN(s1 < vlmax ? vlmax - s1 : 0, vl); \
4797 i_max = MAX(i_min, env->vstart); \
4798 for (i = env->vstart; i < i_max; ++i) { \
4799 if (!vm && !vext_elem_mask(v0, i)) { \
4800 /* set masked-off elements to 1s */ \
4801 vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \
4802 continue; \
4804 *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(i + s1)); \
4807 for (i = i_max; i < vl; ++i) { \
4808 if (vm || vext_elem_mask(v0, i)) { \
4809 *((ETYPE *)vd + H(i)) = 0; \
4813 env->vstart = 0; \
4814 /* set tail elements to 1s */ \
4815 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
4818 /* vslidedown.vx vd, vs2, rs1, vm # vd[i] = vs2[i+rs1] */
4819 GEN_VEXT_VSLIDEDOWN_VX(vslidedown_vx_b, uint8_t, H1)
4820 GEN_VEXT_VSLIDEDOWN_VX(vslidedown_vx_h, uint16_t, H2)
4821 GEN_VEXT_VSLIDEDOWN_VX(vslidedown_vx_w, uint32_t, H4)
4822 GEN_VEXT_VSLIDEDOWN_VX(vslidedown_vx_d, uint64_t, H8)
4824 #define GEN_VEXT_VSLIE1UP(BITWIDTH, H) \
4825 static void vslide1up_##BITWIDTH(void *vd, void *v0, uint64_t s1, \
4826 void *vs2, CPURISCVState *env, \
4827 uint32_t desc) \
4829 typedef uint##BITWIDTH##_t ETYPE; \
4830 uint32_t vm = vext_vm(desc); \
4831 uint32_t vl = env->vl; \
4832 uint32_t esz = sizeof(ETYPE); \
4833 uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
4834 uint32_t vta = vext_vta(desc); \
4835 uint32_t vma = vext_vma(desc); \
4836 uint32_t i; \
4838 for (i = env->vstart; i < vl; i++) { \
4839 if (!vm && !vext_elem_mask(v0, i)) { \
4840 /* set masked-off elements to 1s */ \
4841 vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \
4842 continue; \
4844 if (i == 0) { \
4845 *((ETYPE *)vd + H(i)) = s1; \
4846 } else { \
4847 *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(i - 1)); \
4850 env->vstart = 0; \
4851 /* set tail elements to 1s */ \
4852 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
4855 GEN_VEXT_VSLIE1UP(8, H1)
4856 GEN_VEXT_VSLIE1UP(16, H2)
4857 GEN_VEXT_VSLIE1UP(32, H4)
4858 GEN_VEXT_VSLIE1UP(64, H8)
4860 #define GEN_VEXT_VSLIDE1UP_VX(NAME, BITWIDTH) \
4861 void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \
4862 CPURISCVState *env, uint32_t desc) \
4864 vslide1up_##BITWIDTH(vd, v0, s1, vs2, env, desc); \
4867 /* vslide1up.vx vd, vs2, rs1, vm # vd[0]=x[rs1], vd[i+1] = vs2[i] */
4868 GEN_VEXT_VSLIDE1UP_VX(vslide1up_vx_b, 8)
4869 GEN_VEXT_VSLIDE1UP_VX(vslide1up_vx_h, 16)
4870 GEN_VEXT_VSLIDE1UP_VX(vslide1up_vx_w, 32)
4871 GEN_VEXT_VSLIDE1UP_VX(vslide1up_vx_d, 64)
4873 #define GEN_VEXT_VSLIDE1DOWN(BITWIDTH, H) \
4874 static void vslide1down_##BITWIDTH(void *vd, void *v0, uint64_t s1, \
4875 void *vs2, CPURISCVState *env, \
4876 uint32_t desc) \
4878 typedef uint##BITWIDTH##_t ETYPE; \
4879 uint32_t vm = vext_vm(desc); \
4880 uint32_t vl = env->vl; \
4881 uint32_t esz = sizeof(ETYPE); \
4882 uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
4883 uint32_t vta = vext_vta(desc); \
4884 uint32_t vma = vext_vma(desc); \
4885 uint32_t i; \
4887 for (i = env->vstart; i < vl; i++) { \
4888 if (!vm && !vext_elem_mask(v0, i)) { \
4889 /* set masked-off elements to 1s */ \
4890 vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \
4891 continue; \
4893 if (i == vl - 1) { \
4894 *((ETYPE *)vd + H(i)) = s1; \
4895 } else { \
4896 *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(i + 1)); \
4899 env->vstart = 0; \
4900 /* set tail elements to 1s */ \
4901 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
4904 GEN_VEXT_VSLIDE1DOWN(8, H1)
4905 GEN_VEXT_VSLIDE1DOWN(16, H2)
4906 GEN_VEXT_VSLIDE1DOWN(32, H4)
4907 GEN_VEXT_VSLIDE1DOWN(64, H8)
4909 #define GEN_VEXT_VSLIDE1DOWN_VX(NAME, BITWIDTH) \
4910 void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \
4911 CPURISCVState *env, uint32_t desc) \
4913 vslide1down_##BITWIDTH(vd, v0, s1, vs2, env, desc); \
4916 /* vslide1down.vx vd, vs2, rs1, vm # vd[i] = vs2[i+1], vd[vl-1]=x[rs1] */
4917 GEN_VEXT_VSLIDE1DOWN_VX(vslide1down_vx_b, 8)
4918 GEN_VEXT_VSLIDE1DOWN_VX(vslide1down_vx_h, 16)
4919 GEN_VEXT_VSLIDE1DOWN_VX(vslide1down_vx_w, 32)
4920 GEN_VEXT_VSLIDE1DOWN_VX(vslide1down_vx_d, 64)
4922 /* Vector Floating-Point Slide Instructions */
4923 #define GEN_VEXT_VFSLIDE1UP_VF(NAME, BITWIDTH) \
4924 void HELPER(NAME)(void *vd, void *v0, uint64_t s1, void *vs2, \
4925 CPURISCVState *env, uint32_t desc) \
4927 vslide1up_##BITWIDTH(vd, v0, s1, vs2, env, desc); \
4930 /* vfslide1up.vf vd, vs2, rs1, vm # vd[0]=f[rs1], vd[i+1] = vs2[i] */
4931 GEN_VEXT_VFSLIDE1UP_VF(vfslide1up_vf_h, 16)
4932 GEN_VEXT_VFSLIDE1UP_VF(vfslide1up_vf_w, 32)
4933 GEN_VEXT_VFSLIDE1UP_VF(vfslide1up_vf_d, 64)
4935 #define GEN_VEXT_VFSLIDE1DOWN_VF(NAME, BITWIDTH) \
4936 void HELPER(NAME)(void *vd, void *v0, uint64_t s1, void *vs2, \
4937 CPURISCVState *env, uint32_t desc) \
4939 vslide1down_##BITWIDTH(vd, v0, s1, vs2, env, desc); \
4942 /* vfslide1down.vf vd, vs2, rs1, vm # vd[i] = vs2[i+1], vd[vl-1]=f[rs1] */
4943 GEN_VEXT_VFSLIDE1DOWN_VF(vfslide1down_vf_h, 16)
4944 GEN_VEXT_VFSLIDE1DOWN_VF(vfslide1down_vf_w, 32)
4945 GEN_VEXT_VFSLIDE1DOWN_VF(vfslide1down_vf_d, 64)
4947 /* Vector Register Gather Instruction */
4948 #define GEN_VEXT_VRGATHER_VV(NAME, TS1, TS2, HS1, HS2) \
4949 void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
4950 CPURISCVState *env, uint32_t desc) \
4952 uint32_t vlmax = vext_max_elems(desc, ctzl(sizeof(TS2))); \
4953 uint32_t vm = vext_vm(desc); \
4954 uint32_t vl = env->vl; \
4955 uint32_t esz = sizeof(TS2); \
4956 uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
4957 uint32_t vta = vext_vta(desc); \
4958 uint32_t vma = vext_vma(desc); \
4959 uint64_t index; \
4960 uint32_t i; \
4962 for (i = env->vstart; i < vl; i++) { \
4963 if (!vm && !vext_elem_mask(v0, i)) { \
4964 /* set masked-off elements to 1s */ \
4965 vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \
4966 continue; \
4968 index = *((TS1 *)vs1 + HS1(i)); \
4969 if (index >= vlmax) { \
4970 *((TS2 *)vd + HS2(i)) = 0; \
4971 } else { \
4972 *((TS2 *)vd + HS2(i)) = *((TS2 *)vs2 + HS2(index)); \
4975 env->vstart = 0; \
4976 /* set tail elements to 1s */ \
4977 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
4980 /* vd[i] = (vs1[i] >= VLMAX) ? 0 : vs2[vs1[i]]; */
4981 GEN_VEXT_VRGATHER_VV(vrgather_vv_b, uint8_t, uint8_t, H1, H1)
4982 GEN_VEXT_VRGATHER_VV(vrgather_vv_h, uint16_t, uint16_t, H2, H2)
4983 GEN_VEXT_VRGATHER_VV(vrgather_vv_w, uint32_t, uint32_t, H4, H4)
4984 GEN_VEXT_VRGATHER_VV(vrgather_vv_d, uint64_t, uint64_t, H8, H8)
4986 GEN_VEXT_VRGATHER_VV(vrgatherei16_vv_b, uint16_t, uint8_t, H2, H1)
4987 GEN_VEXT_VRGATHER_VV(vrgatherei16_vv_h, uint16_t, uint16_t, H2, H2)
4988 GEN_VEXT_VRGATHER_VV(vrgatherei16_vv_w, uint16_t, uint32_t, H2, H4)
4989 GEN_VEXT_VRGATHER_VV(vrgatherei16_vv_d, uint16_t, uint64_t, H2, H8)
4991 #define GEN_VEXT_VRGATHER_VX(NAME, ETYPE, H) \
4992 void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \
4993 CPURISCVState *env, uint32_t desc) \
4995 uint32_t vlmax = vext_max_elems(desc, ctzl(sizeof(ETYPE))); \
4996 uint32_t vm = vext_vm(desc); \
4997 uint32_t vl = env->vl; \
4998 uint32_t esz = sizeof(ETYPE); \
4999 uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
5000 uint32_t vta = vext_vta(desc); \
5001 uint32_t vma = vext_vma(desc); \
5002 uint64_t index = s1; \
5003 uint32_t i; \
5005 for (i = env->vstart; i < vl; i++) { \
5006 if (!vm && !vext_elem_mask(v0, i)) { \
5007 /* set masked-off elements to 1s */ \
5008 vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \
5009 continue; \
5011 if (index >= vlmax) { \
5012 *((ETYPE *)vd + H(i)) = 0; \
5013 } else { \
5014 *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(index)); \
5017 env->vstart = 0; \
5018 /* set tail elements to 1s */ \
5019 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
5022 /* vd[i] = (x[rs1] >= VLMAX) ? 0 : vs2[rs1] */
5023 GEN_VEXT_VRGATHER_VX(vrgather_vx_b, uint8_t, H1)
5024 GEN_VEXT_VRGATHER_VX(vrgather_vx_h, uint16_t, H2)
5025 GEN_VEXT_VRGATHER_VX(vrgather_vx_w, uint32_t, H4)
5026 GEN_VEXT_VRGATHER_VX(vrgather_vx_d, uint64_t, H8)
5028 /* Vector Compress Instruction */
5029 #define GEN_VEXT_VCOMPRESS_VM(NAME, ETYPE, H) \
5030 void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
5031 CPURISCVState *env, uint32_t desc) \
5033 uint32_t vl = env->vl; \
5034 uint32_t esz = sizeof(ETYPE); \
5035 uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
5036 uint32_t vta = vext_vta(desc); \
5037 uint32_t num = 0, i; \
5039 for (i = env->vstart; i < vl; i++) { \
5040 if (!vext_elem_mask(vs1, i)) { \
5041 continue; \
5043 *((ETYPE *)vd + H(num)) = *((ETYPE *)vs2 + H(i)); \
5044 num++; \
5046 env->vstart = 0; \
5047 /* set tail elements to 1s */ \
5048 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
5051 /* Compress into vd elements of vs2 where vs1 is enabled */
5052 GEN_VEXT_VCOMPRESS_VM(vcompress_vm_b, uint8_t, H1)
5053 GEN_VEXT_VCOMPRESS_VM(vcompress_vm_h, uint16_t, H2)
5054 GEN_VEXT_VCOMPRESS_VM(vcompress_vm_w, uint32_t, H4)
5055 GEN_VEXT_VCOMPRESS_VM(vcompress_vm_d, uint64_t, H8)
5057 /* Vector Whole Register Move */
5058 void HELPER(vmvr_v)(void *vd, void *vs2, CPURISCVState *env, uint32_t desc)
5060 /* EEW = SEW */
5061 uint32_t maxsz = simd_maxsz(desc);
5062 uint32_t sewb = 1 << FIELD_EX64(env->vtype, VTYPE, VSEW);
5063 uint32_t startb = env->vstart * sewb;
5064 uint32_t i = startb;
5066 memcpy((uint8_t *)vd + H1(i),
5067 (uint8_t *)vs2 + H1(i),
5068 maxsz - startb);
5070 env->vstart = 0;
5073 /* Vector Integer Extension */
5074 #define GEN_VEXT_INT_EXT(NAME, ETYPE, DTYPE, HD, HS1) \
5075 void HELPER(NAME)(void *vd, void *v0, void *vs2, \
5076 CPURISCVState *env, uint32_t desc) \
5078 uint32_t vl = env->vl; \
5079 uint32_t vm = vext_vm(desc); \
5080 uint32_t esz = sizeof(ETYPE); \
5081 uint32_t total_elems = vext_get_total_elems(env, desc, esz); \
5082 uint32_t vta = vext_vta(desc); \
5083 uint32_t vma = vext_vma(desc); \
5084 uint32_t i; \
5086 for (i = env->vstart; i < vl; i++) { \
5087 if (!vm && !vext_elem_mask(v0, i)) { \
5088 /* set masked-off elements to 1s */ \
5089 vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \
5090 continue; \
5092 *((ETYPE *)vd + HD(i)) = *((DTYPE *)vs2 + HS1(i)); \
5094 env->vstart = 0; \
5095 /* set tail elements to 1s */ \
5096 vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \
5099 GEN_VEXT_INT_EXT(vzext_vf2_h, uint16_t, uint8_t, H2, H1)
5100 GEN_VEXT_INT_EXT(vzext_vf2_w, uint32_t, uint16_t, H4, H2)
5101 GEN_VEXT_INT_EXT(vzext_vf2_d, uint64_t, uint32_t, H8, H4)
5102 GEN_VEXT_INT_EXT(vzext_vf4_w, uint32_t, uint8_t, H4, H1)
5103 GEN_VEXT_INT_EXT(vzext_vf4_d, uint64_t, uint16_t, H8, H2)
5104 GEN_VEXT_INT_EXT(vzext_vf8_d, uint64_t, uint8_t, H8, H1)
5106 GEN_VEXT_INT_EXT(vsext_vf2_h, int16_t, int8_t, H2, H1)
5107 GEN_VEXT_INT_EXT(vsext_vf2_w, int32_t, int16_t, H4, H2)
5108 GEN_VEXT_INT_EXT(vsext_vf2_d, int64_t, int32_t, H8, H4)
5109 GEN_VEXT_INT_EXT(vsext_vf4_w, int32_t, int8_t, H4, H1)
5110 GEN_VEXT_INT_EXT(vsext_vf4_d, int64_t, int16_t, H8, H2)
5111 GEN_VEXT_INT_EXT(vsext_vf8_d, int64_t, int8_t, H8, H1)