linux/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#ifndef _LINUX_BITOPS_H
  12#error only <linux/bitops.h> can be included directly
  13#endif
  14
  15#include <linux/compiler.h>
  16
  17/*
  18 * Require 68020 or better.
  19 *
  20 * They use the standard big-endian m680x0 bit ordering.
  21 */
  22
  23#define test_and_set_bit(nr,vaddr) \
  24  (__builtin_constant_p(nr) ? \
  25   __constant_test_and_set_bit(nr, vaddr) : \
  26   __generic_test_and_set_bit(nr, vaddr))
  27
  28#define __test_and_set_bit(nr,vaddr) test_and_set_bit(nr,vaddr)
  29
  30static inline int __constant_test_and_set_bit(int nr, unsigned long *vaddr)
  31{
  32        char *p = (char *)vaddr + (nr ^ 31) / 8;
  33        char retval;
  34
  35        __asm__ __volatile__ ("bset %2,%1; sne %0"
  36                        : "=d" (retval), "+m" (*p)
  37                        : "di" (nr & 7));
  38
  39        return retval;
  40}
  41
  42static inline int __generic_test_and_set_bit(int nr, unsigned long *vaddr)
  43{
  44        char retval;
  45
  46        __asm__ __volatile__ ("bfset %2{%1:#1}; sne %0"
  47                        : "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory");
  48
  49        return retval;
  50}
  51
  52#define set_bit(nr,vaddr) \
  53  (__builtin_constant_p(nr) ? \
  54   __constant_set_bit(nr, vaddr) : \
  55   __generic_set_bit(nr, vaddr))
  56
  57#define __set_bit(nr,vaddr) set_bit(nr,vaddr)
  58
  59static inline void __constant_set_bit(int nr, volatile unsigned long *vaddr)
  60{
  61        char *p = (char *)vaddr + (nr ^ 31) / 8;
  62        __asm__ __volatile__ ("bset %1,%0"
  63                        : "+m" (*p) : "di" (nr & 7));
  64}
  65
  66static inline void __generic_set_bit(int nr, volatile unsigned long *vaddr)
  67{
  68        __asm__ __volatile__ ("bfset %1{%0:#1}"
  69                        : : "d" (nr^31), "o" (*vaddr) : "memory");
  70}
  71
  72#define test_and_clear_bit(nr,vaddr) \
  73  (__builtin_constant_p(nr) ? \
  74   __constant_test_and_clear_bit(nr, vaddr) : \
  75   __generic_test_and_clear_bit(nr, vaddr))
  76
  77#define __test_and_clear_bit(nr,vaddr) test_and_clear_bit(nr,vaddr)
  78
  79static inline int __constant_test_and_clear_bit(int nr, unsigned long *vaddr)
  80{
  81        char *p = (char *)vaddr + (nr ^ 31) / 8;
  82        char retval;
  83
  84        __asm__ __volatile__ ("bclr %2,%1; sne %0"
  85                        : "=d" (retval), "+m" (*p)
  86                        : "di" (nr & 7));
  87
  88        return retval;
  89}
  90
  91static inline int __generic_test_and_clear_bit(int nr, unsigned long *vaddr)
  92{
  93        char retval;
  94
  95        __asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0"
  96                        : "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory");
  97
  98        return retval;
  99}
 100
 101/*
 102 * clear_bit() doesn't provide any barrier for the compiler.
 103 */
 104#define smp_mb__before_clear_bit()      barrier()
 105#define smp_mb__after_clear_bit()       barrier()
 106
 107#define clear_bit(nr,vaddr) \
 108  (__builtin_constant_p(nr) ? \
 109   __constant_clear_bit(nr, vaddr) : \
 110   __generic_clear_bit(nr, vaddr))
 111#define __clear_bit(nr,vaddr) clear_bit(nr,vaddr)
 112
 113static inline void __constant_clear_bit(int nr, volatile unsigned long *vaddr)
 114{
 115        char *p = (char *)vaddr + (nr ^ 31) / 8;
 116        __asm__ __volatile__ ("bclr %1,%0"
 117                        : "+m" (*p) : "di" (nr & 7));
 118}
 119
 120static inline void __generic_clear_bit(int nr, volatile unsigned long *vaddr)
 121{
 122        __asm__ __volatile__ ("bfclr %1{%0:#1}"
 123                        : : "d" (nr^31), "o" (*vaddr) : "memory");
 124}
 125
 126#define test_and_change_bit(nr,vaddr) \
 127  (__builtin_constant_p(nr) ? \
 128   __constant_test_and_change_bit(nr, vaddr) : \
 129   __generic_test_and_change_bit(nr, vaddr))
 130
 131#define __test_and_change_bit(nr,vaddr) test_and_change_bit(nr,vaddr)
 132#define __change_bit(nr,vaddr) change_bit(nr,vaddr)
 133
 134static inline int __constant_test_and_change_bit(int nr, unsigned long *vaddr)
 135{
 136        char *p = (char *)vaddr + (nr ^ 31) / 8;
 137        char retval;
 138
 139        __asm__ __volatile__ ("bchg %2,%1; sne %0"
 140                        : "=d" (retval), "+m" (*p)
 141                        : "di" (nr & 7));
 142
 143        return retval;
 144}
 145
 146static inline int __generic_test_and_change_bit(int nr, unsigned long *vaddr)
 147{
 148        char retval;
 149
 150        __asm__ __volatile__ ("bfchg %2{%1:#1}; sne %0"
 151                        : "=d" (retval) : "d" (nr^31), "o" (*vaddr) : "memory");
 152
 153        return retval;
 154}
 155
 156#define change_bit(nr,vaddr) \
 157  (__builtin_constant_p(nr) ? \
 158   __constant_change_bit(nr, vaddr) : \
 159   __generic_change_bit(nr, vaddr))
 160
 161static inline void __constant_change_bit(int nr, unsigned long *vaddr)
 162{
 163        char *p = (char *)vaddr + (nr ^ 31) / 8;
 164        __asm__ __volatile__ ("bchg %1,%0"
 165                        : "+m" (*p) : "di" (nr & 7));
 166}
 167
 168static inline void __generic_change_bit(int nr, unsigned long *vaddr)
 169{
 170        __asm__ __volatile__ ("bfchg %1{%0:#1}"
 171                        : : "d" (nr^31), "o" (*vaddr) : "memory");
 172}
 173
 174static inline int test_bit(int nr, const unsigned long *vaddr)
 175{
 176        return (vaddr[nr >> 5] & (1UL << (nr & 31))) != 0;
 177}
 178
 179static inline int find_first_zero_bit(const unsigned long *vaddr,
 180                                      unsigned size)
 181{
 182        const unsigned long *p = vaddr;
 183        int res = 32;
 184        unsigned long num;
 185
 186        if (!size)
 187                return 0;
 188
 189        size = (size + 31) >> 5;
 190        while (!(num = ~*p++)) {
 191                if (!--size)
 192                        goto out;
 193        }
 194
 195        __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
 196                              : "=d" (res) : "d" (num & -num));
 197        res ^= 31;
 198out:
 199        return ((long)p - (long)vaddr - 4) * 8 + res;
 200}
 201
 202static inline int find_next_zero_bit(const unsigned long *vaddr, int size,
 203                                     int offset)
 204{
 205        const unsigned long *p = vaddr + (offset >> 5);
 206        int bit = offset & 31UL, res;
 207
 208        if (offset >= size)
 209                return size;
 210
 211        if (bit) {
 212                unsigned long num = ~*p++ & (~0UL << bit);
 213                offset -= bit;
 214
 215                /* Look for zero in first longword */
 216                __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
 217                                      : "=d" (res) : "d" (num & -num));
 218                if (res < 32)
 219                        return offset + (res ^ 31);
 220                offset += 32;
 221        }
 222        /* No zero yet, search remaining full bytes for a zero */
 223        res = find_first_zero_bit(p, size - ((long)p - (long)vaddr) * 8);
 224        return offset + res;
 225}
 226
 227static inline int find_first_bit(const unsigned long *vaddr, unsigned size)
 228{
 229        const unsigned long *p = vaddr;
 230        int res = 32;
 231        unsigned long num;
 232
 233        if (!size)
 234                return 0;
 235
 236        size = (size + 31) >> 5;
 237        while (!(num = *p++)) {
 238                if (!--size)
 239                        goto out;
 240        }
 241
 242        __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
 243                              : "=d" (res) : "d" (num & -num));
 244        res ^= 31;
 245out:
 246        return ((long)p - (long)vaddr - 4) * 8 + res;
 247}
 248
 249static inline int find_next_bit(const unsigned long *vaddr, int size,
 250                                int offset)
 251{
 252        const unsigned long *p = vaddr + (offset >> 5);
 253        int bit = offset & 31UL, res;
 254
 255        if (offset >= size)
 256                return size;
 257
 258        if (bit) {
 259                unsigned long num = *p++ & (~0UL << bit);
 260                offset -= bit;
 261
 262                /* Look for one in first longword */
 263                __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
 264                                      : "=d" (res) : "d" (num & -num));
 265                if (res < 32)
 266                        return offset + (res ^ 31);
 267                offset += 32;
 268        }
 269        /* No one yet, search remaining full bytes for a one */
 270        res = find_first_bit(p, size - ((long)p - (long)vaddr) * 8);
 271        return offset + res;
 272}
 273
 274/*
 275 * ffz = Find First Zero in word. Undefined if no zero exists,
 276 * so code should check against ~0UL first..
 277 */
 278static inline unsigned long ffz(unsigned long word)
 279{
 280        int res;
 281
 282        __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
 283                              : "=d" (res) : "d" (~word & -~word));
 284        return res ^ 31;
 285}
 286
 287#ifdef __KERNEL__
 288
 289/*
 290 * ffs: find first bit set. This is defined the same way as
 291 * the libc and compiler builtin ffs routines, therefore
 292 * differs in spirit from the above ffz (man ffs).
 293 */
 294
 295static inline int ffs(int x)
 296{
 297        int cnt;
 298
 299        asm ("bfffo %1{#0:#0},%0" : "=d" (cnt) : "dm" (x & -x));
 300
 301        return 32 - cnt;
 302}
 303#define __ffs(x) (ffs(x) - 1)
 304
 305/*
 306 * fls: find last bit set.
 307 */
 308
 309static inline int fls(int x)
 310{
 311        int cnt;
 312
 313        asm ("bfffo %1{#0,#0},%0" : "=d" (cnt) : "dm" (x));
 314
 315        return 32 - cnt;
 316}
 317
 318#include <asm-generic/bitops/fls64.h>
 319#include <asm-generic/bitops/sched.h>
 320#include <asm-generic/bitops/hweight.h>
 321#include <asm-generic/bitops/lock.h>
 322
 323/* Bitmap functions for the minix filesystem */
 324
 325static inline int minix_find_first_zero_bit(const void *vaddr, unsigned size)
 326{
 327        const unsigned short *p = vaddr, *addr = vaddr;
 328        int res;
 329        unsigned short num;
 330
 331        if (!size)
 332                return 0;
 333
 334        size = (size >> 4) + ((size & 15) > 0);
 335        while (*p++ == 0xffff)
 336        {
 337                if (--size == 0)
 338                        return (p - addr) << 4;
 339        }
 340
 341        num = ~*--p;
 342        __asm__ __volatile__ ("bfffo %1{#16,#16},%0"
 343                              : "=d" (res) : "d" (num & -num));
 344        return ((p - addr) << 4) + (res ^ 31);
 345}
 346
 347#define minix_test_and_set_bit(nr, addr)        __test_and_set_bit((nr) ^ 16, (unsigned long *)(addr))
 348#define minix_set_bit(nr,addr)                  __set_bit((nr) ^ 16, (unsigned long *)(addr))
 349#define minix_test_and_clear_bit(nr, addr)      __test_and_clear_bit((nr) ^ 16, (unsigned long *)(addr))
 350
 351static inline int minix_test_bit(int nr, const void *vaddr)
 352{
 353        const unsigned short *p = vaddr;
 354        return (p[nr >> 4] & (1U << (nr & 15))) != 0;
 355}
 356
 357/* Bitmap functions for the ext2 filesystem. */
 358
 359#define ext2_set_bit(nr, addr)                  __test_and_set_bit((nr) ^ 24, (unsigned long *)(addr))
 360#define ext2_set_bit_atomic(lock, nr, addr)     test_and_set_bit((nr) ^ 24, (unsigned long *)(addr))
 361#define ext2_clear_bit(nr, addr)                __test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr))
 362#define ext2_clear_bit_atomic(lock, nr, addr)   test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr))
 363
 364static inline int ext2_test_bit(int nr, const void *vaddr)
 365{
 366        const unsigned char *p = vaddr;
 367        return (p[nr >> 3] & (1U << (nr & 7))) != 0;
 368}
 369
 370static inline int ext2_find_first_zero_bit(const void *vaddr, unsigned size)
 371{
 372        const unsigned long *p = vaddr, *addr = vaddr;
 373        int res;
 374
 375        if (!size)
 376                return 0;
 377
 378        size = (size >> 5) + ((size & 31) > 0);
 379        while (*p++ == ~0UL)
 380        {
 381                if (--size == 0)
 382                        return (p - addr) << 5;
 383        }
 384
 385        --p;
 386        for (res = 0; res < 32; res++)
 387                if (!ext2_test_bit (res, p))
 388                        break;
 389        return (p - addr) * 32 + res;
 390}
 391
 392static inline int ext2_find_next_zero_bit(const void *vaddr, unsigned size,
 393                                          unsigned offset)
 394{
 395        const unsigned long *addr = vaddr;
 396        const unsigned long *p = addr + (offset >> 5);
 397        int bit = offset & 31UL, res;
 398
 399        if (offset >= size)
 400                return size;
 401
 402        if (bit) {
 403                /* Look for zero in first longword */
 404                for (res = bit; res < 32; res++)
 405                        if (!ext2_test_bit (res, p))
 406                                return (p - addr) * 32 + res;
 407                p++;
 408        }
 409        /* No zero yet, search remaining full bytes for a zero */
 410        res = ext2_find_first_zero_bit (p, size - 32 * (p - addr));
 411        return (p - addr) * 32 + res;
 412}
 413
 414static inline int ext2_find_first_bit(const void *vaddr, unsigned size)
 415{
 416        const unsigned long *p = vaddr, *addr = vaddr;
 417        int res;
 418
 419        if (!size)
 420                return 0;
 421
 422        size = (size >> 5) + ((size & 31) > 0);
 423        while (*p++ == 0UL) {
 424                if (--size == 0)
 425                        return (p - addr) << 5;
 426        }
 427
 428        --p;
 429        for (res = 0; res < 32; res++)
 430                if (ext2_test_bit(res, p))
 431                        break;
 432        return (p - addr) * 32 + res;
 433}
 434
 435static inline int ext2_find_next_bit(const void *vaddr, unsigned size,
 436                                     unsigned offset)
 437{
 438        const unsigned long *addr = vaddr;
 439        const unsigned long *p = addr + (offset >> 5);
 440        int bit = offset & 31UL, res;
 441
 442        if (offset >= size)
 443                return size;
 444
 445        if (bit) {
 446                /* Look for one in first longword */
 447                for (res = bit; res < 32; res++)
 448                        if (ext2_test_bit(res, p))
 449                                return (p - addr) * 32 + res;
 450                p++;
 451        }
 452        /* No set bit yet, search remaining full bytes for a set bit */
 453        res = ext2_find_first_bit(p, size - 32 * (p - addr));
 454        return (p - addr) * 32 + res;
 455}
 456
 457#endif /* __KERNEL__ */
 458
 459#endif /* _M68K_BITOPS_H */
 460
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.