[MIPS] Remove userspace proofing from <asm/bitops.h>.
[pandora-kernel.git] / include / asm-mips / bitops.h
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (c) 1994 - 1997, 1999, 2000  Ralf Baechle (ralf@gnu.org)
7  * Copyright (c) 1999, 2000  Silicon Graphics, Inc.
8  */
9 #ifndef _ASM_BITOPS_H
10 #define _ASM_BITOPS_H
11
12 #include <linux/compiler.h>
13 #include <linux/irqflags.h>
14 #include <linux/types.h>
15 #include <asm/bug.h>
16 #include <asm/byteorder.h>              /* sigh ... */
17 #include <asm/cpu-features.h>
18 #include <asm/sgidefs.h>
19 #include <asm/war.h>
20
21 #if (_MIPS_SZLONG == 32)
22 #define SZLONG_LOG 5
23 #define SZLONG_MASK 31UL
24 #define __LL            "ll     "
25 #define __SC            "sc     "
26 #define cpu_to_lelongp(x) cpu_to_le32p((__u32 *) (x))
27 #elif (_MIPS_SZLONG == 64)
28 #define SZLONG_LOG 6
29 #define SZLONG_MASK 63UL
30 #define __LL            "lld    "
31 #define __SC            "scd    "
32 #define cpu_to_lelongp(x) cpu_to_le64p((__u64 *) (x))
33 #endif
34
35 /*
36  * clear_bit() doesn't provide any barrier for the compiler.
37  */
38 #define smp_mb__before_clear_bit()      smp_mb()
39 #define smp_mb__after_clear_bit()       smp_mb()
40
41 /*
42  * set_bit - Atomically set a bit in memory
43  * @nr: the bit to set
44  * @addr: the address to start counting from
45  *
46  * This function is atomic and may not be reordered.  See __set_bit()
47  * if you do not require the atomic guarantees.
48  * Note that @nr may be almost arbitrarily large; this function is not
49  * restricted to acting on a single-word quantity.
50  */
51 static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
52 {
53         unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
54         unsigned long temp;
55
56         if (cpu_has_llsc && R10000_LLSC_WAR) {
57                 __asm__ __volatile__(
58                 "       .set    mips3                                   \n"
59                 "1:     " __LL "%0, %1                  # set_bit       \n"
60                 "       or      %0, %2                                  \n"
61                 "       " __SC  "%0, %1                                 \n"
62                 "       beqzl   %0, 1b                                  \n"
63                 "       .set    mips0                                   \n"
64                 : "=&r" (temp), "=m" (*m)
65                 : "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
66         } else if (cpu_has_llsc) {
67                 __asm__ __volatile__(
68                 "       .set    mips3                                   \n"
69                 "1:     " __LL "%0, %1                  # set_bit       \n"
70                 "       or      %0, %2                                  \n"
71                 "       " __SC  "%0, %1                                 \n"
72                 "       beqz    %0, 1b                                  \n"
73                 "       .set    mips0                                   \n"
74                 : "=&r" (temp), "=m" (*m)
75                 : "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
76         } else {
77                 volatile unsigned long *a = addr;
78                 unsigned long mask;
79                 unsigned long flags;
80
81                 a += nr >> SZLONG_LOG;
82                 mask = 1UL << (nr & SZLONG_MASK);
83                 local_irq_save(flags);
84                 *a |= mask;
85                 local_irq_restore(flags);
86         }
87 }
88
89 /*
90  * clear_bit - Clears a bit in memory
91  * @nr: Bit to clear
92  * @addr: Address to start counting from
93  *
94  * clear_bit() is atomic and may not be reordered.  However, it does
95  * not contain a memory barrier, so if it is used for locking purposes,
96  * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
97  * in order to ensure changes are visible on other processors.
98  */
99 static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
100 {
101         unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
102         unsigned long temp;
103
104         if (cpu_has_llsc && R10000_LLSC_WAR) {
105                 __asm__ __volatile__(
106                 "       .set    mips3                                   \n"
107                 "1:     " __LL "%0, %1                  # clear_bit     \n"
108                 "       and     %0, %2                                  \n"
109                 "       " __SC "%0, %1                                  \n"
110                 "       beqzl   %0, 1b                                  \n"
111                 "       .set    mips0                                   \n"
112                 : "=&r" (temp), "=m" (*m)
113                 : "ir" (~(1UL << (nr & SZLONG_MASK))), "m" (*m));
114         } else if (cpu_has_llsc) {
115                 __asm__ __volatile__(
116                 "       .set    mips3                                   \n"
117                 "1:     " __LL "%0, %1                  # clear_bit     \n"
118                 "       and     %0, %2                                  \n"
119                 "       " __SC "%0, %1                                  \n"
120                 "       beqz    %0, 1b                                  \n"
121                 "       .set    mips0                                   \n"
122                 : "=&r" (temp), "=m" (*m)
123                 : "ir" (~(1UL << (nr & SZLONG_MASK))), "m" (*m));
124         } else {
125                 volatile unsigned long *a = addr;
126                 unsigned long mask;
127                 unsigned long flags;
128
129                 a += nr >> SZLONG_LOG;
130                 mask = 1UL << (nr & SZLONG_MASK);
131                 local_irq_save(flags);
132                 *a &= ~mask;
133                 local_irq_restore(flags);
134         }
135 }
136
137 /*
138  * change_bit - Toggle a bit in memory
139  * @nr: Bit to change
140  * @addr: Address to start counting from
141  *
142  * change_bit() is atomic and may not be reordered.
143  * Note that @nr may be almost arbitrarily large; this function is not
144  * restricted to acting on a single-word quantity.
145  */
146 static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
147 {
148         if (cpu_has_llsc && R10000_LLSC_WAR) {
149                 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
150                 unsigned long temp;
151
152                 __asm__ __volatile__(
153                 "       .set    mips3                           \n"
154                 "1:     " __LL "%0, %1          # change_bit    \n"
155                 "       xor     %0, %2                          \n"
156                 "       " __SC  "%0, %1                         \n"
157                 "       beqzl   %0, 1b                          \n"
158                 "       .set    mips0                           \n"
159                 : "=&r" (temp), "=m" (*m)
160                 : "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
161         } else if (cpu_has_llsc) {
162                 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
163                 unsigned long temp;
164
165                 __asm__ __volatile__(
166                 "       .set    mips3                           \n"
167                 "1:     " __LL "%0, %1          # change_bit    \n"
168                 "       xor     %0, %2                          \n"
169                 "       " __SC  "%0, %1                         \n"
170                 "       beqz    %0, 1b                          \n"
171                 "       .set    mips0                           \n"
172                 : "=&r" (temp), "=m" (*m)
173                 : "ir" (1UL << (nr & SZLONG_MASK)), "m" (*m));
174         } else {
175                 volatile unsigned long *a = addr;
176                 unsigned long mask;
177                 unsigned long flags;
178
179                 a += nr >> SZLONG_LOG;
180                 mask = 1UL << (nr & SZLONG_MASK);
181                 local_irq_save(flags);
182                 *a ^= mask;
183                 local_irq_restore(flags);
184         }
185 }
186
187 /*
188  * test_and_set_bit - Set a bit and return its old value
189  * @nr: Bit to set
190  * @addr: Address to count from
191  *
192  * This operation is atomic and cannot be reordered.
193  * It also implies a memory barrier.
194  */
195 static inline int test_and_set_bit(unsigned long nr,
196         volatile unsigned long *addr)
197 {
198         if (cpu_has_llsc && R10000_LLSC_WAR) {
199                 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
200                 unsigned long temp, res;
201
202                 __asm__ __volatile__(
203                 "       .set    mips3                                   \n"
204                 "1:     " __LL "%0, %1          # test_and_set_bit      \n"
205                 "       or      %2, %0, %3                              \n"
206                 "       " __SC  "%2, %1                                 \n"
207                 "       beqzl   %2, 1b                                  \n"
208                 "       and     %2, %0, %3                              \n"
209 #ifdef CONFIG_SMP
210                 "       sync                                            \n"
211 #endif
212                 "       .set    mips0                                   \n"
213                 : "=&r" (temp), "=m" (*m), "=&r" (res)
214                 : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
215                 : "memory");
216
217                 return res != 0;
218         } else if (cpu_has_llsc) {
219                 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
220                 unsigned long temp, res;
221
222                 __asm__ __volatile__(
223                 "       .set    push                                    \n"
224                 "       .set    noreorder                               \n"
225                 "       .set    mips3                                   \n"
226                 "1:     " __LL "%0, %1          # test_and_set_bit      \n"
227                 "       or      %2, %0, %3                              \n"
228                 "       " __SC  "%2, %1                                 \n"
229                 "       beqz    %2, 1b                                  \n"
230                 "        and    %2, %0, %3                              \n"
231 #ifdef CONFIG_SMP
232                 "       sync                                            \n"
233 #endif
234                 "       .set    pop                                     \n"
235                 : "=&r" (temp), "=m" (*m), "=&r" (res)
236                 : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
237                 : "memory");
238
239                 return res != 0;
240         } else {
241                 volatile unsigned long *a = addr;
242                 unsigned long mask;
243                 int retval;
244                 unsigned long flags;
245
246                 a += nr >> SZLONG_LOG;
247                 mask = 1UL << (nr & SZLONG_MASK);
248                 local_irq_save(flags);
249                 retval = (mask & *a) != 0;
250                 *a |= mask;
251                 local_irq_restore(flags);
252
253                 return retval;
254         }
255 }
256
257 /*
258  * test_and_clear_bit - Clear a bit and return its old value
259  * @nr: Bit to clear
260  * @addr: Address to count from
261  *
262  * This operation is atomic and cannot be reordered.
263  * It also implies a memory barrier.
264  */
265 static inline int test_and_clear_bit(unsigned long nr,
266         volatile unsigned long *addr)
267 {
268         if (cpu_has_llsc && R10000_LLSC_WAR) {
269                 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
270                 unsigned long temp, res;
271
272                 __asm__ __volatile__(
273                 "       .set    mips3                                   \n"
274                 "1:     " __LL  "%0, %1         # test_and_clear_bit    \n"
275                 "       or      %2, %0, %3                              \n"
276                 "       xor     %2, %3                                  \n"
277                 "       " __SC  "%2, %1                                 \n"
278                 "       beqzl   %2, 1b                                  \n"
279                 "       and     %2, %0, %3                              \n"
280 #ifdef CONFIG_SMP
281                 "       sync                                            \n"
282 #endif
283                 "       .set    mips0                                   \n"
284                 : "=&r" (temp), "=m" (*m), "=&r" (res)
285                 : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
286                 : "memory");
287
288                 return res != 0;
289         } else if (cpu_has_llsc) {
290                 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
291                 unsigned long temp, res;
292
293                 __asm__ __volatile__(
294                 "       .set    push                                    \n"
295                 "       .set    noreorder                               \n"
296                 "       .set    mips3                                   \n"
297                 "1:     " __LL  "%0, %1         # test_and_clear_bit    \n"
298                 "       or      %2, %0, %3                              \n"
299                 "       xor     %2, %3                                  \n"
300                 "       " __SC  "%2, %1                                 \n"
301                 "       beqz    %2, 1b                                  \n"
302                 "        and    %2, %0, %3                              \n"
303 #ifdef CONFIG_SMP
304                 "       sync                                            \n"
305 #endif
306                 "       .set    pop                                     \n"
307                 : "=&r" (temp), "=m" (*m), "=&r" (res)
308                 : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
309                 : "memory");
310
311                 return res != 0;
312         } else {
313                 volatile unsigned long *a = addr;
314                 unsigned long mask;
315                 int retval;
316                 unsigned long flags;
317
318                 a += nr >> SZLONG_LOG;
319                 mask = 1UL << (nr & SZLONG_MASK);
320                 local_irq_save(flags);
321                 retval = (mask & *a) != 0;
322                 *a &= ~mask;
323                 local_irq_restore(flags);
324
325                 return retval;
326         }
327 }
328
329 /*
330  * test_and_change_bit - Change a bit and return its old value
331  * @nr: Bit to change
332  * @addr: Address to count from
333  *
334  * This operation is atomic and cannot be reordered.
335  * It also implies a memory barrier.
336  */
337 static inline int test_and_change_bit(unsigned long nr,
338         volatile unsigned long *addr)
339 {
340         if (cpu_has_llsc && R10000_LLSC_WAR) {
341                 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
342                 unsigned long temp, res;
343
344                 __asm__ __volatile__(
345                 "       .set    mips3                                   \n"
346                 "1:     " __LL  "%0, %1         # test_and_change_bit   \n"
347                 "       xor     %2, %0, %3                              \n"
348                 "       " __SC  "%2, %1                                 \n"
349                 "       beqzl   %2, 1b                                  \n"
350                 "       and     %2, %0, %3                              \n"
351 #ifdef CONFIG_SMP
352                 "       sync                                            \n"
353 #endif
354                 "       .set    mips0                                   \n"
355                 : "=&r" (temp), "=m" (*m), "=&r" (res)
356                 : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
357                 : "memory");
358
359                 return res != 0;
360         } else if (cpu_has_llsc) {
361                 unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
362                 unsigned long temp, res;
363
364                 __asm__ __volatile__(
365                 "       .set    push                                    \n"
366                 "       .set    noreorder                               \n"
367                 "       .set    mips3                                   \n"
368                 "1:     " __LL  "%0, %1         # test_and_change_bit   \n"
369                 "       xor     %2, %0, %3                              \n"
370                 "       " __SC  "\t%2, %1                               \n"
371                 "       beqz    %2, 1b                                  \n"
372                 "        and    %2, %0, %3                              \n"
373 #ifdef CONFIG_SMP
374                 "       sync                                            \n"
375 #endif
376                 "       .set    pop                                     \n"
377                 : "=&r" (temp), "=m" (*m), "=&r" (res)
378                 : "r" (1UL << (nr & SZLONG_MASK)), "m" (*m)
379                 : "memory");
380
381                 return res != 0;
382         } else {
383                 volatile unsigned long *a = addr;
384                 unsigned long mask, retval;
385                 unsigned long flags;
386
387                 a += nr >> SZLONG_LOG;
388                 mask = 1UL << (nr & SZLONG_MASK);
389                 local_irq_save(flags);
390                 retval = (mask & *a) != 0;
391                 *a ^= mask;
392                 local_irq_restore(flags);
393
394                 return retval;
395         }
396 }
397
398 #include <asm-generic/bitops/non-atomic.h>
399
400 /*
401  * Return the bit position (0..63) of the most significant 1 bit in a word
402  * Returns -1 if no 1 bit exists
403  */
404 static inline int __ilog2(unsigned long x)
405 {
406         int lz;
407
408         if (sizeof(x) == 4) {
409                 __asm__ (
410                 "       .set    push                                    \n"
411                 "       .set    mips32                                  \n"
412                 "       clz     %0, %1                                  \n"
413                 "       .set    pop                                     \n"
414                 : "=r" (lz)
415                 : "r" (x));
416
417                 return 31 - lz;
418         }
419
420         BUG_ON(sizeof(x) != 8);
421
422         __asm__ (
423         "       .set    push                                            \n"
424         "       .set    mips64                                          \n"
425         "       dclz    %0, %1                                          \n"
426         "       .set    pop                                             \n"
427         : "=r" (lz)
428         : "r" (x));
429
430         return 63 - lz;
431 }
432
433 #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
434
435 /*
436  * __ffs - find first bit in word.
437  * @word: The word to search
438  *
439  * Returns 0..SZLONG-1
440  * Undefined if no bit exists, so code should check against 0 first.
441  */
442 static inline unsigned long __ffs(unsigned long word)
443 {
444         return __ilog2(word & -word);
445 }
446
447 /*
448  * fls - find last bit set.
449  * @word: The word to search
450  *
451  * This is defined the same way as ffs.
452  * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
453  */
454 static inline int fls(int word)
455 {
456         __asm__ ("clz %0, %1" : "=r" (word) : "r" (word));
457
458         return 32 - word;
459 }
460
461 #if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPS64)
462 static inline int fls64(__u64 word)
463 {
464         __asm__ ("dclz %0, %1" : "=r" (word) : "r" (word));
465
466         return 64 - word;
467 }
468 #else
469 #include <asm-generic/bitops/fls64.h>
470 #endif
471
472 /*
473  * ffs - find first bit set.
474  * @word: The word to search
475  *
476  * This is defined the same way as
477  * the libc and compiler builtin ffs routines, therefore
478  * differs in spirit from the above ffz (man ffs).
479  */
480 static inline int ffs(int word)
481 {
482         if (!word)
483                 return 0;
484
485         return fls(word & -word);
486 }
487
488 #else
489
490 #include <asm-generic/bitops/__ffs.h>
491 #include <asm-generic/bitops/ffs.h>
492 #include <asm-generic/bitops/fls.h>
493 #include <asm-generic/bitops/fls64.h>
494
495 #endif /*defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) */
496
497 #include <asm-generic/bitops/ffz.h>
498 #include <asm-generic/bitops/find.h>
499
500 #ifdef __KERNEL__
501
502 #include <asm-generic/bitops/sched.h>
503 #include <asm-generic/bitops/hweight.h>
504 #include <asm-generic/bitops/ext2-non-atomic.h>
505 #include <asm-generic/bitops/ext2-atomic.h>
506 #include <asm-generic/bitops/minix.h>
507
508 #endif /* __KERNEL__ */
509
510 #endif /* _ASM_BITOPS_H */