diff options
Diffstat (limited to 'sys/gnu/ext2fs/i386-bitops.h')
-rw-r--r-- | sys/gnu/ext2fs/i386-bitops.h | 180 |
1 files changed, 140 insertions, 40 deletions
diff --git a/sys/gnu/ext2fs/i386-bitops.h b/sys/gnu/ext2fs/i386-bitops.h index ee339bd646f2..86068d069773 100644 --- a/sys/gnu/ext2fs/i386-bitops.h +++ b/sys/gnu/ext2fs/i386-bitops.h @@ -13,86 +13,141 @@ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). */ +#ifdef __SMP__ +#define LOCK_PREFIX "lock ; " +#else +#define LOCK_PREFIX "" +#endif + +/* + * Function prototypes to keep gcc -Wall happy + */ +extern void set_bit(int nr, volatile void * addr); +extern void clear_bit(int nr, volatile void * addr); +extern void change_bit(int nr, volatile void * addr); +extern int test_and_set_bit(int nr, volatile void * addr); +extern int test_and_clear_bit(int nr, volatile void * addr); +extern int test_and_change_bit(int nr, volatile void * addr); +extern int __constant_test_bit(int nr, const volatile void * addr); +extern int __test_bit(int nr, volatile void * addr); +extern int find_first_zero_bit(void * addr, unsigned size); +extern int find_next_zero_bit (void * addr, int size, int offset); +extern unsigned long ffz(unsigned long word); + /* * Some hacks to defeat gcc over-optimizations.. */ struct __dummy { unsigned long a[100]; }; -#define ADDR (*(struct __dummy *) addr) +#define ADDR (*(volatile struct __dummy *) addr) +#define CONST_ADDR (*(volatile const struct __dummy *) addr) -extern __inline__ int set_bit(int nr, void * addr) +extern __inline__ void set_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( LOCK_PREFIX + "btsl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +extern __inline__ void clear_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( LOCK_PREFIX + "btrl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +extern __inline__ void change_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( LOCK_PREFIX + "btcl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +extern __inline__ int test_and_set_bit(int nr, volatile void * addr) { int oldbit; - __asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0" + __asm__ __volatile__( LOCK_PREFIX + "btsl %2,%1\n\tsbbl %0,%0" :"=r" (oldbit),"=m" (ADDR) - :"r" (nr)); + :"Ir" (nr)); return oldbit; } -extern __inline__ int clear_bit(int nr, void * addr) +extern __inline__ int test_and_clear_bit(int nr, volatile void * addr) { int oldbit; - __asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0" + __asm__ __volatile__( LOCK_PREFIX + "btrl %2,%1\n\tsbbl %0,%0" :"=r" (oldbit),"=m" (ADDR) - :"r" (nr)); + :"Ir" (nr)); return oldbit; } -extern __inline__ int change_bit(int nr, void * addr) +extern __inline__ int test_and_change_bit(int nr, volatile void * addr) { int oldbit; - __asm__ __volatile__("btcl %2,%1\n\tsbbl %0,%0" + __asm__ __volatile__( LOCK_PREFIX + "btcl %2,%1\n\tsbbl %0,%0" :"=r" (oldbit),"=m" (ADDR) - :"r" (nr)); + :"Ir" (nr)); return oldbit; } /* - * This routine doesn't need to be atomic, but it's faster to code it - * this way. + * This routine doesn't need to be atomic. */ -extern __inline__ int test_bit(int nr, void * addr) +extern __inline__ int __constant_test_bit(int nr, const volatile void * addr) +{ + return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0; +} + +extern __inline__ int __test_bit(int nr, volatile void * addr) { int oldbit; - __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0" + __asm__ __volatile__( + "btl %2,%1\n\tsbbl %0,%0" :"=r" (oldbit) - :"m" (ADDR),"r" (nr)); + :"m" (ADDR),"Ir" (nr)); return oldbit; } +#define test_bit(nr,addr) \ +(__builtin_constant_p(nr) ? \ + __constant_test_bit((nr),(addr)) : \ + __test_bit((nr),(addr))) + /* * Find-bit routines.. */ -extern inline int find_first_zero_bit(void * addr, unsigned size) +extern __inline__ int find_first_zero_bit(void * addr, unsigned size) { + int d0, d1, d2; int res; if (!size) return 0; - __asm__(" - cld - movl $-1,%%eax - repe; scasl - je 1f - subl $4,%%edi - movl (%%edi),%%eax - notl %%eax - bsfl %%eax,%%edx - jmp 2f -1: xorl %%edx,%%edx -2: subl %%ebx,%%edi - shll $3,%%edi - addl %%edi,%%edx" - :"=d" (res) - :"c" ((size + 31) >> 5), "D" (addr), "b" (addr) - :"ax", "bx", "cx", "di"); + __asm__("movl $-1,%%eax\n\t" + "xorl %%edx,%%edx\n\t" + "repe; scasl\n\t" + "je 1f\n\t" + "xorl -4(%%edi),%%eax\n\t" + "subl $4,%%edi\n\t" + "bsfl %%eax,%%edx\n" + "1:\tsubl %%ebx,%%edi\n\t" + "shll $3,%%edi\n\t" + "addl %%edi,%%edx" + :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2) + :"1" ((size + 31) >> 5), "2" (addr), "b" (addr)); return res; } -extern inline int find_next_zero_bit (void * addr, int size, int offset) +extern __inline__ int find_next_zero_bit (void * addr, int size, int offset) { unsigned long * p = ((unsigned long *) addr) + (offset >> 5); int set = 0, bit = offset & 31, res; @@ -101,11 +156,10 @@ extern inline int find_next_zero_bit (void * addr, int size, int offset) /* * Look for zero in first byte */ - __asm__(" - bsfl %1,%0 - jne 1f - movl $32, %0 -1: " + __asm__("bsfl %1,%0\n\t" + "jne 1f\n\t" + "movl $32, %0\n" + "1:" : "=r" (set) : "r" (~(*p >> bit))); if (set < (32 - bit)) @@ -124,7 +178,7 @@ extern inline int find_next_zero_bit (void * addr, int size, int offset) * ffz = Find First Zero in word. Undefined if no zero exists, * so code should check against ~0UL first.. */ -extern inline unsigned long ffz(unsigned long word) +extern __inline__ unsigned long ffz(unsigned long word) { __asm__("bsfl %1,%0" :"=r" (word) @@ -132,4 +186,50 @@ extern inline unsigned long ffz(unsigned long word) return word; } +#ifdef __KERNEL__ + +/* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +extern __inline__ int ffs(int x) +{ + int r; + + __asm__("bsfl %1,%0\n\t" + "jnz 1f\n\t" + "movl $-1,%0\n" + "1:" : "=r" (r) : "g" (x)); + return r+1; +} + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + +#endif /* __KERNEL__ */ + +#ifdef __KERNEL__ + +#define ext2_set_bit test_and_set_bit +#define ext2_clear_bit test_and_clear_bit +#define ext2_test_bit test_bit +#define ext2_find_first_zero_bit find_first_zero_bit +#define ext2_find_next_zero_bit find_next_zero_bit + +/* Bitmap functions for the minix filesystem. */ +#define minix_set_bit(nr,addr) test_and_set_bit(nr,addr) +#define minix_clear_bit(nr,addr) test_and_clear_bit(nr,addr) +#define minix_test_bit(nr,addr) test_bit(nr,addr) +#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) + +#endif /* __KERNEL__ */ + #endif /* _I386_BITOPS_H */ |