Merge tag 'renesas-cleanup-for-v3.19' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / arch / arc / include / asm / bitops.h
1 /*
2  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
8
9 #ifndef _ASM_BITOPS_H
10 #define _ASM_BITOPS_H
11
12 #ifndef _LINUX_BITOPS_H
13 #error only <linux/bitops.h> can be included directly
14 #endif
15
16 #ifndef __ASSEMBLY__
17
18 #include <linux/types.h>
19 #include <linux/compiler.h>
20 #include <asm/barrier.h>
21
22 /*
23  * Hardware assisted read-modify-write using ARC700 LLOCK/SCOND insns.
24  * The Kconfig glue ensures that in SMP, this is only set if the container
25  * SoC/platform has cross-core coherent LLOCK/SCOND
26  */
27 #if defined(CONFIG_ARC_HAS_LLSC)
28
29 static inline void set_bit(unsigned long nr, volatile unsigned long *m)
30 {
31         unsigned int temp;
32
33         m += nr >> 5;
34
35         if (__builtin_constant_p(nr))
36                 nr &= 0x1f;
37
38         __asm__ __volatile__(
39         "1:     llock   %0, [%1]        \n"
40         "       bset    %0, %0, %2      \n"
41         "       scond   %0, [%1]        \n"
42         "       bnz     1b      \n"
43         : "=&r"(temp)
44         : "r"(m), "ir"(nr)
45         : "cc");
46 }
47
48 static inline void clear_bit(unsigned long nr, volatile unsigned long *m)
49 {
50         unsigned int temp;
51
52         m += nr >> 5;
53
54         if (__builtin_constant_p(nr))
55                 nr &= 0x1f;
56
57         __asm__ __volatile__(
58         "1:     llock   %0, [%1]        \n"
59         "       bclr    %0, %0, %2      \n"
60         "       scond   %0, [%1]        \n"
61         "       bnz     1b      \n"
62         : "=&r"(temp)
63         : "r"(m), "ir"(nr)
64         : "cc");
65 }
66
67 static inline void change_bit(unsigned long nr, volatile unsigned long *m)
68 {
69         unsigned int temp;
70
71         m += nr >> 5;
72
73         if (__builtin_constant_p(nr))
74                 nr &= 0x1f;
75
76         __asm__ __volatile__(
77         "1:     llock   %0, [%1]        \n"
78         "       bxor    %0, %0, %2      \n"
79         "       scond   %0, [%1]        \n"
80         "       bnz     1b              \n"
81         : "=&r"(temp)
82         : "r"(m), "ir"(nr)
83         : "cc");
84 }
85
86 /*
87  * Semantically:
88  *    Test the bit
89  *    if clear
90  *        set it and return 0 (old value)
91  *    else
92  *        return 1 (old value).
93  *
94  * Since ARC lacks a equivalent h/w primitive, the bit is set unconditionally
95  * and the old value of bit is returned
96  */
97 static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *m)
98 {
99         unsigned long old, temp;
100
101         m += nr >> 5;
102
103         if (__builtin_constant_p(nr))
104                 nr &= 0x1f;
105
106         __asm__ __volatile__(
107         "1:     llock   %0, [%2]        \n"
108         "       bset    %1, %0, %3      \n"
109         "       scond   %1, [%2]        \n"
110         "       bnz     1b              \n"
111         : "=&r"(old), "=&r"(temp)
112         : "r"(m), "ir"(nr)
113         : "cc");
114
115         return (old & (1 << nr)) != 0;
116 }
117
118 static inline int
119 test_and_clear_bit(unsigned long nr, volatile unsigned long *m)
120 {
121         unsigned int old, temp;
122
123         m += nr >> 5;
124
125         if (__builtin_constant_p(nr))
126                 nr &= 0x1f;
127
128         __asm__ __volatile__(
129         "1:     llock   %0, [%2]        \n"
130         "       bclr    %1, %0, %3      \n"
131         "       scond   %1, [%2]        \n"
132         "       bnz     1b              \n"
133         : "=&r"(old), "=&r"(temp)
134         : "r"(m), "ir"(nr)
135         : "cc");
136
137         return (old & (1 << nr)) != 0;
138 }
139
140 static inline int
141 test_and_change_bit(unsigned long nr, volatile unsigned long *m)
142 {
143         unsigned int old, temp;
144
145         m += nr >> 5;
146
147         if (__builtin_constant_p(nr))
148                 nr &= 0x1f;
149
150         __asm__ __volatile__(
151         "1:     llock   %0, [%2]        \n"
152         "       bxor    %1, %0, %3      \n"
153         "       scond   %1, [%2]        \n"
154         "       bnz     1b              \n"
155         : "=&r"(old), "=&r"(temp)
156         : "r"(m), "ir"(nr)
157         : "cc");
158
159         return (old & (1 << nr)) != 0;
160 }
161
162 #else   /* !CONFIG_ARC_HAS_LLSC */
163
164 #include <asm/smp.h>
165
166 /*
167  * Non hardware assisted Atomic-R-M-W
168  * Locking would change to irq-disabling only (UP) and spinlocks (SMP)
169  *
170  * There's "significant" micro-optimization in writing our own variants of
171  * bitops (over generic variants)
172  *
173  * (1) The generic APIs have "signed" @nr while we have it "unsigned"
174  *     This avoids extra code to be generated for pointer arithmatic, since
175  *     is "not sure" that index is NOT -ve
176  * (2) Utilize the fact that ARCompact bit fidding insn (BSET/BCLR/ASL) etc
177  *     only consider bottom 5 bits of @nr, so NO need to mask them off.
178  *     (GCC Quirk: however for constant @nr we still need to do the masking
179  *             at compile time)
180  */
181
182 static inline void set_bit(unsigned long nr, volatile unsigned long *m)
183 {
184         unsigned long temp, flags;
185         m += nr >> 5;
186
187         if (__builtin_constant_p(nr))
188                 nr &= 0x1f;
189
190         bitops_lock(flags);
191
192         temp = *m;
193         *m = temp | (1UL << nr);
194
195         bitops_unlock(flags);
196 }
197
198 static inline void clear_bit(unsigned long nr, volatile unsigned long *m)
199 {
200         unsigned long temp, flags;
201         m += nr >> 5;
202
203         if (__builtin_constant_p(nr))
204                 nr &= 0x1f;
205
206         bitops_lock(flags);
207
208         temp = *m;
209         *m = temp & ~(1UL << nr);
210
211         bitops_unlock(flags);
212 }
213
214 static inline void change_bit(unsigned long nr, volatile unsigned long *m)
215 {
216         unsigned long temp, flags;
217         m += nr >> 5;
218
219         if (__builtin_constant_p(nr))
220                 nr &= 0x1f;
221
222         bitops_lock(flags);
223
224         temp = *m;
225         *m = temp ^ (1UL << nr);
226
227         bitops_unlock(flags);
228 }
229
230 static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *m)
231 {
232         unsigned long old, flags;
233         m += nr >> 5;
234
235         if (__builtin_constant_p(nr))
236                 nr &= 0x1f;
237
238         bitops_lock(flags);
239
240         old = *m;
241         *m = old | (1 << nr);
242
243         bitops_unlock(flags);
244
245         return (old & (1 << nr)) != 0;
246 }
247
248 static inline int
249 test_and_clear_bit(unsigned long nr, volatile unsigned long *m)
250 {
251         unsigned long old, flags;
252         m += nr >> 5;
253
254         if (__builtin_constant_p(nr))
255                 nr &= 0x1f;
256
257         bitops_lock(flags);
258
259         old = *m;
260         *m = old & ~(1 << nr);
261
262         bitops_unlock(flags);
263
264         return (old & (1 << nr)) != 0;
265 }
266
267 static inline int
268 test_and_change_bit(unsigned long nr, volatile unsigned long *m)
269 {
270         unsigned long old, flags;
271         m += nr >> 5;
272
273         if (__builtin_constant_p(nr))
274                 nr &= 0x1f;
275
276         bitops_lock(flags);
277
278         old = *m;
279         *m = old ^ (1 << nr);
280
281         bitops_unlock(flags);
282
283         return (old & (1 << nr)) != 0;
284 }
285
286 #endif /* CONFIG_ARC_HAS_LLSC */
287
288 /***************************************
289  * Non atomic variants
290  **************************************/
291
292 static inline void __set_bit(unsigned long nr, volatile unsigned long *m)
293 {
294         unsigned long temp;
295         m += nr >> 5;
296
297         if (__builtin_constant_p(nr))
298                 nr &= 0x1f;
299
300         temp = *m;
301         *m = temp | (1UL << nr);
302 }
303
304 static inline void __clear_bit(unsigned long nr, volatile unsigned long *m)
305 {
306         unsigned long temp;
307         m += nr >> 5;
308
309         if (__builtin_constant_p(nr))
310                 nr &= 0x1f;
311
312         temp = *m;
313         *m = temp & ~(1UL << nr);
314 }
315
316 static inline void __change_bit(unsigned long nr, volatile unsigned long *m)
317 {
318         unsigned long temp;
319         m += nr >> 5;
320
321         if (__builtin_constant_p(nr))
322                 nr &= 0x1f;
323
324         temp = *m;
325         *m = temp ^ (1UL << nr);
326 }
327
328 static inline int
329 __test_and_set_bit(unsigned long nr, volatile unsigned long *m)
330 {
331         unsigned long old;
332         m += nr >> 5;
333
334         if (__builtin_constant_p(nr))
335                 nr &= 0x1f;
336
337         old = *m;
338         *m = old | (1 << nr);
339
340         return (old & (1 << nr)) != 0;
341 }
342
343 static inline int
344 __test_and_clear_bit(unsigned long nr, volatile unsigned long *m)
345 {
346         unsigned long old;
347         m += nr >> 5;
348
349         if (__builtin_constant_p(nr))
350                 nr &= 0x1f;
351
352         old = *m;
353         *m = old & ~(1 << nr);
354
355         return (old & (1 << nr)) != 0;
356 }
357
358 static inline int
359 __test_and_change_bit(unsigned long nr, volatile unsigned long *m)
360 {
361         unsigned long old;
362         m += nr >> 5;
363
364         if (__builtin_constant_p(nr))
365                 nr &= 0x1f;
366
367         old = *m;
368         *m = old ^ (1 << nr);
369
370         return (old & (1 << nr)) != 0;
371 }
372
373 /*
374  * This routine doesn't need to be atomic.
375  */
376 static inline int
377 __constant_test_bit(unsigned int nr, const volatile unsigned long *addr)
378 {
379         return ((1UL << (nr & 31)) &
380                 (((const volatile unsigned int *)addr)[nr >> 5])) != 0;
381 }
382
383 static inline int
384 __test_bit(unsigned int nr, const volatile unsigned long *addr)
385 {
386         unsigned long mask;
387
388         addr += nr >> 5;
389
390         /* ARC700 only considers 5 bits in bit-fiddling insn */
391         mask = 1 << nr;
392
393         return ((mask & *addr) != 0);
394 }
395
396 #define test_bit(nr, addr)      (__builtin_constant_p(nr) ? \
397                                         __constant_test_bit((nr), (addr)) : \
398                                         __test_bit((nr), (addr)))
399
400 /*
401  * Count the number of zeros, starting from MSB
402  * Helper for fls( ) friends
403  * This is a pure count, so (1-32) or (0-31) doesn't apply
404  * It could be 0 to 32, based on num of 0's in there
405  * clz(0x8000_0000) = 0, clz(0xFFFF_FFFF)=0, clz(0) = 32, clz(1) = 31
406  */
407 static inline __attribute__ ((const)) int clz(unsigned int x)
408 {
409         unsigned int res;
410
411         __asm__ __volatile__(
412         "       norm.f  %0, %1          \n"
413         "       mov.n   %0, 0           \n"
414         "       add.p   %0, %0, 1       \n"
415         : "=r"(res)
416         : "r"(x)
417         : "cc");
418
419         return res;
420 }
421
422 static inline int constant_fls(int x)
423 {
424         int r = 32;
425
426         if (!x)
427                 return 0;
428         if (!(x & 0xffff0000u)) {
429                 x <<= 16;
430                 r -= 16;
431         }
432         if (!(x & 0xff000000u)) {
433                 x <<= 8;
434                 r -= 8;
435         }
436         if (!(x & 0xf0000000u)) {
437                 x <<= 4;
438                 r -= 4;
439         }
440         if (!(x & 0xc0000000u)) {
441                 x <<= 2;
442                 r -= 2;
443         }
444         if (!(x & 0x80000000u)) {
445                 x <<= 1;
446                 r -= 1;
447         }
448         return r;
449 }
450
451 /*
452  * fls = Find Last Set in word
453  * @result: [1-32]
454  * fls(1) = 1, fls(0x80000000) = 32, fls(0) = 0
455  */
456 static inline __attribute__ ((const)) int fls(unsigned long x)
457 {
458         if (__builtin_constant_p(x))
459                return constant_fls(x);
460
461         return 32 - clz(x);
462 }
463
464 /*
465  * __fls: Similar to fls, but zero based (0-31)
466  */
467 static inline __attribute__ ((const)) int __fls(unsigned long x)
468 {
469         if (!x)
470                 return 0;
471         else
472                 return fls(x) - 1;
473 }
474
475 /*
476  * ffs = Find First Set in word (LSB to MSB)
477  * @result: [1-32], 0 if all 0's
478  */
479 #define ffs(x)  ({ unsigned long __t = (x); fls(__t & -__t); })
480
481 /*
482  * __ffs: Similar to ffs, but zero based (0-31)
483  */
484 static inline __attribute__ ((const)) int __ffs(unsigned long word)
485 {
486         if (!word)
487                 return word;
488
489         return ffs(word) - 1;
490 }
491
492 /*
493  * ffz = Find First Zero in word.
494  * @return:[0-31], 32 if all 1's
495  */
496 #define ffz(x)  __ffs(~(x))
497
498 #include <asm-generic/bitops/hweight.h>
499 #include <asm-generic/bitops/fls64.h>
500 #include <asm-generic/bitops/sched.h>
501 #include <asm-generic/bitops/lock.h>
502
503 #include <asm-generic/bitops/find.h>
504 #include <asm-generic/bitops/le.h>
505 #include <asm-generic/bitops/ext2-atomic-setbit.h>
506
507 #endif /* !__ASSEMBLY__ */
508
509 #endif