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 */
clz(unsigned int x)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
constant_fls(unsigned int x)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 */
fls(unsigned int x)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 */
__fls(unsigned long x)85*a1db7ad3SAmadeusz Sławiński static inline __attribute__ ((const)) unsigned long __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 */
__ffs(unsigned long word)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 */
fls(unsigned int x)1179d011e12SVineet Gupta static inline __attribute__ ((const)) int fls(unsigned int 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 */
__fls(unsigned long x)134*a1db7ad3SAmadeusz Sławiński static inline __attribute__ ((const)) unsigned long __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 */
ffs(unsigned int x)1449d011e12SVineet Gupta static inline __attribute__ ((const)) int ffs(unsigned int 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 */
__ffs(unsigned long x)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>
189cea43147SVineet Gupta #include <asm-generic/bitops/atomic.h>
190cea43147SVineet Gupta #include <asm-generic/bitops/non-atomic.h>
19114e968baSVineet Gupta
19214e968baSVineet Gupta #include <asm-generic/bitops/le.h>
19314e968baSVineet Gupta #include <asm-generic/bitops/ext2-atomic-setbit.h>
19414e968baSVineet Gupta
19514e968baSVineet Gupta #endif /* !__ASSEMBLY__ */
19614e968baSVineet Gupta
19714e968baSVineet Gupta #endif
198