root/include/asm-mips/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. set_bit
  5. clear_bit
  6. change_bit
  7. test_bit
  8. find_first_zero_bit
  9. find_next_zero_bit
  10. ffz

   1 /*
   2  * include/asm-mips/bitops.h
   3  *
   4  * This file is subject to the terms and conditions of the GNU General Public
   5  * License.  See the file "COPYING" in the main directory of this archive
   6  * for more details.
   7  *
   8  * Copyright (c) 1994, 1995  Ralf Baechle
   9  */
  10 #ifndef __ASM_MIPS_BITOPS_H
  11 #define __ASM_MIPS_BITOPS_H
  12 
  13 #if __mips > 1
  14 
  15 /*
  16  * These functions for MIPS ISA >= 2 are interrupt and SMP proof and
  17  * interrupt friendly
  18  */
  19 #include <asm/mipsregs.h>
  20 
  21 /*
  22  * The following functions will only work for the R4000!
  23  */
  24 extern __inline__ int set_bit(int nr, void *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  25 {
  26         int     mask, retval, mw;
  27 
  28         addr += ((nr >> 3) & ~3);
  29         mask = 1 << (nr & 0x1f);
  30         do {
  31                 mw = load_linked(addr);
  32                 retval = (mask & mw) != 0;
  33                 }
  34         while (!store_conditional(addr, mw|mask));
  35 
  36         return retval;
  37 }
  38 
  39 extern __inline__ int clear_bit(int nr, void *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  40 {
  41         int     mask, retval, mw;
  42 
  43         addr += ((nr >> 3) & ~3);
  44         mask = 1 << (nr & 0x1f);
  45         do {
  46                 mw = load_linked(addr);
  47                 retval = (mask & mw) != 0;
  48                 }
  49         while (!store_conditional(addr, mw & ~mask));
  50 
  51         return retval;
  52 }
  53 
  54 extern __inline__ int change_bit(int nr, void *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  55 {
  56         int     mask, retval, mw;
  57 
  58         addr += ((nr >> 3) & ~3);
  59         mask = 1 << (nr & 0x1f);
  60         do {
  61                 mw = load_linked(addr);
  62                 retval = (mask & mw) != 0;
  63                 }
  64         while (!store_conditional(addr, mw ^ mask));
  65 
  66         return retval;
  67 }
  68 
  69 #else /* __mips <= 1 */
  70 
  71 /*
  72  * These functions are only used for MIPS ISA 1 CPUs.  Since I don't
  73  * believe that someone ever will run Linux/SMP on such a beast I don't
  74  * worry about making them SMP proof.
  75  */
  76 #include <asm/system.h>
  77 
  78 #ifdef __KERNEL__
  79 /*
  80  * Only disable interrupt for kernel mode stuff to keep usermode stuff
  81  * that dares to use kernel include files alive.
  82  */
  83 #define __flags unsigned long flags
  84 #define __cli() cli()
  85 #define __save_flags(x) save_flags(x)
  86 #define __restore_flags(x) restore_flags(x)
  87 #endif /* __KERNEL__ */
  88 
  89 extern __inline__ int set_bit(int nr, void * addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  90 {
  91         int     mask, retval;
  92         int     *a = addr;
  93         __flags;
  94 
  95         a += nr >> 5;
  96         mask = 1 << (nr & 0x1f);
  97         __save_flags(flags);
  98         __cli();
  99         retval = (mask & *a) != 0;
 100         *a |= mask;
 101         __restore_flags(flags);
 102 
 103         return retval;
 104 }
 105 
 106 extern __inline__ int clear_bit(int nr, void * addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 107 {
 108         int     mask, retval;
 109         int     *a = addr;
 110         __flags;
 111 
 112         a += nr >> 5;
 113         mask = 1 << (nr & 0x1f);
 114         __save_flags(flags);
 115         __cli();
 116         retval = (mask & *a) != 0;
 117         *a &= ~mask;
 118         __restore_flags(flags);
 119 
 120         return retval;
 121 }
 122 
 123 extern __inline__ int change_bit(int nr, void * addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 124 {
 125         int     mask, retval;
 126         int     *a = addr;
 127         __flags;
 128 
 129         a += nr >> 5;
 130         mask = 1 << (nr & 0x1f);
 131         __save_flags(flags);
 132         __cli();
 133         retval = (mask & *a) != 0;
 134         *a ^= mask;
 135         __restore_flags(flags);
 136 
 137         return retval;
 138 }
 139 
 140 #undef __flags
 141 #undef __cli()
 142 #undef __save_flags(x)
 143 #undef __restore_flags(x)
 144 
 145 #endif /* __mips <= 1 */
 146 
 147 extern __inline__ int test_bit(int nr, const void *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 148 {
 149         return 1UL & (((const unsigned int *) addr)[nr >> 5] >> (nr & 31));
 150 }
 151 
 152 extern __inline__ int find_first_zero_bit (void *addr, unsigned size)
     /* [previous][next][first][last][top][bottom][index][help] */
 153 {
 154         int res;
 155 
 156         if (!size)
 157                 return 0;
 158 
 159         __asm__(".set\tnoreorder\n\t"
 160                 ".set\tnoat\n"
 161                 "1:\tsubu\t$1,%2,%0\n\t"
 162                 "blez\t$1,2f\n\t"
 163                 "lw\t$1,(%4)\n\t"
 164                 "addiu\t%4,%4,4\n\t"
 165                 "beql\t%1,$1,1b\n\t"
 166                 "addiu\t%0,%0,32\n\t"
 167                 "li\t%1,1\n"
 168                 "1:\tand\t%4,$1,%1\n\t"
 169                 "beq\t$0,%4,2f\n\t"
 170                 "sll\t%1,%1,1\n\t"
 171                 "bne\t$0,%1,1b\n\t"
 172                 "add\t%0,%0,1\n\t"
 173                 ".set\tat\n\t"
 174                 ".set\treorder\n"
 175                 "2:"
 176                 : "=r" (res)
 177                 : "r" ((unsigned int) 0xffffffff),
 178                   "r" (size),
 179                   "0" ((signed int) 0),
 180                   "r" (addr)
 181                 : "$1");
 182 
 183         return res;
 184 }
 185 
 186 extern __inline__ int find_next_zero_bit (void * addr, int size, int offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 187 {
 188         unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
 189         int set = 0, bit = offset & 31, res;
 190         
 191         if (bit) {
 192                 /*
 193                  * Look for zero in first byte
 194                  */
 195                 __asm__(".set\tnoreorder\n\t"
 196                         ".set\tnoat\n"
 197                         "1:\tand\t$1,%2,%1\n\t"
 198                         "beq\t$0,$1,2f\n\t"
 199                         "sll\t%2,%2,1\n\t"
 200                         "bne\t$0,%2,1b\n\t"
 201                         "addiu\t%0,%0,1\n\t"
 202                         ".set\tat\n\t"
 203                         ".set\treorder\n"
 204                         : "=r" (set)
 205                         : "r" (*p >> bit),
 206                           "r" (1),
 207                           "0" (0)
 208                         : "$1");
 209                 if (set < (32 - bit))
 210                         return set + offset;
 211                 set = 32 - bit;
 212                 p++;
 213         }
 214         /*
 215          * No zero yet, search remaining full bytes for a zero
 216          */
 217         res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
 218         return (offset + set + res);
 219 }
 220 
 221 /*
 222  * ffz = Find First Zero in word. Undefined if no zero exists,
 223  * so code should check against ~0UL first..
 224  */
 225 extern __inline__ unsigned long ffz(unsigned long word)
     /* [previous][next][first][last][top][bottom][index][help] */
 226 {
 227         unsigned int    __res;
 228         unsigned int    mask = 1;
 229 
 230         __asm__ __volatile__ (
 231                 ".set\tnoreorder\n\t"
 232                 ".set\tnoat\n\t"
 233                 "move\t%0,$0\n"
 234                 "1:\tand\t$1,%2,%1\n\t"
 235                 "beqz\t$1,2f\n\t"
 236                 "sll\t%1,1\n\t"
 237                 "bnez\t%1,1b\n\t"
 238                 "addiu\t%0,1\n\t"
 239                 ".set\tat\n\t"
 240                 ".set\treorder\n"
 241                 "2:\n\t"
 242                 : "=r" (__res), "=r" (mask)
 243                 : "r" (word), "1" (mask)
 244                 : "$1");
 245 
 246         return __res;
 247 }
 248 
 249 #endif /* __ASM_MIPS_BITOPS_H */

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