qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

bitmanip_helper.c (3666B)


      1 /*
      2  * RISC-V Bitmanip Extension Helpers for QEMU.
      3  *
      4  * Copyright (c) 2020 Kito Cheng, kito.cheng@sifive.com
      5  * Copyright (c) 2020 Frank Chang, frank.chang@sifive.com
      6  * Copyright (c) 2021 Philipp Tomsich, philipp.tomsich@vrull.eu
      7  *
      8  * This program is free software; you can redistribute it and/or modify it
      9  * under the terms and conditions of the GNU General Public License,
     10  * version 2 or later, as published by the Free Software Foundation.
     11  *
     12  * This program is distributed in the hope it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     15  * more details.
     16  *
     17  * You should have received a copy of the GNU General Public License along with
     18  * this program.  If not, see <http://www.gnu.org/licenses/>.
     19  */
     20 
     21 #include "qemu/osdep.h"
     22 #include "qemu/host-utils.h"
     23 #include "exec/exec-all.h"
     24 #include "exec/helper-proto.h"
     25 #include "tcg/tcg.h"
     26 
     27 target_ulong HELPER(clmul)(target_ulong rs1, target_ulong rs2)
     28 {
     29     target_ulong result = 0;
     30 
     31     for (int i = 0; i < TARGET_LONG_BITS; i++) {
     32         if ((rs2 >> i) & 1) {
     33             result ^= (rs1 << i);
     34         }
     35     }
     36 
     37     return result;
     38 }
     39 
     40 target_ulong HELPER(clmulr)(target_ulong rs1, target_ulong rs2)
     41 {
     42     target_ulong result = 0;
     43 
     44     for (int i = 0; i < TARGET_LONG_BITS; i++) {
     45         if ((rs2 >> i) & 1) {
     46             result ^= (rs1 >> (TARGET_LONG_BITS - i - 1));
     47         }
     48     }
     49 
     50     return result;
     51 }
     52 
     53 static inline target_ulong do_swap(target_ulong x, uint64_t mask, int shift)
     54 {
     55     return ((x & mask) << shift) | ((x & ~mask) >> shift);
     56 }
     57 
     58 target_ulong HELPER(brev8)(target_ulong rs1)
     59 {
     60     target_ulong x = rs1;
     61 
     62     x = do_swap(x, 0x5555555555555555ull, 1);
     63     x = do_swap(x, 0x3333333333333333ull, 2);
     64     x = do_swap(x, 0x0f0f0f0f0f0f0f0full, 4);
     65     return x;
     66 }
     67 
     68 static const uint64_t shuf_masks[] = {
     69     dup_const(MO_8, 0x44),
     70     dup_const(MO_8, 0x30),
     71     dup_const(MO_16, 0x0f00),
     72     dup_const(MO_32, 0xff0000)
     73 };
     74 
     75 static inline target_ulong do_shuf_stage(target_ulong src, uint64_t maskL,
     76                                          uint64_t maskR, int shift)
     77 {
     78     target_ulong x = src & ~(maskL | maskR);
     79 
     80     x |= ((src << shift) & maskL) | ((src >> shift) & maskR);
     81     return x;
     82 }
     83 
     84 target_ulong HELPER(unzip)(target_ulong rs1)
     85 {
     86     target_ulong x = rs1;
     87 
     88     x = do_shuf_stage(x, shuf_masks[0], shuf_masks[0] >> 1, 1);
     89     x = do_shuf_stage(x, shuf_masks[1], shuf_masks[1] >> 2, 2);
     90     x = do_shuf_stage(x, shuf_masks[2], shuf_masks[2] >> 4, 4);
     91     x = do_shuf_stage(x, shuf_masks[3], shuf_masks[3] >> 8, 8);
     92     return x;
     93 }
     94 
     95 target_ulong HELPER(zip)(target_ulong rs1)
     96 {
     97     target_ulong x = rs1;
     98 
     99     x = do_shuf_stage(x, shuf_masks[3], shuf_masks[3] >> 8, 8);
    100     x = do_shuf_stage(x, shuf_masks[2], shuf_masks[2] >> 4, 4);
    101     x = do_shuf_stage(x, shuf_masks[1], shuf_masks[1] >> 2, 2);
    102     x = do_shuf_stage(x, shuf_masks[0], shuf_masks[0] >> 1, 1);
    103     return x;
    104 }
    105 
    106 static inline target_ulong do_xperm(target_ulong rs1, target_ulong rs2,
    107                                     uint32_t sz_log2)
    108 {
    109     target_ulong r = 0;
    110     target_ulong sz = 1LL << sz_log2;
    111     target_ulong mask = (1LL << sz) - 1;
    112     target_ulong pos;
    113 
    114     for (int i = 0; i < TARGET_LONG_BITS; i += sz) {
    115         pos = ((rs2 >> i) & mask) << sz_log2;
    116         if (pos < sizeof(target_ulong) * 8) {
    117             r |= ((rs1 >> pos) & mask) << i;
    118         }
    119     }
    120     return r;
    121 }
    122 
    123 target_ulong HELPER(xperm4)(target_ulong rs1, target_ulong rs2)
    124 {
    125     return do_xperm(rs1, rs2, 2);
    126 }
    127 
    128 target_ulong HELPER(xperm8)(target_ulong rs1, target_ulong rs2)
    129 {
    130     return do_xperm(rs1, rs2, 3);
    131 }