Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * include/asm-v850/bitops.h -- Bit operations | |
3 | * | |
4f9a6e10 MB |
4 | * Copyright (C) 2001,02,03,04,05 NEC Electronics Corporation |
5 | * Copyright (C) 2001,02,03,04,05 Miles Bader <miles@gnu.org> | |
1da177e4 LT |
6 | * Copyright (C) 1992 Linus Torvalds. |
7 | * | |
8 | * This file is subject to the terms and conditions of the GNU General | |
9 | * Public License. See the file COPYING in the main directory of this | |
10 | * archive for more details. | |
11 | */ | |
12 | ||
13 | #ifndef __V850_BITOPS_H__ | |
14 | #define __V850_BITOPS_H__ | |
15 | ||
16 | ||
17 | #include <linux/config.h> | |
18 | #include <linux/compiler.h> /* unlikely */ | |
19 | #include <asm/byteorder.h> /* swab32 */ | |
20 | #include <asm/system.h> /* interrupt enable/disable */ | |
21 | ||
22 | ||
23 | #ifdef __KERNEL__ | |
24 | ||
25 | /* | |
26 | * The __ functions are not atomic | |
27 | */ | |
28 | ||
29 | /* | |
30 | * ffz = Find First Zero in word. Undefined if no zero exists, | |
31 | * so code should check against ~0UL first.. | |
32 | */ | |
23f88fe4 | 33 | static inline unsigned long ffz (unsigned long word) |
1da177e4 LT |
34 | { |
35 | unsigned long result = 0; | |
36 | ||
37 | while (word & 1) { | |
38 | result++; | |
39 | word >>= 1; | |
40 | } | |
41 | return result; | |
42 | } | |
43 | ||
44 | ||
45 | /* In the following constant-bit-op macros, a "g" constraint is used when | |
46 | we really need an integer ("i" constraint). This is to avoid | |
47 | warnings/errors from the compiler in the case where the associated | |
48 | operand _isn't_ an integer, and shouldn't produce bogus assembly because | |
49 | use of that form is protected by a guard statement that checks for | |
50 | constants, and should otherwise be removed by the optimizer. This | |
51 | _usually_ works -- however, __builtin_constant_p returns true for a | |
52 | variable with a known constant value too, and unfortunately gcc will | |
53 | happily put the variable in a register and use the register for the "g" | |
54 | constraint'd asm operand. To avoid the latter problem, we add a | |
55 | constant offset to the operand and subtract it back in the asm code; | |
56 | forcing gcc to do arithmetic on the value is usually enough to get it | |
57 | to use a real constant value. This is horrible, and ultimately | |
58 | unreliable too, but it seems to work for now (hopefully gcc will offer | |
59 | us more control in the future, so we can do a better job). */ | |
60 | ||
61 | #define __const_bit_op(op, nr, addr) \ | |
62 | ({ __asm__ (op " (%0 - 0x123), %1" \ | |
63 | :: "g" (((nr) & 0x7) + 0x123), \ | |
64 | "m" (*((char *)(addr) + ((nr) >> 3))) \ | |
65 | : "memory"); }) | |
66 | #define __var_bit_op(op, nr, addr) \ | |
67 | ({ int __nr = (nr); \ | |
68 | __asm__ (op " %0, [%1]" \ | |
69 | :: "r" (__nr & 0x7), \ | |
70 | "r" ((char *)(addr) + (__nr >> 3)) \ | |
71 | : "memory"); }) | |
72 | #define __bit_op(op, nr, addr) \ | |
73 | ((__builtin_constant_p (nr) && (unsigned)(nr) <= 0x7FFFF) \ | |
74 | ? __const_bit_op (op, nr, addr) \ | |
75 | : __var_bit_op (op, nr, addr)) | |
76 | ||
77 | #define __set_bit(nr, addr) __bit_op ("set1", nr, addr) | |
78 | #define __clear_bit(nr, addr) __bit_op ("clr1", nr, addr) | |
79 | #define __change_bit(nr, addr) __bit_op ("not1", nr, addr) | |
80 | ||
81 | /* The bit instructions used by `non-atomic' variants are actually atomic. */ | |
82 | #define set_bit __set_bit | |
83 | #define clear_bit __clear_bit | |
84 | #define change_bit __change_bit | |
85 | ||
86 | ||
87 | #define __const_tns_bit_op(op, nr, addr) \ | |
88 | ({ int __tns_res; \ | |
89 | __asm__ __volatile__ ( \ | |
90 | "tst1 (%1 - 0x123), %2; setf nz, %0; " op " (%1 - 0x123), %2" \ | |
91 | : "=&r" (__tns_res) \ | |
92 | : "g" (((nr) & 0x7) + 0x123), \ | |
93 | "m" (*((char *)(addr) + ((nr) >> 3))) \ | |
94 | : "memory"); \ | |
95 | __tns_res; \ | |
96 | }) | |
97 | #define __var_tns_bit_op(op, nr, addr) \ | |
98 | ({ int __nr = (nr); \ | |
99 | int __tns_res; \ | |
100 | __asm__ __volatile__ ( \ | |
101 | "tst1 %1, [%2]; setf nz, %0; " op " %1, [%2]" \ | |
102 | : "=&r" (__tns_res) \ | |
103 | : "r" (__nr & 0x7), \ | |
104 | "r" ((char *)(addr) + (__nr >> 3)) \ | |
105 | : "memory"); \ | |
106 | __tns_res; \ | |
107 | }) | |
108 | #define __tns_bit_op(op, nr, addr) \ | |
109 | ((__builtin_constant_p (nr) && (unsigned)(nr) <= 0x7FFFF) \ | |
110 | ? __const_tns_bit_op (op, nr, addr) \ | |
111 | : __var_tns_bit_op (op, nr, addr)) | |
112 | #define __tns_atomic_bit_op(op, nr, addr) \ | |
113 | ({ int __tns_atomic_res, __tns_atomic_flags; \ | |
114 | local_irq_save (__tns_atomic_flags); \ | |
115 | __tns_atomic_res = __tns_bit_op (op, nr, addr); \ | |
116 | local_irq_restore (__tns_atomic_flags); \ | |
117 | __tns_atomic_res; \ | |
118 | }) | |
119 | ||
120 | #define __test_and_set_bit(nr, addr) __tns_bit_op ("set1", nr, addr) | |
121 | #define test_and_set_bit(nr, addr) __tns_atomic_bit_op ("set1", nr, addr) | |
122 | ||
123 | #define __test_and_clear_bit(nr, addr) __tns_bit_op ("clr1", nr, addr) | |
124 | #define test_and_clear_bit(nr, addr) __tns_atomic_bit_op ("clr1", nr, addr) | |
125 | ||
126 | #define __test_and_change_bit(nr, addr) __tns_bit_op ("not1", nr, addr) | |
127 | #define test_and_change_bit(nr, addr) __tns_atomic_bit_op ("not1", nr, addr) | |
128 | ||
129 | ||
130 | #define __const_test_bit(nr, addr) \ | |
131 | ({ int __test_bit_res; \ | |
132 | __asm__ __volatile__ ("tst1 (%1 - 0x123), %2; setf nz, %0" \ | |
133 | : "=r" (__test_bit_res) \ | |
134 | : "g" (((nr) & 0x7) + 0x123), \ | |
135 | "m" (*((const char *)(addr) + ((nr) >> 3)))); \ | |
136 | __test_bit_res; \ | |
137 | }) | |
23f88fe4 | 138 | static inline int __test_bit (int nr, const void *addr) |
1da177e4 LT |
139 | { |
140 | int res; | |
141 | __asm__ __volatile__ ("tst1 %1, [%2]; setf nz, %0" | |
142 | : "=r" (res) | |
143 | : "r" (nr & 0x7), "r" (addr + (nr >> 3))); | |
144 | return res; | |
145 | } | |
146 | #define test_bit(nr,addr) \ | |
147 | ((__builtin_constant_p (nr) && (unsigned)(nr) <= 0x7FFFF) \ | |
148 | ? __const_test_bit ((nr), (addr)) \ | |
149 | : __test_bit ((nr), (addr))) | |
150 | ||
151 | ||
152 | /* clear_bit doesn't provide any barrier for the compiler. */ | |
153 | #define smp_mb__before_clear_bit() barrier () | |
154 | #define smp_mb__after_clear_bit() barrier () | |
155 | ||
156 | ||
157 | #define find_first_zero_bit(addr, size) \ | |
158 | find_next_zero_bit ((addr), (size), 0) | |
159 | ||
23f88fe4 | 160 | static inline int find_next_zero_bit(const void *addr, int size, int offset) |
1da177e4 LT |
161 | { |
162 | unsigned long *p = ((unsigned long *) addr) + (offset >> 5); | |
163 | unsigned long result = offset & ~31UL; | |
164 | unsigned long tmp; | |
165 | ||
166 | if (offset >= size) | |
167 | return size; | |
168 | size -= result; | |
169 | offset &= 31UL; | |
170 | if (offset) { | |
171 | tmp = * (p++); | |
172 | tmp |= ~0UL >> (32-offset); | |
173 | if (size < 32) | |
174 | goto found_first; | |
175 | if (~tmp) | |
176 | goto found_middle; | |
177 | size -= 32; | |
178 | result += 32; | |
179 | } | |
180 | while (size & ~31UL) { | |
181 | if (~ (tmp = * (p++))) | |
182 | goto found_middle; | |
183 | result += 32; | |
184 | size -= 32; | |
185 | } | |
186 | if (!size) | |
187 | return result; | |
188 | tmp = *p; | |
189 | ||
190 | found_first: | |
bcc68b86 | 191 | tmp |= ~0UL << size; |
1da177e4 LT |
192 | found_middle: |
193 | return result + ffz (tmp); | |
194 | } | |
195 | ||
196 | ||
197 | /* This is the same as generic_ffs, but we can't use that because it's | |
198 | inline and the #include order mucks things up. */ | |
199 | static inline int generic_ffs_for_find_next_bit(int x) | |
200 | { | |
201 | int r = 1; | |
202 | ||
203 | if (!x) | |
204 | return 0; | |
205 | if (!(x & 0xffff)) { | |
206 | x >>= 16; | |
207 | r += 16; | |
208 | } | |
209 | if (!(x & 0xff)) { | |
210 | x >>= 8; | |
211 | r += 8; | |
212 | } | |
213 | if (!(x & 0xf)) { | |
214 | x >>= 4; | |
215 | r += 4; | |
216 | } | |
217 | if (!(x & 3)) { | |
218 | x >>= 2; | |
219 | r += 2; | |
220 | } | |
221 | if (!(x & 1)) { | |
222 | x >>= 1; | |
223 | r += 1; | |
224 | } | |
225 | return r; | |
226 | } | |
227 | ||
228 | /* | |
229 | * Find next one bit in a bitmap reasonably efficiently. | |
230 | */ | |
231 | static __inline__ unsigned long find_next_bit(const unsigned long *addr, | |
232 | unsigned long size, unsigned long offset) | |
233 | { | |
234 | unsigned int *p = ((unsigned int *) addr) + (offset >> 5); | |
235 | unsigned int result = offset & ~31UL; | |
236 | unsigned int tmp; | |
237 | ||
238 | if (offset >= size) | |
239 | return size; | |
240 | size -= result; | |
241 | offset &= 31UL; | |
242 | if (offset) { | |
243 | tmp = *p++; | |
244 | tmp &= ~0UL << offset; | |
245 | if (size < 32) | |
246 | goto found_first; | |
247 | if (tmp) | |
248 | goto found_middle; | |
249 | size -= 32; | |
250 | result += 32; | |
251 | } | |
252 | while (size >= 32) { | |
253 | if ((tmp = *p++) != 0) | |
254 | goto found_middle; | |
255 | result += 32; | |
256 | size -= 32; | |
257 | } | |
258 | if (!size) | |
259 | return result; | |
260 | tmp = *p; | |
261 | ||
262 | found_first: | |
263 | tmp &= ~0UL >> (32 - size); | |
264 | if (tmp == 0UL) /* Are any bits set? */ | |
265 | return result + size; /* Nope. */ | |
266 | found_middle: | |
267 | return result + generic_ffs_for_find_next_bit(tmp); | |
268 | } | |
269 | ||
270 | /* | |
271 | * find_first_bit - find the first set bit in a memory region | |
272 | */ | |
273 | #define find_first_bit(addr, size) \ | |
274 | find_next_bit((addr), (size), 0) | |
275 | ||
276 | ||
277 | #define ffs(x) generic_ffs (x) | |
278 | #define fls(x) generic_fls (x) | |
3821af2f | 279 | #define fls64(x) generic_fls64(x) |
1da177e4 LT |
280 | #define __ffs(x) ffs(x) |
281 | ||
282 | ||
283 | /* | |
284 | * This is just `generic_ffs' from <linux/bitops.h>, except that it assumes | |
285 | * that at least one bit is set, and returns the real index of the bit | |
286 | * (rather than the bit index + 1, like ffs does). | |
287 | */ | |
288 | static inline int sched_ffs(int x) | |
289 | { | |
290 | int r = 0; | |
291 | ||
292 | if (!(x & 0xffff)) { | |
293 | x >>= 16; | |
294 | r += 16; | |
295 | } | |
296 | if (!(x & 0xff)) { | |
297 | x >>= 8; | |
298 | r += 8; | |
299 | } | |
300 | if (!(x & 0xf)) { | |
301 | x >>= 4; | |
302 | r += 4; | |
303 | } | |
304 | if (!(x & 3)) { | |
305 | x >>= 2; | |
306 | r += 2; | |
307 | } | |
308 | if (!(x & 1)) { | |
309 | x >>= 1; | |
310 | r += 1; | |
311 | } | |
312 | return r; | |
313 | } | |
314 | ||
315 | /* | |
316 | * Every architecture must define this function. It's the fastest | |
317 | * way of searching a 140-bit bitmap where the first 100 bits are | |
318 | * unlikely to be set. It's guaranteed that at least one of the 140 | |
319 | * bits is set. | |
320 | */ | |
321 | static inline int sched_find_first_bit(unsigned long *b) | |
322 | { | |
323 | unsigned offs = 0; | |
324 | while (! *b) { | |
325 | b++; | |
326 | offs += 32; | |
327 | } | |
328 | return sched_ffs (*b) + offs; | |
329 | } | |
330 | ||
331 | /* | |
332 | * hweightN: returns the hamming weight (i.e. the number | |
333 | * of bits set) of a N-bit word | |
334 | */ | |
335 | #define hweight32(x) generic_hweight32 (x) | |
336 | #define hweight16(x) generic_hweight16 (x) | |
337 | #define hweight8(x) generic_hweight8 (x) | |
338 | ||
339 | #define ext2_set_bit test_and_set_bit | |
340 | #define ext2_set_bit_atomic(l,n,a) test_and_set_bit(n,a) | |
341 | #define ext2_clear_bit test_and_clear_bit | |
342 | #define ext2_clear_bit_atomic(l,n,a) test_and_clear_bit(n,a) | |
343 | #define ext2_test_bit test_bit | |
344 | #define ext2_find_first_zero_bit find_first_zero_bit | |
345 | #define ext2_find_next_zero_bit find_next_zero_bit | |
346 | ||
347 | /* Bitmap functions for the minix filesystem. */ | |
348 | #define minix_test_and_set_bit test_and_set_bit | |
349 | #define minix_set_bit set_bit | |
350 | #define minix_test_and_clear_bit test_and_clear_bit | |
351 | #define minix_test_bit test_bit | |
352 | #define minix_find_first_zero_bit find_first_zero_bit | |
353 | ||
354 | #endif /* __KERNEL__ */ | |
355 | ||
356 | #endif /* __V850_BITOPS_H__ */ |