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