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