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