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