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