|
|
1.1 root 1: #ifndef _I386_BITOPS_H
2: #define _I386_BITOPS_H
3:
4: /*
5: * Copyright 1992, Linus Torvalds.
6: */
7:
8: /*
9: * These have to be done with inline assembly: that way the bit-setting
10: * is guaranteed to be atomic. All bit operations return 0 if the bit
11: * was cleared before the operation and != 0 if it was not.
12: *
13: * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
14: */
15:
16: #ifdef __SMP__
17: #define LOCK_PREFIX "lock ; "
18: #define SMPVOL volatile
19: #else
20: #define LOCK_PREFIX ""
21: #define SMPVOL
22: #endif
23:
24: /*
25: * Some hacks to defeat gcc over-optimizations..
26: */
27: struct __dummy { unsigned long a[100]; };
28: #define ADDR (*(struct __dummy *) addr)
29: #define CONST_ADDR (*(const struct __dummy *) addr)
30:
31: extern __inline__ int set_bit(int nr, SMPVOL void * addr)
32: {
33: int oldbit;
34:
35: __asm__ __volatile__(LOCK_PREFIX
36: "btsl %2,%1\n\tsbbl %0,%0"
37: :"=r" (oldbit),"=m" (ADDR)
38: :"ir" (nr));
39: return oldbit;
40: }
41:
42: extern __inline__ int clear_bit(int nr, SMPVOL void * addr)
43: {
44: int oldbit;
45:
46: __asm__ __volatile__(LOCK_PREFIX
47: "btrl %2,%1\n\tsbbl %0,%0"
48: :"=r" (oldbit),"=m" (ADDR)
49: :"ir" (nr));
50: return oldbit;
51: }
52:
53: extern __inline__ int change_bit(int nr, SMPVOL void * addr)
54: {
55: int oldbit;
56:
57: __asm__ __volatile__(LOCK_PREFIX
58: "btcl %2,%1\n\tsbbl %0,%0"
59: :"=r" (oldbit),"=m" (ADDR)
60: :"ir" (nr));
61: return oldbit;
62: }
63:
1.1.1.2 ! root 64: extern __inline__ int test_and_set_bit(int nr, volatile void * addr)
! 65: {
! 66: int oldbit;
! 67:
! 68: __asm__ __volatile__( LOCK_PREFIX
! 69: "btsl %2,%1\n\tsbbl %0,%0"
! 70: :"=r" (oldbit),"=m" (ADDR)
! 71: :"Ir" (nr));
! 72: return oldbit;
! 73: }
! 74:
! 75: extern __inline__ int test_and_clear_bit(int nr, volatile void * addr)
! 76: {
! 77: int oldbit;
! 78:
! 79: __asm__ __volatile__( LOCK_PREFIX
! 80: "btrl %2,%1\n\tsbbl %0,%0"
! 81: :"=r" (oldbit),"=m" (ADDR)
! 82: :"Ir" (nr));
! 83: return oldbit;
! 84: }
! 85:
! 86: extern __inline__ int test_and_change_bit(int nr, volatile void * addr)
! 87: {
! 88: int oldbit;
! 89:
! 90: __asm__ __volatile__( LOCK_PREFIX
! 91: "btcl %2,%1\n\tsbbl %0,%0"
! 92: :"=r" (oldbit),"=m" (ADDR)
! 93: :"Ir" (nr));
! 94: return oldbit;
! 95: }
! 96:
! 97:
1.1 root 98: /*
99: * This routine doesn't need to be atomic.
100: */
101: extern __inline__ int test_bit(int nr, const SMPVOL void * addr)
102: {
103: return ((1UL << (nr & 31)) & (((const unsigned int *) addr)[nr >> 5])) != 0;
104: }
105:
106: /*
107: * Find-bit routines..
108: */
109: extern __inline__ int find_first_zero_bit(void * addr, unsigned size)
110: {
111: int res;
112:
113: if (!size)
114: return 0;
115: __asm__("cld\n\t"
116: "movl $-1,%%eax\n\t"
117: "xorl %%edx,%%edx\n\t"
118: "repe; scasl\n\t"
119: "je 1f\n\t"
120: "xorl -4(%%edi),%%eax\n\t"
121: "subl $4,%%edi\n\t"
122: "bsfl %%eax,%%edx\n"
123: "1:\tsubl %%ebx,%%edi\n\t"
124: "shll $3,%%edi\n\t"
125: "addl %%edi,%%edx"
126: :"=d" (res)
127: :"c" ((size + 31) >> 5), "D" (addr), "b" (addr)
128: :"ax", "cx", "di");
129: return res;
130: }
131:
132: extern __inline__ int find_next_zero_bit (void * addr, int size, int offset)
133: {
134: unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
135: int set = 0, bit = offset & 31, res;
136:
137: if (bit) {
138: /*
139: * Look for zero in first byte
140: */
141: __asm__("bsfl %1,%0\n\t"
142: "jne 1f\n\t"
143: "movl $32, %0\n"
144: "1:"
145: : "=r" (set)
146: : "r" (~(*p >> bit)));
147: if (set < (32 - bit))
148: return set + offset;
149: set = 32 - bit;
150: p++;
151: }
152: /*
153: * No zero yet, search remaining full bytes for a zero
154: */
155: res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
156: return (offset + set + res);
157: }
158:
159: /*
160: * ffz = Find First Zero in word. Undefined if no zero exists,
161: * so code should check against ~0UL first..
162: */
163: extern __inline__ unsigned long ffz(unsigned long word)
164: {
165: __asm__("bsfl %1,%0"
166: :"=r" (word)
167: :"r" (~word));
168: return word;
169: }
170:
1.1.1.2 ! root 171: #ifdef __KERNEL__
! 172:
! 173: /*
! 174: * ffs: find first bit set. This is defined the same way as
! 175: * the libc and compiler builtin ffs routines, therefore
! 176: * differs in spirit from the above ffz (man ffs).
! 177: */
! 178:
! 179: extern __inline__ int ffs(int x)
! 180: {
! 181: int r;
! 182:
! 183: __asm__("bsfl %1,%0\n\t"
! 184: "jnz 1f\n\t"
! 185: "movl $-1,%0\n"
! 186: "1:" : "=r" (r) : "g" (x));
! 187: return r+1;
! 188: }
! 189:
! 190: /*
! 191: * hweightN: returns the hamming weight (i.e. the number
! 192: * of bits set) of a N-bit word
! 193: */
! 194:
! 195: #define hweight32(x) generic_hweight32(x)
! 196: #define hweight16(x) generic_hweight16(x)
! 197: #define hweight8(x) generic_hweight8(x)
! 198:
! 199: #endif /* __KERNEL__ */
! 200:
1.1 root 201: #endif /* _I386_BITOPS_H */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.