1a47a12beSStefan Roese /* 2a47a12beSStefan Roese * bitops.h: Bit string operations on the ppc 3a47a12beSStefan Roese */ 4a47a12beSStefan Roese 5a47a12beSStefan Roese #ifndef _PPC_BITOPS_H 6a47a12beSStefan Roese #define _PPC_BITOPS_H 7a47a12beSStefan Roese 8a47a12beSStefan Roese #include <asm/byteorder.h> 92d2f490dSFabio Estevam #include <asm-generic/bitops/__ffs.h> 10a47a12beSStefan Roese 11a47a12beSStefan Roese /* 12a47a12beSStefan Roese * Arguably these bit operations don't imply any memory barrier or 13a47a12beSStefan Roese * SMP ordering, but in fact a lot of drivers expect them to imply 14a47a12beSStefan Roese * both, since they do on x86 cpus. 15a47a12beSStefan Roese */ 16a47a12beSStefan Roese #ifdef CONFIG_SMP 17a47a12beSStefan Roese #define SMP_WMB "eieio\n" 18a47a12beSStefan Roese #define SMP_MB "\nsync" 19a47a12beSStefan Roese #else 20a47a12beSStefan Roese #define SMP_WMB 21a47a12beSStefan Roese #define SMP_MB 22a47a12beSStefan Roese #endif /* CONFIG_SMP */ 23a47a12beSStefan Roese 24a47a12beSStefan Roese #define __INLINE_BITOPS 1 25a47a12beSStefan Roese 26a47a12beSStefan Roese #if __INLINE_BITOPS 27a47a12beSStefan Roese /* 28a47a12beSStefan Roese * These used to be if'd out here because using : "cc" as a constraint 29a47a12beSStefan Roese * resulted in errors from egcs. Things may be OK with gcc-2.95. 30a47a12beSStefan Roese */ 31*44d0677aSMåns Rullgård static __inline__ void set_bit(int nr, volatile void * addr) 32a47a12beSStefan Roese { 33a47a12beSStefan Roese unsigned long old; 34a47a12beSStefan Roese unsigned long mask = 1 << (nr & 0x1f); 35a47a12beSStefan Roese unsigned long *p = ((unsigned long *)addr) + (nr >> 5); 36a47a12beSStefan Roese 37a47a12beSStefan Roese __asm__ __volatile__(SMP_WMB "\ 38a47a12beSStefan Roese 1: lwarx %0,0,%3\n\ 39a47a12beSStefan Roese or %0,%0,%2\n\ 40a47a12beSStefan Roese stwcx. %0,0,%3\n\ 41a47a12beSStefan Roese bne 1b" 42a47a12beSStefan Roese SMP_MB 43a47a12beSStefan Roese : "=&r" (old), "=m" (*p) 44a47a12beSStefan Roese : "r" (mask), "r" (p), "m" (*p) 45a47a12beSStefan Roese : "cc" ); 46a47a12beSStefan Roese } 47a47a12beSStefan Roese 48*44d0677aSMåns Rullgård static __inline__ void clear_bit(int nr, volatile void *addr) 49a47a12beSStefan Roese { 50a47a12beSStefan Roese unsigned long old; 51a47a12beSStefan Roese unsigned long mask = 1 << (nr & 0x1f); 52a47a12beSStefan Roese unsigned long *p = ((unsigned long *)addr) + (nr >> 5); 53a47a12beSStefan Roese 54a47a12beSStefan Roese __asm__ __volatile__(SMP_WMB "\ 55a47a12beSStefan Roese 1: lwarx %0,0,%3\n\ 56a47a12beSStefan Roese andc %0,%0,%2\n\ 57a47a12beSStefan Roese stwcx. %0,0,%3\n\ 58a47a12beSStefan Roese bne 1b" 59a47a12beSStefan Roese SMP_MB 60a47a12beSStefan Roese : "=&r" (old), "=m" (*p) 61a47a12beSStefan Roese : "r" (mask), "r" (p), "m" (*p) 62a47a12beSStefan Roese : "cc"); 63a47a12beSStefan Roese } 64a47a12beSStefan Roese 65*44d0677aSMåns Rullgård static __inline__ void change_bit(int nr, volatile void *addr) 66a47a12beSStefan Roese { 67a47a12beSStefan Roese unsigned long old; 68a47a12beSStefan Roese unsigned long mask = 1 << (nr & 0x1f); 69a47a12beSStefan Roese unsigned long *p = ((unsigned long *)addr) + (nr >> 5); 70a47a12beSStefan Roese 71a47a12beSStefan Roese __asm__ __volatile__(SMP_WMB "\ 72a47a12beSStefan Roese 1: lwarx %0,0,%3\n\ 73a47a12beSStefan Roese xor %0,%0,%2\n\ 74a47a12beSStefan Roese stwcx. %0,0,%3\n\ 75a47a12beSStefan Roese bne 1b" 76a47a12beSStefan Roese SMP_MB 77a47a12beSStefan Roese : "=&r" (old), "=m" (*p) 78a47a12beSStefan Roese : "r" (mask), "r" (p), "m" (*p) 79a47a12beSStefan Roese : "cc"); 80a47a12beSStefan Roese } 81a47a12beSStefan Roese 82*44d0677aSMåns Rullgård static __inline__ int test_and_set_bit(int nr, volatile void *addr) 83a47a12beSStefan Roese { 84a47a12beSStefan Roese unsigned int old, t; 85a47a12beSStefan Roese unsigned int mask = 1 << (nr & 0x1f); 86a47a12beSStefan Roese volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); 87a47a12beSStefan Roese 88a47a12beSStefan Roese __asm__ __volatile__(SMP_WMB "\ 89a47a12beSStefan Roese 1: lwarx %0,0,%4\n\ 90a47a12beSStefan Roese or %1,%0,%3\n\ 91a47a12beSStefan Roese stwcx. %1,0,%4\n\ 92a47a12beSStefan Roese bne 1b" 93a47a12beSStefan Roese SMP_MB 94a47a12beSStefan Roese : "=&r" (old), "=&r" (t), "=m" (*p) 95a47a12beSStefan Roese : "r" (mask), "r" (p), "m" (*p) 96a47a12beSStefan Roese : "cc"); 97a47a12beSStefan Roese 98a47a12beSStefan Roese return (old & mask) != 0; 99a47a12beSStefan Roese } 100a47a12beSStefan Roese 101*44d0677aSMåns Rullgård static __inline__ int test_and_clear_bit(int nr, volatile void *addr) 102a47a12beSStefan Roese { 103a47a12beSStefan Roese unsigned int old, t; 104a47a12beSStefan Roese unsigned int mask = 1 << (nr & 0x1f); 105a47a12beSStefan Roese volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); 106a47a12beSStefan Roese 107a47a12beSStefan Roese __asm__ __volatile__(SMP_WMB "\ 108a47a12beSStefan Roese 1: lwarx %0,0,%4\n\ 109a47a12beSStefan Roese andc %1,%0,%3\n\ 110a47a12beSStefan Roese stwcx. %1,0,%4\n\ 111a47a12beSStefan Roese bne 1b" 112a47a12beSStefan Roese SMP_MB 113a47a12beSStefan Roese : "=&r" (old), "=&r" (t), "=m" (*p) 114a47a12beSStefan Roese : "r" (mask), "r" (p), "m" (*p) 115a47a12beSStefan Roese : "cc"); 116a47a12beSStefan Roese 117a47a12beSStefan Roese return (old & mask) != 0; 118a47a12beSStefan Roese } 119a47a12beSStefan Roese 120*44d0677aSMåns Rullgård static __inline__ int test_and_change_bit(int nr, volatile void *addr) 121a47a12beSStefan Roese { 122a47a12beSStefan Roese unsigned int old, t; 123a47a12beSStefan Roese unsigned int mask = 1 << (nr & 0x1f); 124a47a12beSStefan Roese volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5); 125a47a12beSStefan Roese 126a47a12beSStefan Roese __asm__ __volatile__(SMP_WMB "\ 127a47a12beSStefan Roese 1: lwarx %0,0,%4\n\ 128a47a12beSStefan Roese xor %1,%0,%3\n\ 129a47a12beSStefan Roese stwcx. %1,0,%4\n\ 130a47a12beSStefan Roese bne 1b" 131a47a12beSStefan Roese SMP_MB 132a47a12beSStefan Roese : "=&r" (old), "=&r" (t), "=m" (*p) 133a47a12beSStefan Roese : "r" (mask), "r" (p), "m" (*p) 134a47a12beSStefan Roese : "cc"); 135a47a12beSStefan Roese 136a47a12beSStefan Roese return (old & mask) != 0; 137a47a12beSStefan Roese } 138a47a12beSStefan Roese #endif /* __INLINE_BITOPS */ 139a47a12beSStefan Roese 140*44d0677aSMåns Rullgård static __inline__ int test_bit(int nr, __const__ volatile void *addr) 141a47a12beSStefan Roese { 142a47a12beSStefan Roese __const__ unsigned int *p = (__const__ unsigned int *) addr; 143a47a12beSStefan Roese 144a47a12beSStefan Roese return ((p[nr >> 5] >> (nr & 0x1f)) & 1) != 0; 145a47a12beSStefan Roese } 146a47a12beSStefan Roese 147a47a12beSStefan Roese /* Return the bit position of the most significant 1 bit in a word */ 148a47a12beSStefan Roese /* - the result is undefined when x == 0 */ 149*44d0677aSMåns Rullgård static __inline__ int __ilog2(unsigned int x) 150a47a12beSStefan Roese { 151a47a12beSStefan Roese int lz; 152a47a12beSStefan Roese 153a47a12beSStefan Roese asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x)); 154a47a12beSStefan Roese return 31 - lz; 155a47a12beSStefan Roese } 156a47a12beSStefan Roese 157*44d0677aSMåns Rullgård static __inline__ int ffz(unsigned int x) 158a47a12beSStefan Roese { 159a47a12beSStefan Roese if ((x = ~x) == 0) 160a47a12beSStefan Roese return 32; 161a47a12beSStefan Roese return __ilog2(x & -x); 162a47a12beSStefan Roese } 163a47a12beSStefan Roese 164a47a12beSStefan Roese /* 165a47a12beSStefan Roese * fls: find last (most-significant) bit set. 166a47a12beSStefan Roese * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. 167a47a12beSStefan Roese * 168a47a12beSStefan Roese * On powerpc, __ilog2(0) returns -1, but this is not safe in general 169a47a12beSStefan Roese */ 170a47a12beSStefan Roese static __inline__ int fls(unsigned int x) 171a47a12beSStefan Roese { 172a47a12beSStefan Roese return __ilog2(x) + 1; 173a47a12beSStefan Roese } 174a47a12beSStefan Roese #define PLATFORM_FLS 175a47a12beSStefan Roese 176a47a12beSStefan Roese /** 177a47a12beSStefan Roese * fls64 - find last set bit in a 64-bit word 178a47a12beSStefan Roese * @x: the word to search 179a47a12beSStefan Roese * 180a47a12beSStefan Roese * This is defined in a similar way as the libc and compiler builtin 181a47a12beSStefan Roese * ffsll, but returns the position of the most significant set bit. 182a47a12beSStefan Roese * 183a47a12beSStefan Roese * fls64(value) returns 0 if value is 0 or the position of the last 184a47a12beSStefan Roese * set bit if value is nonzero. The last (most significant) bit is 185a47a12beSStefan Roese * at position 64. 186a47a12beSStefan Roese */ 187a47a12beSStefan Roese #if BITS_PER_LONG == 32 188a47a12beSStefan Roese static inline int fls64(__u64 x) 189a47a12beSStefan Roese { 190a47a12beSStefan Roese __u32 h = x >> 32; 191a47a12beSStefan Roese if (h) 192a47a12beSStefan Roese return fls(h) + 32; 193a47a12beSStefan Roese return fls(x); 194a47a12beSStefan Roese } 195a47a12beSStefan Roese #elif BITS_PER_LONG == 64 196a47a12beSStefan Roese static inline int fls64(__u64 x) 197a47a12beSStefan Roese { 198a47a12beSStefan Roese if (x == 0) 199a47a12beSStefan Roese return 0; 200a47a12beSStefan Roese return __ilog2(x) + 1; 201a47a12beSStefan Roese } 202a47a12beSStefan Roese #else 203a47a12beSStefan Roese #error BITS_PER_LONG not 32 or 64 204a47a12beSStefan Roese #endif 205a47a12beSStefan Roese 206a47a12beSStefan Roese #ifdef __KERNEL__ 207a47a12beSStefan Roese 208a47a12beSStefan Roese /* 209a47a12beSStefan Roese * ffs: find first bit set. This is defined the same way as 210a47a12beSStefan Roese * the libc and compiler builtin ffs routines, therefore 211a47a12beSStefan Roese * differs in spirit from the above ffz (man ffs). 212a47a12beSStefan Roese */ 213*44d0677aSMåns Rullgård static __inline__ int ffs(int x) 214a47a12beSStefan Roese { 215a47a12beSStefan Roese return __ilog2(x & -x) + 1; 216a47a12beSStefan Roese } 217a47a12beSStefan Roese #define PLATFORM_FFS 218a47a12beSStefan Roese 219a47a12beSStefan Roese /* 220a47a12beSStefan Roese * hweightN: returns the hamming weight (i.e. the number 221a47a12beSStefan Roese * of bits set) of a N-bit word 222a47a12beSStefan Roese */ 223a47a12beSStefan Roese 224a47a12beSStefan Roese #define hweight32(x) generic_hweight32(x) 225a47a12beSStefan Roese #define hweight16(x) generic_hweight16(x) 226a47a12beSStefan Roese #define hweight8(x) generic_hweight8(x) 227a47a12beSStefan Roese 228a47a12beSStefan Roese #endif /* __KERNEL__ */ 229a47a12beSStefan Roese 230a47a12beSStefan Roese /* 231a47a12beSStefan Roese * This implementation of find_{first,next}_zero_bit was stolen from 232a47a12beSStefan Roese * Linus' asm-alpha/bitops.h. 233a47a12beSStefan Roese */ 234a47a12beSStefan Roese #define find_first_zero_bit(addr, size) \ 235a47a12beSStefan Roese find_next_zero_bit((addr), (size), 0) 236a47a12beSStefan Roese 237*44d0677aSMåns Rullgård static __inline__ unsigned long find_next_zero_bit(void * addr, 238a47a12beSStefan Roese unsigned long size, unsigned long offset) 239a47a12beSStefan Roese { 240a47a12beSStefan Roese unsigned int * p = ((unsigned int *) addr) + (offset >> 5); 241a47a12beSStefan Roese unsigned int result = offset & ~31UL; 242a47a12beSStefan Roese unsigned int tmp; 243a47a12beSStefan Roese 244a47a12beSStefan Roese if (offset >= size) 245a47a12beSStefan Roese return size; 246a47a12beSStefan Roese size -= result; 247a47a12beSStefan Roese offset &= 31UL; 248a47a12beSStefan Roese if (offset) { 249a47a12beSStefan Roese tmp = *p++; 250a47a12beSStefan Roese tmp |= ~0UL >> (32-offset); 251a47a12beSStefan Roese if (size < 32) 252a47a12beSStefan Roese goto found_first; 253a47a12beSStefan Roese if (tmp != ~0U) 254a47a12beSStefan Roese goto found_middle; 255a47a12beSStefan Roese size -= 32; 256a47a12beSStefan Roese result += 32; 257a47a12beSStefan Roese } 258a47a12beSStefan Roese while (size >= 32) { 259a47a12beSStefan Roese if ((tmp = *p++) != ~0U) 260a47a12beSStefan Roese goto found_middle; 261a47a12beSStefan Roese result += 32; 262a47a12beSStefan Roese size -= 32; 263a47a12beSStefan Roese } 264a47a12beSStefan Roese if (!size) 265a47a12beSStefan Roese return result; 266a47a12beSStefan Roese tmp = *p; 267a47a12beSStefan Roese found_first: 268a47a12beSStefan Roese tmp |= ~0UL << size; 269a47a12beSStefan Roese found_middle: 270a47a12beSStefan Roese return result + ffz(tmp); 271a47a12beSStefan Roese } 272a47a12beSStefan Roese 273a47a12beSStefan Roese 274a47a12beSStefan Roese #define _EXT2_HAVE_ASM_BITOPS_ 275a47a12beSStefan Roese 276a47a12beSStefan Roese #ifdef __KERNEL__ 277a47a12beSStefan Roese /* 278a47a12beSStefan Roese * test_and_{set,clear}_bit guarantee atomicity without 279a47a12beSStefan Roese * disabling interrupts. 280a47a12beSStefan Roese */ 281a47a12beSStefan Roese #define ext2_set_bit(nr, addr) test_and_set_bit((nr) ^ 0x18, addr) 282a47a12beSStefan Roese #define ext2_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 0x18, addr) 283a47a12beSStefan Roese 284a47a12beSStefan Roese #else 285*44d0677aSMåns Rullgård static __inline__ int ext2_set_bit(int nr, void * addr) 286a47a12beSStefan Roese { 287a47a12beSStefan Roese int mask; 288a47a12beSStefan Roese unsigned char *ADDR = (unsigned char *) addr; 289a47a12beSStefan Roese int oldbit; 290a47a12beSStefan Roese 291a47a12beSStefan Roese ADDR += nr >> 3; 292a47a12beSStefan Roese mask = 1 << (nr & 0x07); 293a47a12beSStefan Roese oldbit = (*ADDR & mask) ? 1 : 0; 294a47a12beSStefan Roese *ADDR |= mask; 295a47a12beSStefan Roese return oldbit; 296a47a12beSStefan Roese } 297a47a12beSStefan Roese 298*44d0677aSMåns Rullgård static __inline__ int ext2_clear_bit(int nr, void * addr) 299a47a12beSStefan Roese { 300a47a12beSStefan Roese int mask; 301a47a12beSStefan Roese unsigned char *ADDR = (unsigned char *) addr; 302a47a12beSStefan Roese int oldbit; 303a47a12beSStefan Roese 304a47a12beSStefan Roese ADDR += nr >> 3; 305a47a12beSStefan Roese mask = 1 << (nr & 0x07); 306a47a12beSStefan Roese oldbit = (*ADDR & mask) ? 1 : 0; 307a47a12beSStefan Roese *ADDR = *ADDR & ~mask; 308a47a12beSStefan Roese return oldbit; 309a47a12beSStefan Roese } 310a47a12beSStefan Roese #endif /* __KERNEL__ */ 311a47a12beSStefan Roese 312*44d0677aSMåns Rullgård static __inline__ int ext2_test_bit(int nr, __const__ void * addr) 313a47a12beSStefan Roese { 314a47a12beSStefan Roese __const__ unsigned char *ADDR = (__const__ unsigned char *) addr; 315a47a12beSStefan Roese 316a47a12beSStefan Roese return (ADDR[nr >> 3] >> (nr & 7)) & 1; 317a47a12beSStefan Roese } 318a47a12beSStefan Roese 319a47a12beSStefan Roese /* 320a47a12beSStefan Roese * This implementation of ext2_find_{first,next}_zero_bit was stolen from 321a47a12beSStefan Roese * Linus' asm-alpha/bitops.h and modified for a big-endian machine. 322a47a12beSStefan Roese */ 323a47a12beSStefan Roese 324a47a12beSStefan Roese #define ext2_find_first_zero_bit(addr, size) \ 325a47a12beSStefan Roese ext2_find_next_zero_bit((addr), (size), 0) 326a47a12beSStefan Roese 327a47a12beSStefan Roese static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, 328a47a12beSStefan Roese unsigned long size, unsigned long offset) 329a47a12beSStefan Roese { 330a47a12beSStefan Roese unsigned int *p = ((unsigned int *) addr) + (offset >> 5); 331a47a12beSStefan Roese unsigned int result = offset & ~31UL; 332a47a12beSStefan Roese unsigned int tmp; 333a47a12beSStefan Roese 334a47a12beSStefan Roese if (offset >= size) 335a47a12beSStefan Roese return size; 336a47a12beSStefan Roese size -= result; 337a47a12beSStefan Roese offset &= 31UL; 338a47a12beSStefan Roese if (offset) { 339a47a12beSStefan Roese tmp = cpu_to_le32p(p++); 340a47a12beSStefan Roese tmp |= ~0UL >> (32-offset); 341a47a12beSStefan Roese if (size < 32) 342a47a12beSStefan Roese goto found_first; 343a47a12beSStefan Roese if (tmp != ~0U) 344a47a12beSStefan Roese goto found_middle; 345a47a12beSStefan Roese size -= 32; 346a47a12beSStefan Roese result += 32; 347a47a12beSStefan Roese } 348a47a12beSStefan Roese while (size >= 32) { 349a47a12beSStefan Roese if ((tmp = cpu_to_le32p(p++)) != ~0U) 350a47a12beSStefan Roese goto found_middle; 351a47a12beSStefan Roese result += 32; 352a47a12beSStefan Roese size -= 32; 353a47a12beSStefan Roese } 354a47a12beSStefan Roese if (!size) 355a47a12beSStefan Roese return result; 356a47a12beSStefan Roese tmp = cpu_to_le32p(p); 357a47a12beSStefan Roese found_first: 358a47a12beSStefan Roese tmp |= ~0U << size; 359a47a12beSStefan Roese found_middle: 360a47a12beSStefan Roese return result + ffz(tmp); 361a47a12beSStefan Roese } 362a47a12beSStefan Roese 363a47a12beSStefan Roese /* Bitmap functions for the minix filesystem. */ 364a47a12beSStefan Roese #define minix_test_and_set_bit(nr,addr) ext2_set_bit(nr,addr) 365a47a12beSStefan Roese #define minix_set_bit(nr,addr) ((void)ext2_set_bit(nr,addr)) 366a47a12beSStefan Roese #define minix_test_and_clear_bit(nr,addr) ext2_clear_bit(nr,addr) 367a47a12beSStefan Roese #define minix_test_bit(nr,addr) ext2_test_bit(nr,addr) 368a47a12beSStefan Roese #define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size) 369a47a12beSStefan Roese 370a47a12beSStefan Roese #endif /* _PPC_BITOPS_H */ 371