uboot/arch/microblaze/include/asm/bitops.h
<<
>>
Prefs
   1#ifndef _MICROBLAZE_BITOPS_H
   2#define _MICROBLAZE_BITOPS_H
   3
   4/*
   5 * Copyright 1992, Linus Torvalds.
   6 */
   7
   8#include <asm/byteorder.h>      /* swab32 */
   9#include <asm/system.h>         /* save_flags */
  10#include <asm-generic/bitops/fls.h>
  11#include <asm-generic/bitops/__fls.h>
  12#include <asm-generic/bitops/fls64.h>
  13#include <asm-generic/bitops/__ffs.h>
  14
  15#ifdef __KERNEL__
  16/*
  17 * The __ functions are not atomic
  18 */
  19
  20/*
  21 * ffz = Find First Zero in word. Undefined if no zero exists,
  22 * so code should check against ~0UL first..
  23 */
  24static inline unsigned long ffz(unsigned long word)
  25{
  26        unsigned long result = 0;
  27
  28        while(word & 1) {
  29                result++;
  30                word >>= 1;
  31        }
  32        return result;
  33}
  34
  35
  36static inline void set_bit(int nr, volatile void *addr)
  37{
  38        int     * a = (int *) addr;
  39        int     mask;
  40        unsigned long flags;
  41
  42        a += nr >> 5;
  43        mask = 1 << (nr & 0x1f);
  44        save_flags_cli(flags);
  45        *a |= mask;
  46        restore_flags(flags);
  47}
  48
  49static inline void __set_bit(int nr, volatile void *addr)
  50{
  51        int     * a = (int *) addr;
  52        int     mask;
  53
  54        a += nr >> 5;
  55        mask = 1 << (nr & 0x1f);
  56        *a |= mask;
  57}
  58#define PLATFORM__SET_BIT
  59
  60/*
  61 * clear_bit() doesn't provide any barrier for the compiler.
  62 */
  63#define smp_mb__before_clear_bit()      barrier()
  64#define smp_mb__after_clear_bit()       barrier()
  65
  66static inline void clear_bit(int nr, volatile void *addr)
  67{
  68        int     * a = (int *) addr;
  69        int     mask;
  70        unsigned long flags;
  71
  72        a += nr >> 5;
  73        mask = 1 << (nr & 0x1f);
  74        save_flags_cli(flags);
  75        *a &= ~mask;
  76        restore_flags(flags);
  77}
  78
  79#define __clear_bit(nr, addr) clear_bit(nr, addr)
  80#define PLATFORM__CLEAR_BIT
  81
  82static inline void change_bit(int nr, volatile void *addr)
  83{
  84        int mask;
  85        unsigned long flags;
  86        unsigned long *ADDR = (unsigned long *) addr;
  87
  88        ADDR += nr >> 5;
  89        mask = 1 << (nr & 31);
  90        save_flags_cli(flags);
  91        *ADDR ^= mask;
  92        restore_flags(flags);
  93}
  94
  95static inline void __change_bit(int nr, volatile void *addr)
  96{
  97        int mask;
  98        unsigned long *ADDR = (unsigned long *) addr;
  99
 100        ADDR += nr >> 5;
 101        mask = 1 << (nr & 31);
 102        *ADDR ^= mask;
 103}
 104
 105static inline int test_and_set_bit(int nr, volatile void *addr)
 106{
 107        int     mask, retval;
 108        volatile unsigned int *a = (volatile unsigned int *) addr;
 109        unsigned long flags;
 110
 111        a += nr >> 5;
 112        mask = 1 << (nr & 0x1f);
 113        save_flags_cli(flags);
 114        retval = (mask & *a) != 0;
 115        *a |= mask;
 116        restore_flags(flags);
 117
 118        return retval;
 119}
 120
 121static inline int __test_and_set_bit(int nr, volatile void *addr)
 122{
 123        int     mask, retval;
 124        volatile unsigned int *a = (volatile unsigned int *) addr;
 125
 126        a += nr >> 5;
 127        mask = 1 << (nr & 0x1f);
 128        retval = (mask & *a) != 0;
 129        *a |= mask;
 130        return retval;
 131}
 132
 133static inline int test_and_clear_bit(int nr, volatile void *addr)
 134{
 135        int     mask, retval;
 136        volatile unsigned int *a = (volatile unsigned int *) addr;
 137        unsigned long flags;
 138
 139        a += nr >> 5;
 140        mask = 1 << (nr & 0x1f);
 141        save_flags_cli(flags);
 142        retval = (mask & *a) != 0;
 143        *a &= ~mask;
 144        restore_flags(flags);
 145
 146        return retval;
 147}
 148
 149static inline int __test_and_clear_bit(int nr, volatile void *addr)
 150{
 151        int     mask, retval;
 152        volatile unsigned int *a = (volatile unsigned int *) addr;
 153
 154        a += nr >> 5;
 155        mask = 1 << (nr & 0x1f);
 156        retval = (mask & *a) != 0;
 157        *a &= ~mask;
 158        return retval;
 159}
 160
 161static inline int test_and_change_bit(int nr, volatile void *addr)
 162{
 163        int     mask, retval;
 164        volatile unsigned int *a = (volatile unsigned int *) addr;
 165        unsigned long flags;
 166
 167        a += nr >> 5;
 168        mask = 1 << (nr & 0x1f);
 169        save_flags_cli(flags);
 170        retval = (mask & *a) != 0;
 171        *a ^= mask;
 172        restore_flags(flags);
 173
 174        return retval;
 175}
 176
 177static inline int __test_and_change_bit(int nr, volatile void *addr)
 178{
 179        int     mask, retval;
 180        volatile unsigned int *a = (volatile unsigned int *) addr;
 181
 182        a += nr >> 5;
 183        mask = 1 << (nr & 0x1f);
 184        retval = (mask & *a) != 0;
 185        *a ^= mask;
 186        return retval;
 187}
 188
 189/*
 190 * This routine doesn't need to be atomic.
 191 */
 192static inline int __constant_test_bit(int nr, const volatile void *addr)
 193{
 194        return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
 195}
 196
 197static inline int __test_bit(int nr, volatile void *addr)
 198{
 199        int     * a = (int *) addr;
 200        int     mask;
 201
 202        a += nr >> 5;
 203        mask = 1 << (nr & 0x1f);
 204        return ((mask & *a) != 0);
 205}
 206
 207#define test_bit(nr,addr) \
 208(__builtin_constant_p(nr) ? \
 209 __constant_test_bit((nr),(addr)) : \
 210 __test_bit((nr),(addr)))
 211
 212#define find_first_zero_bit(addr, size) \
 213        find_next_zero_bit((addr), (size), 0)
 214
 215static inline int find_next_zero_bit(void *addr, int size, int offset)
 216{
 217        unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
 218        unsigned long result = offset & ~31UL;
 219        unsigned long tmp;
 220
 221        if (offset >= size)
 222                return size;
 223        size -= result;
 224        offset &= 31UL;
 225        if (offset) {
 226                tmp = *(p++);
 227                tmp |= ~0UL >> (32-offset);
 228                if (size < 32)
 229                        goto found_first;
 230                if (~tmp)
 231                        goto found_middle;
 232                size -= 32;
 233                result += 32;
 234        }
 235        while (size & ~31UL) {
 236                if (~(tmp = *(p++)))
 237                        goto found_middle;
 238                result += 32;
 239                size -= 32;
 240        }
 241        if (!size)
 242                return result;
 243        tmp = *p;
 244
 245found_first:
 246        tmp |= ~0UL >> size;
 247found_middle:
 248        return result + ffz(tmp);
 249}
 250
 251/*
 252 * hweightN: returns the hamming weight (i.e. the number
 253 * of bits set) of a N-bit word
 254 */
 255
 256#define hweight32(x) generic_hweight32(x)
 257#define hweight16(x) generic_hweight16(x)
 258#define hweight8(x) generic_hweight8(x)
 259
 260
 261static inline int ext2_set_bit(int nr, volatile void *addr)
 262{
 263        int             mask, retval;
 264        unsigned long   flags;
 265        volatile unsigned char  *ADDR = (unsigned char *) addr;
 266
 267        ADDR += nr >> 3;
 268        mask = 1 << (nr & 0x07);
 269        save_flags_cli(flags);
 270        retval = (mask & *ADDR) != 0;
 271        *ADDR |= mask;
 272        restore_flags(flags);
 273        return retval;
 274}
 275
 276static inline int ext2_clear_bit(int nr, volatile void *addr)
 277{
 278        int             mask, retval;
 279        unsigned long   flags;
 280        volatile unsigned char  *ADDR = (unsigned char *) addr;
 281
 282        ADDR += nr >> 3;
 283        mask = 1 << (nr & 0x07);
 284        save_flags_cli(flags);
 285        retval = (mask & *ADDR) != 0;
 286        *ADDR &= ~mask;
 287        restore_flags(flags);
 288        return retval;
 289}
 290
 291static inline int ext2_test_bit(int nr, const volatile void *addr)
 292{
 293        int                     mask;
 294        const volatile unsigned char    *ADDR = (const unsigned char *) addr;
 295
 296        ADDR += nr >> 3;
 297        mask = 1 << (nr & 0x07);
 298        return ((mask & *ADDR) != 0);
 299}
 300
 301#define ext2_find_first_zero_bit(addr, size) \
 302        ext2_find_next_zero_bit((addr), (size), 0)
 303
 304static inline unsigned long ext2_find_next_zero_bit(void *addr,
 305                                unsigned long size, unsigned long offset)
 306{
 307        unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
 308        unsigned long result = offset & ~31UL;
 309        unsigned long tmp;
 310
 311        if (offset >= size)
 312                return size;
 313        size -= result;
 314        offset &= 31UL;
 315        if(offset) {
 316                /* We hold the little endian value in tmp, but then the
 317                 * shift is illegal. So we could keep a big endian value
 318                 * in tmp, like this:
 319                 *
 320                 * tmp = __swab32(*(p++));
 321                 * tmp |= ~0UL >> (32-offset);
 322                 *
 323                 * but this would decrease preformance, so we change the
 324                 * shift:
 325                 */
 326                tmp = *(p++);
 327                tmp |= __swab32(~0UL >> (32-offset));
 328                if(size < 32)
 329                        goto found_first;
 330                if(~tmp)
 331                        goto found_middle;
 332                size -= 32;
 333                result += 32;
 334        }
 335        while(size & ~31UL) {
 336                if(~(tmp = *(p++)))
 337                        goto found_middle;
 338                result += 32;
 339                size -= 32;
 340        }
 341        if(!size)
 342                return result;
 343        tmp = *p;
 344
 345found_first:
 346        /* tmp is little endian, so we would have to swab the shift,
 347         * see above. But then we have to swab tmp below for ffz, so
 348         * we might as well do this here.
 349         */
 350        return result + ffz(__swab32(tmp) | (~0UL << size));
 351found_middle:
 352        return result + ffz(__swab32(tmp));
 353}
 354
 355/* Bitmap functions for the minix filesystem.  */
 356#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
 357#define minix_set_bit(nr,addr) set_bit(nr,addr)
 358#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
 359#define minix_test_bit(nr,addr) test_bit(nr,addr)
 360#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
 361
 362/**
 363 * hweightN - returns the hamming weight of a N-bit word
 364 * @x: the word to weigh
 365 *
 366 * The Hamming Weight of a number is the total number of bits set in it.
 367 */
 368
 369#define hweight32(x) generic_hweight32(x)
 370#define hweight16(x) generic_hweight16(x)
 371#define hweight8(x) generic_hweight8(x)
 372
 373#endif /* __KERNEL__ */
 374
 375#endif /* _MICROBLAZE_BITOPS_H */
 376