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