1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Based on arch/x86/include/asm/arch_hweight.h 4 */ 5 6 #ifndef _ASM_RISCV_HWEIGHT_H 7 #define _ASM_RISCV_HWEIGHT_H 8 9 #include <asm/alternative-macros.h> 10 #include <asm/hwcap.h> 11 12 #if (BITS_PER_LONG == 64) 13 #define CPOPW "cpopw " 14 #elif (BITS_PER_LONG == 32) 15 #define CPOPW "cpop " 16 #else 17 #error "Unexpected BITS_PER_LONG" 18 #endif 19 20 static __always_inline unsigned int __arch_hweight32(unsigned int w) 21 { 22 #ifdef CONFIG_RISCV_ISA_ZBB 23 asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0, 24 RISCV_ISA_EXT_ZBB, 1) 25 : : : : legacy); 26 27 asm (".option push\n" 28 ".option arch,+zbb\n" 29 CPOPW "%0, %1\n" 30 ".option pop\n" 31 : "=r" (w) : "r" (w) :); 32 33 return w; 34 35 legacy: 36 #endif 37 return __sw_hweight32(w); 38 } 39 40 static inline unsigned int __arch_hweight16(unsigned int w) 41 { 42 return __arch_hweight32(w & 0xffff); 43 } 44 45 static inline unsigned int __arch_hweight8(unsigned int w) 46 { 47 return __arch_hweight32(w & 0xff); 48 } 49 50 #if BITS_PER_LONG == 64 51 static __always_inline unsigned long __arch_hweight64(__u64 w) 52 { 53 # ifdef CONFIG_RISCV_ISA_ZBB 54 asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0, 55 RISCV_ISA_EXT_ZBB, 1) 56 : : : : legacy); 57 58 asm (".option push\n" 59 ".option arch,+zbb\n" 60 "cpop %0, %1\n" 61 ".option pop\n" 62 : "=r" (w) : "r" (w) :); 63 64 return w; 65 66 legacy: 67 # endif 68 return __sw_hweight64(w); 69 } 70 #else /* BITS_PER_LONG == 64 */ 71 static inline unsigned long __arch_hweight64(__u64 w) 72 { 73 return __arch_hweight32((u32)w) + 74 __arch_hweight32((u32)(w >> 32)); 75 } 76 #endif /* !(BITS_PER_LONG == 64) */ 77 78 #endif /* _ASM_RISCV_HWEIGHT_H */ 79