2 * RISC-V Bitmanip Extension Helpers for QEMU.
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
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.
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
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/>.
21 #include "qemu/osdep.h"
22 #include "qemu/host-utils.h"
23 #include "exec/exec-all.h"
24 #include "exec/helper-proto.h"
27 target_ulong
HELPER(clmul
)(target_ulong rs1
, target_ulong rs2
)
29 target_ulong result
= 0;
31 for (int i
= 0; i
< TARGET_LONG_BITS
; i
++) {
40 target_ulong
HELPER(clmulr
)(target_ulong rs1
, target_ulong rs2
)
42 target_ulong result
= 0;
44 for (int i
= 0; i
< TARGET_LONG_BITS
; i
++) {
46 result
^= (rs1
>> (TARGET_LONG_BITS
- i
- 1));
53 static inline target_ulong
do_swap(target_ulong x
, uint64_t mask
, int shift
)
55 return ((x
& mask
) << shift
) | ((x
& ~mask
) >> shift
);
58 target_ulong
HELPER(brev8
)(target_ulong rs1
)
62 x
= do_swap(x
, 0x5555555555555555ull
, 1);
63 x
= do_swap(x
, 0x3333333333333333ull
, 2);
64 x
= do_swap(x
, 0x0f0f0f0f0f0f0f0full
, 4);
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)
75 static inline target_ulong
do_shuf_stage(target_ulong src
, uint64_t maskL
,
76 uint64_t maskR
, int shift
)
78 target_ulong x
= src
& ~(maskL
| maskR
);
80 x
|= ((src
<< shift
) & maskL
) | ((src
>> shift
) & maskR
);
84 target_ulong
HELPER(unzip
)(target_ulong rs1
)
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);
95 target_ulong
HELPER(zip
)(target_ulong rs1
)
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);
106 static inline target_ulong
do_xperm(target_ulong rs1
, target_ulong rs2
,
110 target_ulong sz
= 1LL << sz_log2
;
111 target_ulong mask
= (1LL << sz
) - 1;
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
;
123 target_ulong
HELPER(xperm4
)(target_ulong rs1
, target_ulong rs2
)
125 return do_xperm(rs1
, rs2
, 2);
128 target_ulong
HELPER(xperm8
)(target_ulong rs1
, target_ulong rs2
)
130 return do_xperm(rs1
, rs2
, 3);