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 * Copyright (c) 2021 Philipp Tomsich, philipp.tomsich@vrull.eu 7 * 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. 11 * 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 15 * more details. 16 * 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/>. 19 */ 20 21 #include "qemu/osdep.h" 22 #include "qemu/host-utils.h" 23 #include "exec/exec-all.h" 24 #include "exec/helper-proto.h" 25 #include "tcg/tcg.h" 26 27 static const uint64_t adjacent_masks[] = { 28 dup_const(MO_8, 0x55), 29 dup_const(MO_8, 0x33), 30 dup_const(MO_8, 0x0f), 31 dup_const(MO_16, 0xff), 32 dup_const(MO_32, 0xffff), 33 UINT32_MAX 34 }; 35 36 static inline target_ulong do_swap(target_ulong x, uint64_t mask, int shift) 37 { 38 return ((x & mask) << shift) | ((x & ~mask) >> shift); 39 } 40 41 static target_ulong do_grev(target_ulong rs1, 42 target_ulong rs2, 43 int bits) 44 { 45 target_ulong x = rs1; 46 int i, shift; 47 48 for (i = 0, shift = 1; shift < bits; i++, shift <<= 1) { 49 if (rs2 & shift) { 50 x = do_swap(x, adjacent_masks[i], shift); 51 } 52 } 53 54 return x; 55 } 56 57 target_ulong HELPER(grev)(target_ulong rs1, target_ulong rs2) 58 { 59 return do_grev(rs1, rs2, TARGET_LONG_BITS); 60 } 61 62 target_ulong HELPER(grevw)(target_ulong rs1, target_ulong rs2) 63 { 64 return do_grev(rs1, rs2, 32); 65 } 66 67 target_ulong HELPER(clmul)(target_ulong rs1, target_ulong rs2) 68 { 69 target_ulong result = 0; 70 71 for (int i = 0; i < TARGET_LONG_BITS; i++) { 72 if ((rs2 >> i) & 1) { 73 result ^= (rs1 << i); 74 } 75 } 76 77 return result; 78 } 79 80 target_ulong HELPER(clmulr)(target_ulong rs1, target_ulong rs2) 81 { 82 target_ulong result = 0; 83 84 for (int i = 0; i < TARGET_LONG_BITS; i++) { 85 if ((rs2 >> i) & 1) { 86 result ^= (rs1 >> (TARGET_LONG_BITS - i - 1)); 87 } 88 } 89 90 return result; 91 } 92