xref: /OK3568_Linux_fs/u-boot/arch/microblaze/include/asm/bitops.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun #ifndef _MICROBLAZE_BITOPS_H
2*4882a593Smuzhiyun #define _MICROBLAZE_BITOPS_H
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun /*
5*4882a593Smuzhiyun  * Copyright 1992, Linus Torvalds.
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <asm/byteorder.h>	/* swab32 */
9*4882a593Smuzhiyun #include <asm/system.h>		/* save_flags */
10*4882a593Smuzhiyun #include <asm-generic/bitops/fls.h>
11*4882a593Smuzhiyun #include <asm-generic/bitops/__fls.h>
12*4882a593Smuzhiyun #include <asm-generic/bitops/fls64.h>
13*4882a593Smuzhiyun #include <asm-generic/bitops/__ffs.h>
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #ifdef __KERNEL__
16*4882a593Smuzhiyun /*
17*4882a593Smuzhiyun  * The __ functions are not atomic
18*4882a593Smuzhiyun  */
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun /*
21*4882a593Smuzhiyun  * ffz = Find First Zero in word. Undefined if no zero exists,
22*4882a593Smuzhiyun  * so code should check against ~0UL first..
23*4882a593Smuzhiyun  */
ffz(unsigned long word)24*4882a593Smuzhiyun static inline unsigned long ffz(unsigned long word)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun 	unsigned long result = 0;
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun 	while(word & 1) {
29*4882a593Smuzhiyun 		result++;
30*4882a593Smuzhiyun 		word >>= 1;
31*4882a593Smuzhiyun 	}
32*4882a593Smuzhiyun 	return result;
33*4882a593Smuzhiyun }
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun 
set_bit(int nr,volatile void * addr)36*4882a593Smuzhiyun static inline void set_bit(int nr, volatile void *addr)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	int	* a = (int *) addr;
39*4882a593Smuzhiyun 	int	mask;
40*4882a593Smuzhiyun 	unsigned long flags;
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	a += nr >> 5;
43*4882a593Smuzhiyun 	mask = 1 << (nr & 0x1f);
44*4882a593Smuzhiyun 	save_flags_cli(flags);
45*4882a593Smuzhiyun 	*a |= mask;
46*4882a593Smuzhiyun 	restore_flags(flags);
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun 
__set_bit(int nr,volatile void * addr)49*4882a593Smuzhiyun static inline void __set_bit(int nr, volatile void *addr)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun 	int	* a = (int *) addr;
52*4882a593Smuzhiyun 	int	mask;
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun 	a += nr >> 5;
55*4882a593Smuzhiyun 	mask = 1 << (nr & 0x1f);
56*4882a593Smuzhiyun 	*a |= mask;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun #define PLATFORM__SET_BIT
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun /*
61*4882a593Smuzhiyun  * clear_bit() doesn't provide any barrier for the compiler.
62*4882a593Smuzhiyun  */
63*4882a593Smuzhiyun #define smp_mb__before_clear_bit()	barrier()
64*4882a593Smuzhiyun #define smp_mb__after_clear_bit()	barrier()
65*4882a593Smuzhiyun 
clear_bit(int nr,volatile void * addr)66*4882a593Smuzhiyun static inline void clear_bit(int nr, volatile void *addr)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun 	int	* a = (int *) addr;
69*4882a593Smuzhiyun 	int	mask;
70*4882a593Smuzhiyun 	unsigned long flags;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	a += nr >> 5;
73*4882a593Smuzhiyun 	mask = 1 << (nr & 0x1f);
74*4882a593Smuzhiyun 	save_flags_cli(flags);
75*4882a593Smuzhiyun 	*a &= ~mask;
76*4882a593Smuzhiyun 	restore_flags(flags);
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun #define __clear_bit(nr, addr) clear_bit(nr, addr)
80*4882a593Smuzhiyun #define PLATFORM__CLEAR_BIT
81*4882a593Smuzhiyun 
change_bit(int nr,volatile void * addr)82*4882a593Smuzhiyun static inline void change_bit(int nr, volatile void *addr)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun 	int mask;
85*4882a593Smuzhiyun 	unsigned long flags;
86*4882a593Smuzhiyun 	unsigned long *ADDR = (unsigned long *) addr;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	ADDR += nr >> 5;
89*4882a593Smuzhiyun 	mask = 1 << (nr & 31);
90*4882a593Smuzhiyun 	save_flags_cli(flags);
91*4882a593Smuzhiyun 	*ADDR ^= mask;
92*4882a593Smuzhiyun 	restore_flags(flags);
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun 
__change_bit(int nr,volatile void * addr)95*4882a593Smuzhiyun static inline void __change_bit(int nr, volatile void *addr)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun 	int mask;
98*4882a593Smuzhiyun 	unsigned long *ADDR = (unsigned long *) addr;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 	ADDR += nr >> 5;
101*4882a593Smuzhiyun 	mask = 1 << (nr & 31);
102*4882a593Smuzhiyun 	*ADDR ^= mask;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun 
test_and_set_bit(int nr,volatile void * addr)105*4882a593Smuzhiyun static inline int test_and_set_bit(int nr, volatile void *addr)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun 	int	mask, retval;
108*4882a593Smuzhiyun 	volatile unsigned int *a = (volatile unsigned int *) addr;
109*4882a593Smuzhiyun 	unsigned long flags;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	a += nr >> 5;
112*4882a593Smuzhiyun 	mask = 1 << (nr & 0x1f);
113*4882a593Smuzhiyun 	save_flags_cli(flags);
114*4882a593Smuzhiyun 	retval = (mask & *a) != 0;
115*4882a593Smuzhiyun 	*a |= mask;
116*4882a593Smuzhiyun 	restore_flags(flags);
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	return retval;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun 
__test_and_set_bit(int nr,volatile void * addr)121*4882a593Smuzhiyun static inline int __test_and_set_bit(int nr, volatile void *addr)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun 	int	mask, retval;
124*4882a593Smuzhiyun 	volatile unsigned int *a = (volatile unsigned int *) addr;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	a += nr >> 5;
127*4882a593Smuzhiyun 	mask = 1 << (nr & 0x1f);
128*4882a593Smuzhiyun 	retval = (mask & *a) != 0;
129*4882a593Smuzhiyun 	*a |= mask;
130*4882a593Smuzhiyun 	return retval;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun 
test_and_clear_bit(int nr,volatile void * addr)133*4882a593Smuzhiyun static inline int test_and_clear_bit(int nr, volatile void *addr)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun 	int	mask, retval;
136*4882a593Smuzhiyun 	volatile unsigned int *a = (volatile unsigned int *) addr;
137*4882a593Smuzhiyun 	unsigned long flags;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	a += nr >> 5;
140*4882a593Smuzhiyun 	mask = 1 << (nr & 0x1f);
141*4882a593Smuzhiyun 	save_flags_cli(flags);
142*4882a593Smuzhiyun 	retval = (mask & *a) != 0;
143*4882a593Smuzhiyun 	*a &= ~mask;
144*4882a593Smuzhiyun 	restore_flags(flags);
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	return retval;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun 
__test_and_clear_bit(int nr,volatile void * addr)149*4882a593Smuzhiyun static inline int __test_and_clear_bit(int nr, volatile void *addr)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun 	int	mask, retval;
152*4882a593Smuzhiyun 	volatile unsigned int *a = (volatile unsigned int *) addr;
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	a += nr >> 5;
155*4882a593Smuzhiyun 	mask = 1 << (nr & 0x1f);
156*4882a593Smuzhiyun 	retval = (mask & *a) != 0;
157*4882a593Smuzhiyun 	*a &= ~mask;
158*4882a593Smuzhiyun 	return retval;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun 
test_and_change_bit(int nr,volatile void * addr)161*4882a593Smuzhiyun static inline int test_and_change_bit(int nr, volatile void *addr)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun 	int	mask, retval;
164*4882a593Smuzhiyun 	volatile unsigned int *a = (volatile unsigned int *) addr;
165*4882a593Smuzhiyun 	unsigned long flags;
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	a += nr >> 5;
168*4882a593Smuzhiyun 	mask = 1 << (nr & 0x1f);
169*4882a593Smuzhiyun 	save_flags_cli(flags);
170*4882a593Smuzhiyun 	retval = (mask & *a) != 0;
171*4882a593Smuzhiyun 	*a ^= mask;
172*4882a593Smuzhiyun 	restore_flags(flags);
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	return retval;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun 
__test_and_change_bit(int nr,volatile void * addr)177*4882a593Smuzhiyun static inline int __test_and_change_bit(int nr, volatile void *addr)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun 	int	mask, retval;
180*4882a593Smuzhiyun 	volatile unsigned int *a = (volatile unsigned int *) addr;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	a += nr >> 5;
183*4882a593Smuzhiyun 	mask = 1 << (nr & 0x1f);
184*4882a593Smuzhiyun 	retval = (mask & *a) != 0;
185*4882a593Smuzhiyun 	*a ^= mask;
186*4882a593Smuzhiyun 	return retval;
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun /*
190*4882a593Smuzhiyun  * This routine doesn't need to be atomic.
191*4882a593Smuzhiyun  */
__constant_test_bit(int nr,const volatile void * addr)192*4882a593Smuzhiyun static inline int __constant_test_bit(int nr, const volatile void *addr)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun 	return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun 
__test_bit(int nr,volatile void * addr)197*4882a593Smuzhiyun static inline int __test_bit(int nr, volatile void *addr)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun 	int	* a = (int *) addr;
200*4882a593Smuzhiyun 	int	mask;
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	a += nr >> 5;
203*4882a593Smuzhiyun 	mask = 1 << (nr & 0x1f);
204*4882a593Smuzhiyun 	return ((mask & *a) != 0);
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun #define test_bit(nr,addr) \
208*4882a593Smuzhiyun (__builtin_constant_p(nr) ? \
209*4882a593Smuzhiyun  __constant_test_bit((nr),(addr)) : \
210*4882a593Smuzhiyun  __test_bit((nr),(addr)))
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun #define find_first_zero_bit(addr, size) \
213*4882a593Smuzhiyun 	find_next_zero_bit((addr), (size), 0)
214*4882a593Smuzhiyun 
find_next_zero_bit(void * addr,int size,int offset)215*4882a593Smuzhiyun static inline int find_next_zero_bit(void *addr, int size, int offset)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun 	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
218*4882a593Smuzhiyun 	unsigned long result = offset & ~31UL;
219*4882a593Smuzhiyun 	unsigned long tmp;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	if (offset >= size)
222*4882a593Smuzhiyun 		return size;
223*4882a593Smuzhiyun 	size -= result;
224*4882a593Smuzhiyun 	offset &= 31UL;
225*4882a593Smuzhiyun 	if (offset) {
226*4882a593Smuzhiyun 		tmp = *(p++);
227*4882a593Smuzhiyun 		tmp |= ~0UL >> (32-offset);
228*4882a593Smuzhiyun 		if (size < 32)
229*4882a593Smuzhiyun 			goto found_first;
230*4882a593Smuzhiyun 		if (~tmp)
231*4882a593Smuzhiyun 			goto found_middle;
232*4882a593Smuzhiyun 		size -= 32;
233*4882a593Smuzhiyun 		result += 32;
234*4882a593Smuzhiyun 	}
235*4882a593Smuzhiyun 	while (size & ~31UL) {
236*4882a593Smuzhiyun 		if (~(tmp = *(p++)))
237*4882a593Smuzhiyun 			goto found_middle;
238*4882a593Smuzhiyun 		result += 32;
239*4882a593Smuzhiyun 		size -= 32;
240*4882a593Smuzhiyun 	}
241*4882a593Smuzhiyun 	if (!size)
242*4882a593Smuzhiyun 		return result;
243*4882a593Smuzhiyun 	tmp = *p;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun found_first:
246*4882a593Smuzhiyun 	tmp |= ~0UL >> size;
247*4882a593Smuzhiyun found_middle:
248*4882a593Smuzhiyun 	return result + ffz(tmp);
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun /*
252*4882a593Smuzhiyun  * hweightN: returns the hamming weight (i.e. the number
253*4882a593Smuzhiyun  * of bits set) of a N-bit word
254*4882a593Smuzhiyun  */
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun #define hweight32(x) generic_hweight32(x)
257*4882a593Smuzhiyun #define hweight16(x) generic_hweight16(x)
258*4882a593Smuzhiyun #define hweight8(x) generic_hweight8(x)
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 
ext2_set_bit(int nr,volatile void * addr)261*4882a593Smuzhiyun static inline int ext2_set_bit(int nr, volatile void *addr)
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun 	int		mask, retval;
264*4882a593Smuzhiyun 	unsigned long	flags;
265*4882a593Smuzhiyun 	volatile unsigned char	*ADDR = (unsigned char *) addr;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	ADDR += nr >> 3;
268*4882a593Smuzhiyun 	mask = 1 << (nr & 0x07);
269*4882a593Smuzhiyun 	save_flags_cli(flags);
270*4882a593Smuzhiyun 	retval = (mask & *ADDR) != 0;
271*4882a593Smuzhiyun 	*ADDR |= mask;
272*4882a593Smuzhiyun 	restore_flags(flags);
273*4882a593Smuzhiyun 	return retval;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun 
ext2_clear_bit(int nr,volatile void * addr)276*4882a593Smuzhiyun static inline int ext2_clear_bit(int nr, volatile void *addr)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun 	int		mask, retval;
279*4882a593Smuzhiyun 	unsigned long	flags;
280*4882a593Smuzhiyun 	volatile unsigned char	*ADDR = (unsigned char *) addr;
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	ADDR += nr >> 3;
283*4882a593Smuzhiyun 	mask = 1 << (nr & 0x07);
284*4882a593Smuzhiyun 	save_flags_cli(flags);
285*4882a593Smuzhiyun 	retval = (mask & *ADDR) != 0;
286*4882a593Smuzhiyun 	*ADDR &= ~mask;
287*4882a593Smuzhiyun 	restore_flags(flags);
288*4882a593Smuzhiyun 	return retval;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun 
ext2_test_bit(int nr,const volatile void * addr)291*4882a593Smuzhiyun static inline int ext2_test_bit(int nr, const volatile void *addr)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun 	int			mask;
294*4882a593Smuzhiyun 	const volatile unsigned char	*ADDR = (const unsigned char *) addr;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	ADDR += nr >> 3;
297*4882a593Smuzhiyun 	mask = 1 << (nr & 0x07);
298*4882a593Smuzhiyun 	return ((mask & *ADDR) != 0);
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun #define ext2_find_first_zero_bit(addr, size) \
302*4882a593Smuzhiyun 	ext2_find_next_zero_bit((addr), (size), 0)
303*4882a593Smuzhiyun 
ext2_find_next_zero_bit(void * addr,unsigned long size,unsigned long offset)304*4882a593Smuzhiyun static inline unsigned long ext2_find_next_zero_bit(void *addr,
305*4882a593Smuzhiyun 				unsigned long size, unsigned long offset)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun 	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
308*4882a593Smuzhiyun 	unsigned long result = offset & ~31UL;
309*4882a593Smuzhiyun 	unsigned long tmp;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	if (offset >= size)
312*4882a593Smuzhiyun 		return size;
313*4882a593Smuzhiyun 	size -= result;
314*4882a593Smuzhiyun 	offset &= 31UL;
315*4882a593Smuzhiyun 	if(offset) {
316*4882a593Smuzhiyun 		/* We hold the little endian value in tmp, but then the
317*4882a593Smuzhiyun 		 * shift is illegal. So we could keep a big endian value
318*4882a593Smuzhiyun 		 * in tmp, like this:
319*4882a593Smuzhiyun 		 *
320*4882a593Smuzhiyun 		 * tmp = __swab32(*(p++));
321*4882a593Smuzhiyun 		 * tmp |= ~0UL >> (32-offset);
322*4882a593Smuzhiyun 		 *
323*4882a593Smuzhiyun 		 * but this would decrease preformance, so we change the
324*4882a593Smuzhiyun 		 * shift:
325*4882a593Smuzhiyun 		 */
326*4882a593Smuzhiyun 		tmp = *(p++);
327*4882a593Smuzhiyun 		tmp |= __swab32(~0UL >> (32-offset));
328*4882a593Smuzhiyun 		if(size < 32)
329*4882a593Smuzhiyun 			goto found_first;
330*4882a593Smuzhiyun 		if(~tmp)
331*4882a593Smuzhiyun 			goto found_middle;
332*4882a593Smuzhiyun 		size -= 32;
333*4882a593Smuzhiyun 		result += 32;
334*4882a593Smuzhiyun 	}
335*4882a593Smuzhiyun 	while(size & ~31UL) {
336*4882a593Smuzhiyun 		if(~(tmp = *(p++)))
337*4882a593Smuzhiyun 			goto found_middle;
338*4882a593Smuzhiyun 		result += 32;
339*4882a593Smuzhiyun 		size -= 32;
340*4882a593Smuzhiyun 	}
341*4882a593Smuzhiyun 	if(!size)
342*4882a593Smuzhiyun 		return result;
343*4882a593Smuzhiyun 	tmp = *p;
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun found_first:
346*4882a593Smuzhiyun 	/* tmp is little endian, so we would have to swab the shift,
347*4882a593Smuzhiyun 	 * see above. But then we have to swab tmp below for ffz, so
348*4882a593Smuzhiyun 	 * we might as well do this here.
349*4882a593Smuzhiyun 	 */
350*4882a593Smuzhiyun 	return result + ffz(__swab32(tmp) | (~0UL << size));
351*4882a593Smuzhiyun found_middle:
352*4882a593Smuzhiyun 	return result + ffz(__swab32(tmp));
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun /* Bitmap functions for the minix filesystem.  */
356*4882a593Smuzhiyun #define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
357*4882a593Smuzhiyun #define minix_set_bit(nr,addr) set_bit(nr,addr)
358*4882a593Smuzhiyun #define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
359*4882a593Smuzhiyun #define minix_test_bit(nr,addr) test_bit(nr,addr)
360*4882a593Smuzhiyun #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun /**
363*4882a593Smuzhiyun  * hweightN - returns the hamming weight of a N-bit word
364*4882a593Smuzhiyun  * @x: the word to weigh
365*4882a593Smuzhiyun  *
366*4882a593Smuzhiyun  * The Hamming Weight of a number is the total number of bits set in it.
367*4882a593Smuzhiyun  */
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun #define hweight32(x) generic_hweight32(x)
370*4882a593Smuzhiyun #define hweight16(x) generic_hweight16(x)
371*4882a593Smuzhiyun #define hweight8(x) generic_hweight8(x)
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun #endif /* __KERNEL__ */
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun #endif /* _MICROBLAZE_BITOPS_H */
376