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

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