|
|
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:
64: /*
65: * This routine doesn't need to be atomic.
66: */
67: extern __inline__ int test_bit(int nr, const SMPVOL void * addr)
68: {
69: return ((1UL << (nr & 31)) & (((const unsigned int *) addr)[nr >> 5])) != 0;
70: }
71:
72: /*
73: * Find-bit routines..
74: */
75: extern __inline__ int find_first_zero_bit(void * addr, unsigned size)
76: {
77: int res;
78:
79: if (!size)
80: return 0;
81: __asm__("cld\n\t"
82: "movl $-1,%%eax\n\t"
83: "xorl %%edx,%%edx\n\t"
84: "repe; scasl\n\t"
85: "je 1f\n\t"
86: "xorl -4(%%edi),%%eax\n\t"
87: "subl $4,%%edi\n\t"
88: "bsfl %%eax,%%edx\n"
89: "1:\tsubl %%ebx,%%edi\n\t"
90: "shll $3,%%edi\n\t"
91: "addl %%edi,%%edx"
92: :"=d" (res)
93: :"c" ((size + 31) >> 5), "D" (addr), "b" (addr)
94: :"ax", "cx", "di");
95: return res;
96: }
97:
98: extern __inline__ int find_next_zero_bit (void * addr, int size, int offset)
99: {
100: unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
101: int set = 0, bit = offset & 31, res;
102:
103: if (bit) {
104: /*
105: * Look for zero in first byte
106: */
107: __asm__("bsfl %1,%0\n\t"
108: "jne 1f\n\t"
109: "movl $32, %0\n"
110: "1:"
111: : "=r" (set)
112: : "r" (~(*p >> bit)));
113: if (set < (32 - bit))
114: return set + offset;
115: set = 32 - bit;
116: p++;
117: }
118: /*
119: * No zero yet, search remaining full bytes for a zero
120: */
121: res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
122: return (offset + set + res);
123: }
124:
125: /*
126: * ffz = Find First Zero in word. Undefined if no zero exists,
127: * so code should check against ~0UL first..
128: */
129: extern __inline__ unsigned long ffz(unsigned long word)
130: {
131: __asm__("bsfl %1,%0"
132: :"=r" (word)
133: :"r" (~word));
134: return word;
135: }
136:
137: #endif /* _I386_BITOPS_H */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.