xref: /openbmc/linux/arch/xtensa/include/asm/bitops.h (revision b387dc044efaa07cd8a47316c83fe2a5c08f9650)
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 #ifndef _LINUX_BITOPS_H
17367b8112SChris Zankel #error only <linux/bitops.h> can be included directly
18367b8112SChris Zankel #endif
19367b8112SChris Zankel 
20367b8112SChris Zankel #include <asm/processor.h>
21367b8112SChris Zankel #include <asm/byteorder.h>
2209a01c0cSPeter Zijlstra #include <asm/barrier.h>
23367b8112SChris Zankel 
24367b8112SChris Zankel #include <asm-generic/bitops/non-atomic.h>
25367b8112SChris Zankel 
26367b8112SChris Zankel #if XCHAL_HAVE_NSA
27367b8112SChris Zankel 
28367b8112SChris Zankel static inline unsigned long __cntlz (unsigned long x)
29367b8112SChris Zankel {
30367b8112SChris Zankel 	int lz;
31367b8112SChris Zankel 	asm ("nsau %0, %1" : "=r" (lz) : "r" (x));
32367b8112SChris Zankel 	return lz;
33367b8112SChris Zankel }
34367b8112SChris Zankel 
35367b8112SChris Zankel /*
36367b8112SChris Zankel  * ffz: Find first zero in word. Undefined if no zero exists.
37367b8112SChris Zankel  * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
38367b8112SChris Zankel  */
39367b8112SChris Zankel 
40367b8112SChris Zankel static inline int ffz(unsigned long x)
41367b8112SChris Zankel {
42367b8112SChris Zankel 	return 31 - __cntlz(~x & -~x);
43367b8112SChris Zankel }
44367b8112SChris Zankel 
45367b8112SChris Zankel /*
46367b8112SChris Zankel  * __ffs: Find first bit set in word. Return 0 for bit 0
47367b8112SChris Zankel  */
48367b8112SChris Zankel 
4912c8007dSMax Filippov static inline unsigned long __ffs(unsigned long x)
50367b8112SChris Zankel {
51367b8112SChris Zankel 	return 31 - __cntlz(x & -x);
52367b8112SChris Zankel }
53367b8112SChris Zankel 
54367b8112SChris Zankel /*
55367b8112SChris Zankel  * ffs: Find first bit set in word. This is defined the same way as
56367b8112SChris Zankel  * the libc and compiler builtin ffs routines, therefore
57367b8112SChris Zankel  * differs in spirit from the above ffz (man ffs).
58367b8112SChris Zankel  */
59367b8112SChris Zankel 
60367b8112SChris Zankel static inline int ffs(unsigned long x)
61367b8112SChris Zankel {
62367b8112SChris Zankel 	return 32 - __cntlz(x & -x);
63367b8112SChris Zankel }
64367b8112SChris Zankel 
65367b8112SChris Zankel /*
66367b8112SChris Zankel  * fls: Find last (most-significant) bit set in word.
67367b8112SChris Zankel  * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
68367b8112SChris Zankel  */
69367b8112SChris Zankel 
70367b8112SChris Zankel static inline int fls (unsigned int x)
71367b8112SChris Zankel {
72367b8112SChris Zankel 	return 32 - __cntlz(x);
73367b8112SChris Zankel }
74367b8112SChris Zankel 
7552fefcecSLinus Torvalds /**
7652fefcecSLinus Torvalds  * __fls - find last (most-significant) set bit in a long word
7752fefcecSLinus Torvalds  * @word: the word to search
7852fefcecSLinus Torvalds  *
7952fefcecSLinus Torvalds  * Undefined if no set bit exists, so code should check against 0 first.
8052fefcecSLinus Torvalds  */
8152fefcecSLinus Torvalds static inline unsigned long __fls(unsigned long word)
8252fefcecSLinus Torvalds {
8352fefcecSLinus Torvalds 	return 31 - __cntlz(word);
8452fefcecSLinus Torvalds }
85367b8112SChris Zankel #else
86367b8112SChris Zankel 
87367b8112SChris Zankel /* Use the generic implementation if we don't have the nsa/nsau instructions. */
88367b8112SChris Zankel 
89367b8112SChris Zankel # include <asm-generic/bitops/ffs.h>
90367b8112SChris Zankel # include <asm-generic/bitops/__ffs.h>
91367b8112SChris Zankel # include <asm-generic/bitops/ffz.h>
92367b8112SChris Zankel # include <asm-generic/bitops/fls.h>
9352fefcecSLinus Torvalds # include <asm-generic/bitops/__fls.h>
94367b8112SChris Zankel 
95367b8112SChris Zankel #endif
96367b8112SChris Zankel 
97367b8112SChris Zankel #include <asm-generic/bitops/fls64.h>
98e5a9f6adSMax Filippov 
99f7c34874SMax Filippov #if XCHAL_HAVE_EXCLUSIVE
100f7c34874SMax Filippov 
101*b387dc04SMax Filippov #define BIT_OP(op, insn, inv)						\
102*b387dc04SMax Filippov static inline void op##_bit(unsigned int bit, volatile unsigned long *p)\
103*b387dc04SMax Filippov {									\
104*b387dc04SMax Filippov 	unsigned long tmp;						\
105*b387dc04SMax Filippov 	unsigned long mask = 1UL << (bit & 31);				\
106*b387dc04SMax Filippov 									\
107*b387dc04SMax Filippov 	p += bit >> 5;							\
108*b387dc04SMax Filippov 									\
109*b387dc04SMax Filippov 	__asm__ __volatile__(						\
110*b387dc04SMax Filippov 			"1:     l32ex   %0, %2\n"			\
111*b387dc04SMax Filippov 			"      "insn"   %0, %0, %1\n"			\
112*b387dc04SMax Filippov 			"       s32ex   %0, %2\n"			\
113*b387dc04SMax Filippov 			"       getex   %0\n"				\
114*b387dc04SMax Filippov 			"       beqz    %0, 1b\n"			\
115*b387dc04SMax Filippov 			: "=&a" (tmp)					\
116*b387dc04SMax Filippov 			: "a" (inv mask), "a" (p)			\
117*b387dc04SMax Filippov 			: "memory");					\
118f7c34874SMax Filippov }
119f7c34874SMax Filippov 
120*b387dc04SMax Filippov #define TEST_AND_BIT_OP(op, insn, inv)					\
121*b387dc04SMax Filippov static inline int							\
122*b387dc04SMax Filippov test_and_##op##_bit(unsigned int bit, volatile unsigned long *p)	\
123*b387dc04SMax Filippov {									\
124*b387dc04SMax Filippov 	unsigned long tmp, value;					\
125*b387dc04SMax Filippov 	unsigned long mask = 1UL << (bit & 31);				\
126*b387dc04SMax Filippov 									\
127*b387dc04SMax Filippov 	p += bit >> 5;							\
128*b387dc04SMax Filippov 									\
129*b387dc04SMax Filippov 	__asm__ __volatile__(						\
130*b387dc04SMax Filippov 			"1:     l32ex   %1, %3\n"			\
131*b387dc04SMax Filippov 			"      "insn"   %0, %1, %2\n"			\
132*b387dc04SMax Filippov 			"       s32ex   %0, %3\n"			\
133*b387dc04SMax Filippov 			"       getex   %0\n"				\
134*b387dc04SMax Filippov 			"       beqz    %0, 1b\n"			\
135*b387dc04SMax Filippov 			: "=&a" (tmp), "=&a" (value)			\
136*b387dc04SMax Filippov 			: "a" (inv mask), "a" (p)			\
137*b387dc04SMax Filippov 			: "memory");					\
138*b387dc04SMax Filippov 									\
139*b387dc04SMax Filippov 	return value & mask;						\
140f7c34874SMax Filippov }
141f7c34874SMax Filippov 
142f7c34874SMax Filippov #elif XCHAL_HAVE_S32C1I
143e5a9f6adSMax Filippov 
144*b387dc04SMax Filippov #define BIT_OP(op, insn, inv)						\
145*b387dc04SMax Filippov static inline void op##_bit(unsigned int bit, volatile unsigned long *p)\
146*b387dc04SMax Filippov {									\
147*b387dc04SMax Filippov 	unsigned long tmp, value;					\
148*b387dc04SMax Filippov 	unsigned long mask = 1UL << (bit & 31);				\
149*b387dc04SMax Filippov 									\
150*b387dc04SMax Filippov 	p += bit >> 5;							\
151*b387dc04SMax Filippov 									\
152*b387dc04SMax Filippov 	__asm__ __volatile__(						\
153*b387dc04SMax Filippov 			"1:     l32i    %1, %3, 0\n"			\
154*b387dc04SMax Filippov 			"       wsr     %1, scompare1\n"		\
155*b387dc04SMax Filippov 			"      "insn"   %0, %1, %2\n"			\
156*b387dc04SMax Filippov 			"       s32c1i  %0, %3, 0\n"			\
157*b387dc04SMax Filippov 			"       bne     %0, %1, 1b\n"			\
158*b387dc04SMax Filippov 			: "=&a" (tmp), "=&a" (value)			\
159*b387dc04SMax Filippov 			: "a" (inv mask), "a" (p)			\
160*b387dc04SMax Filippov 			: "memory");					\
161e5a9f6adSMax Filippov }
162e5a9f6adSMax Filippov 
163*b387dc04SMax Filippov #define TEST_AND_BIT_OP(op, insn, inv)					\
164*b387dc04SMax Filippov static inline int							\
165*b387dc04SMax Filippov test_and_##op##_bit(unsigned int bit, volatile unsigned long *p)	\
166*b387dc04SMax Filippov {									\
167*b387dc04SMax Filippov 	unsigned long tmp, value;					\
168*b387dc04SMax Filippov 	unsigned long mask = 1UL << (bit & 31);				\
169*b387dc04SMax Filippov 									\
170*b387dc04SMax Filippov 	p += bit >> 5;							\
171*b387dc04SMax Filippov 									\
172*b387dc04SMax Filippov 	__asm__ __volatile__(						\
173*b387dc04SMax Filippov 			"1:     l32i    %1, %3, 0\n"			\
174*b387dc04SMax Filippov 			"       wsr     %1, scompare1\n"		\
175*b387dc04SMax Filippov 			"      "insn"   %0, %1, %2\n"			\
176*b387dc04SMax Filippov 			"       s32c1i  %0, %3, 0\n"			\
177*b387dc04SMax Filippov 			"       bne     %0, %1, 1b\n"			\
178*b387dc04SMax Filippov 			: "=&a" (tmp), "=&a" (value)			\
179*b387dc04SMax Filippov 			: "a" (inv mask), "a" (p)			\
180*b387dc04SMax Filippov 			: "memory");					\
181*b387dc04SMax Filippov 									\
182*b387dc04SMax Filippov 	return tmp & mask;						\
183e5a9f6adSMax Filippov }
184e5a9f6adSMax Filippov 
185e5a9f6adSMax Filippov #else
186e5a9f6adSMax Filippov 
187*b387dc04SMax Filippov #define BIT_OP(op, insn, inv)
188*b387dc04SMax Filippov #define TEST_AND_BIT_OP(op, insn, inv)
189*b387dc04SMax Filippov 
190e5a9f6adSMax Filippov #include <asm-generic/bitops/atomic.h>
191e5a9f6adSMax Filippov 
192e5a9f6adSMax Filippov #endif /* XCHAL_HAVE_S32C1I */
193e5a9f6adSMax Filippov 
194*b387dc04SMax Filippov #define BIT_OPS(op, insn, inv)		\
195*b387dc04SMax Filippov 	BIT_OP(op, insn, inv)		\
196*b387dc04SMax Filippov 	TEST_AND_BIT_OP(op, insn, inv)
197*b387dc04SMax Filippov 
198*b387dc04SMax Filippov BIT_OPS(set, "or", )
199*b387dc04SMax Filippov BIT_OPS(clear, "and", ~)
200*b387dc04SMax Filippov BIT_OPS(change, "xor", )
201*b387dc04SMax Filippov 
202*b387dc04SMax Filippov #undef BIT_OPS
203*b387dc04SMax Filippov #undef BIT_OP
204*b387dc04SMax Filippov #undef TEST_AND_BIT_OP
205*b387dc04SMax Filippov 
206367b8112SChris Zankel #include <asm-generic/bitops/find.h>
207861b5ae7SAkinobu Mita #include <asm-generic/bitops/le.h>
208367b8112SChris Zankel 
209148817baSAkinobu Mita #include <asm-generic/bitops/ext2-atomic-setbit.h>
210367b8112SChris Zankel 
211367b8112SChris Zankel #include <asm-generic/bitops/hweight.h>
212367b8112SChris Zankel #include <asm-generic/bitops/lock.h>
213367b8112SChris Zankel #include <asm-generic/bitops/sched.h>
214367b8112SChris Zankel 
215367b8112SChris Zankel #endif	/* _XTENSA_BITOPS_H */
216