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