diff options
Diffstat (limited to 'arch/x86/include/asm/arch_hweight.h')
-rw-r--r-- | arch/x86/include/asm/arch_hweight.h | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/arch/x86/include/asm/arch_hweight.h b/arch/x86/include/asm/arch_hweight.h new file mode 100644 index 000000000..ba88edd0d --- /dev/null +++ b/arch/x86/include/asm/arch_hweight.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_X86_HWEIGHT_H +#define _ASM_X86_HWEIGHT_H + +#include <asm/cpufeatures.h> + +#ifdef CONFIG_64BIT +#define REG_IN "D" +#define REG_OUT "a" +#else +#define REG_IN "a" +#define REG_OUT "a" +#endif + +static __always_inline unsigned int __arch_hweight32(unsigned int w) +{ + unsigned int res; + + asm (ALTERNATIVE("call __sw_hweight32", "popcntl %1, %0", X86_FEATURE_POPCNT) + : "="REG_OUT (res) + : REG_IN (w)); + + return res; +} + +static inline unsigned int __arch_hweight16(unsigned int w) +{ + return __arch_hweight32(w & 0xffff); +} + +static inline unsigned int __arch_hweight8(unsigned int w) +{ + return __arch_hweight32(w & 0xff); +} + +#ifdef CONFIG_X86_32 +static inline unsigned long __arch_hweight64(__u64 w) +{ + return __arch_hweight32((u32)w) + + __arch_hweight32((u32)(w >> 32)); +} +#else +static __always_inline unsigned long __arch_hweight64(__u64 w) +{ + unsigned long res; + + asm (ALTERNATIVE("call __sw_hweight64", "popcntq %1, %0", X86_FEATURE_POPCNT) + : "="REG_OUT (res) + : REG_IN (w)); + + return res; +} +#endif /* CONFIG_X86_32 */ + +#endif |