blob: e7cd63175de443f68aa536237a82a92120ca08f3 [file] [log] [blame]
Borislav Petkovd61931d2010-03-05 17:34:46 +01001#ifndef _ASM_X86_HWEIGHT_H
2#define _ASM_X86_HWEIGHT_H
3
Borislav Petkovcd4d09e2016-01-26 22:12:04 +01004#include <asm/cpufeatures.h>
5
Borislav Petkovd61931d2010-03-05 17:34:46 +01006#ifdef CONFIG_64BIT
Borislav Petkovf5967102016-05-30 12:56:27 +02007/* popcnt %edi, %eax */
8#define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc7"
Borislav Petkovd61931d2010-03-05 17:34:46 +01009/* popcnt %rdi, %rax */
H. Peter Anvinc59bd562010-05-17 15:13:23 -070010#define POPCNT64 ".byte 0xf3,0x48,0x0f,0xb8,0xc7"
Borislav Petkovd61931d2010-03-05 17:34:46 +010011#define REG_IN "D"
12#define REG_OUT "a"
13#else
14/* popcnt %eax, %eax */
H. Peter Anvinc59bd562010-05-17 15:13:23 -070015#define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc0"
Borislav Petkovd61931d2010-03-05 17:34:46 +010016#define REG_IN "a"
17#define REG_OUT "a"
18#endif
19
Borislav Petkovf5967102016-05-30 12:56:27 +020020#define __HAVE_ARCH_SW_HWEIGHT
21
Denys Vlasenkod14edb12015-08-04 16:15:15 +020022static __always_inline unsigned int __arch_hweight32(unsigned int w)
Borislav Petkovd61931d2010-03-05 17:34:46 +010023{
Borislav Petkovf5967102016-05-30 12:56:27 +020024 unsigned int res;
Borislav Petkovd61931d2010-03-05 17:34:46 +010025
H. Peter Anvinc59bd562010-05-17 15:13:23 -070026 asm (ALTERNATIVE("call __sw_hweight32", POPCNT32, X86_FEATURE_POPCNT)
Borislav Petkovf5967102016-05-30 12:56:27 +020027 : "="REG_OUT (res)
28 : REG_IN (w));
Borislav Petkovd61931d2010-03-05 17:34:46 +010029
30 return res;
31}
32
33static inline unsigned int __arch_hweight16(unsigned int w)
34{
35 return __arch_hweight32(w & 0xffff);
36}
37
38static inline unsigned int __arch_hweight8(unsigned int w)
39{
40 return __arch_hweight32(w & 0xff);
41}
42
Denys Vlasenkod14edb12015-08-04 16:15:15 +020043#ifdef CONFIG_X86_32
Borislav Petkovd61931d2010-03-05 17:34:46 +010044static inline unsigned long __arch_hweight64(__u64 w)
45{
Denys Vlasenkod14edb12015-08-04 16:15:15 +020046 return __arch_hweight32((u32)w) +
47 __arch_hweight32((u32)(w >> 32));
48}
49#else
50static __always_inline unsigned long __arch_hweight64(__u64 w)
51{
Borislav Petkovf5967102016-05-30 12:56:27 +020052 unsigned long res;
Borislav Petkovd61931d2010-03-05 17:34:46 +010053
H. Peter Anvinc59bd562010-05-17 15:13:23 -070054 asm (ALTERNATIVE("call __sw_hweight64", POPCNT64, X86_FEATURE_POPCNT)
Borislav Petkovf5967102016-05-30 12:56:27 +020055 : "="REG_OUT (res)
56 : REG_IN (w));
Borislav Petkovd61931d2010-03-05 17:34:46 +010057
58 return res;
59}
Denys Vlasenkod14edb12015-08-04 16:15:15 +020060#endif /* CONFIG_X86_32 */
Borislav Petkovd61931d2010-03-05 17:34:46 +010061
62#endif