xref: /openbmc/linux/arch/x86/lib/hweight.S (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */
2f5967101SBorislav Petkov#include <linux/linkage.h>
3784d5699SAl Viro#include <asm/export.h>
4f5967101SBorislav Petkov
5f5967101SBorislav Petkov#include <asm/asm.h>
6f5967101SBorislav Petkov
7f5967101SBorislav Petkov/*
8f5967101SBorislav Petkov * unsigned int __sw_hweight32(unsigned int w)
9f5967101SBorislav Petkov * %rdi: w
10f5967101SBorislav Petkov */
116dcc5627SJiri SlabySYM_FUNC_START(__sw_hweight32)
12f5967101SBorislav Petkov
13f5967101SBorislav Petkov#ifdef CONFIG_X86_64
14f5967101SBorislav Petkov	movl %edi, %eax				# w
15f5967101SBorislav Petkov#endif
16f5967101SBorislav Petkov	__ASM_SIZE(push,) %__ASM_REG(dx)
17f5967101SBorislav Petkov	movl %eax, %edx				# w -> t
18f5967101SBorislav Petkov	shrl %edx				# t >>= 1
19f5967101SBorislav Petkov	andl $0x55555555, %edx			# t &= 0x55555555
20f5967101SBorislav Petkov	subl %edx, %eax				# w -= t
21f5967101SBorislav Petkov
22f5967101SBorislav Petkov	movl %eax, %edx				# w -> t
23f5967101SBorislav Petkov	shrl $2, %eax				# w_tmp >>= 2
24f5967101SBorislav Petkov	andl $0x33333333, %edx			# t	&= 0x33333333
25f5967101SBorislav Petkov	andl $0x33333333, %eax			# w_tmp &= 0x33333333
26f5967101SBorislav Petkov	addl %edx, %eax				# w = w_tmp + t
27f5967101SBorislav Petkov
28f5967101SBorislav Petkov	movl %eax, %edx				# w -> t
29f5967101SBorislav Petkov	shrl $4, %edx				# t >>= 4
30f5967101SBorislav Petkov	addl %edx, %eax				# w_tmp += t
31f5967101SBorislav Petkov	andl  $0x0f0f0f0f, %eax			# w_tmp &= 0x0f0f0f0f
32f5967101SBorislav Petkov	imull $0x01010101, %eax, %eax		# w_tmp *= 0x01010101
33f5967101SBorislav Petkov	shrl $24, %eax				# w = w_tmp >> 24
34f5967101SBorislav Petkov	__ASM_SIZE(pop,) %__ASM_REG(dx)
35*f94909ceSPeter Zijlstra	RET
366dcc5627SJiri SlabySYM_FUNC_END(__sw_hweight32)
37784d5699SAl ViroEXPORT_SYMBOL(__sw_hweight32)
38f5967101SBorislav Petkov
396dcc5627SJiri SlabySYM_FUNC_START(__sw_hweight64)
40f5967101SBorislav Petkov#ifdef CONFIG_X86_64
4165ea11ecSVille Syrjälä	pushq   %rdi
42f5967101SBorislav Petkov	pushq   %rdx
43f5967101SBorislav Petkov
44f5967101SBorislav Petkov	movq    %rdi, %rdx                      # w -> t
45f5967101SBorislav Petkov	movabsq $0x5555555555555555, %rax
46f5967101SBorislav Petkov	shrq    %rdx                            # t >>= 1
47f5967101SBorislav Petkov	andq    %rdx, %rax                      # t &= 0x5555555555555555
48f5967101SBorislav Petkov	movabsq $0x3333333333333333, %rdx
49f5967101SBorislav Petkov	subq    %rax, %rdi                      # w -= t
50f5967101SBorislav Petkov
51f5967101SBorislav Petkov	movq    %rdi, %rax                      # w -> t
52f5967101SBorislav Petkov	shrq    $2, %rdi                        # w_tmp >>= 2
53f5967101SBorislav Petkov	andq    %rdx, %rax                      # t     &= 0x3333333333333333
54f5967101SBorislav Petkov	andq    %rdi, %rdx                      # w_tmp &= 0x3333333333333333
55f5967101SBorislav Petkov	addq    %rdx, %rax                      # w = w_tmp + t
56f5967101SBorislav Petkov
57f5967101SBorislav Petkov	movq    %rax, %rdx                      # w -> t
58f5967101SBorislav Petkov	shrq    $4, %rdx                        # t >>= 4
59f5967101SBorislav Petkov	addq    %rdx, %rax                      # w_tmp += t
60f5967101SBorislav Petkov	movabsq $0x0f0f0f0f0f0f0f0f, %rdx
61f5967101SBorislav Petkov	andq    %rdx, %rax                      # w_tmp &= 0x0f0f0f0f0f0f0f0f
62f5967101SBorislav Petkov	movabsq $0x0101010101010101, %rdx
63f5967101SBorislav Petkov	imulq   %rdx, %rax                      # w_tmp *= 0x0101010101010101
64f5967101SBorislav Petkov	shrq    $56, %rax                       # w = w_tmp >> 56
65f5967101SBorislav Petkov
66f5967101SBorislav Petkov	popq    %rdx
6765ea11ecSVille Syrjälä	popq    %rdi
68*f94909ceSPeter Zijlstra	RET
69f5967101SBorislav Petkov#else /* CONFIG_X86_32 */
70f5967101SBorislav Petkov	/* We're getting an u64 arg in (%eax,%edx): unsigned long hweight64(__u64 w) */
71f5967101SBorislav Petkov	pushl   %ecx
72f5967101SBorislav Petkov
73f5967101SBorislav Petkov	call    __sw_hweight32
74f5967101SBorislav Petkov	movl    %eax, %ecx                      # stash away result
75f5967101SBorislav Petkov	movl    %edx, %eax                      # second part of input
76f5967101SBorislav Petkov	call    __sw_hweight32
77f5967101SBorislav Petkov	addl    %ecx, %eax                      # result
78f5967101SBorislav Petkov
79f5967101SBorislav Petkov	popl    %ecx
80*f94909ceSPeter Zijlstra	RET
81f5967101SBorislav Petkov#endif
826dcc5627SJiri SlabySYM_FUNC_END(__sw_hweight64)
83784d5699SAl ViroEXPORT_SYMBOL(__sw_hweight64)
84