1 /*
2 * Copyright 1995, Russell King.
3 * Various bits and pieces copyrights include:
4 * Linus Torvalds (test_bit).
5 * Big endian support: Copyright 2001, Nicolas Pitre
6 * reworked by rmk.
7 */
8
9 #ifndef _ARM_BITOPS_H
10 #define _ARM_BITOPS_H
11
12 #include <asm/asm_defns.h>
13
14 /*
15 * Non-atomic bit manipulation.
16 *
17 * Implemented using atomics to be interrupt safe. Could alternatively
18 * implement with local interrupt masking.
19 */
20 #define __set_bit(n,p) set_bit(n,p)
21 #define __clear_bit(n,p) clear_bit(n,p)
22
23 #define BITS_PER_WORD 32
24 #define BIT(nr) (1UL << (nr))
25 #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_WORD))
26 #define BIT_WORD(nr) ((nr) / BITS_PER_WORD)
27 #define BIT_ULL(nr) (1ULL << (nr))
28 #define BITS_PER_BYTE 8
29
30 #define ADDR (*(volatile int *) addr)
31 #define CONST_ADDR (*(const volatile int *) addr)
32
33 #if defined(CONFIG_ARM_32)
34 # include <asm/arm32/bitops.h>
35 #elif defined(CONFIG_ARM_64)
36 # include <asm/arm64/bitops.h>
37 #else
38 # error "unknown ARM variant"
39 #endif
40
41 /**
42 * __test_and_set_bit - Set a bit and return its old value
43 * @nr: Bit to set
44 * @addr: Address to count from
45 *
46 * This operation is non-atomic and can be reordered.
47 * If two examples of this operation race, one can appear to succeed
48 * but actually fail. You must protect multiple accesses with a lock.
49 */
__test_and_set_bit(int nr,volatile void * addr)50 static inline int __test_and_set_bit(int nr, volatile void *addr)
51 {
52 unsigned int mask = BIT_MASK(nr);
53 volatile unsigned int *p =
54 ((volatile unsigned int *)addr) + BIT_WORD(nr);
55 unsigned int old = *p;
56
57 *p = old | mask;
58 return (old & mask) != 0;
59 }
60
61 /**
62 * __test_and_clear_bit - Clear a bit and return its old value
63 * @nr: Bit to clear
64 * @addr: Address to count from
65 *
66 * This operation is non-atomic and can be reordered.
67 * If two examples of this operation race, one can appear to succeed
68 * but actually fail. You must protect multiple accesses with a lock.
69 */
__test_and_clear_bit(int nr,volatile void * addr)70 static inline int __test_and_clear_bit(int nr, volatile void *addr)
71 {
72 unsigned int mask = BIT_MASK(nr);
73 volatile unsigned int *p =
74 ((volatile unsigned int *)addr) + BIT_WORD(nr);
75 unsigned int old = *p;
76
77 *p = old & ~mask;
78 return (old & mask) != 0;
79 }
80
81 /* WARNING: non atomic and it can be reordered! */
__test_and_change_bit(int nr,volatile void * addr)82 static inline int __test_and_change_bit(int nr,
83 volatile void *addr)
84 {
85 unsigned int mask = BIT_MASK(nr);
86 volatile unsigned int *p =
87 ((volatile unsigned int *)addr) + BIT_WORD(nr);
88 unsigned int old = *p;
89
90 *p = old ^ mask;
91 return (old & mask) != 0;
92 }
93
94 /**
95 * test_bit - Determine whether a bit is set
96 * @nr: bit number to test
97 * @addr: Address to start counting from
98 */
test_bit(int nr,const volatile void * addr)99 static inline int test_bit(int nr, const volatile void *addr)
100 {
101 const volatile unsigned int *p = (const volatile unsigned int *)addr;
102 return 1UL & (p[BIT_WORD(nr)] >> (nr & (BITS_PER_WORD-1)));
103 }
104
105 /*
106 * On ARMv5 and above those functions can be implemented around
107 * the clz instruction for much better code efficiency.
108 */
109
fls(unsigned int x)110 static inline int fls(unsigned int x)
111 {
112 int ret;
113
114 if (__builtin_constant_p(x))
115 return generic_fls(x);
116
117 asm("clz\t%"__OP32"0, %"__OP32"1" : "=r" (ret) : "r" (x));
118 return 32 - ret;
119 }
120
121
122 #define ffs(x) ({ unsigned int __t = (x); fls(__t & -__t); })
123 #define ffsl(x) ({ unsigned long __t = (x); flsl(__t & -__t); })
124
125 /**
126 * find_first_set_bit - find the first set bit in @word
127 * @word: the word to search
128 *
129 * Returns the bit-number of the first set bit (first bit being 0).
130 * The input must *not* be zero.
131 */
find_first_set_bit(unsigned long word)132 static inline unsigned int find_first_set_bit(unsigned long word)
133 {
134 return ffsl(word) - 1;
135 }
136
137 /**
138 * hweightN - returns the hamming weight of a N-bit word
139 * @x: the word to weigh
140 *
141 * The Hamming Weight of a number is the total number of bits set in it.
142 */
143 #define hweight64(x) generic_hweight64(x)
144 #define hweight32(x) generic_hweight32(x)
145 #define hweight16(x) generic_hweight16(x)
146 #define hweight8(x) generic_hweight8(x)
147
148 #endif /* _ARM_BITOPS_H */
149 /*
150 * Local variables:
151 * mode: C
152 * c-file-style: "BSD"
153 * c-basic-offset: 4
154 * indent-tabs-mode: nil
155 * End:
156 */
157