Initial import from FreeBSD RELENG_4:
[games.git] / sys / vfs / gnu / ext2fs / i386-bitops.h
1 /* $FreeBSD: src/sys/gnu/ext2fs/i386-bitops.h,v 1.5 1999/11/15 23:16:06 obrien Exp $ */
2 /*
3  * this is mixture of i386/bitops.h and asm/string.h
4  * taken from the Linux source tree 
5  *
6  * XXX replace with Mach routines or reprogram in C
7  */
8 #ifndef _SYS_GNU_EXT2FS_I386_BITOPS_H_
9 #define _SYS_GNU_EXT2FS_I386_BITOPS_H_
10
11 /*
12  * Copyright 1992, Linus Torvalds.
13  */
14
15 /*
16  * These have to be done with inline assembly: that way the bit-setting
17  * is guaranteed to be atomic. All bit operations return 0 if the bit
18  * was cleared before the operation and != 0 if it was not.
19  *
20  * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
21  */
22
23 /*
24  * Some hacks to defeat gcc over-optimizations..
25  */
26 struct __dummy { unsigned long a[100]; };
27 #define ADDR (*(struct __dummy *) addr)
28
29 static __inline__ int set_bit(int nr, void * addr)
30 {
31         int oldbit;
32
33         __asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0"
34                 :"=r" (oldbit),"=m" (ADDR)
35                 :"ir" (nr));
36         return oldbit;
37 }
38
39 static __inline__ int clear_bit(int nr, void * addr)
40 {
41         int oldbit;
42
43         __asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0"
44                 :"=r" (oldbit),"=m" (ADDR)
45                 :"ir" (nr));
46         return oldbit;
47 }
48
49 static __inline__ int change_bit(int nr, void * addr)
50 {
51         int oldbit;
52
53         __asm__ __volatile__("btcl %2,%1\n\tsbbl %0,%0"
54                 :"=r" (oldbit),"=m" (ADDR)
55                 :"ir" (nr));
56         return oldbit;
57 }
58
59 /*
60  * This routine doesn't need to be atomic, but it's faster to code it
61  * this way.
62  */
63 static __inline__ int test_bit(int nr, void * addr)
64 {
65         int oldbit;
66
67         __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
68                 :"=r" (oldbit)
69                 :"m" (ADDR),"ir" (nr));
70         return oldbit;
71 }
72
73 /*
74  * Find-bit routines..
75  */
76 static __inline__ int find_first_zero_bit(void * addr, unsigned size)
77 {
78         int res;
79         int _count = (size + 31) >> 5;
80
81         if (!size)
82                 return 0;
83         __asm__("                       \n\
84                 cld                     \n\
85                 movl $-1,%%eax          \n\
86                 xorl %%edx,%%edx        \n\
87                 repe; scasl             \n\
88                 je 1f                   \n\
89                 xorl -4(%%edi),%%eax    \n\
90                 subl $4,%%edi           \n\
91                 bsfl %%eax,%%edx        \n\
92 1:              subl %%ebx,%%edi        \n\
93                 shll $3,%%edi           \n\
94                 addl %%edi,%%edx"
95                 : "=c" (_count), "=D" (addr), "=d" (res)
96                 : "0" (_count), "1" (addr), "b" (addr)
97                 : "ax");
98         return res;
99 }
100
101 static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
102 {
103         unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
104         int set = 0, bit = offset & 31, res;
105         
106         if (bit) {
107                 /*
108                  * Look for zero in first byte
109                  */
110                 __asm__("                       \n\
111                         bsfl %1,%0              \n\
112                         jne 1f                  \n\
113                         movl $32, %0            \n\
114 1:                      "
115                         : "=r" (set)
116                         : "r" (~(*p >> bit)));
117                 if (set < (32 - bit))
118                         return set + offset;
119                 set = 32 - bit;
120                 p++;
121         }
122         /*
123          * No zero yet, search remaining full bytes for a zero
124          */
125         res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
126         return (offset + set + res);
127 }
128
129 /*
130  * ffz = Find First Zero in word. Undefined if no zero exists,
131  * so code should check against ~0UL first..
132  */
133 static __inline__ unsigned long ffz(unsigned long word)
134 {
135         __asm__("bsfl %1,%0"
136                 :"=r" (word)
137                 :"r" (~word));
138         return word;
139 }
140
141 /* 
142  * memscan() taken from linux asm/string.h
143  */
144 /*
145  * find the first occurrence of byte 'c', or 1 past the area if none
146  */
147 static __inline__ char * memscan(void * addr, unsigned char c, int size)
148 {
149         if (!size)
150                 return addr;
151         __asm__("                       \n\
152                 cld                     \n\
153                 repnz; scasb            \n\
154                 jnz 1f                  \n\
155                 dec %%edi               \n\
156 1:              "
157                 : "=D" (addr), "=c" (size)
158                 : "0" (addr), "1" (size), "a" (c));
159         return addr;
160 }
161
162 #endif /* !_SYS_GNU_EXT2FS_I386_BITOPS_H_ */