1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _ASM_X86_HWEIGHT_H 3 #define _ASM_X86_HWEIGHT_H 4 5 #include <asm/cpufeatures.h> 6 7 #ifdef CONFIG_64BIT 8 /* popcnt %edi, %eax */ 9 #define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc7" 10 /* popcnt %rdi, %rax */ 11 #define POPCNT64 ".byte 0xf3,0x48,0x0f,0xb8,0xc7" 12 #define REG_IN "D" 13 #define REG_OUT "a" 14 #else 15 /* popcnt %eax, %eax */ 16 #define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc0" 17 #define REG_IN "a" 18 #define REG_OUT "a" 19 #endif 20 21 #define __HAVE_ARCH_SW_HWEIGHT 22 23 static __always_inline unsigned int __arch_hweight32(unsigned int w) 24 { 25 unsigned int res; 26 27 asm (ALTERNATIVE("call __sw_hweight32", POPCNT32, X86_FEATURE_POPCNT) 28 : "="REG_OUT (res) 29 : REG_IN (w)); 30 31 return res; 32 } 33 34 static inline unsigned int __arch_hweight16(unsigned int w) 35 { 36 return __arch_hweight32(w & 0xffff); 37 } 38 39 static inline unsigned int __arch_hweight8(unsigned int w) 40 { 41 return __arch_hweight32(w & 0xff); 42 } 43 44 #ifdef CONFIG_X86_32 45 static inline unsigned long __arch_hweight64(__u64 w) 46 { 47 return __arch_hweight32((u32)w) + 48 __arch_hweight32((u32)(w >> 32)); 49 } 50 #else 51 static __always_inline unsigned long __arch_hweight64(__u64 w) 52 { 53 unsigned long res; 54 55 asm (ALTERNATIVE("call __sw_hweight64", POPCNT64, X86_FEATURE_POPCNT) 56 : "="REG_OUT (res) 57 : REG_IN (w)); 58 59 return res; 60 } 61 #endif /* CONFIG_X86_32 */ 62 63 #endif 64