xref: /qemu/target/riscv/bitmanip_helper.c (revision fd4b81a304a5d50e719019d22eacca2d8ef4de69)
1831ec7f3SFrank Chang /*
2831ec7f3SFrank Chang  * RISC-V Bitmanip Extension Helpers for QEMU.
3831ec7f3SFrank Chang  *
4831ec7f3SFrank Chang  * Copyright (c) 2020 Kito Cheng, kito.cheng@sifive.com
5831ec7f3SFrank Chang  * Copyright (c) 2020 Frank Chang, frank.chang@sifive.com
6*fd4b81a3SPhilipp Tomsich  * Copyright (c) 2021 Philipp Tomsich, philipp.tomsich@vrull.eu
7831ec7f3SFrank Chang  *
8831ec7f3SFrank Chang  * This program is free software; you can redistribute it and/or modify it
9831ec7f3SFrank Chang  * under the terms and conditions of the GNU General Public License,
10831ec7f3SFrank Chang  * version 2 or later, as published by the Free Software Foundation.
11831ec7f3SFrank Chang  *
12831ec7f3SFrank Chang  * This program is distributed in the hope it will be useful, but WITHOUT
13831ec7f3SFrank Chang  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14831ec7f3SFrank Chang  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15831ec7f3SFrank Chang  * more details.
16831ec7f3SFrank Chang  *
17831ec7f3SFrank Chang  * You should have received a copy of the GNU General Public License along with
18831ec7f3SFrank Chang  * this program.  If not, see <http://www.gnu.org/licenses/>.
19831ec7f3SFrank Chang  */
20831ec7f3SFrank Chang 
21831ec7f3SFrank Chang #include "qemu/osdep.h"
22831ec7f3SFrank Chang #include "qemu/host-utils.h"
23831ec7f3SFrank Chang #include "exec/exec-all.h"
24831ec7f3SFrank Chang #include "exec/helper-proto.h"
25831ec7f3SFrank Chang #include "tcg/tcg.h"
26831ec7f3SFrank Chang 
27831ec7f3SFrank Chang static const uint64_t adjacent_masks[] = {
28831ec7f3SFrank Chang     dup_const(MO_8, 0x55),
29831ec7f3SFrank Chang     dup_const(MO_8, 0x33),
30831ec7f3SFrank Chang     dup_const(MO_8, 0x0f),
31831ec7f3SFrank Chang     dup_const(MO_16, 0xff),
32831ec7f3SFrank Chang     dup_const(MO_32, 0xffff),
33831ec7f3SFrank Chang     UINT32_MAX
34831ec7f3SFrank Chang };
35831ec7f3SFrank Chang 
36831ec7f3SFrank Chang static inline target_ulong do_swap(target_ulong x, uint64_t mask, int shift)
37831ec7f3SFrank Chang {
38831ec7f3SFrank Chang     return ((x & mask) << shift) | ((x & ~mask) >> shift);
39831ec7f3SFrank Chang }
40831ec7f3SFrank Chang 
41831ec7f3SFrank Chang static target_ulong do_grev(target_ulong rs1,
42831ec7f3SFrank Chang                             target_ulong rs2,
43831ec7f3SFrank Chang                             int bits)
44831ec7f3SFrank Chang {
45831ec7f3SFrank Chang     target_ulong x = rs1;
46831ec7f3SFrank Chang     int i, shift;
47831ec7f3SFrank Chang 
48831ec7f3SFrank Chang     for (i = 0, shift = 1; shift < bits; i++, shift <<= 1) {
49831ec7f3SFrank Chang         if (rs2 & shift) {
50831ec7f3SFrank Chang             x = do_swap(x, adjacent_masks[i], shift);
51831ec7f3SFrank Chang         }
52831ec7f3SFrank Chang     }
53831ec7f3SFrank Chang 
54831ec7f3SFrank Chang     return x;
55831ec7f3SFrank Chang }
56831ec7f3SFrank Chang 
57831ec7f3SFrank Chang target_ulong HELPER(grev)(target_ulong rs1, target_ulong rs2)
58831ec7f3SFrank Chang {
59831ec7f3SFrank Chang     return do_grev(rs1, rs2, TARGET_LONG_BITS);
60831ec7f3SFrank Chang }
61831ec7f3SFrank Chang 
62831ec7f3SFrank Chang target_ulong HELPER(grevw)(target_ulong rs1, target_ulong rs2)
63831ec7f3SFrank Chang {
64831ec7f3SFrank Chang     return do_grev(rs1, rs2, 32);
65831ec7f3SFrank Chang }
66c24f0422SFrank Chang 
67c24f0422SFrank Chang static target_ulong do_gorc(target_ulong rs1,
68c24f0422SFrank Chang                             target_ulong rs2,
69c24f0422SFrank Chang                             int bits)
70c24f0422SFrank Chang {
71c24f0422SFrank Chang     target_ulong x = rs1;
72c24f0422SFrank Chang     int i, shift;
73c24f0422SFrank Chang 
74c24f0422SFrank Chang     for (i = 0, shift = 1; shift < bits; i++, shift <<= 1) {
75c24f0422SFrank Chang         if (rs2 & shift) {
76c24f0422SFrank Chang             x |= do_swap(x, adjacent_masks[i], shift);
77c24f0422SFrank Chang         }
78c24f0422SFrank Chang     }
79c24f0422SFrank Chang 
80c24f0422SFrank Chang     return x;
81c24f0422SFrank Chang }
82c24f0422SFrank Chang 
83c24f0422SFrank Chang target_ulong HELPER(gorc)(target_ulong rs1, target_ulong rs2)
84c24f0422SFrank Chang {
85c24f0422SFrank Chang     return do_gorc(rs1, rs2, TARGET_LONG_BITS);
86c24f0422SFrank Chang }
87c24f0422SFrank Chang 
88c24f0422SFrank Chang target_ulong HELPER(gorcw)(target_ulong rs1, target_ulong rs2)
89c24f0422SFrank Chang {
90c24f0422SFrank Chang     return do_gorc(rs1, rs2, 32);
91c24f0422SFrank Chang }
92*fd4b81a3SPhilipp Tomsich 
93*fd4b81a3SPhilipp Tomsich target_ulong HELPER(clmul)(target_ulong rs1, target_ulong rs2)
94*fd4b81a3SPhilipp Tomsich {
95*fd4b81a3SPhilipp Tomsich     target_ulong result = 0;
96*fd4b81a3SPhilipp Tomsich 
97*fd4b81a3SPhilipp Tomsich     for (int i = 0; i < TARGET_LONG_BITS; i++) {
98*fd4b81a3SPhilipp Tomsich         if ((rs2 >> i) & 1) {
99*fd4b81a3SPhilipp Tomsich             result ^= (rs1 << i);
100*fd4b81a3SPhilipp Tomsich         }
101*fd4b81a3SPhilipp Tomsich     }
102*fd4b81a3SPhilipp Tomsich 
103*fd4b81a3SPhilipp Tomsich     return result;
104*fd4b81a3SPhilipp Tomsich }
105*fd4b81a3SPhilipp Tomsich 
106*fd4b81a3SPhilipp Tomsich target_ulong HELPER(clmulr)(target_ulong rs1, target_ulong rs2)
107*fd4b81a3SPhilipp Tomsich {
108*fd4b81a3SPhilipp Tomsich     target_ulong result = 0;
109*fd4b81a3SPhilipp Tomsich 
110*fd4b81a3SPhilipp Tomsich     for (int i = 0; i < TARGET_LONG_BITS; i++) {
111*fd4b81a3SPhilipp Tomsich         if ((rs2 >> i) & 1) {
112*fd4b81a3SPhilipp Tomsich             result ^= (rs1 >> (TARGET_LONG_BITS - i - 1));
113*fd4b81a3SPhilipp Tomsich         }
114*fd4b81a3SPhilipp Tomsich     }
115*fd4b81a3SPhilipp Tomsich 
116*fd4b81a3SPhilipp Tomsich     return result;
117*fd4b81a3SPhilipp Tomsich }
118