|
|
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:
1.1.1.3 ! root 31: static __inline__ int set_bit(int nr, SMPVOL void * addr)
1.1 root 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:
1.1.1.3 ! root 42: static __inline__ int clear_bit(int nr, SMPVOL void * addr)
1.1 root 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:
1.1.1.3 ! root 53: static __inline__ int change_bit(int nr, SMPVOL void * addr)
1.1 root 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.3 ! root 64: static __inline__ int test_and_set_bit(int nr, volatile void * addr)
1.1.1.2 root 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:
1.1.1.3 ! root 75: static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
1.1.1.2 root 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:
1.1.1.3 ! root 86: static __inline__ int test_and_change_bit(int nr, volatile void * addr)
1.1.1.2 root 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: */
1.1.1.3 ! root 101: static __inline__ int test_bit(int nr, const SMPVOL void * addr)
1.1 root 102: {
103: return ((1UL << (nr & 31)) & (((const unsigned int *) addr)[nr >> 5])) != 0;
104: }
105:
106: /*
107: * Find-bit routines..
108: */
1.1.1.3 ! root 109: static __inline__ int find_first_zero_bit(void * addr, unsigned size)
1.1 root 110: {
1.1.1.3 ! root 111: int d0, d1, d2;
1.1 root 112: int res;
113:
114: if (!size)
115: return 0;
116: __asm__("cld\n\t"
117: "movl $-1,%%eax\n\t"
118: "xorl %%edx,%%edx\n\t"
119: "repe; scasl\n\t"
120: "je 1f\n\t"
121: "xorl -4(%%edi),%%eax\n\t"
122: "subl $4,%%edi\n\t"
123: "bsfl %%eax,%%edx\n"
124: "1:\tsubl %%ebx,%%edi\n\t"
125: "shll $3,%%edi\n\t"
126: "addl %%edi,%%edx"
1.1.1.3 ! root 127: :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
! 128: :"1" ((size + 31) >> 5), "2" (addr), "b" (addr));
1.1 root 129: return res;
130: }
131:
1.1.1.3 ! root 132: static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
1.1 root 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: */
1.1.1.3 ! root 163: static __inline__ unsigned long ffz(unsigned long word)
1.1 root 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:
1.1.1.3 ! root 179: static __inline__ int ffs(int x)
1.1.1.2 root 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.