home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / include / asm-i386 / bitops.h next >
Encoding:
C/C++ Source or Header  |  1994-08-22  |  2.6 KB  |  136 lines

  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. /*
  17.  * Some hacks to defeat gcc over-optimizations..
  18.  */
  19. struct __dummy { unsigned long a[100]; };
  20. #define ADDR (*(struct __dummy *) addr)
  21.  
  22. extern __inline__ int set_bit(int nr, void * addr)
  23. {
  24.     int oldbit;
  25.  
  26.     __asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0"
  27.         :"=r" (oldbit),"=m" (ADDR)
  28.         :"r" (nr));
  29.     return oldbit;
  30. }
  31.  
  32. extern __inline__ int clear_bit(int nr, void * addr)
  33. {
  34.     int oldbit;
  35.  
  36.     __asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0"
  37.         :"=r" (oldbit),"=m" (ADDR)
  38.         :"r" (nr));
  39.     return oldbit;
  40. }
  41.  
  42. extern __inline__ int change_bit(int nr, void * addr)
  43. {
  44.     int oldbit;
  45.  
  46.     __asm__ __volatile__("btcl %2,%1\n\tsbbl %0,%0"
  47.         :"=r" (oldbit),"=m" (ADDR)
  48.         :"r" (nr));
  49.     return oldbit;
  50. }
  51.  
  52. /*
  53.  * This routine doesn't need to be atomic, but it's faster to code it
  54.  * this way.
  55.  */
  56. extern __inline__ int test_bit(int nr, void * addr)
  57. {
  58.     int oldbit;
  59.  
  60.     __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
  61.         :"=r" (oldbit)
  62.         :"m" (ADDR),"r" (nr));
  63.     return oldbit;
  64. }
  65.  
  66. /*
  67.  * Find-bit routines..
  68.  */
  69. extern inline int find_first_zero_bit(void * addr, unsigned size)
  70. {
  71.     int res;
  72.  
  73.     if (!size)
  74.         return 0;
  75.     __asm__("
  76.         cld
  77.         movl $-1,%%eax
  78.         repe; scasl
  79.         je 1f
  80.         subl $4,%%edi
  81.         movl (%%edi),%%eax
  82.         notl %%eax
  83.         bsfl %%eax,%%edx
  84.         jmp 2f
  85. 1:        xorl %%edx,%%edx
  86. 2:        subl %%ebx,%%edi
  87.         shll $3,%%edi
  88.         addl %%edi,%%edx"
  89.         :"=d" (res)
  90.         :"c" ((size + 31) >> 5), "D" (addr), "b" (addr)
  91.         :"ax", "bx", "cx", "di");
  92.     return res;
  93. }
  94.  
  95. extern inline int find_next_zero_bit (void * addr, int size, int offset)
  96. {
  97.     unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
  98.     int set = 0, bit = offset & 31, res;
  99.     
  100.     if (bit) {
  101.         /*
  102.          * Look for zero in first byte
  103.          */
  104.         __asm__("
  105.             bsfl %1,%0
  106.             jne 1f
  107.             movl $32, %0
  108. 1:            "
  109.             : "=r" (set)
  110.             : "r" (~(*p >> bit)));
  111.         if (set < (32 - bit))
  112.             return set + offset;
  113.         set = 32 - bit;
  114.         p++;
  115.     }
  116.     /*
  117.      * No zero yet, search remaining full bytes for a zero
  118.      */
  119.     res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
  120.     return (offset + set + res);
  121. }
  122.  
  123. /*
  124.  * ffz = Find First Zero in word. Undefined if no zero exists,
  125.  * so code should check against ~0UL first..
  126.  */
  127. extern inline unsigned long ffz(unsigned long word)
  128. {
  129.     __asm__("bsfl %1,%0"
  130.         :"=r" (word)
  131.         :"r" (~word));
  132.     return word;
  133. }
  134.  
  135. #endif /* _I386_BITOPS_H */
  136.