1 #ifndef _PARISC_BITOPS_H
2 #define _PARISC_BITOPS_H
4 #include <linux/spinlock.h>
5 #include <asm/system.h>
6 #include <asm/byteorder.h>
7 #include <asm/atomic.h>
10 * HP-PARISC specific bit operations
11 * for a detailed description of the functions please refer
12 * to include/asm-i386/bitops.h or kerneldoc
16 # define SHIFT_PER_LONG 6
18 # define BITS_PER_LONG 64
21 # define SHIFT_PER_LONG 5
23 # define BITS_PER_LONG 32
27 #define CHOP_SHIFTCOUNT(x) ((x) & (BITS_PER_LONG - 1))
30 #define smp_mb__before_clear_bit() smp_mb()
31 #define smp_mb__after_clear_bit() smp_mb()
33 static __inline__ void set_bit(int nr, void * address)
36 unsigned long *addr = (unsigned long *) address;
39 addr += (nr >> SHIFT_PER_LONG);
40 mask = 1L << CHOP_SHIFTCOUNT(nr);
41 SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
43 SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
46 static __inline__ void __set_bit(int nr, void * address)
49 unsigned long *addr = (unsigned long *) address;
51 addr += (nr >> SHIFT_PER_LONG);
52 mask = 1L << CHOP_SHIFTCOUNT(nr);
56 static __inline__ void clear_bit(int nr, void * address)
59 unsigned long *addr = (unsigned long *) address;
62 addr += (nr >> SHIFT_PER_LONG);
63 mask = 1L << CHOP_SHIFTCOUNT(nr);
64 SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
66 SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
69 static __inline__ void change_bit(int nr, void * address)
72 unsigned long *addr = (unsigned long *) address;
75 addr += (nr >> SHIFT_PER_LONG);
76 mask = 1L << CHOP_SHIFTCOUNT(nr);
77 SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
79 SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
82 static __inline__ void __change_bit(int nr, void * address)
85 unsigned long *addr = (unsigned long *) address;
87 addr += (nr >> SHIFT_PER_LONG);
88 mask = 1L << CHOP_SHIFTCOUNT(nr);
92 static __inline__ int test_and_set_bit(int nr, void * address)
95 unsigned long *addr = (unsigned long *) address;
99 addr += (nr >> SHIFT_PER_LONG);
100 mask = 1L << CHOP_SHIFTCOUNT(nr);
101 SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
102 oldbit = (*addr & mask) ? 1 : 0;
104 SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
109 static __inline__ int __test_and_set_bit(int nr, void * address)
112 unsigned long *addr = (unsigned long *) address;
115 addr += (nr >> SHIFT_PER_LONG);
116 mask = 1L << CHOP_SHIFTCOUNT(nr);
117 oldbit = (*addr & mask) ? 1 : 0;
123 static __inline__ int test_and_clear_bit(int nr, void * address)
126 unsigned long *addr = (unsigned long *) address;
130 addr += (nr >> SHIFT_PER_LONG);
131 mask = 1L << CHOP_SHIFTCOUNT(nr);
132 SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
133 oldbit = (*addr & mask) ? 1 : 0;
135 SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
140 static __inline__ int __test_and_clear_bit(int nr, void * address)
143 unsigned long *addr = (unsigned long *) address;
146 addr += (nr >> SHIFT_PER_LONG);
147 mask = 1L << CHOP_SHIFTCOUNT(nr);
148 oldbit = (*addr & mask) ? 1 : 0;
154 static __inline__ int test_and_change_bit(int nr, void * address)
157 unsigned long *addr = (unsigned long *) address;
161 addr += (nr >> SHIFT_PER_LONG);
162 mask = 1L << CHOP_SHIFTCOUNT(nr);
163 SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
164 oldbit = (*addr & mask) ? 1 : 0;
166 SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
171 static __inline__ int __test_and_change_bit(int nr, void * address)
174 unsigned long *addr = (unsigned long *) address;
177 addr += (nr >> SHIFT_PER_LONG);
178 mask = 1L << CHOP_SHIFTCOUNT(nr);
179 oldbit = (*addr & mask) ? 1 : 0;
185 static __inline__ int test_bit(int nr, const void *address)
188 unsigned long *addr = (unsigned long *) address;
190 addr += (nr >> SHIFT_PER_LONG);
191 mask = 1L << CHOP_SHIFTCOUNT(nr);
193 return !!(*addr & mask);
196 extern __inline__ unsigned long ffz(unsigned long word)
198 unsigned long result;
212 * ffs: find first bit set. This is defined the same way as
213 * the libc and compiler builtin ffs routines, therefore
214 * differs in spirit from the above ffz (man ffs).
217 #define ffs(x) generic_ffs(x)
220 * hweightN: returns the hamming weight (i.e. the number
221 * of bits set) of a N-bit word
224 #define hweight32(x) generic_hweight32(x)
225 #define hweight16(x) generic_hweight16(x)
226 #define hweight8(x) generic_hweight8(x)
228 #endif /* __KERNEL__ */
231 * This implementation of find_{first,next}_zero_bit was stolen from
232 * Linus' asm-alpha/bitops.h.
234 #define find_first_zero_bit(addr, size) \
235 find_next_zero_bit((addr), (size), 0)
237 static __inline__ unsigned long find_next_zero_bit(void * addr, unsigned long size, unsigned long offset)
239 unsigned long * p = ((unsigned long *) addr) + (offset >> SHIFT_PER_LONG);
240 unsigned long result = offset & ~(BITS_PER_LONG-1);
246 offset &= (BITS_PER_LONG-1);
249 tmp |= ~0UL >> (BITS_PER_LONG-offset);
250 if (size < BITS_PER_LONG)
254 size -= BITS_PER_LONG;
255 result += BITS_PER_LONG;
257 while (size & ~(BITS_PER_LONG -1)) {
260 result += BITS_PER_LONG;
261 size -= BITS_PER_LONG;
269 return result + ffz(tmp);
272 #define _EXT2_HAVE_ASM_BITOPS_
276 * test_and_{set,clear}_bit guarantee atomicity without
277 * disabling interrupts.
280 #define ext2_set_bit(nr, addr) test_and_set_bit((nr) ^ 0x38, addr)
281 #define ext2_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 0x38, addr)
283 #define ext2_set_bit(nr, addr) test_and_set_bit((nr) ^ 0x18, addr)
284 #define ext2_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 0x18, addr)
287 #endif /* __KERNEL__ */
289 static __inline__ int ext2_test_bit(int nr, __const__ void * addr)
291 __const__ unsigned char *ADDR = (__const__ unsigned char *) addr;
293 return (ADDR[nr >> 3] >> (nr & 7)) & 1;
297 * This implementation of ext2_find_{first,next}_zero_bit was stolen from
298 * Linus' asm-alpha/bitops.h and modified for a big-endian machine.
301 #define ext2_find_first_zero_bit(addr, size) \
302 ext2_find_next_zero_bit((addr), (size), 0)
304 extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr,
305 unsigned long size, unsigned long offset)
307 unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
308 unsigned int result = offset & ~31UL;
316 tmp = cpu_to_le32p(p++);
317 tmp |= ~0UL >> (32-offset);
326 if ((tmp = cpu_to_le32p(p++)) != ~0U)
333 tmp = cpu_to_le32p(p);
337 return result + ffz(tmp);
340 /* Bitmap functions for the minix filesystem. */
341 #define minix_test_and_set_bit(nr,addr) ext2_set_bit(nr,addr)
342 #define minix_set_bit(nr,addr) ((void)ext2_set_bit(nr,addr))
343 #define minix_test_and_clear_bit(nr,addr) ext2_clear_bit(nr,addr)
344 #define minix_test_bit(nr,addr) ext2_test_bit(nr,addr)
345 #define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size)
347 #endif /* _PARISC_BITOPS_H */