root/include/asm-alpha/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. ffz
  6. find_next_zero_bit

   1 #ifndef _ALPHA_BITOPS_H
   2 #define _ALPHA_BITOPS_H
   3 
   4 /*
   5  * Copyright 1994, 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 64 is the LSB of (addr+1).
  14  */
  15 
  16 extern __inline__ unsigned long set_bit(unsigned long nr, void * addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  17 {
  18         unsigned long oldbit;
  19         unsigned long temp;
  20         unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
  21 
  22         __asm__ __volatile__(
  23                 "\n1:\t"
  24                 "ldl_l %0,%1\n\t"
  25                 "and %0,%3,%2\n\t"
  26                 "bne %2,2f\n\t"
  27                 "xor %0,%3,%0\n\t"
  28                 "stl_c %0,%1\n\t"
  29                 "beq %0,1b\n"
  30                 "2:"
  31                 :"=&r" (temp),
  32                  "=m" (*m),
  33                  "=&r" (oldbit)
  34                 :"r" (1UL << (nr & 31)),
  35                  "m" (*m));
  36         return oldbit != 0;
  37 }
  38 
  39 extern __inline__ unsigned long clear_bit(unsigned long nr, void * addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  40 {
  41         unsigned long oldbit;
  42         unsigned long temp;
  43         unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
  44 
  45         __asm__ __volatile__(
  46                 "\n1:\t"
  47                 "ldl_l %0,%1\n\t"
  48                 "and %0,%3,%2\n\t"
  49                 "beq %2,2f\n\t"
  50                 "xor %0,%3,%0\n\t"
  51                 "stl_c %0,%1\n\t"
  52                 "beq %0,1b\n"
  53                 "2:"
  54                 :"=&r" (temp),
  55                  "=m" (*m),
  56                  "=&r" (oldbit)
  57                 :"r" (1UL << (nr & 31)),
  58                  "m" (*m));
  59         return oldbit != 0;
  60 }
  61 
  62 extern __inline__ unsigned long change_bit(unsigned long nr, void * addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  63 {
  64         unsigned long oldbit;
  65         unsigned long temp;
  66         unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
  67 
  68         __asm__ __volatile__(
  69                 "\n1:\t"
  70                 "ldl_l %0,%1\n\t"
  71                 "and %0,%3,%2\n\t"
  72                 "xor %0,%3,%0\n\t"
  73                 "stl_c %0,%1\n\t"
  74                 "beq %0,1b\n"
  75                 :"=&r" (temp),
  76                  "=m" (*m),
  77                  "=&r" (oldbit)
  78                 :"r" (1UL << (nr & 31)),
  79                  "m" (*m));
  80         return oldbit != 0;
  81 }
  82 
  83 extern __inline__ unsigned long test_bit(int nr, const void * addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  84 {
  85         return 1UL & (((int *) addr)[nr >> 5] >> (nr & 31));
  86 }
  87 
  88 /*
  89  * ffz = Find First Zero in word. Undefined if no zero exists,
  90  * so code should check against ~0UL first..
  91  *
  92  * This uses the cmpbge insn to check which byte contains the zero.
  93  * I don't know if that's actually a good idea, but it's fun and the
  94  * resulting LBS tests should be natural on the alpha.. Besides, I'm
  95  * just teaching myself the asm of the alpha anyway.
  96  */
  97 extern inline unsigned long ffz(unsigned long word)
     /* [previous][next][first][last][top][bottom][index][help] */
  98 {
  99         unsigned long result = 0;
 100         unsigned long tmp;
 101 
 102         __asm__("cmpbge %1,%0,%0"
 103                 :"=r" (tmp)
 104                 :"r" (word), "0" (~0UL));
 105         while (tmp & 1) {
 106                 word >>= 8;
 107                 tmp >>= 1;
 108                 result += 8;
 109         }
 110         while (word & 1) {
 111                 result++;
 112                 word >>= 1;
 113         }
 114         return result;
 115 }
 116 
 117 /*
 118  * Find next zero bit in a bitmap reasonably efficiently..
 119  */
 120 extern inline unsigned long find_next_zero_bit(void * addr, unsigned long size, unsigned long offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 121 {
 122         unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
 123         unsigned long result = offset & ~63UL;
 124         unsigned long tmp;
 125 
 126         if (offset >= size)
 127                 return size;
 128         size -= result;
 129         offset &= 63UL;
 130         if (offset) {
 131                 tmp = *(p++);
 132                 tmp |= ~0UL >> (64-offset);
 133                 if (size < 64)
 134                         goto found_first;
 135                 if (~tmp)
 136                         goto found_middle;
 137                 size -= 64;
 138                 result += 64;
 139         }
 140         while (size & ~63UL) {
 141                 if (~(tmp = *(p++)))
 142                         goto found_middle;
 143                 result += 64;
 144                 size -= 64;
 145         }
 146         if (!size)
 147                 return result;
 148         tmp = *p;
 149 found_first:
 150         tmp |= ~0UL << size;
 151 found_middle:
 152         return result + ffz(tmp);
 153 }
 154 
 155 /*
 156  * The optimizer actually does good code for this case..
 157  */
 158 #define find_first_zero_bit(addr, size) \
 159         find_next_zero_bit((addr), (size), 0)
 160 
 161 #endif /* _ALPHA_BITOPS_H */

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