xref: /openbmc/linux/arch/arc/include/asm/bitops.h (revision cea43147905f1c2b7b48104a5304cf5229f45bec)
1d2912cb1SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
214e968baSVineet Gupta /*
314e968baSVineet Gupta  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
414e968baSVineet Gupta  */
514e968baSVineet Gupta 
614e968baSVineet Gupta #ifndef _ASM_BITOPS_H
714e968baSVineet Gupta #define _ASM_BITOPS_H
814e968baSVineet Gupta 
914e968baSVineet Gupta #ifndef _LINUX_BITOPS_H
1014e968baSVineet Gupta #error only <linux/bitops.h> can be included directly
1114e968baSVineet Gupta #endif
1214e968baSVineet Gupta 
1314e968baSVineet Gupta #ifndef __ASSEMBLY__
1414e968baSVineet Gupta 
1514e968baSVineet Gupta #include <linux/types.h>
1614e968baSVineet Gupta #include <linux/compiler.h>
1714e968baSVineet Gupta 
181f6ccfffSVineet Gupta #ifdef CONFIG_ISA_ARCOMPACT
191f6ccfffSVineet Gupta 
2014e968baSVineet Gupta /*
2114e968baSVineet Gupta  * Count the number of zeros, starting from MSB
2214e968baSVineet Gupta  * Helper for fls( ) friends
2314e968baSVineet Gupta  * This is a pure count, so (1-32) or (0-31) doesn't apply
2414e968baSVineet Gupta  * It could be 0 to 32, based on num of 0's in there
2514e968baSVineet Gupta  * clz(0x8000_0000) = 0, clz(0xFFFF_FFFF)=0, clz(0) = 32, clz(1) = 31
2614e968baSVineet Gupta  */
2714e968baSVineet Gupta static inline __attribute__ ((const)) int clz(unsigned int x)
2814e968baSVineet Gupta {
2914e968baSVineet Gupta 	unsigned int res;
3014e968baSVineet Gupta 
3114e968baSVineet Gupta 	__asm__ __volatile__(
3214e968baSVineet Gupta 	"	norm.f  %0, %1		\n"
3314e968baSVineet Gupta 	"	mov.n   %0, 0		\n"
3414e968baSVineet Gupta 	"	add.p   %0, %0, 1	\n"
3514e968baSVineet Gupta 	: "=r"(res)
3614e968baSVineet Gupta 	: "r"(x)
3714e968baSVineet Gupta 	: "cc");
3814e968baSVineet Gupta 
3914e968baSVineet Gupta 	return res;
4014e968baSVineet Gupta }
4114e968baSVineet Gupta 
423fc2579eSMatthew Wilcox static inline int constant_fls(unsigned int x)
4314e968baSVineet Gupta {
4414e968baSVineet Gupta 	int r = 32;
4514e968baSVineet Gupta 
4614e968baSVineet Gupta 	if (!x)
4714e968baSVineet Gupta 		return 0;
4814e968baSVineet Gupta 	if (!(x & 0xffff0000u)) {
4914e968baSVineet Gupta 		x <<= 16;
5014e968baSVineet Gupta 		r -= 16;
5114e968baSVineet Gupta 	}
5214e968baSVineet Gupta 	if (!(x & 0xff000000u)) {
5314e968baSVineet Gupta 		x <<= 8;
5414e968baSVineet Gupta 		r -= 8;
5514e968baSVineet Gupta 	}
5614e968baSVineet Gupta 	if (!(x & 0xf0000000u)) {
5714e968baSVineet Gupta 		x <<= 4;
5814e968baSVineet Gupta 		r -= 4;
5914e968baSVineet Gupta 	}
6014e968baSVineet Gupta 	if (!(x & 0xc0000000u)) {
6114e968baSVineet Gupta 		x <<= 2;
6214e968baSVineet Gupta 		r -= 2;
6314e968baSVineet Gupta 	}
6478aec9bbSGustavo Pimentel 	if (!(x & 0x80000000u))
6514e968baSVineet Gupta 		r -= 1;
6614e968baSVineet Gupta 	return r;
6714e968baSVineet Gupta }
6814e968baSVineet Gupta 
6914e968baSVineet Gupta /*
7014e968baSVineet Gupta  * fls = Find Last Set in word
7114e968baSVineet Gupta  * @result: [1-32]
7214e968baSVineet Gupta  * fls(1) = 1, fls(0x80000000) = 32, fls(0) = 0
7314e968baSVineet Gupta  */
743fc2579eSMatthew Wilcox static inline __attribute__ ((const)) int fls(unsigned int x)
7514e968baSVineet Gupta {
7614e968baSVineet Gupta 	if (__builtin_constant_p(x))
7714e968baSVineet Gupta 	       return constant_fls(x);
7814e968baSVineet Gupta 
7914e968baSVineet Gupta 	return 32 - clz(x);
8014e968baSVineet Gupta }
8114e968baSVineet Gupta 
8214e968baSVineet Gupta /*
8314e968baSVineet Gupta  * __fls: Similar to fls, but zero based (0-31)
8414e968baSVineet Gupta  */
8514e968baSVineet Gupta static inline __attribute__ ((const)) int __fls(unsigned long x)
8614e968baSVineet Gupta {
8714e968baSVineet Gupta 	if (!x)
8814e968baSVineet Gupta 		return 0;
8914e968baSVineet Gupta 	else
9014e968baSVineet Gupta 		return fls(x) - 1;
9114e968baSVineet Gupta }
9214e968baSVineet Gupta 
9314e968baSVineet Gupta /*
9414e968baSVineet Gupta  * ffs = Find First Set in word (LSB to MSB)
9514e968baSVineet Gupta  * @result: [1-32], 0 if all 0's
9614e968baSVineet Gupta  */
9714e968baSVineet Gupta #define ffs(x)	({ unsigned long __t = (x); fls(__t & -__t); })
9814e968baSVineet Gupta 
9914e968baSVineet Gupta /*
10014e968baSVineet Gupta  * __ffs: Similar to ffs, but zero based (0-31)
10114e968baSVineet Gupta  */
1024e868f84SEugeniy Paltsev static inline __attribute__ ((const)) unsigned long __ffs(unsigned long word)
10314e968baSVineet Gupta {
10414e968baSVineet Gupta 	if (!word)
10514e968baSVineet Gupta 		return word;
10614e968baSVineet Gupta 
10714e968baSVineet Gupta 	return ffs(word) - 1;
10814e968baSVineet Gupta }
10914e968baSVineet Gupta 
1101f6ccfffSVineet Gupta #else	/* CONFIG_ISA_ARCV2 */
1111f6ccfffSVineet Gupta 
1121f6ccfffSVineet Gupta /*
1131f6ccfffSVineet Gupta  * fls = Find Last Set in word
1141f6ccfffSVineet Gupta  * @result: [1-32]
1151f6ccfffSVineet Gupta  * fls(1) = 1, fls(0x80000000) = 32, fls(0) = 0
1161f6ccfffSVineet Gupta  */
1171f6ccfffSVineet Gupta static inline __attribute__ ((const)) int fls(unsigned long x)
1181f6ccfffSVineet Gupta {
1191f6ccfffSVineet Gupta 	int n;
1201f6ccfffSVineet Gupta 
1211f6ccfffSVineet Gupta 	asm volatile(
1221f6ccfffSVineet Gupta 	"	fls.f	%0, %1		\n"  /* 0:31; 0(Z) if src 0 */
1231f6ccfffSVineet Gupta 	"	add.nz	%0, %0, 1	\n"  /* 0:31 -> 1:32 */
1241f6ccfffSVineet Gupta 	: "=r"(n)	/* Early clobber not needed */
1251f6ccfffSVineet Gupta 	: "r"(x)
1261f6ccfffSVineet Gupta 	: "cc");
1271f6ccfffSVineet Gupta 
1281f6ccfffSVineet Gupta 	return n;
1291f6ccfffSVineet Gupta }
1301f6ccfffSVineet Gupta 
1311f6ccfffSVineet Gupta /*
1321f6ccfffSVineet Gupta  * __fls: Similar to fls, but zero based (0-31). Also 0 if no bit set
1331f6ccfffSVineet Gupta  */
1341f6ccfffSVineet Gupta static inline __attribute__ ((const)) int __fls(unsigned long x)
1351f6ccfffSVineet Gupta {
1361f6ccfffSVineet Gupta 	/* FLS insn has exactly same semantics as the API */
1371f6ccfffSVineet Gupta 	return	__builtin_arc_fls(x);
1381f6ccfffSVineet Gupta }
1391f6ccfffSVineet Gupta 
1401f6ccfffSVineet Gupta /*
1411f6ccfffSVineet Gupta  * ffs = Find First Set in word (LSB to MSB)
1421f6ccfffSVineet Gupta  * @result: [1-32], 0 if all 0's
1431f6ccfffSVineet Gupta  */
1441f6ccfffSVineet Gupta static inline __attribute__ ((const)) int ffs(unsigned long x)
1451f6ccfffSVineet Gupta {
1461f6ccfffSVineet Gupta 	int n;
1471f6ccfffSVineet Gupta 
1481f6ccfffSVineet Gupta 	asm volatile(
1491f6ccfffSVineet Gupta 	"	ffs.f	%0, %1		\n"  /* 0:31; 31(Z) if src 0 */
1501f6ccfffSVineet Gupta 	"	add.nz	%0, %0, 1	\n"  /* 0:31 -> 1:32 */
1511f6ccfffSVineet Gupta 	"	mov.z	%0, 0		\n"  /* 31(Z)-> 0 */
1521f6ccfffSVineet Gupta 	: "=r"(n)	/* Early clobber not needed */
1531f6ccfffSVineet Gupta 	: "r"(x)
1541f6ccfffSVineet Gupta 	: "cc");
1551f6ccfffSVineet Gupta 
1561f6ccfffSVineet Gupta 	return n;
1571f6ccfffSVineet Gupta }
1581f6ccfffSVineet Gupta 
1591f6ccfffSVineet Gupta /*
1601f6ccfffSVineet Gupta  * __ffs: Similar to ffs, but zero based (0-31)
1611f6ccfffSVineet Gupta  */
1624e868f84SEugeniy Paltsev static inline __attribute__ ((const)) unsigned long __ffs(unsigned long x)
1631f6ccfffSVineet Gupta {
1644e868f84SEugeniy Paltsev 	unsigned long n;
1651f6ccfffSVineet Gupta 
1661f6ccfffSVineet Gupta 	asm volatile(
1671f6ccfffSVineet Gupta 	"	ffs.f	%0, %1		\n"  /* 0:31; 31(Z) if src 0 */
1681f6ccfffSVineet Gupta 	"	mov.z	%0, 0		\n"  /* 31(Z)-> 0 */
1691f6ccfffSVineet Gupta 	: "=r"(n)
1701f6ccfffSVineet Gupta 	: "r"(x)
1711f6ccfffSVineet Gupta 	: "cc");
1721f6ccfffSVineet Gupta 
1731f6ccfffSVineet Gupta 	return n;
1741f6ccfffSVineet Gupta 
1751f6ccfffSVineet Gupta }
1761f6ccfffSVineet Gupta 
1771f6ccfffSVineet Gupta #endif	/* CONFIG_ISA_ARCOMPACT */
1781f6ccfffSVineet Gupta 
17914e968baSVineet Gupta /*
18014e968baSVineet Gupta  * ffz = Find First Zero in word.
18114e968baSVineet Gupta  * @return:[0-31], 32 if all 1's
18214e968baSVineet Gupta  */
18314e968baSVineet Gupta #define ffz(x)	__ffs(~(x))
18414e968baSVineet Gupta 
18514e968baSVineet Gupta #include <asm-generic/bitops/hweight.h>
18614e968baSVineet Gupta #include <asm-generic/bitops/fls64.h>
18714e968baSVineet Gupta #include <asm-generic/bitops/sched.h>
18814e968baSVineet Gupta #include <asm-generic/bitops/lock.h>
189*cea43147SVineet Gupta #include <asm-generic/bitops/atomic.h>
190*cea43147SVineet Gupta #include <asm-generic/bitops/non-atomic.h>
19114e968baSVineet Gupta 
19214e968baSVineet Gupta #include <asm-generic/bitops/find.h>
19314e968baSVineet Gupta #include <asm-generic/bitops/le.h>
19414e968baSVineet Gupta #include <asm-generic/bitops/ext2-atomic-setbit.h>
19514e968baSVineet Gupta 
19614e968baSVineet Gupta #endif /* !__ASSEMBLY__ */
19714e968baSVineet Gupta 
19814e968baSVineet Gupta #endif
199