root/include/asm-sparc/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
  7. ext2_set_bit
  8. ext2_clear_bit
  9. ext2_test_bit
  10. ext2_find_next_zero_bit

   1 /* $Id: bitops.h,v 1.23 1996/04/20 07:54:35 davem Exp $
   2  * bitops.h: Bit string operations on the Sparc.
   3  *
   4  * Copyright 1995, David S. Miller (davem@caip.rutgers.edu).
   5  */
   6 
   7 #ifndef _SPARC_BITOPS_H
   8 #define _SPARC_BITOPS_H
   9 
  10 #include <linux/kernel.h>
  11 
  12 #ifdef __KERNEL__
  13 #include <asm/system.h>
  14 #endif
  15 
  16 #ifdef __SMP__
  17 
  18 #define SMPVOL volatile
  19 
  20 #else
  21 
  22 #define SMPVOL
  23 
  24 #endif
  25 
  26 /* Set bit 'nr' in 32-bit quantity at address 'addr' where bit '0'
  27  * is in the highest of the four bytes and bit '31' is the high bit
  28  * within the first byte. Sparc is BIG-Endian. Unless noted otherwise
  29  * all bit-ops return 0 if bit was previously clear and != 0 otherwise.
  30  */
  31 
  32 extern __inline__ unsigned long set_bit(unsigned long nr, SMPVOL void *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  33 {
  34         int mask, flags;
  35         unsigned long *ADDR = (unsigned long *) addr;
  36         unsigned long oldbit;
  37 
  38         ADDR += nr >> 5;
  39         mask = 1 << (nr & 31);
  40         save_flags(flags); cli();
  41         oldbit = (mask & *ADDR);
  42         *ADDR |= mask;
  43         restore_flags(flags);
  44         return oldbit != 0;
  45 }
  46 
  47 extern __inline__ unsigned long clear_bit(unsigned long nr, SMPVOL void *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  48 {
  49         int mask, flags;
  50         unsigned long *ADDR = (unsigned long *) addr;
  51         unsigned long oldbit;
  52 
  53         ADDR += nr >> 5;
  54         mask = 1 << (nr & 31);
  55         save_flags(flags); cli();
  56         oldbit = (mask & *ADDR);
  57         *ADDR &= ~mask;
  58         restore_flags(flags);
  59         return oldbit != 0;
  60 }
  61 
  62 extern __inline__ unsigned long change_bit(unsigned long nr, SMPVOL void *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  63 {
  64         int mask, flags;
  65         unsigned long *ADDR = (unsigned long *) addr;
  66         unsigned long oldbit;
  67 
  68         ADDR += nr >> 5;
  69         mask = 1 << (nr & 31);
  70         save_flags(flags); cli();
  71         oldbit = (mask & *ADDR);
  72         *ADDR ^= mask;
  73         restore_flags(flags);
  74         return oldbit != 0;
  75 }
  76 
  77 /* The following routine need not be atomic. */
  78 extern __inline__ unsigned long test_bit(int nr, const SMPVOL void *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  79 {
  80         return ((1UL << (nr & 31)) & (((const unsigned int *) addr)[nr >> 5])) != 0;
  81 }
  82 
  83 /* The easy/cheese version for now. */
  84 extern __inline__ unsigned long ffz(unsigned long word)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86         unsigned long result = 0;
  87 
  88         while(word & 1) {
  89                 result++;
  90                 word >>= 1;
  91         }
  92         return result;
  93 }
  94 
  95 /* find_next_zero_bit() finds the first zero bit in a bit string of length
  96  * 'size' bits, starting the search at bit 'offset'. This is largely based
  97  * on Linus's ALPHA routines, which are pretty portable BTW.
  98  */
  99 
 100 extern __inline__ unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 101 {
 102         unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
 103         unsigned long result = offset & ~31UL;
 104         unsigned long tmp;
 105 
 106         if (offset >= size)
 107                 return size;
 108         size -= result;
 109         offset &= 31UL;
 110         if (offset) {
 111                 tmp = *(p++);
 112                 tmp |= ~0UL >> (32-offset);
 113                 if (size < 32)
 114                         goto found_first;
 115                 if (~tmp)
 116                         goto found_middle;
 117                 size -= 32;
 118                 result += 32;
 119         }
 120         while (size & ~31UL) {
 121                 if (~(tmp = *(p++)))
 122                         goto found_middle;
 123                 result += 32;
 124                 size -= 32;
 125         }
 126         if (!size)
 127                 return result;
 128         tmp = *p;
 129 
 130 found_first:
 131         tmp |= ~0UL >> size;
 132 found_middle:
 133         return result + ffz(tmp);
 134 }
 135 
 136 /* Linus sez that gcc can optimize the following correctly, we'll see if this
 137  * holds on the Sparc as it does for the ALPHA.
 138  */
 139 
 140 #define find_first_zero_bit(addr, size) \
 141         find_next_zero_bit((addr), (size), 0)
 142 
 143 /* Now for the ext2 filesystem bit operations and helper routines. */
 144 
 145 extern __inline__ int ext2_set_bit(int nr,void * addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 146 {
 147         int             mask, retval, flags;
 148         unsigned char   *ADDR = (unsigned char *) addr;
 149 
 150         ADDR += nr >> 3;
 151         mask = 1 << (nr & 0x07);
 152         save_flags(flags); cli();
 153         retval = (mask & *ADDR) != 0;
 154         *ADDR |= mask;
 155         restore_flags(flags);
 156         return retval;
 157 }
 158 
 159 extern __inline__ int ext2_clear_bit(int nr, void * addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161         int             mask, retval, flags;
 162         unsigned char   *ADDR = (unsigned char *) addr;
 163 
 164         ADDR += nr >> 3;
 165         mask = 1 << (nr & 0x07);
 166         save_flags(flags); cli();
 167         retval = (mask & *ADDR) != 0;
 168         *ADDR &= ~mask;
 169         restore_flags(flags);
 170         return retval;
 171 }
 172 
 173 extern __inline__ int ext2_test_bit(int nr, const void * addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 174 {
 175         int                     mask;
 176         const unsigned char     *ADDR = (const unsigned char *) addr;
 177 
 178         ADDR += nr >> 3;
 179         mask = 1 << (nr & 0x07);
 180         return ((mask & *ADDR) != 0);
 181 }
 182 
 183 #define ext2_find_first_zero_bit(addr, size) \
 184         ext2_find_next_zero_bit((addr), (size), 0)
 185 
 186 extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 187 {
 188         unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
 189         unsigned long result = offset & ~31UL;
 190         unsigned long tmp;
 191 
 192         if (offset >= size)
 193                 return size;
 194         size -= result;
 195         offset &= 31UL;
 196         if(offset) {
 197                 tmp = *(p++);
 198                 tmp |= ~0UL << (32-offset);
 199                 if(size < 32)
 200                         goto found_first;
 201                 if(~tmp)
 202                         goto found_middle;
 203                 size -= 32;
 204                 result += 32;
 205         }
 206         while(size & ~31UL) {
 207                 if(~(tmp = *(p++)))
 208                         goto found_middle;
 209                 result += 32;
 210                 size -= 32;
 211         }
 212         if(!size)
 213                 return result;
 214         tmp = *p;
 215 
 216 found_first:
 217         tmp |= ~0UL << size;
 218 found_middle:
 219         tmp = ((tmp>>24) | ((tmp>>8)&0xff00) | ((tmp<<8)&0xff0000) | (tmp<<24));
 220         return result + ffz(tmp);
 221 }
 222 
 223 #endif /* defined(_SPARC_BITOPS_H) */
 224 

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