1d61931d8SBorislav Petkov #ifndef _ASM_X86_HWEIGHT_H 2d61931d8SBorislav Petkov #define _ASM_X86_HWEIGHT_H 3d61931d8SBorislav Petkov 4cd4d09ecSBorislav Petkov #include <asm/cpufeatures.h> 5cd4d09ecSBorislav Petkov 6d61931d8SBorislav Petkov #ifdef CONFIG_64BIT 7c59bd568SH. Peter Anvin /* popcnt %edi, %eax -- redundant REX prefix for alignment */ 8c59bd568SH. Peter Anvin #define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7" 9d61931d8SBorislav Petkov /* popcnt %rdi, %rax */ 10c59bd568SH. Peter Anvin #define POPCNT64 ".byte 0xf3,0x48,0x0f,0xb8,0xc7" 11d61931d8SBorislav Petkov #define REG_IN "D" 12d61931d8SBorislav Petkov #define REG_OUT "a" 13d61931d8SBorislav Petkov #else 14d61931d8SBorislav Petkov /* popcnt %eax, %eax */ 15c59bd568SH. Peter Anvin #define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc0" 16d61931d8SBorislav Petkov #define REG_IN "a" 17d61931d8SBorislav Petkov #define REG_OUT "a" 18d61931d8SBorislav Petkov #endif 19d61931d8SBorislav Petkov 20d61931d8SBorislav Petkov /* 21d61931d8SBorislav Petkov * __sw_hweightXX are called from within the alternatives below 22d61931d8SBorislav Petkov * and callee-clobbered registers need to be taken care of. See 23d61931d8SBorislav Petkov * ARCH_HWEIGHT_CFLAGS in <arch/x86/Kconfig> for the respective 24d61931d8SBorislav Petkov * compiler switches. 25d61931d8SBorislav Petkov */ 26d14edb16SDenys Vlasenko static __always_inline unsigned int __arch_hweight32(unsigned int w) 27d61931d8SBorislav Petkov { 28d61931d8SBorislav Petkov unsigned int res = 0; 29d61931d8SBorislav Petkov 30c59bd568SH. Peter Anvin asm (ALTERNATIVE("call __sw_hweight32", POPCNT32, X86_FEATURE_POPCNT) 31d61931d8SBorislav Petkov : "="REG_OUT (res) 32d61931d8SBorislav Petkov : REG_IN (w)); 33d61931d8SBorislav Petkov 34d61931d8SBorislav Petkov return res; 35d61931d8SBorislav Petkov } 36d61931d8SBorislav Petkov 37d61931d8SBorislav Petkov static inline unsigned int __arch_hweight16(unsigned int w) 38d61931d8SBorislav Petkov { 39d61931d8SBorislav Petkov return __arch_hweight32(w & 0xffff); 40d61931d8SBorislav Petkov } 41d61931d8SBorislav Petkov 42d61931d8SBorislav Petkov static inline unsigned int __arch_hweight8(unsigned int w) 43d61931d8SBorislav Petkov { 44d61931d8SBorislav Petkov return __arch_hweight32(w & 0xff); 45d61931d8SBorislav Petkov } 46d61931d8SBorislav Petkov 47d14edb16SDenys Vlasenko #ifdef CONFIG_X86_32 48d61931d8SBorislav Petkov static inline unsigned long __arch_hweight64(__u64 w) 49d61931d8SBorislav Petkov { 50d14edb16SDenys Vlasenko return __arch_hweight32((u32)w) + 51d14edb16SDenys Vlasenko __arch_hweight32((u32)(w >> 32)); 52d14edb16SDenys Vlasenko } 53d14edb16SDenys Vlasenko #else 54d14edb16SDenys Vlasenko static __always_inline unsigned long __arch_hweight64(__u64 w) 55d14edb16SDenys Vlasenko { 56d61931d8SBorislav Petkov unsigned long res = 0; 57d61931d8SBorislav Petkov 58c59bd568SH. Peter Anvin asm (ALTERNATIVE("call __sw_hweight64", POPCNT64, X86_FEATURE_POPCNT) 59d61931d8SBorislav Petkov : "="REG_OUT (res) 60d61931d8SBorislav Petkov : REG_IN (w)); 61d61931d8SBorislav Petkov 62d61931d8SBorislav Petkov return res; 63d61931d8SBorislav Petkov } 64d14edb16SDenys Vlasenko #endif /* CONFIG_X86_32 */ 65d61931d8SBorislav Petkov 66d61931d8SBorislav Petkov #endif 67