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