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 6831ec7f3SFrank Chang * 7831ec7f3SFrank Chang * This program is free software; you can redistribute it and/or modify it 8831ec7f3SFrank Chang * under the terms and conditions of the GNU General Public License, 9831ec7f3SFrank Chang * version 2 or later, as published by the Free Software Foundation. 10831ec7f3SFrank Chang * 11831ec7f3SFrank Chang * This program is distributed in the hope it will be useful, but WITHOUT 12831ec7f3SFrank Chang * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13831ec7f3SFrank Chang * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14831ec7f3SFrank Chang * more details. 15831ec7f3SFrank Chang * 16831ec7f3SFrank Chang * You should have received a copy of the GNU General Public License along with 17831ec7f3SFrank Chang * this program. If not, see <http://www.gnu.org/licenses/>. 18831ec7f3SFrank Chang */ 19831ec7f3SFrank Chang 20831ec7f3SFrank Chang #include "qemu/osdep.h" 21831ec7f3SFrank Chang #include "qemu/host-utils.h" 22831ec7f3SFrank Chang #include "exec/exec-all.h" 23831ec7f3SFrank Chang #include "exec/helper-proto.h" 24831ec7f3SFrank Chang #include "tcg/tcg.h" 25831ec7f3SFrank Chang 26831ec7f3SFrank Chang static const uint64_t adjacent_masks[] = { 27831ec7f3SFrank Chang dup_const(MO_8, 0x55), 28831ec7f3SFrank Chang dup_const(MO_8, 0x33), 29831ec7f3SFrank Chang dup_const(MO_8, 0x0f), 30831ec7f3SFrank Chang dup_const(MO_16, 0xff), 31831ec7f3SFrank Chang dup_const(MO_32, 0xffff), 32831ec7f3SFrank Chang UINT32_MAX 33831ec7f3SFrank Chang }; 34831ec7f3SFrank Chang 35831ec7f3SFrank Chang static inline target_ulong do_swap(target_ulong x, uint64_t mask, int shift) 36831ec7f3SFrank Chang { 37831ec7f3SFrank Chang return ((x & mask) << shift) | ((x & ~mask) >> shift); 38831ec7f3SFrank Chang } 39831ec7f3SFrank Chang 40831ec7f3SFrank Chang static target_ulong do_grev(target_ulong rs1, 41831ec7f3SFrank Chang target_ulong rs2, 42831ec7f3SFrank Chang int bits) 43831ec7f3SFrank Chang { 44831ec7f3SFrank Chang target_ulong x = rs1; 45831ec7f3SFrank Chang int i, shift; 46831ec7f3SFrank Chang 47831ec7f3SFrank Chang for (i = 0, shift = 1; shift < bits; i++, shift <<= 1) { 48831ec7f3SFrank Chang if (rs2 & shift) { 49831ec7f3SFrank Chang x = do_swap(x, adjacent_masks[i], shift); 50831ec7f3SFrank Chang } 51831ec7f3SFrank Chang } 52831ec7f3SFrank Chang 53831ec7f3SFrank Chang return x; 54831ec7f3SFrank Chang } 55831ec7f3SFrank Chang 56831ec7f3SFrank Chang target_ulong HELPER(grev)(target_ulong rs1, target_ulong rs2) 57831ec7f3SFrank Chang { 58831ec7f3SFrank Chang return do_grev(rs1, rs2, TARGET_LONG_BITS); 59831ec7f3SFrank Chang } 60831ec7f3SFrank Chang 61831ec7f3SFrank Chang target_ulong HELPER(grevw)(target_ulong rs1, target_ulong rs2) 62831ec7f3SFrank Chang { 63831ec7f3SFrank Chang return do_grev(rs1, rs2, 32); 64831ec7f3SFrank Chang } 65*c24f0422SFrank Chang 66*c24f0422SFrank Chang static target_ulong do_gorc(target_ulong rs1, 67*c24f0422SFrank Chang target_ulong rs2, 68*c24f0422SFrank Chang int bits) 69*c24f0422SFrank Chang { 70*c24f0422SFrank Chang target_ulong x = rs1; 71*c24f0422SFrank Chang int i, shift; 72*c24f0422SFrank Chang 73*c24f0422SFrank Chang for (i = 0, shift = 1; shift < bits; i++, shift <<= 1) { 74*c24f0422SFrank Chang if (rs2 & shift) { 75*c24f0422SFrank Chang x |= do_swap(x, adjacent_masks[i], shift); 76*c24f0422SFrank Chang } 77*c24f0422SFrank Chang } 78*c24f0422SFrank Chang 79*c24f0422SFrank Chang return x; 80*c24f0422SFrank Chang } 81*c24f0422SFrank Chang 82*c24f0422SFrank Chang target_ulong HELPER(gorc)(target_ulong rs1, target_ulong rs2) 83*c24f0422SFrank Chang { 84*c24f0422SFrank Chang return do_gorc(rs1, rs2, TARGET_LONG_BITS); 85*c24f0422SFrank Chang } 86*c24f0422SFrank Chang 87*c24f0422SFrank Chang target_ulong HELPER(gorcw)(target_ulong rs1, target_ulong rs2) 88*c24f0422SFrank Chang { 89*c24f0422SFrank Chang return do_gorc(rs1, rs2, 32); 90*c24f0422SFrank Chang } 91