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