root/include/asm-i386/bitops.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. set_bit
  2. clear_bit
  3. change_bit
  4. test_bit
  5. find_first_zero_bit
  6. find_next_zero_bit
  7. ffz

   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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  68 {
  69         return 1UL & (((const unsigned int *) addr)[nr >> 5] >> (nr & 31));
  70 }
  71 
  72 /*
  73  * Find-bit routines..
  74  */
  75 extern __inline__ int find_first_zero_bit(void * addr, unsigned size)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131         __asm__("bsfl %1,%0"
 132                 :"=r" (word)
 133                 :"r" (~word));
 134         return word;
 135 }
 136 
 137 #endif /* _I386_BITOPS_H */

/* [previous][next][first][last][top][bottom][index][help] */