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