xref: /openbmc/linux/arch/xtensa/include/asm/bitops.h (revision f7c34874f04a80d6c39a32f08da2529e59602d3c)
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 
99*f7c34874SMax Filippov #if XCHAL_HAVE_EXCLUSIVE
100*f7c34874SMax Filippov 
101*f7c34874SMax Filippov static inline void set_bit(unsigned int bit, volatile unsigned long *p)
102*f7c34874SMax Filippov {
103*f7c34874SMax Filippov 	unsigned long tmp;
104*f7c34874SMax Filippov 	unsigned long mask = 1UL << (bit & 31);
105*f7c34874SMax Filippov 
106*f7c34874SMax Filippov 	p += bit >> 5;
107*f7c34874SMax Filippov 
108*f7c34874SMax Filippov 	__asm__ __volatile__(
109*f7c34874SMax Filippov 			"1:     l32ex   %0, %2\n"
110*f7c34874SMax Filippov 			"       or      %0, %0, %1\n"
111*f7c34874SMax Filippov 			"       s32ex   %0, %2\n"
112*f7c34874SMax Filippov 			"       getex   %0\n"
113*f7c34874SMax Filippov 			"       beqz    %0, 1b\n"
114*f7c34874SMax Filippov 			: "=&a" (tmp)
115*f7c34874SMax Filippov 			: "a" (mask), "a" (p)
116*f7c34874SMax Filippov 			: "memory");
117*f7c34874SMax Filippov }
118*f7c34874SMax Filippov 
119*f7c34874SMax Filippov static inline void clear_bit(unsigned int bit, volatile unsigned long *p)
120*f7c34874SMax Filippov {
121*f7c34874SMax Filippov 	unsigned long tmp;
122*f7c34874SMax Filippov 	unsigned long mask = 1UL << (bit & 31);
123*f7c34874SMax Filippov 
124*f7c34874SMax Filippov 	p += bit >> 5;
125*f7c34874SMax Filippov 
126*f7c34874SMax Filippov 	__asm__ __volatile__(
127*f7c34874SMax Filippov 			"1:     l32ex   %0, %2\n"
128*f7c34874SMax Filippov 			"       and     %0, %0, %1\n"
129*f7c34874SMax Filippov 			"       s32ex   %0, %2\n"
130*f7c34874SMax Filippov 			"       getex   %0\n"
131*f7c34874SMax Filippov 			"       beqz    %0, 1b\n"
132*f7c34874SMax Filippov 			: "=&a" (tmp)
133*f7c34874SMax Filippov 			: "a" (~mask), "a" (p)
134*f7c34874SMax Filippov 			: "memory");
135*f7c34874SMax Filippov }
136*f7c34874SMax Filippov 
137*f7c34874SMax Filippov static inline void change_bit(unsigned int bit, volatile unsigned long *p)
138*f7c34874SMax Filippov {
139*f7c34874SMax Filippov 	unsigned long tmp;
140*f7c34874SMax Filippov 	unsigned long mask = 1UL << (bit & 31);
141*f7c34874SMax Filippov 
142*f7c34874SMax Filippov 	p += bit >> 5;
143*f7c34874SMax Filippov 
144*f7c34874SMax Filippov 	__asm__ __volatile__(
145*f7c34874SMax Filippov 			"1:     l32ex   %0, %2\n"
146*f7c34874SMax Filippov 			"       xor     %0, %0, %1\n"
147*f7c34874SMax Filippov 			"       s32ex   %0, %2\n"
148*f7c34874SMax Filippov 			"       getex   %0\n"
149*f7c34874SMax Filippov 			"       beqz    %0, 1b\n"
150*f7c34874SMax Filippov 			: "=&a" (tmp)
151*f7c34874SMax Filippov 			: "a" (~mask), "a" (p)
152*f7c34874SMax Filippov 			: "memory");
153*f7c34874SMax Filippov }
154*f7c34874SMax Filippov 
155*f7c34874SMax Filippov static inline int
156*f7c34874SMax Filippov test_and_set_bit(unsigned int bit, volatile unsigned long *p)
157*f7c34874SMax Filippov {
158*f7c34874SMax Filippov 	unsigned long tmp, value;
159*f7c34874SMax Filippov 	unsigned long mask = 1UL << (bit & 31);
160*f7c34874SMax Filippov 
161*f7c34874SMax Filippov 	p += bit >> 5;
162*f7c34874SMax Filippov 
163*f7c34874SMax Filippov 	__asm__ __volatile__(
164*f7c34874SMax Filippov 			"1:     l32ex   %1, %3\n"
165*f7c34874SMax Filippov 			"       or      %0, %1, %2\n"
166*f7c34874SMax Filippov 			"       s32ex   %0, %3\n"
167*f7c34874SMax Filippov 			"       getex   %0\n"
168*f7c34874SMax Filippov 			"       beqz    %0, 1b\n"
169*f7c34874SMax Filippov 			: "=&a" (tmp), "=&a" (value)
170*f7c34874SMax Filippov 			: "a" (mask), "a" (p)
171*f7c34874SMax Filippov 			: "memory");
172*f7c34874SMax Filippov 
173*f7c34874SMax Filippov 	return value & mask;
174*f7c34874SMax Filippov }
175*f7c34874SMax Filippov 
176*f7c34874SMax Filippov static inline int
177*f7c34874SMax Filippov test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
178*f7c34874SMax Filippov {
179*f7c34874SMax Filippov 	unsigned long tmp, value;
180*f7c34874SMax Filippov 	unsigned long mask = 1UL << (bit & 31);
181*f7c34874SMax Filippov 
182*f7c34874SMax Filippov 	p += bit >> 5;
183*f7c34874SMax Filippov 
184*f7c34874SMax Filippov 	__asm__ __volatile__(
185*f7c34874SMax Filippov 			"1:     l32ex   %1, %3\n"
186*f7c34874SMax Filippov 			"       and     %0, %1, %2\n"
187*f7c34874SMax Filippov 			"       s32ex   %0, %3\n"
188*f7c34874SMax Filippov 			"       getex   %0\n"
189*f7c34874SMax Filippov 			"       beqz    %0, 1b\n"
190*f7c34874SMax Filippov 			: "=&a" (tmp), "=&a" (value)
191*f7c34874SMax Filippov 			: "a" (~mask), "a" (p)
192*f7c34874SMax Filippov 			: "memory");
193*f7c34874SMax Filippov 
194*f7c34874SMax Filippov 	return value & mask;
195*f7c34874SMax Filippov }
196*f7c34874SMax Filippov 
197*f7c34874SMax Filippov static inline int
198*f7c34874SMax Filippov test_and_change_bit(unsigned int bit, volatile unsigned long *p)
199*f7c34874SMax Filippov {
200*f7c34874SMax Filippov 	unsigned long tmp, value;
201*f7c34874SMax Filippov 	unsigned long mask = 1UL << (bit & 31);
202*f7c34874SMax Filippov 
203*f7c34874SMax Filippov 	p += bit >> 5;
204*f7c34874SMax Filippov 
205*f7c34874SMax Filippov 	__asm__ __volatile__(
206*f7c34874SMax Filippov 			"1:     l32ex   %1, %3\n"
207*f7c34874SMax Filippov 			"       xor     %0, %1, %2\n"
208*f7c34874SMax Filippov 			"       s32ex   %0, %3\n"
209*f7c34874SMax Filippov 			"       getex   %0\n"
210*f7c34874SMax Filippov 			"       beqz    %0, 1b\n"
211*f7c34874SMax Filippov 			: "=&a" (tmp), "=&a" (value)
212*f7c34874SMax Filippov 			: "a" (mask), "a" (p)
213*f7c34874SMax Filippov 			: "memory");
214*f7c34874SMax Filippov 
215*f7c34874SMax Filippov 	return value & mask;
216*f7c34874SMax Filippov }
217*f7c34874SMax Filippov 
218*f7c34874SMax Filippov #elif XCHAL_HAVE_S32C1I
219e5a9f6adSMax Filippov 
220e5a9f6adSMax Filippov static inline void set_bit(unsigned int bit, volatile unsigned long *p)
221e5a9f6adSMax Filippov {
222e5a9f6adSMax Filippov 	unsigned long tmp, value;
223e5a9f6adSMax Filippov 	unsigned long mask = 1UL << (bit & 31);
224e5a9f6adSMax Filippov 
225e5a9f6adSMax Filippov 	p += bit >> 5;
226e5a9f6adSMax Filippov 
227e5a9f6adSMax Filippov 	__asm__ __volatile__(
228e5a9f6adSMax Filippov 			"1:     l32i    %1, %3, 0\n"
229e5a9f6adSMax Filippov 			"       wsr     %1, scompare1\n"
230e5a9f6adSMax Filippov 			"       or      %0, %1, %2\n"
231e5a9f6adSMax Filippov 			"       s32c1i  %0, %3, 0\n"
232e5a9f6adSMax Filippov 			"       bne     %0, %1, 1b\n"
233e5a9f6adSMax Filippov 			: "=&a" (tmp), "=&a" (value)
234e5a9f6adSMax Filippov 			: "a" (mask), "a" (p)
235e5a9f6adSMax Filippov 			: "memory");
236e5a9f6adSMax Filippov }
237e5a9f6adSMax Filippov 
238e5a9f6adSMax Filippov static inline void clear_bit(unsigned int bit, volatile unsigned long *p)
239e5a9f6adSMax Filippov {
240e5a9f6adSMax Filippov 	unsigned long tmp, value;
241e5a9f6adSMax Filippov 	unsigned long mask = 1UL << (bit & 31);
242e5a9f6adSMax Filippov 
243e5a9f6adSMax Filippov 	p += bit >> 5;
244e5a9f6adSMax Filippov 
245e5a9f6adSMax Filippov 	__asm__ __volatile__(
246e5a9f6adSMax Filippov 			"1:     l32i    %1, %3, 0\n"
247e5a9f6adSMax Filippov 			"       wsr     %1, scompare1\n"
248e5a9f6adSMax Filippov 			"       and     %0, %1, %2\n"
249e5a9f6adSMax Filippov 			"       s32c1i  %0, %3, 0\n"
250e5a9f6adSMax Filippov 			"       bne     %0, %1, 1b\n"
251e5a9f6adSMax Filippov 			: "=&a" (tmp), "=&a" (value)
252e5a9f6adSMax Filippov 			: "a" (~mask), "a" (p)
253e5a9f6adSMax Filippov 			: "memory");
254e5a9f6adSMax Filippov }
255e5a9f6adSMax Filippov 
256e5a9f6adSMax Filippov static inline void change_bit(unsigned int bit, volatile unsigned long *p)
257e5a9f6adSMax Filippov {
258e5a9f6adSMax Filippov 	unsigned long tmp, value;
259e5a9f6adSMax Filippov 	unsigned long mask = 1UL << (bit & 31);
260e5a9f6adSMax Filippov 
261e5a9f6adSMax Filippov 	p += bit >> 5;
262e5a9f6adSMax Filippov 
263e5a9f6adSMax Filippov 	__asm__ __volatile__(
264e5a9f6adSMax Filippov 			"1:     l32i    %1, %3, 0\n"
265e5a9f6adSMax Filippov 			"       wsr     %1, scompare1\n"
266e5a9f6adSMax Filippov 			"       xor     %0, %1, %2\n"
267e5a9f6adSMax Filippov 			"       s32c1i  %0, %3, 0\n"
268e5a9f6adSMax Filippov 			"       bne     %0, %1, 1b\n"
269e5a9f6adSMax Filippov 			: "=&a" (tmp), "=&a" (value)
270e5a9f6adSMax Filippov 			: "a" (mask), "a" (p)
271e5a9f6adSMax Filippov 			: "memory");
272e5a9f6adSMax Filippov }
273e5a9f6adSMax Filippov 
274e5a9f6adSMax Filippov static inline int
275e5a9f6adSMax Filippov test_and_set_bit(unsigned int bit, volatile unsigned long *p)
276e5a9f6adSMax Filippov {
277e5a9f6adSMax Filippov 	unsigned long tmp, value;
278e5a9f6adSMax Filippov 	unsigned long mask = 1UL << (bit & 31);
279e5a9f6adSMax Filippov 
280e5a9f6adSMax Filippov 	p += bit >> 5;
281e5a9f6adSMax Filippov 
282e5a9f6adSMax Filippov 	__asm__ __volatile__(
283e5a9f6adSMax Filippov 			"1:     l32i    %1, %3, 0\n"
284e5a9f6adSMax Filippov 			"       wsr     %1, scompare1\n"
285e5a9f6adSMax Filippov 			"       or      %0, %1, %2\n"
286e5a9f6adSMax Filippov 			"       s32c1i  %0, %3, 0\n"
287e5a9f6adSMax Filippov 			"       bne     %0, %1, 1b\n"
288e5a9f6adSMax Filippov 			: "=&a" (tmp), "=&a" (value)
289e5a9f6adSMax Filippov 			: "a" (mask), "a" (p)
290e5a9f6adSMax Filippov 			: "memory");
291e5a9f6adSMax Filippov 
292e5a9f6adSMax Filippov 	return tmp & mask;
293e5a9f6adSMax Filippov }
294e5a9f6adSMax Filippov 
295e5a9f6adSMax Filippov static inline int
296e5a9f6adSMax Filippov test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
297e5a9f6adSMax Filippov {
298e5a9f6adSMax Filippov 	unsigned long tmp, value;
299e5a9f6adSMax Filippov 	unsigned long mask = 1UL << (bit & 31);
300e5a9f6adSMax Filippov 
301e5a9f6adSMax Filippov 	p += bit >> 5;
302e5a9f6adSMax Filippov 
303e5a9f6adSMax Filippov 	__asm__ __volatile__(
304e5a9f6adSMax Filippov 			"1:     l32i    %1, %3, 0\n"
305e5a9f6adSMax Filippov 			"       wsr     %1, scompare1\n"
306e5a9f6adSMax Filippov 			"       and     %0, %1, %2\n"
307e5a9f6adSMax Filippov 			"       s32c1i  %0, %3, 0\n"
308e5a9f6adSMax Filippov 			"       bne     %0, %1, 1b\n"
309e5a9f6adSMax Filippov 			: "=&a" (tmp), "=&a" (value)
310e5a9f6adSMax Filippov 			: "a" (~mask), "a" (p)
311e5a9f6adSMax Filippov 			: "memory");
312e5a9f6adSMax Filippov 
313e5a9f6adSMax Filippov 	return tmp & mask;
314e5a9f6adSMax Filippov }
315e5a9f6adSMax Filippov 
316e5a9f6adSMax Filippov static inline int
317e5a9f6adSMax Filippov test_and_change_bit(unsigned int bit, volatile unsigned long *p)
318e5a9f6adSMax Filippov {
319e5a9f6adSMax Filippov 	unsigned long tmp, value;
320e5a9f6adSMax Filippov 	unsigned long mask = 1UL << (bit & 31);
321e5a9f6adSMax Filippov 
322e5a9f6adSMax Filippov 	p += bit >> 5;
323e5a9f6adSMax Filippov 
324e5a9f6adSMax Filippov 	__asm__ __volatile__(
325e5a9f6adSMax Filippov 			"1:     l32i    %1, %3, 0\n"
326e5a9f6adSMax Filippov 			"       wsr     %1, scompare1\n"
327e5a9f6adSMax Filippov 			"       xor     %0, %1, %2\n"
328e5a9f6adSMax Filippov 			"       s32c1i  %0, %3, 0\n"
329e5a9f6adSMax Filippov 			"       bne     %0, %1, 1b\n"
330e5a9f6adSMax Filippov 			: "=&a" (tmp), "=&a" (value)
331e5a9f6adSMax Filippov 			: "a" (mask), "a" (p)
332e5a9f6adSMax Filippov 			: "memory");
333e5a9f6adSMax Filippov 
334e5a9f6adSMax Filippov 	return tmp & mask;
335e5a9f6adSMax Filippov }
336e5a9f6adSMax Filippov 
337e5a9f6adSMax Filippov #else
338e5a9f6adSMax Filippov 
339e5a9f6adSMax Filippov #include <asm-generic/bitops/atomic.h>
340e5a9f6adSMax Filippov 
341e5a9f6adSMax Filippov #endif /* XCHAL_HAVE_S32C1I */
342e5a9f6adSMax Filippov 
343367b8112SChris Zankel #include <asm-generic/bitops/find.h>
344861b5ae7SAkinobu Mita #include <asm-generic/bitops/le.h>
345367b8112SChris Zankel 
346148817baSAkinobu Mita #include <asm-generic/bitops/ext2-atomic-setbit.h>
347367b8112SChris Zankel 
348367b8112SChris Zankel #include <asm-generic/bitops/hweight.h>
349367b8112SChris Zankel #include <asm-generic/bitops/lock.h>
350367b8112SChris Zankel #include <asm-generic/bitops/sched.h>
351367b8112SChris Zankel 
352367b8112SChris Zankel #endif	/* _XTENSA_BITOPS_H */
353