Branch data Line data Source code
1 : : #ifndef __CR_BITOPS_H__
2 : : #define __CR_BITOPS_H__
3 : :
4 : : #include "asm/bitsperlong.h"
5 : :
6 : : #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
7 : : #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG)
8 : :
9 : : #define DECLARE_BITMAP(name, bits) \
10 : : unsigned long name[BITS_TO_LONGS(bits)]
11 : :
12 : : #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)
13 : : /* Technically wrong, but this avoids compilation errors on some gcc
14 : : versions. */
15 : : #define BITOP_ADDR(x) "=m" (*(volatile long *) (x))
16 : : #else
17 : : #define BITOP_ADDR(x) "+m" (*(volatile long *) (x))
18 : : #endif
19 : :
20 : : #define ADDR BITOP_ADDR(addr)
21 : :
22 : : static inline void set_bit(int nr, volatile unsigned long *addr)
23 : : {
24 : 323663 : asm volatile("btsl %1,%0" : ADDR : "Ir" (nr) : "memory");
25 : : }
26 : :
27 : : static inline void change_bit(int nr, volatile unsigned long *addr)
28 : : {
29 : : asm volatile("btcl %1,%0" : ADDR : "Ir" (nr));
30 : : }
31 : :
32 : : static inline int test_bit(int nr, volatile const unsigned long *addr)
33 : : {
34 : : int oldbit;
35 : :
36 : 4584332 : asm volatile("bt %2,%1\n\t"
37 : : "sbb %0,%0"
38 : : : "=r" (oldbit)
39 : : : "m" (*(unsigned long *)addr), "Ir" (nr));
40 : :
41 : : return oldbit;
42 : : }
43 : :
44 : : static inline void clear_bit(int nr, volatile unsigned long *addr)
45 : : {
46 : 1810 : asm volatile("btrl %1,%0" : ADDR : "Ir" (nr));
47 : : }
48 : :
49 : : /**
50 : : * __ffs - find first set bit in word
51 : : * @word: The word to search
52 : : *
53 : : * Undefined if no bit exists, so code should check against 0 first.
54 : : */
55 : : static inline unsigned long __ffs(unsigned long word)
56 : : {
57 : 32 : asm("bsf %1,%0"
58 : : : "=r" (word)
59 : : : "rm" (word));
60 : : return word;
61 : : }
62 : :
63 : : #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
64 : :
65 : : /*
66 : : * Find the next set bit in a memory region.
67 : : */
68 : : static inline
69 : 835 : unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
70 : : unsigned long offset)
71 : : {
72 : 835 : const unsigned long *p = addr + BITOP_WORD(offset);
73 : 835 : unsigned long result = offset & ~(BITS_PER_LONG-1);
74 : : unsigned long tmp;
75 : :
76 [ + - ]: 835 : if (offset >= size)
77 : : return size;
78 : 835 : size -= result;
79 : 835 : offset %= BITS_PER_LONG;
80 [ + + ]: 835 : if (offset) {
81 : 32 : tmp = *(p++);
82 : 32 : tmp &= (~0UL << offset);
83 [ + - ]: 32 : if (size < BITS_PER_LONG)
84 : : goto found_first;
85 [ + - ]: 32 : if (tmp)
86 : : goto found_middle;
87 : 32 : size -= BITS_PER_LONG;
88 : 835 : result += BITS_PER_LONG;
89 : : }
90 [ + + ]: 4015 : while (size & ~(BITS_PER_LONG-1)) {
91 [ + + ]: 3212 : if ((tmp = *(p++)))
92 : : goto found_middle;
93 : 3180 : result += BITS_PER_LONG;
94 : 3180 : size -= BITS_PER_LONG;
95 : : }
96 [ - + ]: 803 : if (!size)
97 : : return result;
98 : 0 : tmp = *p;
99 : :
100 : : found_first:
101 : 0 : tmp &= (~0UL >> (BITS_PER_LONG - size));
102 [ # # ]: 0 : if (tmp == 0UL) /* Are any bits set? */
103 : 0 : return result + size; /* Nope. */
104 : : found_middle:
105 : 32 : return result + __ffs(tmp);
106 : : }
107 : :
108 : : #define for_each_bit(i, bitmask) \
109 : : for (i = find_next_bit(bitmask, sizeof(bitmask), 0); \
110 : : i < sizeof(bitmask); \
111 : : i = find_next_bit(bitmask, sizeof(bitmask), i + 1))
112 : :
113 : : #endif /* __CR_BITOPS_H__ */
|