linux-old/include/asm-m68k/bitops.h
<<
>>
Prefs
   1#ifndef _M68K_BITOPS_H
   2#define _M68K_BITOPS_H
   3/*
   4 * Copyright 1992, Linus Torvalds.
   5 *
   6 * This file is subject to the terms and conditions of the GNU General Public
   7 * License.  See the file COPYING in the main directory of this archive
   8 * for more details.
   9 */
  10
  11/*
  12 * Require 68020 or better.
  13 *
  14 * They use the standard big-endian m680x0 bit ordering.
  15 */
  16
  17#define test_and_set_bit(nr,vaddr) \
  18  (__builtin_constant_p(nr) ? \
  19   __constant_test_and_set_bit(nr, vaddr) : \
  20   __generic_test_and_set_bit(nr, vaddr))
  21
  22static inline int __constant_test_and_set_bit(int nr, volatile void *vaddr)
  23{
  24        char retval;
  25
  26        __asm__ __volatile__ ("bset %2,%1; sne %0"
  27             : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3])
  28             : "di" (nr & 7));
  29
  30        return retval;
  31}
  32
  33static inline int __generic_test_and_set_bit(int nr, volatile void *vaddr)
  34{
  35        char retval;
  36
  37        __asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0"
  38             : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory");
  39
  40        return retval;
  41}
  42
  43#define set_bit(nr,vaddr) \
  44  (__builtin_constant_p(nr) ? \
  45   __constant_set_bit(nr, vaddr) : \
  46   __generic_set_bit(nr, vaddr))
  47
  48#define __set_bit(nr,vaddr) set_bit(nr,vaddr) 
  49
  50static inline void __constant_set_bit(int nr, volatile void *vaddr)
  51{
  52        __asm__ __volatile__ ("bset %1,%0"
  53             : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7));
  54}
  55
  56static inline void __generic_set_bit(int nr, volatile void *vaddr)
  57{
  58        __asm__ __volatile__ ("bfset %1@{%0:#1}"
  59             : : "d" (nr^31), "a" (vaddr) : "memory");
  60}
  61
  62#define test_and_clear_bit(nr,vaddr) \
  63  (__builtin_constant_p(nr) ? \
  64   __constant_test_and_clear_bit(nr, vaddr) : \
  65   __generic_test_and_clear_bit(nr, vaddr))
  66
  67#define __test_and_clear_bit(nr,vaddr) test_and_clear_bit(nr,vaddr)
  68
  69static inline int __constant_test_and_clear_bit(int nr, volatile void *vaddr)
  70{
  71        char retval;
  72
  73        __asm__ __volatile__ ("bclr %2,%1; sne %0"
  74             : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3])
  75             : "di" (nr & 7));
  76
  77        return retval;
  78}
  79
  80static inline int __generic_test_and_clear_bit(int nr, volatile void *vaddr)
  81{
  82        char retval;
  83
  84        __asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0"
  85             : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory");
  86
  87        return retval;
  88}
  89
  90/*
  91 * clear_bit() doesn't provide any barrier for the compiler.
  92 */
  93#define smp_mb__before_clear_bit()      barrier()
  94#define smp_mb__after_clear_bit()       barrier()
  95
  96#define clear_bit(nr,vaddr) \
  97  (__builtin_constant_p(nr) ? \
  98   __constant_clear_bit(nr, vaddr) : \
  99   __generic_clear_bit(nr, vaddr))
 100
 101static inline void __constant_clear_bit(int nr, volatile void *vaddr)
 102{
 103        __asm__ __volatile__ ("bclr %1,%0"
 104             : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7));
 105}
 106
 107static inline void __generic_clear_bit(int nr, volatile void *vaddr)
 108{
 109        __asm__ __volatile__ ("bfclr %1@{%0:#1}"
 110             : : "d" (nr^31), "a" (vaddr) : "memory");
 111}
 112
 113#define test_and_change_bit(nr,vaddr) \
 114  (__builtin_constant_p(nr) ? \
 115   __constant_test_and_change_bit(nr, vaddr) : \
 116   __generic_test_and_change_bit(nr, vaddr))
 117
 118#define __test_and_change_bit(nr,vaddr) test_and_change_bit(nr,vaddr)
 119#define __change_bit(nr,vaddr) change_bit(nr,vaddr)
 120
 121static inline int __constant_test_and_change_bit(int nr, volatile void *vaddr)
 122{
 123        char retval;
 124
 125        __asm__ __volatile__ ("bchg %2,%1; sne %0"
 126             : "=d" (retval), "+m" (((volatile char *)vaddr)[(nr^31) >> 3])
 127             : "di" (nr & 7));
 128
 129        return retval;
 130}
 131
 132static inline int __generic_test_and_change_bit(int nr, volatile void *vaddr)
 133{
 134        char retval;
 135
 136        __asm__ __volatile__ ("bfchg %2@{%1:#1}; sne %0"
 137             : "=d" (retval) : "d" (nr^31), "a" (vaddr) : "memory");
 138
 139        return retval;
 140}
 141
 142#define change_bit(nr,vaddr) \
 143  (__builtin_constant_p(nr) ? \
 144   __constant_change_bit(nr, vaddr) : \
 145   __generic_change_bit(nr, vaddr))
 146
 147static inline void __constant_change_bit(int nr, volatile void *vaddr)
 148{
 149        __asm__ __volatile__ ("bchg %1,%0"
 150             : "+m" (((volatile char *)vaddr)[(nr^31) >> 3]) : "di" (nr & 7));
 151}
 152
 153static inline void __generic_change_bit(int nr, volatile void *vaddr)
 154{
 155        __asm__ __volatile__ ("bfchg %1@{%0:#1}"
 156             : : "d" (nr^31), "a" (vaddr) : "memory");
 157}
 158
 159static inline int test_bit(int nr, const volatile void *vaddr)
 160{
 161        return ((1UL << (nr & 31)) & (((const volatile unsigned int *) vaddr)[nr >> 5])) != 0;
 162}
 163
 164static inline int find_first_zero_bit(void *vaddr, unsigned size)
 165{
 166        unsigned long *p = vaddr, *addr = vaddr;
 167        unsigned long allones = ~0UL;
 168        int res;
 169        unsigned long num;
 170
 171        if (!size)
 172                return 0;
 173
 174        size = (size >> 5) + ((size & 31) > 0);
 175        while (*p++ == allones)
 176        {
 177                if (--size == 0)
 178                        return (p - addr) << 5;
 179        }
 180
 181        num = ~*--p;
 182        __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
 183                              : "=d" (res) : "d" (num & -num));
 184        return ((p - addr) << 5) + (res ^ 31);
 185}
 186
 187static inline int find_next_zero_bit(void *vaddr, int size, int offset)
 188{
 189        unsigned long *addr = vaddr;
 190        unsigned long *p = addr + (offset >> 5);
 191        int set = 0, bit = offset & 31UL, res;
 192
 193        if (offset >= size)
 194                return size;
 195
 196        if (bit) {
 197                unsigned long num = ~*p & (~0UL << bit);
 198
 199                /* Look for zero in first longword */
 200                __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
 201                                      : "=d" (res) : "d" (num & -num));
 202                if (res < 32)
 203                        return (offset & ~31UL) + (res ^ 31);
 204                set = 32 - bit;
 205                p++;
 206        }
 207        /* No zero yet, search remaining full bytes for a zero */
 208        res = find_first_zero_bit (p, size - 32 * (p - addr));
 209        return (offset + set + res);
 210}
 211
 212/*
 213 * ffz = Find First Zero in word. Undefined if no zero exists,
 214 * so code should check against ~0UL first..
 215 */
 216static inline unsigned long ffz(unsigned long word)
 217{
 218        int res;
 219
 220        __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
 221                              : "=d" (res) : "d" (~word & -~word));
 222        return res ^ 31;
 223}
 224
 225#ifdef __KERNEL__
 226
 227/*
 228 * ffs: find first bit set. This is defined the same way as
 229 * the libc and compiler builtin ffs routines, therefore
 230 * differs in spirit from the above ffz (man ffs).
 231 */
 232
 233static inline int ffs(int x)
 234{
 235        int cnt;
 236
 237        __asm__ __volatile__("bfffo %1{#0:#0},%0" : "=d" (cnt) : "dm" (x & -x));
 238
 239        return 32 - cnt;
 240}
 241
 242/*
 243 * hweightN: returns the hamming weight (i.e. the number
 244 * of bits set) of a N-bit word
 245 */
 246
 247#define hweight32(x) generic_hweight32(x)
 248#define hweight16(x) generic_hweight16(x)
 249#define hweight8(x) generic_hweight8(x)
 250
 251/* Bitmap functions for the minix filesystem */
 252
 253static inline int minix_find_first_zero_bit(const void *vaddr, unsigned size)
 254{
 255        const unsigned short *p = vaddr, *addr = vaddr;
 256        int res;
 257        unsigned short num;
 258
 259        if (!size)
 260                return 0;
 261
 262        size = (size >> 4) + ((size & 15) > 0);
 263        while (*p++ == 0xffff)
 264        {
 265                if (--size == 0)
 266                        return (p - addr) << 4;
 267        }
 268
 269        num = ~*--p;
 270        __asm__ __volatile__ ("bfffo %1{#16,#16},%0"
 271                              : "=d" (res) : "d" (num & -num));
 272        return ((p - addr) << 4) + (res ^ 31);
 273}
 274
 275static inline int minix_test_and_set_bit(int nr, volatile void *vaddr)
 276{
 277        char retval;
 278
 279        __asm__ __volatile__ ("bfset %2{%1:#1}; sne %0"
 280             : "=d" (retval) : "d" (nr^15), "m" (*(volatile char *)vaddr) : "memory");
 281
 282        return retval;
 283}
 284
 285#define minix_set_bit(nr,addr)  ((void)minix_test_and_set_bit(nr,addr))
 286
 287static inline int minix_test_and_clear_bit(int nr, volatile void *vaddr)
 288{
 289        char retval;
 290
 291        __asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0"
 292             : "=d" (retval) : "d" (nr^15), "m" (*(volatile char *) vaddr) : "memory");
 293
 294        return retval;
 295}
 296
 297static inline int minix_test_bit(int nr, const volatile void *vaddr)
 298{
 299        return ((1U << (nr & 15)) & (((const volatile unsigned short *) vaddr)[nr >> 4])) != 0;
 300}
 301
 302/* Bitmap functions for the ext2 filesystem. */
 303
 304static inline int ext2_set_bit(int nr, volatile void *vaddr)
 305{
 306        char retval;
 307
 308        __asm__ __volatile__ ("bfset %2{%1,#1}; sne %0"
 309             : "=d" (retval) : "d" (nr^7), "m" (*(volatile char *) vaddr) : "memory");
 310
 311        return retval;
 312}
 313
 314static inline int ext2_clear_bit(int nr, volatile void *vaddr)
 315{
 316        char retval;
 317
 318        __asm__ __volatile__ ("bfclr %2{%1,#1}; sne %0"
 319             : "=d" (retval) : "d" (nr^7), "m" (*(volatile char *) vaddr) : "memory");
 320
 321        return retval;
 322}
 323
 324static inline int ext2_test_bit(int nr, const volatile void *vaddr)
 325{
 326        return ((1U << (nr & 7)) & (((const volatile unsigned char *) vaddr)[nr >> 3])) != 0;
 327}
 328
 329static inline int ext2_find_first_zero_bit(const void *vaddr, unsigned size)
 330{
 331        const unsigned long *p = vaddr, *addr = vaddr;
 332        int res;
 333
 334        if (!size)
 335                return 0;
 336
 337        size = (size >> 5) + ((size & 31) > 0);
 338        while (*p++ == ~0UL)
 339        {
 340                if (--size == 0)
 341                        return (p - addr) << 5;
 342        }
 343
 344        --p;
 345        for (res = 0; res < 32; res++)
 346                if (!ext2_test_bit (res, p))
 347                        break;
 348        return (p - addr) * 32 + res;
 349}
 350
 351static inline int ext2_find_next_zero_bit(const void *vaddr, unsigned size,
 352                                          unsigned offset)
 353{
 354        const unsigned long *addr = vaddr;
 355        const unsigned long *p = addr + (offset >> 5);
 356        int bit = offset & 31UL, res;
 357
 358        if (offset >= size)
 359                return size;
 360
 361        if (bit) {
 362                /* Look for zero in first longword */
 363                for (res = bit; res < 32; res++)
 364                        if (!ext2_test_bit (res, p))
 365                                return (p - addr) * 32 + res;
 366                p++;
 367        }
 368        /* No zero yet, search remaining full bytes for a zero */
 369        res = ext2_find_first_zero_bit (p, size - 32 * (p - addr));
 370        return (p - addr) * 32 + res;
 371}
 372
 373#endif /* __KERNEL__ */
 374
 375#endif /* _M68K_BITOPS_H */
 376
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.