18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef _ALPHA_BITOPS_H 38c2ecf20Sopenharmony_ci#define _ALPHA_BITOPS_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#ifndef _LINUX_BITOPS_H 68c2ecf20Sopenharmony_ci#error only <linux/bitops.h> can be included directly 78c2ecf20Sopenharmony_ci#endif 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <asm/compiler.h> 108c2ecf20Sopenharmony_ci#include <asm/barrier.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci/* 138c2ecf20Sopenharmony_ci * Copyright 1994, Linus Torvalds. 148c2ecf20Sopenharmony_ci */ 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/* 178c2ecf20Sopenharmony_ci * These have to be done with inline assembly: that way the bit-setting 188c2ecf20Sopenharmony_ci * is guaranteed to be atomic. All bit operations return 0 if the bit 198c2ecf20Sopenharmony_ci * was cleared before the operation and != 0 if it was not. 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * To get proper branch prediction for the main line, we must branch 228c2ecf20Sopenharmony_ci * forward to code at the end of this object's .text section, then 238c2ecf20Sopenharmony_ci * branch back to restart the operation. 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * bit 0 is the LSB of addr; bit 64 is the LSB of (addr+1). 268c2ecf20Sopenharmony_ci */ 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic inline void 298c2ecf20Sopenharmony_ciset_bit(unsigned long nr, volatile void * addr) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci unsigned long temp; 328c2ecf20Sopenharmony_ci int *m = ((int *) addr) + (nr >> 5); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci __asm__ __volatile__( 358c2ecf20Sopenharmony_ci "1: ldl_l %0,%3\n" 368c2ecf20Sopenharmony_ci " bis %0,%2,%0\n" 378c2ecf20Sopenharmony_ci " stl_c %0,%1\n" 388c2ecf20Sopenharmony_ci " beq %0,2f\n" 398c2ecf20Sopenharmony_ci ".subsection 2\n" 408c2ecf20Sopenharmony_ci "2: br 1b\n" 418c2ecf20Sopenharmony_ci ".previous" 428c2ecf20Sopenharmony_ci :"=&r" (temp), "=m" (*m) 438c2ecf20Sopenharmony_ci :"Ir" (1UL << (nr & 31)), "m" (*m)); 448c2ecf20Sopenharmony_ci} 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/* 478c2ecf20Sopenharmony_ci * WARNING: non atomic version. 488c2ecf20Sopenharmony_ci */ 498c2ecf20Sopenharmony_cistatic inline void 508c2ecf20Sopenharmony_ci__set_bit(unsigned long nr, volatile void * addr) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci int *m = ((int *) addr) + (nr >> 5); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci *m |= 1 << (nr & 31); 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic inline void 588c2ecf20Sopenharmony_ciclear_bit(unsigned long nr, volatile void * addr) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci unsigned long temp; 618c2ecf20Sopenharmony_ci int *m = ((int *) addr) + (nr >> 5); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci __asm__ __volatile__( 648c2ecf20Sopenharmony_ci "1: ldl_l %0,%3\n" 658c2ecf20Sopenharmony_ci " bic %0,%2,%0\n" 668c2ecf20Sopenharmony_ci " stl_c %0,%1\n" 678c2ecf20Sopenharmony_ci " beq %0,2f\n" 688c2ecf20Sopenharmony_ci ".subsection 2\n" 698c2ecf20Sopenharmony_ci "2: br 1b\n" 708c2ecf20Sopenharmony_ci ".previous" 718c2ecf20Sopenharmony_ci :"=&r" (temp), "=m" (*m) 728c2ecf20Sopenharmony_ci :"Ir" (1UL << (nr & 31)), "m" (*m)); 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic inline void 768c2ecf20Sopenharmony_ciclear_bit_unlock(unsigned long nr, volatile void * addr) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci smp_mb(); 798c2ecf20Sopenharmony_ci clear_bit(nr, addr); 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci/* 838c2ecf20Sopenharmony_ci * WARNING: non atomic version. 848c2ecf20Sopenharmony_ci */ 858c2ecf20Sopenharmony_cistatic __inline__ void 868c2ecf20Sopenharmony_ci__clear_bit(unsigned long nr, volatile void * addr) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci int *m = ((int *) addr) + (nr >> 5); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci *m &= ~(1 << (nr & 31)); 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic inline void 948c2ecf20Sopenharmony_ci__clear_bit_unlock(unsigned long nr, volatile void * addr) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci smp_mb(); 978c2ecf20Sopenharmony_ci __clear_bit(nr, addr); 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic inline void 1018c2ecf20Sopenharmony_cichange_bit(unsigned long nr, volatile void * addr) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci unsigned long temp; 1048c2ecf20Sopenharmony_ci int *m = ((int *) addr) + (nr >> 5); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci __asm__ __volatile__( 1078c2ecf20Sopenharmony_ci "1: ldl_l %0,%3\n" 1088c2ecf20Sopenharmony_ci " xor %0,%2,%0\n" 1098c2ecf20Sopenharmony_ci " stl_c %0,%1\n" 1108c2ecf20Sopenharmony_ci " beq %0,2f\n" 1118c2ecf20Sopenharmony_ci ".subsection 2\n" 1128c2ecf20Sopenharmony_ci "2: br 1b\n" 1138c2ecf20Sopenharmony_ci ".previous" 1148c2ecf20Sopenharmony_ci :"=&r" (temp), "=m" (*m) 1158c2ecf20Sopenharmony_ci :"Ir" (1UL << (nr & 31)), "m" (*m)); 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci/* 1198c2ecf20Sopenharmony_ci * WARNING: non atomic version. 1208c2ecf20Sopenharmony_ci */ 1218c2ecf20Sopenharmony_cistatic __inline__ void 1228c2ecf20Sopenharmony_ci__change_bit(unsigned long nr, volatile void * addr) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci int *m = ((int *) addr) + (nr >> 5); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci *m ^= 1 << (nr & 31); 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistatic inline int 1308c2ecf20Sopenharmony_citest_and_set_bit(unsigned long nr, volatile void *addr) 1318c2ecf20Sopenharmony_ci{ 1328c2ecf20Sopenharmony_ci unsigned long oldbit; 1338c2ecf20Sopenharmony_ci unsigned long temp; 1348c2ecf20Sopenharmony_ci int *m = ((int *) addr) + (nr >> 5); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci __asm__ __volatile__( 1378c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 1388c2ecf20Sopenharmony_ci " mb\n" 1398c2ecf20Sopenharmony_ci#endif 1408c2ecf20Sopenharmony_ci "1: ldl_l %0,%4\n" 1418c2ecf20Sopenharmony_ci " and %0,%3,%2\n" 1428c2ecf20Sopenharmony_ci " bne %2,2f\n" 1438c2ecf20Sopenharmony_ci " xor %0,%3,%0\n" 1448c2ecf20Sopenharmony_ci " stl_c %0,%1\n" 1458c2ecf20Sopenharmony_ci " beq %0,3f\n" 1468c2ecf20Sopenharmony_ci "2:\n" 1478c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 1488c2ecf20Sopenharmony_ci " mb\n" 1498c2ecf20Sopenharmony_ci#endif 1508c2ecf20Sopenharmony_ci ".subsection 2\n" 1518c2ecf20Sopenharmony_ci "3: br 1b\n" 1528c2ecf20Sopenharmony_ci ".previous" 1538c2ecf20Sopenharmony_ci :"=&r" (temp), "=m" (*m), "=&r" (oldbit) 1548c2ecf20Sopenharmony_ci :"Ir" (1UL << (nr & 31)), "m" (*m) : "memory"); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci return oldbit != 0; 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistatic inline int 1608c2ecf20Sopenharmony_citest_and_set_bit_lock(unsigned long nr, volatile void *addr) 1618c2ecf20Sopenharmony_ci{ 1628c2ecf20Sopenharmony_ci unsigned long oldbit; 1638c2ecf20Sopenharmony_ci unsigned long temp; 1648c2ecf20Sopenharmony_ci int *m = ((int *) addr) + (nr >> 5); 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci __asm__ __volatile__( 1678c2ecf20Sopenharmony_ci "1: ldl_l %0,%4\n" 1688c2ecf20Sopenharmony_ci " and %0,%3,%2\n" 1698c2ecf20Sopenharmony_ci " bne %2,2f\n" 1708c2ecf20Sopenharmony_ci " xor %0,%3,%0\n" 1718c2ecf20Sopenharmony_ci " stl_c %0,%1\n" 1728c2ecf20Sopenharmony_ci " beq %0,3f\n" 1738c2ecf20Sopenharmony_ci "2:\n" 1748c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 1758c2ecf20Sopenharmony_ci " mb\n" 1768c2ecf20Sopenharmony_ci#endif 1778c2ecf20Sopenharmony_ci ".subsection 2\n" 1788c2ecf20Sopenharmony_ci "3: br 1b\n" 1798c2ecf20Sopenharmony_ci ".previous" 1808c2ecf20Sopenharmony_ci :"=&r" (temp), "=m" (*m), "=&r" (oldbit) 1818c2ecf20Sopenharmony_ci :"Ir" (1UL << (nr & 31)), "m" (*m) : "memory"); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci return oldbit != 0; 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci/* 1878c2ecf20Sopenharmony_ci * WARNING: non atomic version. 1888c2ecf20Sopenharmony_ci */ 1898c2ecf20Sopenharmony_cistatic inline int 1908c2ecf20Sopenharmony_ci__test_and_set_bit(unsigned long nr, volatile void * addr) 1918c2ecf20Sopenharmony_ci{ 1928c2ecf20Sopenharmony_ci unsigned long mask = 1 << (nr & 0x1f); 1938c2ecf20Sopenharmony_ci int *m = ((int *) addr) + (nr >> 5); 1948c2ecf20Sopenharmony_ci int old = *m; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci *m = old | mask; 1978c2ecf20Sopenharmony_ci return (old & mask) != 0; 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistatic inline int 2018c2ecf20Sopenharmony_citest_and_clear_bit(unsigned long nr, volatile void * addr) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci unsigned long oldbit; 2048c2ecf20Sopenharmony_ci unsigned long temp; 2058c2ecf20Sopenharmony_ci int *m = ((int *) addr) + (nr >> 5); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci __asm__ __volatile__( 2088c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 2098c2ecf20Sopenharmony_ci " mb\n" 2108c2ecf20Sopenharmony_ci#endif 2118c2ecf20Sopenharmony_ci "1: ldl_l %0,%4\n" 2128c2ecf20Sopenharmony_ci " and %0,%3,%2\n" 2138c2ecf20Sopenharmony_ci " beq %2,2f\n" 2148c2ecf20Sopenharmony_ci " xor %0,%3,%0\n" 2158c2ecf20Sopenharmony_ci " stl_c %0,%1\n" 2168c2ecf20Sopenharmony_ci " beq %0,3f\n" 2178c2ecf20Sopenharmony_ci "2:\n" 2188c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 2198c2ecf20Sopenharmony_ci " mb\n" 2208c2ecf20Sopenharmony_ci#endif 2218c2ecf20Sopenharmony_ci ".subsection 2\n" 2228c2ecf20Sopenharmony_ci "3: br 1b\n" 2238c2ecf20Sopenharmony_ci ".previous" 2248c2ecf20Sopenharmony_ci :"=&r" (temp), "=m" (*m), "=&r" (oldbit) 2258c2ecf20Sopenharmony_ci :"Ir" (1UL << (nr & 31)), "m" (*m) : "memory"); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci return oldbit != 0; 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci/* 2318c2ecf20Sopenharmony_ci * WARNING: non atomic version. 2328c2ecf20Sopenharmony_ci */ 2338c2ecf20Sopenharmony_cistatic inline int 2348c2ecf20Sopenharmony_ci__test_and_clear_bit(unsigned long nr, volatile void * addr) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci unsigned long mask = 1 << (nr & 0x1f); 2378c2ecf20Sopenharmony_ci int *m = ((int *) addr) + (nr >> 5); 2388c2ecf20Sopenharmony_ci int old = *m; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci *m = old & ~mask; 2418c2ecf20Sopenharmony_ci return (old & mask) != 0; 2428c2ecf20Sopenharmony_ci} 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_cistatic inline int 2458c2ecf20Sopenharmony_citest_and_change_bit(unsigned long nr, volatile void * addr) 2468c2ecf20Sopenharmony_ci{ 2478c2ecf20Sopenharmony_ci unsigned long oldbit; 2488c2ecf20Sopenharmony_ci unsigned long temp; 2498c2ecf20Sopenharmony_ci int *m = ((int *) addr) + (nr >> 5); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci __asm__ __volatile__( 2528c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 2538c2ecf20Sopenharmony_ci " mb\n" 2548c2ecf20Sopenharmony_ci#endif 2558c2ecf20Sopenharmony_ci "1: ldl_l %0,%4\n" 2568c2ecf20Sopenharmony_ci " and %0,%3,%2\n" 2578c2ecf20Sopenharmony_ci " xor %0,%3,%0\n" 2588c2ecf20Sopenharmony_ci " stl_c %0,%1\n" 2598c2ecf20Sopenharmony_ci " beq %0,3f\n" 2608c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 2618c2ecf20Sopenharmony_ci " mb\n" 2628c2ecf20Sopenharmony_ci#endif 2638c2ecf20Sopenharmony_ci ".subsection 2\n" 2648c2ecf20Sopenharmony_ci "3: br 1b\n" 2658c2ecf20Sopenharmony_ci ".previous" 2668c2ecf20Sopenharmony_ci :"=&r" (temp), "=m" (*m), "=&r" (oldbit) 2678c2ecf20Sopenharmony_ci :"Ir" (1UL << (nr & 31)), "m" (*m) : "memory"); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci return oldbit != 0; 2708c2ecf20Sopenharmony_ci} 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci/* 2738c2ecf20Sopenharmony_ci * WARNING: non atomic version. 2748c2ecf20Sopenharmony_ci */ 2758c2ecf20Sopenharmony_cistatic __inline__ int 2768c2ecf20Sopenharmony_ci__test_and_change_bit(unsigned long nr, volatile void * addr) 2778c2ecf20Sopenharmony_ci{ 2788c2ecf20Sopenharmony_ci unsigned long mask = 1 << (nr & 0x1f); 2798c2ecf20Sopenharmony_ci int *m = ((int *) addr) + (nr >> 5); 2808c2ecf20Sopenharmony_ci int old = *m; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci *m = old ^ mask; 2838c2ecf20Sopenharmony_ci return (old & mask) != 0; 2848c2ecf20Sopenharmony_ci} 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cistatic inline int 2878c2ecf20Sopenharmony_citest_bit(int nr, const volatile void * addr) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci return (1UL & (((const int *) addr)[nr >> 5] >> (nr & 31))) != 0UL; 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci/* 2938c2ecf20Sopenharmony_ci * ffz = Find First Zero in word. Undefined if no zero exists, 2948c2ecf20Sopenharmony_ci * so code should check against ~0UL first.. 2958c2ecf20Sopenharmony_ci * 2968c2ecf20Sopenharmony_ci * Do a binary search on the bits. Due to the nature of large 2978c2ecf20Sopenharmony_ci * constants on the alpha, it is worthwhile to split the search. 2988c2ecf20Sopenharmony_ci */ 2998c2ecf20Sopenharmony_cistatic inline unsigned long ffz_b(unsigned long x) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci unsigned long sum, x1, x2, x4; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci x = ~x & -~x; /* set first 0 bit, clear others */ 3048c2ecf20Sopenharmony_ci x1 = x & 0xAA; 3058c2ecf20Sopenharmony_ci x2 = x & 0xCC; 3068c2ecf20Sopenharmony_ci x4 = x & 0xF0; 3078c2ecf20Sopenharmony_ci sum = x2 ? 2 : 0; 3088c2ecf20Sopenharmony_ci sum += (x4 != 0) * 4; 3098c2ecf20Sopenharmony_ci sum += (x1 != 0); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci return sum; 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_cistatic inline unsigned long ffz(unsigned long word) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci#if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67) 3178c2ecf20Sopenharmony_ci /* Whee. EV67 can calculate it directly. */ 3188c2ecf20Sopenharmony_ci return __kernel_cttz(~word); 3198c2ecf20Sopenharmony_ci#else 3208c2ecf20Sopenharmony_ci unsigned long bits, qofs, bofs; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci bits = __kernel_cmpbge(word, ~0UL); 3238c2ecf20Sopenharmony_ci qofs = ffz_b(bits); 3248c2ecf20Sopenharmony_ci bits = __kernel_extbl(word, qofs); 3258c2ecf20Sopenharmony_ci bofs = ffz_b(bits); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci return qofs*8 + bofs; 3288c2ecf20Sopenharmony_ci#endif 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci/* 3328c2ecf20Sopenharmony_ci * __ffs = Find First set bit in word. Undefined if no set bit exists. 3338c2ecf20Sopenharmony_ci */ 3348c2ecf20Sopenharmony_cistatic inline unsigned long __ffs(unsigned long word) 3358c2ecf20Sopenharmony_ci{ 3368c2ecf20Sopenharmony_ci#if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67) 3378c2ecf20Sopenharmony_ci /* Whee. EV67 can calculate it directly. */ 3388c2ecf20Sopenharmony_ci return __kernel_cttz(word); 3398c2ecf20Sopenharmony_ci#else 3408c2ecf20Sopenharmony_ci unsigned long bits, qofs, bofs; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci bits = __kernel_cmpbge(0, word); 3438c2ecf20Sopenharmony_ci qofs = ffz_b(bits); 3448c2ecf20Sopenharmony_ci bits = __kernel_extbl(word, qofs); 3458c2ecf20Sopenharmony_ci bofs = ffz_b(~bits); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci return qofs*8 + bofs; 3488c2ecf20Sopenharmony_ci#endif 3498c2ecf20Sopenharmony_ci} 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci#ifdef __KERNEL__ 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci/* 3548c2ecf20Sopenharmony_ci * ffs: find first bit set. This is defined the same way as 3558c2ecf20Sopenharmony_ci * the libc and compiler builtin ffs routines, therefore 3568c2ecf20Sopenharmony_ci * differs in spirit from the above __ffs. 3578c2ecf20Sopenharmony_ci */ 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_cistatic inline int ffs(int word) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci int result = __ffs(word) + 1; 3628c2ecf20Sopenharmony_ci return word ? result : 0; 3638c2ecf20Sopenharmony_ci} 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci/* 3668c2ecf20Sopenharmony_ci * fls: find last bit set. 3678c2ecf20Sopenharmony_ci */ 3688c2ecf20Sopenharmony_ci#if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67) 3698c2ecf20Sopenharmony_cistatic inline int fls64(unsigned long word) 3708c2ecf20Sopenharmony_ci{ 3718c2ecf20Sopenharmony_ci return 64 - __kernel_ctlz(word); 3728c2ecf20Sopenharmony_ci} 3738c2ecf20Sopenharmony_ci#else 3748c2ecf20Sopenharmony_ciextern const unsigned char __flsm1_tab[256]; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_cistatic inline int fls64(unsigned long x) 3778c2ecf20Sopenharmony_ci{ 3788c2ecf20Sopenharmony_ci unsigned long t, a, r; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci t = __kernel_cmpbge (x, 0x0101010101010101UL); 3818c2ecf20Sopenharmony_ci a = __flsm1_tab[t]; 3828c2ecf20Sopenharmony_ci t = __kernel_extbl (x, a); 3838c2ecf20Sopenharmony_ci r = a*8 + __flsm1_tab[t] + (x != 0); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci return r; 3868c2ecf20Sopenharmony_ci} 3878c2ecf20Sopenharmony_ci#endif 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_cistatic inline unsigned long __fls(unsigned long x) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci return fls64(x) - 1; 3928c2ecf20Sopenharmony_ci} 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_cistatic inline int fls(unsigned int x) 3958c2ecf20Sopenharmony_ci{ 3968c2ecf20Sopenharmony_ci return fls64(x); 3978c2ecf20Sopenharmony_ci} 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci/* 4008c2ecf20Sopenharmony_ci * hweightN: returns the hamming weight (i.e. the number 4018c2ecf20Sopenharmony_ci * of bits set) of a N-bit word 4028c2ecf20Sopenharmony_ci */ 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci#if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67) 4058c2ecf20Sopenharmony_ci/* Whee. EV67 can calculate it directly. */ 4068c2ecf20Sopenharmony_cistatic inline unsigned long __arch_hweight64(unsigned long w) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci return __kernel_ctpop(w); 4098c2ecf20Sopenharmony_ci} 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_cistatic inline unsigned int __arch_hweight32(unsigned int w) 4128c2ecf20Sopenharmony_ci{ 4138c2ecf20Sopenharmony_ci return __arch_hweight64(w); 4148c2ecf20Sopenharmony_ci} 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_cistatic inline unsigned int __arch_hweight16(unsigned int w) 4178c2ecf20Sopenharmony_ci{ 4188c2ecf20Sopenharmony_ci return __arch_hweight64(w & 0xffff); 4198c2ecf20Sopenharmony_ci} 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_cistatic inline unsigned int __arch_hweight8(unsigned int w) 4228c2ecf20Sopenharmony_ci{ 4238c2ecf20Sopenharmony_ci return __arch_hweight64(w & 0xff); 4248c2ecf20Sopenharmony_ci} 4258c2ecf20Sopenharmony_ci#else 4268c2ecf20Sopenharmony_ci#include <asm-generic/bitops/arch_hweight.h> 4278c2ecf20Sopenharmony_ci#endif 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci#include <asm-generic/bitops/const_hweight.h> 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci#endif /* __KERNEL__ */ 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci#include <asm-generic/bitops/find.h> 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci#ifdef __KERNEL__ 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci/* 4388c2ecf20Sopenharmony_ci * Every architecture must define this function. It's the fastest 4398c2ecf20Sopenharmony_ci * way of searching a 100-bit bitmap. It's guaranteed that at least 4408c2ecf20Sopenharmony_ci * one of the 100 bits is cleared. 4418c2ecf20Sopenharmony_ci */ 4428c2ecf20Sopenharmony_cistatic inline unsigned long 4438c2ecf20Sopenharmony_cisched_find_first_bit(const unsigned long b[2]) 4448c2ecf20Sopenharmony_ci{ 4458c2ecf20Sopenharmony_ci unsigned long b0, b1, ofs, tmp; 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci b0 = b[0]; 4488c2ecf20Sopenharmony_ci b1 = b[1]; 4498c2ecf20Sopenharmony_ci ofs = (b0 ? 0 : 64); 4508c2ecf20Sopenharmony_ci tmp = (b0 ? b0 : b1); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci return __ffs(tmp) + ofs; 4538c2ecf20Sopenharmony_ci} 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci#include <asm-generic/bitops/le.h> 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci#include <asm-generic/bitops/ext2-atomic-setbit.h> 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci#endif /* __KERNEL__ */ 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci#endif /* _ALPHA_BITOPS_H */ 462