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