xref: /qemu/target/riscv/bitmanip_helper.c (revision f9734d5d4078f17daf328b9e113aaffe3d00ecaf)
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  }
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  }
91