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 target_ulong HELPER(clmul)(target_ulong rs1, target_ulong rs2) 28 { 29 target_ulong result = 0; 30 31 for (int i = 0; i < TARGET_LONG_BITS; i++) { 32 if ((rs2 >> i) & 1) { 33 result ^= (rs1 << i); 34 } 35 } 36 37 return result; 38 } 39 40 target_ulong HELPER(clmulr)(target_ulong rs1, target_ulong rs2) 41 { 42 target_ulong result = 0; 43 44 for (int i = 0; i < TARGET_LONG_BITS; i++) { 45 if ((rs2 >> i) & 1) { 46 result ^= (rs1 >> (TARGET_LONG_BITS - i - 1)); 47 } 48 } 49 50 return result; 51 } 52 53 static inline target_ulong do_swap(target_ulong x, uint64_t mask, int shift) 54 { 55 return ((x & mask) << shift) | ((x & ~mask) >> shift); 56 } 57 58 target_ulong HELPER(brev8)(target_ulong rs1) 59 { 60 target_ulong x = rs1; 61 62 x = do_swap(x, 0x5555555555555555ull, 1); 63 x = do_swap(x, 0x3333333333333333ull, 2); 64 x = do_swap(x, 0x0f0f0f0f0f0f0f0full, 4); 65 return x; 66 } 67 68 static const uint64_t shuf_masks[] = { 69 dup_const(MO_8, 0x44), 70 dup_const(MO_8, 0x30), 71 dup_const(MO_16, 0x0f00), 72 dup_const(MO_32, 0xff0000) 73 }; 74 75 static inline target_ulong do_shuf_stage(target_ulong src, uint64_t maskL, 76 uint64_t maskR, int shift) 77 { 78 target_ulong x = src & ~(maskL | maskR); 79 80 x |= ((src << shift) & maskL) | ((src >> shift) & maskR); 81 return x; 82 } 83 84 target_ulong HELPER(unzip)(target_ulong rs1) 85 { 86 target_ulong x = rs1; 87 88 x = do_shuf_stage(x, shuf_masks[0], shuf_masks[0] >> 1, 1); 89 x = do_shuf_stage(x, shuf_masks[1], shuf_masks[1] >> 2, 2); 90 x = do_shuf_stage(x, shuf_masks[2], shuf_masks[2] >> 4, 4); 91 x = do_shuf_stage(x, shuf_masks[3], shuf_masks[3] >> 8, 8); 92 return x; 93 } 94 95 target_ulong HELPER(zip)(target_ulong rs1) 96 { 97 target_ulong x = rs1; 98 99 x = do_shuf_stage(x, shuf_masks[3], shuf_masks[3] >> 8, 8); 100 x = do_shuf_stage(x, shuf_masks[2], shuf_masks[2] >> 4, 4); 101 x = do_shuf_stage(x, shuf_masks[1], shuf_masks[1] >> 2, 2); 102 x = do_shuf_stage(x, shuf_masks[0], shuf_masks[0] >> 1, 1); 103 return x; 104 } 105 106 static inline target_ulong do_xperm(target_ulong rs1, target_ulong rs2, 107 uint32_t sz_log2) 108 { 109 target_ulong r = 0; 110 target_ulong sz = 1LL << sz_log2; 111 target_ulong mask = (1LL << sz) - 1; 112 target_ulong pos; 113 114 for (int i = 0; i < TARGET_LONG_BITS; i += sz) { 115 pos = ((rs2 >> i) & mask) << sz_log2; 116 if (pos < sizeof(target_ulong) * 8) { 117 r |= ((rs1 >> pos) & mask) << i; 118 } 119 } 120 return r; 121 } 122 123 target_ulong HELPER(xperm4)(target_ulong rs1, target_ulong rs2) 124 { 125 return do_xperm(rs1, rs2, 2); 126 } 127 128 target_ulong HELPER(xperm8)(target_ulong rs1, target_ulong rs2) 129 { 130 return do_xperm(rs1, rs2, 3); 131 } 132