summaryrefslogtreecommitdiff
path: root/sys/gnu/ext2fs/i386-bitops.h
diff options
context:
space:
mode:
Diffstat (limited to 'sys/gnu/ext2fs/i386-bitops.h')
-rw-r--r--sys/gnu/ext2fs/i386-bitops.h180
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 */