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