xref: /openbmc/linux/arch/xtensa/include/asm/bitops.h (revision 148817ba092f9f6edd35bad3c6c6b8e8f90fe2ed)
1367b8112SChris Zankel /*
2367b8112SChris Zankel  * include/asm-xtensa/bitops.h
3367b8112SChris Zankel  *
4367b8112SChris Zankel  * Atomic operations that C can't guarantee us.Useful for resource counting etc.
5367b8112SChris Zankel  *
6367b8112SChris Zankel  * This file is subject to the terms and conditions of the GNU General Public
7367b8112SChris Zankel  * License.  See the file "COPYING" in the main directory of this archive
8367b8112SChris Zankel  * for more details.
9367b8112SChris Zankel  *
10367b8112SChris Zankel  * Copyright (C) 2001 - 2007 Tensilica Inc.
11367b8112SChris Zankel  */
12367b8112SChris Zankel 
13367b8112SChris Zankel #ifndef _XTENSA_BITOPS_H
14367b8112SChris Zankel #define _XTENSA_BITOPS_H
15367b8112SChris Zankel 
16367b8112SChris Zankel #ifdef __KERNEL__
17367b8112SChris Zankel 
18367b8112SChris Zankel #ifndef _LINUX_BITOPS_H
19367b8112SChris Zankel #error only <linux/bitops.h> can be included directly
20367b8112SChris Zankel #endif
21367b8112SChris Zankel 
22367b8112SChris Zankel #include <asm/processor.h>
23367b8112SChris Zankel #include <asm/byteorder.h>
24367b8112SChris Zankel #include <asm/system.h>
25367b8112SChris Zankel 
26367b8112SChris Zankel #ifdef CONFIG_SMP
27367b8112SChris Zankel # error SMP not supported on this architecture
28367b8112SChris Zankel #endif
29367b8112SChris Zankel 
30367b8112SChris Zankel #define smp_mb__before_clear_bit()	barrier()
31367b8112SChris Zankel #define smp_mb__after_clear_bit()	barrier()
32367b8112SChris Zankel 
33367b8112SChris Zankel #include <asm-generic/bitops/atomic.h>
34367b8112SChris Zankel #include <asm-generic/bitops/non-atomic.h>
35367b8112SChris Zankel 
36367b8112SChris Zankel #if XCHAL_HAVE_NSA
37367b8112SChris Zankel 
38367b8112SChris Zankel static inline unsigned long __cntlz (unsigned long x)
39367b8112SChris Zankel {
40367b8112SChris Zankel 	int lz;
41367b8112SChris Zankel 	asm ("nsau %0, %1" : "=r" (lz) : "r" (x));
42367b8112SChris Zankel 	return lz;
43367b8112SChris Zankel }
44367b8112SChris Zankel 
45367b8112SChris Zankel /*
46367b8112SChris Zankel  * ffz: Find first zero in word. Undefined if no zero exists.
47367b8112SChris Zankel  * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
48367b8112SChris Zankel  */
49367b8112SChris Zankel 
50367b8112SChris Zankel static inline int ffz(unsigned long x)
51367b8112SChris Zankel {
52367b8112SChris Zankel 	return 31 - __cntlz(~x & -~x);
53367b8112SChris Zankel }
54367b8112SChris Zankel 
55367b8112SChris Zankel /*
56367b8112SChris Zankel  * __ffs: Find first bit set in word. Return 0 for bit 0
57367b8112SChris Zankel  */
58367b8112SChris Zankel 
59367b8112SChris Zankel static inline int __ffs(unsigned long x)
60367b8112SChris Zankel {
61367b8112SChris Zankel 	return 31 - __cntlz(x & -x);
62367b8112SChris Zankel }
63367b8112SChris Zankel 
64367b8112SChris Zankel /*
65367b8112SChris Zankel  * ffs: Find first bit set in word. This is defined the same way as
66367b8112SChris Zankel  * the libc and compiler builtin ffs routines, therefore
67367b8112SChris Zankel  * differs in spirit from the above ffz (man ffs).
68367b8112SChris Zankel  */
69367b8112SChris Zankel 
70367b8112SChris Zankel static inline int ffs(unsigned long x)
71367b8112SChris Zankel {
72367b8112SChris Zankel 	return 32 - __cntlz(x & -x);
73367b8112SChris Zankel }
74367b8112SChris Zankel 
75367b8112SChris Zankel /*
76367b8112SChris Zankel  * fls: Find last (most-significant) bit set in word.
77367b8112SChris Zankel  * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
78367b8112SChris Zankel  */
79367b8112SChris Zankel 
80367b8112SChris Zankel static inline int fls (unsigned int x)
81367b8112SChris Zankel {
82367b8112SChris Zankel 	return 32 - __cntlz(x);
83367b8112SChris Zankel }
84367b8112SChris Zankel 
8552fefcecSLinus Torvalds /**
8652fefcecSLinus Torvalds  * __fls - find last (most-significant) set bit in a long word
8752fefcecSLinus Torvalds  * @word: the word to search
8852fefcecSLinus Torvalds  *
8952fefcecSLinus Torvalds  * Undefined if no set bit exists, so code should check against 0 first.
9052fefcecSLinus Torvalds  */
9152fefcecSLinus Torvalds static inline unsigned long __fls(unsigned long word)
9252fefcecSLinus Torvalds {
9352fefcecSLinus Torvalds 	return 31 - __cntlz(word);
9452fefcecSLinus Torvalds }
95367b8112SChris Zankel #else
96367b8112SChris Zankel 
97367b8112SChris Zankel /* Use the generic implementation if we don't have the nsa/nsau instructions. */
98367b8112SChris Zankel 
99367b8112SChris Zankel # include <asm-generic/bitops/ffs.h>
100367b8112SChris Zankel # include <asm-generic/bitops/__ffs.h>
101367b8112SChris Zankel # include <asm-generic/bitops/ffz.h>
102367b8112SChris Zankel # include <asm-generic/bitops/fls.h>
10352fefcecSLinus Torvalds # include <asm-generic/bitops/__fls.h>
104367b8112SChris Zankel 
105367b8112SChris Zankel #endif
106367b8112SChris Zankel 
107367b8112SChris Zankel #include <asm-generic/bitops/fls64.h>
108367b8112SChris Zankel #include <asm-generic/bitops/find.h>
109861b5ae7SAkinobu Mita #include <asm-generic/bitops/le.h>
110367b8112SChris Zankel 
111*148817baSAkinobu Mita #include <asm-generic/bitops/ext2-atomic-setbit.h>
112367b8112SChris Zankel 
113367b8112SChris Zankel #include <asm-generic/bitops/hweight.h>
114367b8112SChris Zankel #include <asm-generic/bitops/lock.h>
115367b8112SChris Zankel #include <asm-generic/bitops/sched.h>
116367b8112SChris Zankel 
117367b8112SChris Zankel #endif	/* __KERNEL__ */
118367b8112SChris Zankel 
119367b8112SChris Zankel #endif	/* _XTENSA_BITOPS_H */
120