xref: /rk3399_rockchip-uboot/arch/microblaze/include/asm/bitops.h (revision 4c60850792e003bcafd16c324237a19307763829)
1819833afSPeter Tyser #ifndef _MICROBLAZE_BITOPS_H
2819833afSPeter Tyser #define _MICROBLAZE_BITOPS_H
3819833afSPeter Tyser 
4819833afSPeter Tyser /*
5819833afSPeter Tyser  * Copyright 1992, Linus Torvalds.
6819833afSPeter Tyser  */
7819833afSPeter Tyser 
8819833afSPeter Tyser #include <asm/byteorder.h>	/* swab32 */
9819833afSPeter Tyser #include <asm/system.h>		/* save_flags */
10e6e7b7c0SFabio Estevam #include <asm-generic/bitops/fls.h>
11e6e7b7c0SFabio Estevam #include <asm-generic/bitops/__fls.h>
12e6e7b7c0SFabio Estevam #include <asm-generic/bitops/fls64.h>
13e6e7b7c0SFabio Estevam #include <asm-generic/bitops/__ffs.h>
14819833afSPeter Tyser 
15819833afSPeter Tyser #ifdef __KERNEL__
16819833afSPeter Tyser /*
17819833afSPeter Tyser  * The __ functions are not atomic
18819833afSPeter Tyser  */
19819833afSPeter Tyser 
20819833afSPeter Tyser /*
21819833afSPeter Tyser  * ffz = Find First Zero in word. Undefined if no zero exists,
22819833afSPeter Tyser  * so code should check against ~0UL first..
23819833afSPeter Tyser  */
ffz(unsigned long word)24*e0f21e1cSNathan Rossi static inline unsigned long ffz(unsigned long word)
25819833afSPeter Tyser {
26819833afSPeter Tyser 	unsigned long result = 0;
27819833afSPeter Tyser 
28819833afSPeter Tyser 	while(word & 1) {
29819833afSPeter Tyser 		result++;
30819833afSPeter Tyser 		word >>= 1;
31819833afSPeter Tyser 	}
32819833afSPeter Tyser 	return result;
33819833afSPeter Tyser }
34819833afSPeter Tyser 
35819833afSPeter Tyser 
set_bit(int nr,volatile void * addr)36*e0f21e1cSNathan Rossi static inline void set_bit(int nr, volatile void *addr)
37819833afSPeter Tyser {
38819833afSPeter Tyser 	int	* a = (int *) addr;
39819833afSPeter Tyser 	int	mask;
40819833afSPeter Tyser 	unsigned long flags;
41819833afSPeter Tyser 
42819833afSPeter Tyser 	a += nr >> 5;
43819833afSPeter Tyser 	mask = 1 << (nr & 0x1f);
44819833afSPeter Tyser 	save_flags_cli(flags);
45819833afSPeter Tyser 	*a |= mask;
46819833afSPeter Tyser 	restore_flags(flags);
47819833afSPeter Tyser }
48819833afSPeter Tyser 
__set_bit(int nr,volatile void * addr)49*e0f21e1cSNathan Rossi static inline void __set_bit(int nr, volatile void *addr)
50819833afSPeter Tyser {
51819833afSPeter Tyser 	int	* a = (int *) addr;
52819833afSPeter Tyser 	int	mask;
53819833afSPeter Tyser 
54819833afSPeter Tyser 	a += nr >> 5;
55819833afSPeter Tyser 	mask = 1 << (nr & 0x1f);
56819833afSPeter Tyser 	*a |= mask;
57819833afSPeter Tyser }
58819833afSPeter Tyser #define PLATFORM__SET_BIT
59819833afSPeter Tyser 
60819833afSPeter Tyser /*
61819833afSPeter Tyser  * clear_bit() doesn't provide any barrier for the compiler.
62819833afSPeter Tyser  */
63819833afSPeter Tyser #define smp_mb__before_clear_bit()	barrier()
64819833afSPeter Tyser #define smp_mb__after_clear_bit()	barrier()
65819833afSPeter Tyser 
clear_bit(int nr,volatile void * addr)66*e0f21e1cSNathan Rossi static inline void clear_bit(int nr, volatile void *addr)
67819833afSPeter Tyser {
68819833afSPeter Tyser 	int	* a = (int *) addr;
69819833afSPeter Tyser 	int	mask;
70819833afSPeter Tyser 	unsigned long flags;
71819833afSPeter Tyser 
72819833afSPeter Tyser 	a += nr >> 5;
73819833afSPeter Tyser 	mask = 1 << (nr & 0x1f);
74819833afSPeter Tyser 	save_flags_cli(flags);
75819833afSPeter Tyser 	*a &= ~mask;
76819833afSPeter Tyser 	restore_flags(flags);
77819833afSPeter Tyser }
78819833afSPeter Tyser 
79*e0f21e1cSNathan Rossi #define __clear_bit(nr, addr) clear_bit(nr, addr)
80*e0f21e1cSNathan Rossi #define PLATFORM__CLEAR_BIT
81*e0f21e1cSNathan Rossi 
change_bit(int nr,volatile void * addr)82*e0f21e1cSNathan Rossi static inline void change_bit(int nr, volatile void *addr)
83819833afSPeter Tyser {
84819833afSPeter Tyser 	int mask;
85819833afSPeter Tyser 	unsigned long flags;
86819833afSPeter Tyser 	unsigned long *ADDR = (unsigned long *) addr;
87819833afSPeter Tyser 
88819833afSPeter Tyser 	ADDR += nr >> 5;
89819833afSPeter Tyser 	mask = 1 << (nr & 31);
90819833afSPeter Tyser 	save_flags_cli(flags);
91819833afSPeter Tyser 	*ADDR ^= mask;
92819833afSPeter Tyser 	restore_flags(flags);
93819833afSPeter Tyser }
94819833afSPeter Tyser 
__change_bit(int nr,volatile void * addr)95*e0f21e1cSNathan Rossi static inline void __change_bit(int nr, volatile void *addr)
96819833afSPeter Tyser {
97819833afSPeter Tyser 	int mask;
98819833afSPeter Tyser 	unsigned long *ADDR = (unsigned long *) addr;
99819833afSPeter Tyser 
100819833afSPeter Tyser 	ADDR += nr >> 5;
101819833afSPeter Tyser 	mask = 1 << (nr & 31);
102819833afSPeter Tyser 	*ADDR ^= mask;
103819833afSPeter Tyser }
104819833afSPeter Tyser 
test_and_set_bit(int nr,volatile void * addr)105*e0f21e1cSNathan Rossi static inline int test_and_set_bit(int nr, volatile void *addr)
106819833afSPeter Tyser {
107819833afSPeter Tyser 	int	mask, retval;
108819833afSPeter Tyser 	volatile unsigned int *a = (volatile unsigned int *) addr;
109819833afSPeter Tyser 	unsigned long flags;
110819833afSPeter Tyser 
111819833afSPeter Tyser 	a += nr >> 5;
112819833afSPeter Tyser 	mask = 1 << (nr & 0x1f);
113819833afSPeter Tyser 	save_flags_cli(flags);
114819833afSPeter Tyser 	retval = (mask & *a) != 0;
115819833afSPeter Tyser 	*a |= mask;
116819833afSPeter Tyser 	restore_flags(flags);
117819833afSPeter Tyser 
118819833afSPeter Tyser 	return retval;
119819833afSPeter Tyser }
120819833afSPeter Tyser 
__test_and_set_bit(int nr,volatile void * addr)121*e0f21e1cSNathan Rossi static inline int __test_and_set_bit(int nr, volatile void *addr)
122819833afSPeter Tyser {
123819833afSPeter Tyser 	int	mask, retval;
124819833afSPeter Tyser 	volatile unsigned int *a = (volatile unsigned int *) addr;
125819833afSPeter Tyser 
126819833afSPeter Tyser 	a += nr >> 5;
127819833afSPeter Tyser 	mask = 1 << (nr & 0x1f);
128819833afSPeter Tyser 	retval = (mask & *a) != 0;
129819833afSPeter Tyser 	*a |= mask;
130819833afSPeter Tyser 	return retval;
131819833afSPeter Tyser }
132819833afSPeter Tyser 
test_and_clear_bit(int nr,volatile void * addr)133*e0f21e1cSNathan Rossi static inline int test_and_clear_bit(int nr, volatile void *addr)
134819833afSPeter Tyser {
135819833afSPeter Tyser 	int	mask, retval;
136819833afSPeter Tyser 	volatile unsigned int *a = (volatile unsigned int *) addr;
137819833afSPeter Tyser 	unsigned long flags;
138819833afSPeter Tyser 
139819833afSPeter Tyser 	a += nr >> 5;
140819833afSPeter Tyser 	mask = 1 << (nr & 0x1f);
141819833afSPeter Tyser 	save_flags_cli(flags);
142819833afSPeter Tyser 	retval = (mask & *a) != 0;
143819833afSPeter Tyser 	*a &= ~mask;
144819833afSPeter Tyser 	restore_flags(flags);
145819833afSPeter Tyser 
146819833afSPeter Tyser 	return retval;
147819833afSPeter Tyser }
148819833afSPeter Tyser 
__test_and_clear_bit(int nr,volatile void * addr)149*e0f21e1cSNathan Rossi static inline int __test_and_clear_bit(int nr, volatile void *addr)
150819833afSPeter Tyser {
151819833afSPeter Tyser 	int	mask, retval;
152819833afSPeter Tyser 	volatile unsigned int *a = (volatile unsigned int *) addr;
153819833afSPeter Tyser 
154819833afSPeter Tyser 	a += nr >> 5;
155819833afSPeter Tyser 	mask = 1 << (nr & 0x1f);
156819833afSPeter Tyser 	retval = (mask & *a) != 0;
157819833afSPeter Tyser 	*a &= ~mask;
158819833afSPeter Tyser 	return retval;
159819833afSPeter Tyser }
160819833afSPeter Tyser 
test_and_change_bit(int nr,volatile void * addr)161*e0f21e1cSNathan Rossi static inline int test_and_change_bit(int nr, volatile void *addr)
162819833afSPeter Tyser {
163819833afSPeter Tyser 	int	mask, retval;
164819833afSPeter Tyser 	volatile unsigned int *a = (volatile unsigned int *) addr;
165819833afSPeter Tyser 	unsigned long flags;
166819833afSPeter Tyser 
167819833afSPeter Tyser 	a += nr >> 5;
168819833afSPeter Tyser 	mask = 1 << (nr & 0x1f);
169819833afSPeter Tyser 	save_flags_cli(flags);
170819833afSPeter Tyser 	retval = (mask & *a) != 0;
171819833afSPeter Tyser 	*a ^= mask;
172819833afSPeter Tyser 	restore_flags(flags);
173819833afSPeter Tyser 
174819833afSPeter Tyser 	return retval;
175819833afSPeter Tyser }
176819833afSPeter Tyser 
__test_and_change_bit(int nr,volatile void * addr)177*e0f21e1cSNathan Rossi static inline int __test_and_change_bit(int nr, volatile void *addr)
178819833afSPeter Tyser {
179819833afSPeter Tyser 	int	mask, retval;
180819833afSPeter Tyser 	volatile unsigned int *a = (volatile unsigned int *) addr;
181819833afSPeter Tyser 
182819833afSPeter Tyser 	a += nr >> 5;
183819833afSPeter Tyser 	mask = 1 << (nr & 0x1f);
184819833afSPeter Tyser 	retval = (mask & *a) != 0;
185819833afSPeter Tyser 	*a ^= mask;
186819833afSPeter Tyser 	return retval;
187819833afSPeter Tyser }
188819833afSPeter Tyser 
189819833afSPeter Tyser /*
190819833afSPeter Tyser  * This routine doesn't need to be atomic.
191819833afSPeter Tyser  */
__constant_test_bit(int nr,const volatile void * addr)192*e0f21e1cSNathan Rossi static inline int __constant_test_bit(int nr, const volatile void *addr)
193819833afSPeter Tyser {
194819833afSPeter Tyser 	return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
195819833afSPeter Tyser }
196819833afSPeter Tyser 
__test_bit(int nr,volatile void * addr)197*e0f21e1cSNathan Rossi static inline int __test_bit(int nr, volatile void *addr)
198819833afSPeter Tyser {
199819833afSPeter Tyser 	int	* a = (int *) addr;
200819833afSPeter Tyser 	int	mask;
201819833afSPeter Tyser 
202819833afSPeter Tyser 	a += nr >> 5;
203819833afSPeter Tyser 	mask = 1 << (nr & 0x1f);
204819833afSPeter Tyser 	return ((mask & *a) != 0);
205819833afSPeter Tyser }
206819833afSPeter Tyser 
207819833afSPeter Tyser #define test_bit(nr,addr) \
208819833afSPeter Tyser (__builtin_constant_p(nr) ? \
209819833afSPeter Tyser  __constant_test_bit((nr),(addr)) : \
210819833afSPeter Tyser  __test_bit((nr),(addr)))
211819833afSPeter Tyser 
212819833afSPeter Tyser #define find_first_zero_bit(addr, size) \
213819833afSPeter Tyser 	find_next_zero_bit((addr), (size), 0)
214819833afSPeter Tyser 
find_next_zero_bit(void * addr,int size,int offset)215*e0f21e1cSNathan Rossi static inline int find_next_zero_bit(void *addr, int size, int offset)
216819833afSPeter Tyser {
217819833afSPeter Tyser 	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
218819833afSPeter Tyser 	unsigned long result = offset & ~31UL;
219819833afSPeter Tyser 	unsigned long tmp;
220819833afSPeter Tyser 
221819833afSPeter Tyser 	if (offset >= size)
222819833afSPeter Tyser 		return size;
223819833afSPeter Tyser 	size -= result;
224819833afSPeter Tyser 	offset &= 31UL;
225819833afSPeter Tyser 	if (offset) {
226819833afSPeter Tyser 		tmp = *(p++);
227819833afSPeter Tyser 		tmp |= ~0UL >> (32-offset);
228819833afSPeter Tyser 		if (size < 32)
229819833afSPeter Tyser 			goto found_first;
230819833afSPeter Tyser 		if (~tmp)
231819833afSPeter Tyser 			goto found_middle;
232819833afSPeter Tyser 		size -= 32;
233819833afSPeter Tyser 		result += 32;
234819833afSPeter Tyser 	}
235819833afSPeter Tyser 	while (size & ~31UL) {
236819833afSPeter Tyser 		if (~(tmp = *(p++)))
237819833afSPeter Tyser 			goto found_middle;
238819833afSPeter Tyser 		result += 32;
239819833afSPeter Tyser 		size -= 32;
240819833afSPeter Tyser 	}
241819833afSPeter Tyser 	if (!size)
242819833afSPeter Tyser 		return result;
243819833afSPeter Tyser 	tmp = *p;
244819833afSPeter Tyser 
245819833afSPeter Tyser found_first:
246819833afSPeter Tyser 	tmp |= ~0UL >> size;
247819833afSPeter Tyser found_middle:
248819833afSPeter Tyser 	return result + ffz(tmp);
249819833afSPeter Tyser }
250819833afSPeter Tyser 
251819833afSPeter Tyser /*
252819833afSPeter Tyser  * hweightN: returns the hamming weight (i.e. the number
253819833afSPeter Tyser  * of bits set) of a N-bit word
254819833afSPeter Tyser  */
255819833afSPeter Tyser 
256819833afSPeter Tyser #define hweight32(x) generic_hweight32(x)
257819833afSPeter Tyser #define hweight16(x) generic_hweight16(x)
258819833afSPeter Tyser #define hweight8(x) generic_hweight8(x)
259819833afSPeter Tyser 
260819833afSPeter Tyser 
ext2_set_bit(int nr,volatile void * addr)261*e0f21e1cSNathan Rossi static inline int ext2_set_bit(int nr, volatile void *addr)
262819833afSPeter Tyser {
263819833afSPeter Tyser 	int		mask, retval;
264819833afSPeter Tyser 	unsigned long	flags;
265819833afSPeter Tyser 	volatile unsigned char	*ADDR = (unsigned char *) addr;
266819833afSPeter Tyser 
267819833afSPeter Tyser 	ADDR += nr >> 3;
268819833afSPeter Tyser 	mask = 1 << (nr & 0x07);
269819833afSPeter Tyser 	save_flags_cli(flags);
270819833afSPeter Tyser 	retval = (mask & *ADDR) != 0;
271819833afSPeter Tyser 	*ADDR |= mask;
272819833afSPeter Tyser 	restore_flags(flags);
273819833afSPeter Tyser 	return retval;
274819833afSPeter Tyser }
275819833afSPeter Tyser 
ext2_clear_bit(int nr,volatile void * addr)276*e0f21e1cSNathan Rossi static inline int ext2_clear_bit(int nr, volatile void *addr)
277819833afSPeter Tyser {
278819833afSPeter Tyser 	int		mask, retval;
279819833afSPeter Tyser 	unsigned long	flags;
280819833afSPeter Tyser 	volatile unsigned char	*ADDR = (unsigned char *) addr;
281819833afSPeter Tyser 
282819833afSPeter Tyser 	ADDR += nr >> 3;
283819833afSPeter Tyser 	mask = 1 << (nr & 0x07);
284819833afSPeter Tyser 	save_flags_cli(flags);
285819833afSPeter Tyser 	retval = (mask & *ADDR) != 0;
286819833afSPeter Tyser 	*ADDR &= ~mask;
287819833afSPeter Tyser 	restore_flags(flags);
288819833afSPeter Tyser 	return retval;
289819833afSPeter Tyser }
290819833afSPeter Tyser 
ext2_test_bit(int nr,const volatile void * addr)291*e0f21e1cSNathan Rossi static inline int ext2_test_bit(int nr, const volatile void *addr)
292819833afSPeter Tyser {
293819833afSPeter Tyser 	int			mask;
294819833afSPeter Tyser 	const volatile unsigned char	*ADDR = (const unsigned char *) addr;
295819833afSPeter Tyser 
296819833afSPeter Tyser 	ADDR += nr >> 3;
297819833afSPeter Tyser 	mask = 1 << (nr & 0x07);
298819833afSPeter Tyser 	return ((mask & *ADDR) != 0);
299819833afSPeter Tyser }
300819833afSPeter Tyser 
301819833afSPeter Tyser #define ext2_find_first_zero_bit(addr, size) \
302819833afSPeter Tyser 	ext2_find_next_zero_bit((addr), (size), 0)
303819833afSPeter Tyser 
ext2_find_next_zero_bit(void * addr,unsigned long size,unsigned long offset)304548ce4bfSMichal Simek static inline unsigned long ext2_find_next_zero_bit(void *addr,
305548ce4bfSMichal Simek 				unsigned long size, unsigned long offset)
306819833afSPeter Tyser {
307819833afSPeter Tyser 	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
308819833afSPeter Tyser 	unsigned long result = offset & ~31UL;
309819833afSPeter Tyser 	unsigned long tmp;
310819833afSPeter Tyser 
311819833afSPeter Tyser 	if (offset >= size)
312819833afSPeter Tyser 		return size;
313819833afSPeter Tyser 	size -= result;
314819833afSPeter Tyser 	offset &= 31UL;
315819833afSPeter Tyser 	if(offset) {
316819833afSPeter Tyser 		/* We hold the little endian value in tmp, but then the
317819833afSPeter Tyser 		 * shift is illegal. So we could keep a big endian value
318819833afSPeter Tyser 		 * in tmp, like this:
319819833afSPeter Tyser 		 *
320819833afSPeter Tyser 		 * tmp = __swab32(*(p++));
321819833afSPeter Tyser 		 * tmp |= ~0UL >> (32-offset);
322819833afSPeter Tyser 		 *
323819833afSPeter Tyser 		 * but this would decrease preformance, so we change the
324819833afSPeter Tyser 		 * shift:
325819833afSPeter Tyser 		 */
326819833afSPeter Tyser 		tmp = *(p++);
327819833afSPeter Tyser 		tmp |= __swab32(~0UL >> (32-offset));
328819833afSPeter Tyser 		if(size < 32)
329819833afSPeter Tyser 			goto found_first;
330819833afSPeter Tyser 		if(~tmp)
331819833afSPeter Tyser 			goto found_middle;
332819833afSPeter Tyser 		size -= 32;
333819833afSPeter Tyser 		result += 32;
334819833afSPeter Tyser 	}
335819833afSPeter Tyser 	while(size & ~31UL) {
336819833afSPeter Tyser 		if(~(tmp = *(p++)))
337819833afSPeter Tyser 			goto found_middle;
338819833afSPeter Tyser 		result += 32;
339819833afSPeter Tyser 		size -= 32;
340819833afSPeter Tyser 	}
341819833afSPeter Tyser 	if(!size)
342819833afSPeter Tyser 		return result;
343819833afSPeter Tyser 	tmp = *p;
344819833afSPeter Tyser 
345819833afSPeter Tyser found_first:
346819833afSPeter Tyser 	/* tmp is little endian, so we would have to swab the shift,
347819833afSPeter Tyser 	 * see above. But then we have to swab tmp below for ffz, so
348819833afSPeter Tyser 	 * we might as well do this here.
349819833afSPeter Tyser 	 */
350819833afSPeter Tyser 	return result + ffz(__swab32(tmp) | (~0UL << size));
351819833afSPeter Tyser found_middle:
352819833afSPeter Tyser 	return result + ffz(__swab32(tmp));
353819833afSPeter Tyser }
354819833afSPeter Tyser 
355819833afSPeter Tyser /* Bitmap functions for the minix filesystem.  */
356819833afSPeter Tyser #define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
357819833afSPeter Tyser #define minix_set_bit(nr,addr) set_bit(nr,addr)
358819833afSPeter Tyser #define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
359819833afSPeter Tyser #define minix_test_bit(nr,addr) test_bit(nr,addr)
360819833afSPeter Tyser #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
361819833afSPeter Tyser 
362819833afSPeter Tyser /**
363819833afSPeter Tyser  * hweightN - returns the hamming weight of a N-bit word
364819833afSPeter Tyser  * @x: the word to weigh
365819833afSPeter Tyser  *
366819833afSPeter Tyser  * The Hamming Weight of a number is the total number of bits set in it.
367819833afSPeter Tyser  */
368819833afSPeter Tyser 
369819833afSPeter Tyser #define hweight32(x) generic_hweight32(x)
370819833afSPeter Tyser #define hweight16(x) generic_hweight16(x)
371819833afSPeter Tyser #define hweight8(x) generic_hweight8(x)
372819833afSPeter Tyser 
373819833afSPeter Tyser #endif /* __KERNEL__ */
374819833afSPeter Tyser 
375819833afSPeter Tyser #endif /* _MICROBLAZE_BITOPS_H */
376