|
|
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.