xref: /openbmc/qemu/target/riscv/vector_internals.c (revision 7f5f3e5acd630c8b11b2a91f6d8ba2a0c6ab5524)
198f40dd2SKiran Ostrolenk /*
298f40dd2SKiran Ostrolenk  * RISC-V Vector Extension Internals
398f40dd2SKiran Ostrolenk  *
498f40dd2SKiran Ostrolenk  * Copyright (c) 2020 T-Head Semiconductor Co., Ltd. All rights reserved.
598f40dd2SKiran Ostrolenk  *
698f40dd2SKiran Ostrolenk  * This program is free software; you can redistribute it and/or modify it
798f40dd2SKiran Ostrolenk  * under the terms and conditions of the GNU General Public License,
898f40dd2SKiran Ostrolenk  * version 2 or later, as published by the Free Software Foundation.
998f40dd2SKiran Ostrolenk  *
1098f40dd2SKiran Ostrolenk  * This program is distributed in the hope it will be useful, but WITHOUT
1198f40dd2SKiran Ostrolenk  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1298f40dd2SKiran Ostrolenk  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
1398f40dd2SKiran Ostrolenk  * more details.
1498f40dd2SKiran Ostrolenk  *
1598f40dd2SKiran Ostrolenk  * You should have received a copy of the GNU General Public License along with
1698f40dd2SKiran Ostrolenk  * this program.  If not, see <http://www.gnu.org/licenses/>.
1798f40dd2SKiran Ostrolenk  */
1898f40dd2SKiran Ostrolenk 
19be355a44SPeter Maydell #include "qemu/osdep.h"
2098f40dd2SKiran Ostrolenk #include "vector_internals.h"
2198f40dd2SKiran Ostrolenk 
2298f40dd2SKiran Ostrolenk /* set agnostic elements to 1s */
vext_set_elems_1s(void * base,uint32_t is_agnostic,uint32_t cnt,uint32_t tot)2398f40dd2SKiran Ostrolenk void vext_set_elems_1s(void *base, uint32_t is_agnostic, uint32_t cnt,
2498f40dd2SKiran Ostrolenk                        uint32_t tot)
2598f40dd2SKiran Ostrolenk {
2698f40dd2SKiran Ostrolenk     if (is_agnostic == 0) {
2798f40dd2SKiran Ostrolenk         /* policy undisturbed */
2898f40dd2SKiran Ostrolenk         return;
2998f40dd2SKiran Ostrolenk     }
3098f40dd2SKiran Ostrolenk     if (tot - cnt == 0) {
3198f40dd2SKiran Ostrolenk         return ;
3298f40dd2SKiran Ostrolenk     }
3375115d88SHuang Tao 
3475115d88SHuang Tao     if (HOST_BIG_ENDIAN) {
3575115d88SHuang Tao         /*
3675115d88SHuang Tao          * Deal the situation when the elements are insdie
3775115d88SHuang Tao          * only one uint64 block including setting the
3875115d88SHuang Tao          * masked-off element.
3975115d88SHuang Tao          */
4075115d88SHuang Tao         if (((tot - 1) ^ cnt) < 8) {
4175115d88SHuang Tao             memset(base + H1(tot - 1), -1, tot - cnt);
4275115d88SHuang Tao             return;
4375115d88SHuang Tao         }
4475115d88SHuang Tao         /*
4575115d88SHuang Tao          * Otherwise, at least cross two uint64_t blocks.
4675115d88SHuang Tao          * Set first unaligned block.
4775115d88SHuang Tao          */
4875115d88SHuang Tao         if (cnt % 8 != 0) {
4975115d88SHuang Tao             uint32_t j = ROUND_UP(cnt, 8);
5075115d88SHuang Tao             memset(base + H1(j - 1), -1, j - cnt);
5175115d88SHuang Tao             cnt = j;
5275115d88SHuang Tao         }
5375115d88SHuang Tao         /* Set other 64bit aligend blocks */
5475115d88SHuang Tao     }
5598f40dd2SKiran Ostrolenk     memset(base + cnt, -1, tot - cnt);
5698f40dd2SKiran Ostrolenk }
5798f40dd2SKiran Ostrolenk 
do_vext_vv(void * vd,void * v0,void * vs1,void * vs2,CPURISCVState * env,uint32_t desc,opivv2_fn * fn,uint32_t esz)5898f40dd2SKiran Ostrolenk void do_vext_vv(void *vd, void *v0, void *vs1, void *vs2,
5998f40dd2SKiran Ostrolenk                 CPURISCVState *env, uint32_t desc,
6098f40dd2SKiran Ostrolenk                 opivv2_fn *fn, uint32_t esz)
6198f40dd2SKiran Ostrolenk {
6298f40dd2SKiran Ostrolenk     uint32_t vm = vext_vm(desc);
6398f40dd2SKiran Ostrolenk     uint32_t vl = env->vl;
6498f40dd2SKiran Ostrolenk     uint32_t total_elems = vext_get_total_elems(env, desc, esz);
6598f40dd2SKiran Ostrolenk     uint32_t vta = vext_vta(desc);
6698f40dd2SKiran Ostrolenk     uint32_t vma = vext_vma(desc);
6798f40dd2SKiran Ostrolenk     uint32_t i;
6898f40dd2SKiran Ostrolenk 
69*7f5f3e5aSChao Liu     VSTART_CHECK_EARLY_EXIT(env, vl);
70df4252b2SDaniel Henrique Barboza 
7198f40dd2SKiran Ostrolenk     for (i = env->vstart; i < vl; i++) {
7298f40dd2SKiran Ostrolenk         if (!vm && !vext_elem_mask(v0, i)) {
7398f40dd2SKiran Ostrolenk             /* set masked-off elements to 1s */
7498f40dd2SKiran Ostrolenk             vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz);
7598f40dd2SKiran Ostrolenk             continue;
7698f40dd2SKiran Ostrolenk         }
7798f40dd2SKiran Ostrolenk         fn(vd, vs1, vs2, i);
7898f40dd2SKiran Ostrolenk     }
7998f40dd2SKiran Ostrolenk     env->vstart = 0;
8098f40dd2SKiran Ostrolenk     /* set tail elements to 1s */
8198f40dd2SKiran Ostrolenk     vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);
8298f40dd2SKiran Ostrolenk }
8398f40dd2SKiran Ostrolenk 
do_vext_vx(void * vd,void * v0,target_long s1,void * vs2,CPURISCVState * env,uint32_t desc,opivx2_fn fn,uint32_t esz)8498f40dd2SKiran Ostrolenk void do_vext_vx(void *vd, void *v0, target_long s1, void *vs2,
8598f40dd2SKiran Ostrolenk                 CPURISCVState *env, uint32_t desc,
8698f40dd2SKiran Ostrolenk                 opivx2_fn fn, uint32_t esz)
8798f40dd2SKiran Ostrolenk {
8898f40dd2SKiran Ostrolenk     uint32_t vm = vext_vm(desc);
8998f40dd2SKiran Ostrolenk     uint32_t vl = env->vl;
9098f40dd2SKiran Ostrolenk     uint32_t total_elems = vext_get_total_elems(env, desc, esz);
9198f40dd2SKiran Ostrolenk     uint32_t vta = vext_vta(desc);
9298f40dd2SKiran Ostrolenk     uint32_t vma = vext_vma(desc);
9398f40dd2SKiran Ostrolenk     uint32_t i;
9498f40dd2SKiran Ostrolenk 
95*7f5f3e5aSChao Liu     VSTART_CHECK_EARLY_EXIT(env, vl);
96df4252b2SDaniel Henrique Barboza 
9798f40dd2SKiran Ostrolenk     for (i = env->vstart; i < vl; i++) {
9898f40dd2SKiran Ostrolenk         if (!vm && !vext_elem_mask(v0, i)) {
9998f40dd2SKiran Ostrolenk             /* set masked-off elements to 1s */
10098f40dd2SKiran Ostrolenk             vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz);
10198f40dd2SKiran Ostrolenk             continue;
10298f40dd2SKiran Ostrolenk         }
10398f40dd2SKiran Ostrolenk         fn(vd, s1, vs2, i);
10498f40dd2SKiran Ostrolenk     }
10598f40dd2SKiran Ostrolenk     env->vstart = 0;
10698f40dd2SKiran Ostrolenk     /* set tail elements to 1s */
10798f40dd2SKiran Ostrolenk     vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz);
10898f40dd2SKiran Ostrolenk }
109