]>
Commit | Line | Data |
---|---|---|
831ec7f3 FC |
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 | * | |
7 | * This program is free software; you can redistribute it and/or modify it | |
8 | * under the terms and conditions of the GNU General Public License, | |
9 | * version 2 or later, as published by the Free Software Foundation. | |
10 | * | |
11 | * This program is distributed in the hope it will be useful, but WITHOUT | |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
14 | * more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License along with | |
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
20 | #include "qemu/osdep.h" | |
21 | #include "qemu/host-utils.h" | |
22 | #include "exec/exec-all.h" | |
23 | #include "exec/helper-proto.h" | |
24 | #include "tcg/tcg.h" | |
25 | ||
26 | static const uint64_t adjacent_masks[] = { | |
27 | dup_const(MO_8, 0x55), | |
28 | dup_const(MO_8, 0x33), | |
29 | dup_const(MO_8, 0x0f), | |
30 | dup_const(MO_16, 0xff), | |
31 | dup_const(MO_32, 0xffff), | |
32 | UINT32_MAX | |
33 | }; | |
34 | ||
35 | static inline target_ulong do_swap(target_ulong x, uint64_t mask, int shift) | |
36 | { | |
37 | return ((x & mask) << shift) | ((x & ~mask) >> shift); | |
38 | } | |
39 | ||
40 | static target_ulong do_grev(target_ulong rs1, | |
41 | target_ulong rs2, | |
42 | int bits) | |
43 | { | |
44 | target_ulong x = rs1; | |
45 | int i, shift; | |
46 | ||
47 | for (i = 0, shift = 1; shift < bits; i++, shift <<= 1) { | |
48 | if (rs2 & shift) { | |
49 | x = do_swap(x, adjacent_masks[i], shift); | |
50 | } | |
51 | } | |
52 | ||
53 | return x; | |
54 | } | |
55 | ||
56 | target_ulong HELPER(grev)(target_ulong rs1, target_ulong rs2) | |
57 | { | |
58 | return do_grev(rs1, rs2, TARGET_LONG_BITS); | |
59 | } | |
60 | ||
61 | target_ulong HELPER(grevw)(target_ulong rs1, target_ulong rs2) | |
62 | { | |
63 | return do_grev(rs1, rs2, 32); | |
64 | } | |
c24f0422 FC |
65 | |
66 | static target_ulong do_gorc(target_ulong rs1, | |
67 | target_ulong rs2, | |
68 | int bits) | |
69 | { | |
70 | target_ulong x = rs1; | |
71 | int i, shift; | |
72 | ||
73 | for (i = 0, shift = 1; shift < bits; i++, shift <<= 1) { | |
74 | if (rs2 & shift) { | |
75 | x |= do_swap(x, adjacent_masks[i], shift); | |
76 | } | |
77 | } | |
78 | ||
79 | return x; | |
80 | } | |
81 | ||
82 | target_ulong HELPER(gorc)(target_ulong rs1, target_ulong rs2) | |
83 | { | |
84 | return do_gorc(rs1, rs2, TARGET_LONG_BITS); | |
85 | } | |
86 | ||
87 | target_ulong HELPER(gorcw)(target_ulong rs1, target_ulong rs2) | |
88 | { | |
89 | return do_gorc(rs1, rs2, 32); | |
90 | } |