|
|
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: #else
19: #define LOCK_PREFIX ""
20: #endif
21:
22: /*
23: * Some hacks to defeat gcc over-optimizations..
24: */
25: struct __dummy { unsigned long a[100]; };
26: #define ADDR (*(struct __dummy *) addr)
27: #define CONST_ADDR (*(const struct __dummy *) addr)
28:
29: extern __inline__ int set_bit(int nr, void * addr)
30: {
31: int oldbit;
32:
33: __asm__ __volatile__(LOCK_PREFIX
34: "btsl %2,%1\n\tsbbl %0,%0"
35: :"=r" (oldbit),"=m" (ADDR)
36: :"ir" (nr));
37: return oldbit;
38: }
39:
40: extern __inline__ int clear_bit(int nr, void * addr)
41: {
42: int oldbit;
43:
44: __asm__ __volatile__(LOCK_PREFIX
45: "btrl %2,%1\n\tsbbl %0,%0"
46: :"=r" (oldbit),"=m" (ADDR)
47: :"ir" (nr));
48: return oldbit;
49: }
50:
51: extern __inline__ int change_bit(int nr, void * addr)
52: {
53: int oldbit;
54:
55: __asm__ __volatile__(LOCK_PREFIX
56: "btcl %2,%1\n\tsbbl %0,%0"
57: :"=r" (oldbit),"=m" (ADDR)
58: :"ir" (nr));
59: return oldbit;
60: }
61:
62: /*
63: * This routine doesn't need to be atomic.
64: */
65: extern __inline__ int test_bit(int nr, const void * addr)
66: {
67: return 1UL & (((const unsigned int *) addr)[nr >> 5] >> (nr & 31));
68: }
69:
70: /*
71: * Find-bit routines..
72: */
73: extern __inline__ int find_first_zero_bit(void * addr, unsigned size)
74: {
75: int res;
76:
77: if (!size)
78: return 0;
79: __asm__("
80: cld
81: movl $-1,%%eax
82: xorl %%edx,%%edx
83: repe; scasl
84: je 1f
85: xorl -4(%%edi),%%eax
86: subl $4,%%edi
87: bsfl %%eax,%%edx
88: 1: subl %%ebx,%%edi
89: shll $3,%%edi
90: addl %%edi,%%edx"
91: :"=d" (res)
92: :"c" ((size + 31) >> 5), "D" (addr), "b" (addr)
93: :"ax", "cx", "di");
94: return res;
95: }
96:
97: extern __inline__ int find_next_zero_bit (void * addr, int size, int offset)
98: {
99: unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
100: int set = 0, bit = offset & 31, res;
101:
102: if (bit) {
103: /*
104: * Look for zero in first byte
105: */
106: __asm__("
107: bsfl %1,%0
108: jne 1f
109: movl $32, %0
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.