linux/arch/m68k/include/asm/bitops_mm.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
 318static inline int __fls(int x)
 319{
 320        return fls(x) - 1;
 321}
 322
 323#include <asm-generic/bitops/fls64.h>
 324#include <asm-generic/bitops/sched.h>
 325#include <asm-generic/bitops/hweight.h>
 326#include <asm-generic/bitops/lock.h>
 327
 328/* Bitmap functions for the minix filesystem */
 329
 330static inline int minix_find_first_zero_bit(const void *vaddr, unsigned size)
 331{
 332        const unsigned short *p = vaddr, *addr = vaddr;
 333        int res;
 334        unsigned short num;
 335
 336        if (!size)
 337                return 0;
 338
 339        size = (size >> 4) + ((size & 15) > 0);
 340        while (*p++ == 0xffff)
 341        {
 342                if (--size == 0)
 343                        return (p - addr) << 4;
 344        }
 345
 346        num = ~*--p;
 347        __asm__ __volatile__ ("bfffo %1{#16,#16},%0"
 348                              : "=d" (res) : "d" (num & -num));
 349        return ((p - addr) << 4) + (res ^ 31);
 350}
 351
 352#define minix_test_and_set_bit(nr, addr)        __test_and_set_bit((nr) ^ 16, (unsigned long *)(addr))
 353#define minix_set_bit(nr,addr)                  __set_bit((nr) ^ 16, (unsigned long *)(addr))
 354#define minix_test_and_clear_bit(nr, addr)      __test_and_clear_bit((nr) ^ 16, (unsigned long *)(addr))
 355
 356static inline int minix_test_bit(int nr, const void *vaddr)
 357{
 358        const unsigned short *p = vaddr;
 359        return (p[nr >> 4] & (1U << (nr & 15))) != 0;
 360}
 361
 362/* Bitmap functions for the ext2 filesystem. */
 363
 364#define ext2_set_bit(nr, addr)                  __test_and_set_bit((nr) ^ 24, (unsigned long *)(addr))
 365#define ext2_set_bit_atomic(lock, nr, addr)     test_and_set_bit((nr) ^ 24, (unsigned long *)(addr))
 366#define ext2_clear_bit(nr, addr)                __test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr))
 367#define ext2_clear_bit_atomic(lock, nr, addr)   test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr))
 368#define ext2_find_next_zero_bit(addr, size, offset) \
 369        generic_find_next_zero_le_bit((unsigned long *)addr, size, offset)
 370#define ext2_find_next_bit(addr, size, offset) \
 371        generic_find_next_le_bit((unsigned long *)addr, size, offset)
 372
 373static inline int ext2_test_bit(int nr, const void *vaddr)
 374{
 375        const unsigned char *p = vaddr;
 376        return (p[nr >> 3] & (1U << (nr & 7))) != 0;
 377}
 378
 379static inline int ext2_find_first_zero_bit(const void *vaddr, unsigned size)
 380{
 381        const unsigned long *p = vaddr, *addr = vaddr;
 382        int res;
 383
 384        if (!size)
 385                return 0;
 386
 387        size = (size >> 5) + ((size & 31) > 0);
 388        while (*p++ == ~0UL)
 389        {
 390                if (--size == 0)
 391                        return (p - addr) << 5;
 392        }
 393
 394        --p;
 395        for (res = 0; res < 32; res++)
 396                if (!ext2_test_bit (res, p))
 397                        break;
 398        return (p - addr) * 32 + res;
 399}
 400
 401static inline unsigned long generic_find_next_zero_le_bit(const unsigned long *addr,
 402                unsigned long size, unsigned long offset)
 403{
 404        const unsigned long *p = addr + (offset >> 5);
 405        int bit = offset & 31UL, res;
 406
 407        if (offset >= size)
 408                return size;
 409
 410        if (bit) {
 411                /* Look for zero in first longword */
 412                for (res = bit; res < 32; res++)
 413                        if (!ext2_test_bit (res, p))
 414                                return (p - addr) * 32 + res;
 415                p++;
 416        }
 417        /* No zero yet, search remaining full bytes for a zero */
 418        res = ext2_find_first_zero_bit (p, size - 32 * (p - addr));
 419        return (p - addr) * 32 + res;
 420}
 421
 422static inline int ext2_find_first_bit(const void *vaddr, unsigned size)
 423{
 424        const unsigned long *p = vaddr, *addr = vaddr;
 425        int res;
 426
 427        if (!size)
 428                return 0;
 429
 430        size = (size >> 5) + ((size & 31) > 0);
 431        while (*p++ == 0UL) {
 432                if (--size == 0)
 433                        return (p - addr) << 5;
 434        }
 435
 436        --p;
 437        for (res = 0; res < 32; res++)
 438                if (ext2_test_bit(res, p))
 439                        break;
 440        return (p - addr) * 32 + res;
 441}
 442
 443static inline unsigned long generic_find_next_le_bit(const unsigned long *addr,
 444                unsigned long size, unsigned long offset)
 445{
 446        const unsigned long *p = addr + (offset >> 5);
 447        int bit = offset & 31UL, res;
 448
 449        if (offset >= size)
 450                return size;
 451
 452        if (bit) {
 453                /* Look for one in first longword */
 454                for (res = bit; res < 32; res++)
 455                        if (ext2_test_bit(res, p))
 456                                return (p - addr) * 32 + res;
 457                p++;
 458        }
 459        /* No set bit yet, search remaining full bytes for a set bit */
 460        res = ext2_find_first_bit(p, size - 32 * (p - addr));
 461        return (p - addr) * 32 + res;
 462}
 463
 464#endif /* __KERNEL__ */
 465
 466#endif /* _M68K_BITOPS_H */
 467
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.