18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _ASM_X86_BITOPS_H
38c2ecf20Sopenharmony_ci#define _ASM_X86_BITOPS_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci/*
68c2ecf20Sopenharmony_ci * Copyright 1992, Linus Torvalds.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Note: inlines with more than a single statement should be marked
98c2ecf20Sopenharmony_ci * __always_inline to avoid problems with older gcc's inlining heuristics.
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#ifndef _LINUX_BITOPS_H
138c2ecf20Sopenharmony_ci#error only <linux/bitops.h> can be included directly
148c2ecf20Sopenharmony_ci#endif
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include <linux/compiler.h>
178c2ecf20Sopenharmony_ci#include <asm/alternative.h>
188c2ecf20Sopenharmony_ci#include <asm/rmwcc.h>
198c2ecf20Sopenharmony_ci#include <asm/barrier.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#if BITS_PER_LONG == 32
228c2ecf20Sopenharmony_ci# define _BITOPS_LONG_SHIFT 5
238c2ecf20Sopenharmony_ci#elif BITS_PER_LONG == 64
248c2ecf20Sopenharmony_ci# define _BITOPS_LONG_SHIFT 6
258c2ecf20Sopenharmony_ci#else
268c2ecf20Sopenharmony_ci# error "Unexpected BITS_PER_LONG"
278c2ecf20Sopenharmony_ci#endif
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#define BIT_64(n)			(U64_C(1) << (n))
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/*
328c2ecf20Sopenharmony_ci * These have to be done with inline assembly: that way the bit-setting
338c2ecf20Sopenharmony_ci * is guaranteed to be atomic. All bit operations return 0 if the bit
348c2ecf20Sopenharmony_ci * was cleared before the operation and != 0 if it was not.
358c2ecf20Sopenharmony_ci *
368c2ecf20Sopenharmony_ci * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
378c2ecf20Sopenharmony_ci */
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#define RLONG_ADDR(x)			 "m" (*(volatile long *) (x))
408c2ecf20Sopenharmony_ci#define WBYTE_ADDR(x)			"+m" (*(volatile char *) (x))
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci#define ADDR				RLONG_ADDR(addr)
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci/*
458c2ecf20Sopenharmony_ci * We do the locked ops that don't return the old value as
468c2ecf20Sopenharmony_ci * a mask operation on a byte.
478c2ecf20Sopenharmony_ci */
488c2ecf20Sopenharmony_ci#define CONST_MASK_ADDR(nr, addr)	WBYTE_ADDR((void *)(addr) + ((nr)>>3))
498c2ecf20Sopenharmony_ci#define CONST_MASK(nr)			(1 << ((nr) & 7))
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_cistatic __always_inline void
528c2ecf20Sopenharmony_ciarch_set_bit(long nr, volatile unsigned long *addr)
538c2ecf20Sopenharmony_ci{
548c2ecf20Sopenharmony_ci	if (__builtin_constant_p(nr)) {
558c2ecf20Sopenharmony_ci		asm volatile(LOCK_PREFIX "orb %b1,%0"
568c2ecf20Sopenharmony_ci			: CONST_MASK_ADDR(nr, addr)
578c2ecf20Sopenharmony_ci			: "iq" (CONST_MASK(nr))
588c2ecf20Sopenharmony_ci			: "memory");
598c2ecf20Sopenharmony_ci	} else {
608c2ecf20Sopenharmony_ci		asm volatile(LOCK_PREFIX __ASM_SIZE(bts) " %1,%0"
618c2ecf20Sopenharmony_ci			: : RLONG_ADDR(addr), "Ir" (nr) : "memory");
628c2ecf20Sopenharmony_ci	}
638c2ecf20Sopenharmony_ci}
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic __always_inline void
668c2ecf20Sopenharmony_ciarch___set_bit(long nr, volatile unsigned long *addr)
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	asm volatile(__ASM_SIZE(bts) " %1,%0" : : ADDR, "Ir" (nr) : "memory");
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistatic __always_inline void
728c2ecf20Sopenharmony_ciarch_clear_bit(long nr, volatile unsigned long *addr)
738c2ecf20Sopenharmony_ci{
748c2ecf20Sopenharmony_ci	if (__builtin_constant_p(nr)) {
758c2ecf20Sopenharmony_ci		asm volatile(LOCK_PREFIX "andb %b1,%0"
768c2ecf20Sopenharmony_ci			: CONST_MASK_ADDR(nr, addr)
778c2ecf20Sopenharmony_ci			: "iq" (~CONST_MASK(nr)));
788c2ecf20Sopenharmony_ci	} else {
798c2ecf20Sopenharmony_ci		asm volatile(LOCK_PREFIX __ASM_SIZE(btr) " %1,%0"
808c2ecf20Sopenharmony_ci			: : RLONG_ADDR(addr), "Ir" (nr) : "memory");
818c2ecf20Sopenharmony_ci	}
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistatic __always_inline void
858c2ecf20Sopenharmony_ciarch_clear_bit_unlock(long nr, volatile unsigned long *addr)
868c2ecf20Sopenharmony_ci{
878c2ecf20Sopenharmony_ci	barrier();
888c2ecf20Sopenharmony_ci	arch_clear_bit(nr, addr);
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic __always_inline void
928c2ecf20Sopenharmony_ciarch___clear_bit(long nr, volatile unsigned long *addr)
938c2ecf20Sopenharmony_ci{
948c2ecf20Sopenharmony_ci	asm volatile(__ASM_SIZE(btr) " %1,%0" : : ADDR, "Ir" (nr) : "memory");
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cistatic __always_inline bool
988c2ecf20Sopenharmony_ciarch_clear_bit_unlock_is_negative_byte(long nr, volatile unsigned long *addr)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	bool negative;
1018c2ecf20Sopenharmony_ci	asm volatile(LOCK_PREFIX "andb %2,%1"
1028c2ecf20Sopenharmony_ci		CC_SET(s)
1038c2ecf20Sopenharmony_ci		: CC_OUT(s) (negative), WBYTE_ADDR(addr)
1048c2ecf20Sopenharmony_ci		: "ir" ((char) ~(1 << nr)) : "memory");
1058c2ecf20Sopenharmony_ci	return negative;
1068c2ecf20Sopenharmony_ci}
1078c2ecf20Sopenharmony_ci#define arch_clear_bit_unlock_is_negative_byte                                 \
1088c2ecf20Sopenharmony_ci	arch_clear_bit_unlock_is_negative_byte
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cistatic __always_inline void
1118c2ecf20Sopenharmony_ciarch___clear_bit_unlock(long nr, volatile unsigned long *addr)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	arch___clear_bit(nr, addr);
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cistatic __always_inline void
1178c2ecf20Sopenharmony_ciarch___change_bit(long nr, volatile unsigned long *addr)
1188c2ecf20Sopenharmony_ci{
1198c2ecf20Sopenharmony_ci	asm volatile(__ASM_SIZE(btc) " %1,%0" : : ADDR, "Ir" (nr) : "memory");
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cistatic __always_inline void
1238c2ecf20Sopenharmony_ciarch_change_bit(long nr, volatile unsigned long *addr)
1248c2ecf20Sopenharmony_ci{
1258c2ecf20Sopenharmony_ci	if (__builtin_constant_p(nr)) {
1268c2ecf20Sopenharmony_ci		asm volatile(LOCK_PREFIX "xorb %b1,%0"
1278c2ecf20Sopenharmony_ci			: CONST_MASK_ADDR(nr, addr)
1288c2ecf20Sopenharmony_ci			: "iq" (CONST_MASK(nr)));
1298c2ecf20Sopenharmony_ci	} else {
1308c2ecf20Sopenharmony_ci		asm volatile(LOCK_PREFIX __ASM_SIZE(btc) " %1,%0"
1318c2ecf20Sopenharmony_ci			: : RLONG_ADDR(addr), "Ir" (nr) : "memory");
1328c2ecf20Sopenharmony_ci	}
1338c2ecf20Sopenharmony_ci}
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_cistatic __always_inline bool
1368c2ecf20Sopenharmony_ciarch_test_and_set_bit(long nr, volatile unsigned long *addr)
1378c2ecf20Sopenharmony_ci{
1388c2ecf20Sopenharmony_ci	return GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(bts), *addr, c, "Ir", nr);
1398c2ecf20Sopenharmony_ci}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistatic __always_inline bool
1428c2ecf20Sopenharmony_ciarch_test_and_set_bit_lock(long nr, volatile unsigned long *addr)
1438c2ecf20Sopenharmony_ci{
1448c2ecf20Sopenharmony_ci	return arch_test_and_set_bit(nr, addr);
1458c2ecf20Sopenharmony_ci}
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_cistatic __always_inline bool
1488c2ecf20Sopenharmony_ciarch___test_and_set_bit(long nr, volatile unsigned long *addr)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	bool oldbit;
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	asm(__ASM_SIZE(bts) " %2,%1"
1538c2ecf20Sopenharmony_ci	    CC_SET(c)
1548c2ecf20Sopenharmony_ci	    : CC_OUT(c) (oldbit)
1558c2ecf20Sopenharmony_ci	    : ADDR, "Ir" (nr) : "memory");
1568c2ecf20Sopenharmony_ci	return oldbit;
1578c2ecf20Sopenharmony_ci}
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_cistatic __always_inline bool
1608c2ecf20Sopenharmony_ciarch_test_and_clear_bit(long nr, volatile unsigned long *addr)
1618c2ecf20Sopenharmony_ci{
1628c2ecf20Sopenharmony_ci	return GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(btr), *addr, c, "Ir", nr);
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci/*
1668c2ecf20Sopenharmony_ci * Note: the operation is performed atomically with respect to
1678c2ecf20Sopenharmony_ci * the local CPU, but not other CPUs. Portable code should not
1688c2ecf20Sopenharmony_ci * rely on this behaviour.
1698c2ecf20Sopenharmony_ci * KVM relies on this behaviour on x86 for modifying memory that is also
1708c2ecf20Sopenharmony_ci * accessed from a hypervisor on the same CPU if running in a VM: don't change
1718c2ecf20Sopenharmony_ci * this without also updating arch/x86/kernel/kvm.c
1728c2ecf20Sopenharmony_ci */
1738c2ecf20Sopenharmony_cistatic __always_inline bool
1748c2ecf20Sopenharmony_ciarch___test_and_clear_bit(long nr, volatile unsigned long *addr)
1758c2ecf20Sopenharmony_ci{
1768c2ecf20Sopenharmony_ci	bool oldbit;
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	asm volatile(__ASM_SIZE(btr) " %2,%1"
1798c2ecf20Sopenharmony_ci		     CC_SET(c)
1808c2ecf20Sopenharmony_ci		     : CC_OUT(c) (oldbit)
1818c2ecf20Sopenharmony_ci		     : ADDR, "Ir" (nr) : "memory");
1828c2ecf20Sopenharmony_ci	return oldbit;
1838c2ecf20Sopenharmony_ci}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_cistatic __always_inline bool
1868c2ecf20Sopenharmony_ciarch___test_and_change_bit(long nr, volatile unsigned long *addr)
1878c2ecf20Sopenharmony_ci{
1888c2ecf20Sopenharmony_ci	bool oldbit;
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	asm volatile(__ASM_SIZE(btc) " %2,%1"
1918c2ecf20Sopenharmony_ci		     CC_SET(c)
1928c2ecf20Sopenharmony_ci		     : CC_OUT(c) (oldbit)
1938c2ecf20Sopenharmony_ci		     : ADDR, "Ir" (nr) : "memory");
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	return oldbit;
1968c2ecf20Sopenharmony_ci}
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_cistatic __always_inline bool
1998c2ecf20Sopenharmony_ciarch_test_and_change_bit(long nr, volatile unsigned long *addr)
2008c2ecf20Sopenharmony_ci{
2018c2ecf20Sopenharmony_ci	return GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(btc), *addr, c, "Ir", nr);
2028c2ecf20Sopenharmony_ci}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_cistatic __always_inline bool constant_test_bit(long nr, const volatile unsigned long *addr)
2058c2ecf20Sopenharmony_ci{
2068c2ecf20Sopenharmony_ci	return ((1UL << (nr & (BITS_PER_LONG-1))) &
2078c2ecf20Sopenharmony_ci		(addr[nr >> _BITOPS_LONG_SHIFT])) != 0;
2088c2ecf20Sopenharmony_ci}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_cistatic __always_inline bool variable_test_bit(long nr, volatile const unsigned long *addr)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	bool oldbit;
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	asm volatile(__ASM_SIZE(bt) " %2,%1"
2158c2ecf20Sopenharmony_ci		     CC_SET(c)
2168c2ecf20Sopenharmony_ci		     : CC_OUT(c) (oldbit)
2178c2ecf20Sopenharmony_ci		     : "m" (*(unsigned long *)addr), "Ir" (nr) : "memory");
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	return oldbit;
2208c2ecf20Sopenharmony_ci}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci#define arch_test_bit(nr, addr)			\
2238c2ecf20Sopenharmony_ci	(__builtin_constant_p((nr))		\
2248c2ecf20Sopenharmony_ci	 ? constant_test_bit((nr), (addr))	\
2258c2ecf20Sopenharmony_ci	 : variable_test_bit((nr), (addr)))
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci/**
2288c2ecf20Sopenharmony_ci * __ffs - find first set bit in word
2298c2ecf20Sopenharmony_ci * @word: The word to search
2308c2ecf20Sopenharmony_ci *
2318c2ecf20Sopenharmony_ci * Undefined if no bit exists, so code should check against 0 first.
2328c2ecf20Sopenharmony_ci */
2338c2ecf20Sopenharmony_cistatic __always_inline unsigned long __ffs(unsigned long word)
2348c2ecf20Sopenharmony_ci{
2358c2ecf20Sopenharmony_ci	asm("rep; bsf %1,%0"
2368c2ecf20Sopenharmony_ci		: "=r" (word)
2378c2ecf20Sopenharmony_ci		: "rm" (word));
2388c2ecf20Sopenharmony_ci	return word;
2398c2ecf20Sopenharmony_ci}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci/**
2428c2ecf20Sopenharmony_ci * ffz - find first zero bit in word
2438c2ecf20Sopenharmony_ci * @word: The word to search
2448c2ecf20Sopenharmony_ci *
2458c2ecf20Sopenharmony_ci * Undefined if no zero exists, so code should check against ~0UL first.
2468c2ecf20Sopenharmony_ci */
2478c2ecf20Sopenharmony_cistatic __always_inline unsigned long ffz(unsigned long word)
2488c2ecf20Sopenharmony_ci{
2498c2ecf20Sopenharmony_ci	asm("rep; bsf %1,%0"
2508c2ecf20Sopenharmony_ci		: "=r" (word)
2518c2ecf20Sopenharmony_ci		: "r" (~word));
2528c2ecf20Sopenharmony_ci	return word;
2538c2ecf20Sopenharmony_ci}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci/*
2568c2ecf20Sopenharmony_ci * __fls: find last set bit in word
2578c2ecf20Sopenharmony_ci * @word: The word to search
2588c2ecf20Sopenharmony_ci *
2598c2ecf20Sopenharmony_ci * Undefined if no set bit exists, so code should check against 0 first.
2608c2ecf20Sopenharmony_ci */
2618c2ecf20Sopenharmony_cistatic __always_inline unsigned long __fls(unsigned long word)
2628c2ecf20Sopenharmony_ci{
2638c2ecf20Sopenharmony_ci	asm("bsr %1,%0"
2648c2ecf20Sopenharmony_ci	    : "=r" (word)
2658c2ecf20Sopenharmony_ci	    : "rm" (word));
2668c2ecf20Sopenharmony_ci	return word;
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci#undef ADDR
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci#ifdef __KERNEL__
2728c2ecf20Sopenharmony_ci/**
2738c2ecf20Sopenharmony_ci * ffs - find first set bit in word
2748c2ecf20Sopenharmony_ci * @x: the word to search
2758c2ecf20Sopenharmony_ci *
2768c2ecf20Sopenharmony_ci * This is defined the same way as the libc and compiler builtin ffs
2778c2ecf20Sopenharmony_ci * routines, therefore differs in spirit from the other bitops.
2788c2ecf20Sopenharmony_ci *
2798c2ecf20Sopenharmony_ci * ffs(value) returns 0 if value is 0 or the position of the first
2808c2ecf20Sopenharmony_ci * set bit if value is nonzero. The first (least significant) bit
2818c2ecf20Sopenharmony_ci * is at position 1.
2828c2ecf20Sopenharmony_ci */
2838c2ecf20Sopenharmony_cistatic __always_inline int ffs(int x)
2848c2ecf20Sopenharmony_ci{
2858c2ecf20Sopenharmony_ci	int r;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_64
2888c2ecf20Sopenharmony_ci	/*
2898c2ecf20Sopenharmony_ci	 * AMD64 says BSFL won't clobber the dest reg if x==0; Intel64 says the
2908c2ecf20Sopenharmony_ci	 * dest reg is undefined if x==0, but their CPU architect says its
2918c2ecf20Sopenharmony_ci	 * value is written to set it to the same as before, except that the
2928c2ecf20Sopenharmony_ci	 * top 32 bits will be cleared.
2938c2ecf20Sopenharmony_ci	 *
2948c2ecf20Sopenharmony_ci	 * We cannot do this on 32 bits because at the very least some
2958c2ecf20Sopenharmony_ci	 * 486 CPUs did not behave this way.
2968c2ecf20Sopenharmony_ci	 */
2978c2ecf20Sopenharmony_ci	asm("bsfl %1,%0"
2988c2ecf20Sopenharmony_ci	    : "=r" (r)
2998c2ecf20Sopenharmony_ci	    : "rm" (x), "0" (-1));
3008c2ecf20Sopenharmony_ci#elif defined(CONFIG_X86_CMOV)
3018c2ecf20Sopenharmony_ci	asm("bsfl %1,%0\n\t"
3028c2ecf20Sopenharmony_ci	    "cmovzl %2,%0"
3038c2ecf20Sopenharmony_ci	    : "=&r" (r) : "rm" (x), "r" (-1));
3048c2ecf20Sopenharmony_ci#else
3058c2ecf20Sopenharmony_ci	asm("bsfl %1,%0\n\t"
3068c2ecf20Sopenharmony_ci	    "jnz 1f\n\t"
3078c2ecf20Sopenharmony_ci	    "movl $-1,%0\n"
3088c2ecf20Sopenharmony_ci	    "1:" : "=r" (r) : "rm" (x));
3098c2ecf20Sopenharmony_ci#endif
3108c2ecf20Sopenharmony_ci	return r + 1;
3118c2ecf20Sopenharmony_ci}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci/**
3148c2ecf20Sopenharmony_ci * fls - find last set bit in word
3158c2ecf20Sopenharmony_ci * @x: the word to search
3168c2ecf20Sopenharmony_ci *
3178c2ecf20Sopenharmony_ci * This is defined in a similar way as the libc and compiler builtin
3188c2ecf20Sopenharmony_ci * ffs, but returns the position of the most significant set bit.
3198c2ecf20Sopenharmony_ci *
3208c2ecf20Sopenharmony_ci * fls(value) returns 0 if value is 0 or the position of the last
3218c2ecf20Sopenharmony_ci * set bit if value is nonzero. The last (most significant) bit is
3228c2ecf20Sopenharmony_ci * at position 32.
3238c2ecf20Sopenharmony_ci */
3248c2ecf20Sopenharmony_cistatic __always_inline int fls(unsigned int x)
3258c2ecf20Sopenharmony_ci{
3268c2ecf20Sopenharmony_ci	int r;
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_64
3298c2ecf20Sopenharmony_ci	/*
3308c2ecf20Sopenharmony_ci	 * AMD64 says BSRL won't clobber the dest reg if x==0; Intel64 says the
3318c2ecf20Sopenharmony_ci	 * dest reg is undefined if x==0, but their CPU architect says its
3328c2ecf20Sopenharmony_ci	 * value is written to set it to the same as before, except that the
3338c2ecf20Sopenharmony_ci	 * top 32 bits will be cleared.
3348c2ecf20Sopenharmony_ci	 *
3358c2ecf20Sopenharmony_ci	 * We cannot do this on 32 bits because at the very least some
3368c2ecf20Sopenharmony_ci	 * 486 CPUs did not behave this way.
3378c2ecf20Sopenharmony_ci	 */
3388c2ecf20Sopenharmony_ci	asm("bsrl %1,%0"
3398c2ecf20Sopenharmony_ci	    : "=r" (r)
3408c2ecf20Sopenharmony_ci	    : "rm" (x), "0" (-1));
3418c2ecf20Sopenharmony_ci#elif defined(CONFIG_X86_CMOV)
3428c2ecf20Sopenharmony_ci	asm("bsrl %1,%0\n\t"
3438c2ecf20Sopenharmony_ci	    "cmovzl %2,%0"
3448c2ecf20Sopenharmony_ci	    : "=&r" (r) : "rm" (x), "rm" (-1));
3458c2ecf20Sopenharmony_ci#else
3468c2ecf20Sopenharmony_ci	asm("bsrl %1,%0\n\t"
3478c2ecf20Sopenharmony_ci	    "jnz 1f\n\t"
3488c2ecf20Sopenharmony_ci	    "movl $-1,%0\n"
3498c2ecf20Sopenharmony_ci	    "1:" : "=r" (r) : "rm" (x));
3508c2ecf20Sopenharmony_ci#endif
3518c2ecf20Sopenharmony_ci	return r + 1;
3528c2ecf20Sopenharmony_ci}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci/**
3558c2ecf20Sopenharmony_ci * fls64 - find last set bit in a 64-bit word
3568c2ecf20Sopenharmony_ci * @x: the word to search
3578c2ecf20Sopenharmony_ci *
3588c2ecf20Sopenharmony_ci * This is defined in a similar way as the libc and compiler builtin
3598c2ecf20Sopenharmony_ci * ffsll, but returns the position of the most significant set bit.
3608c2ecf20Sopenharmony_ci *
3618c2ecf20Sopenharmony_ci * fls64(value) returns 0 if value is 0 or the position of the last
3628c2ecf20Sopenharmony_ci * set bit if value is nonzero. The last (most significant) bit is
3638c2ecf20Sopenharmony_ci * at position 64.
3648c2ecf20Sopenharmony_ci */
3658c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_64
3668c2ecf20Sopenharmony_cistatic __always_inline int fls64(__u64 x)
3678c2ecf20Sopenharmony_ci{
3688c2ecf20Sopenharmony_ci	int bitpos = -1;
3698c2ecf20Sopenharmony_ci	/*
3708c2ecf20Sopenharmony_ci	 * AMD64 says BSRQ won't clobber the dest reg if x==0; Intel64 says the
3718c2ecf20Sopenharmony_ci	 * dest reg is undefined if x==0, but their CPU architect says its
3728c2ecf20Sopenharmony_ci	 * value is written to set it to the same as before.
3738c2ecf20Sopenharmony_ci	 */
3748c2ecf20Sopenharmony_ci	asm("bsrq %1,%q0"
3758c2ecf20Sopenharmony_ci	    : "+r" (bitpos)
3768c2ecf20Sopenharmony_ci	    : "rm" (x));
3778c2ecf20Sopenharmony_ci	return bitpos + 1;
3788c2ecf20Sopenharmony_ci}
3798c2ecf20Sopenharmony_ci#else
3808c2ecf20Sopenharmony_ci#include <asm-generic/bitops/fls64.h>
3818c2ecf20Sopenharmony_ci#endif
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci#include <asm-generic/bitops/find.h>
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci#include <asm-generic/bitops/sched.h>
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci#include <asm/arch_hweight.h>
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci#include <asm-generic/bitops/const_hweight.h>
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci#include <asm-generic/bitops/instrumented-atomic.h>
3928c2ecf20Sopenharmony_ci#include <asm-generic/bitops/instrumented-non-atomic.h>
3938c2ecf20Sopenharmony_ci#include <asm-generic/bitops/instrumented-lock.h>
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci#include <asm-generic/bitops/le.h>
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci#include <asm-generic/bitops/ext2-atomic-setbit.h>
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci#endif /* __KERNEL__ */
4008c2ecf20Sopenharmony_ci#endif /* _ASM_X86_BITOPS_H */
401