linux/arch/m68k/include/asm/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#include <asm/barrier.h>
  17
  18/*
  19 *      Bit access functions vary across the ColdFire and 68k families.
  20 *      So we will break them out here, and then macro in the ones we want.
  21 *
  22 *      ColdFire - supports standard bset/bclr/bchg with register operand only
  23 *      68000    - supports standard bset/bclr/bchg with memory operand
  24 *      >= 68020 - also supports the bfset/bfclr/bfchg instructions
  25 *
  26 *      Although it is possible to use only the bset/bclr/bchg with register
  27 *      operands on all platforms you end up with larger generated code.
  28 *      So we use the best form possible on a given platform.
  29 */
  30
  31static inline void bset_reg_set_bit(int nr, volatile unsigned long *vaddr)
  32{
  33        char *p = (char *)vaddr + (nr ^ 31) / 8;
  34
  35        __asm__ __volatile__ ("bset %1,(%0)"
  36                :
  37                : "a" (p), "di" (nr & 7)
  38                : "memory");
  39}
  40
  41static inline void bset_mem_set_bit(int nr, volatile unsigned long *vaddr)
  42{
  43        char *p = (char *)vaddr + (nr ^ 31) / 8;
  44
  45        __asm__ __volatile__ ("bset %1,%0"
  46                : "+m" (*p)
  47                : "di" (nr & 7));
  48}
  49
  50static inline void bfset_mem_set_bit(int nr, volatile unsigned long *vaddr)
  51{
  52        __asm__ __volatile__ ("bfset %1{%0:#1}"
  53                :
  54                : "d" (nr ^ 31), "o" (*vaddr)
  55                : "memory");
  56}
  57
  58#if defined(CONFIG_COLDFIRE)
  59#define set_bit(nr, vaddr)      bset_reg_set_bit(nr, vaddr)
  60#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
  61#define set_bit(nr, vaddr)      bset_mem_set_bit(nr, vaddr)
  62#else
  63#define set_bit(nr, vaddr)      (__builtin_constant_p(nr) ? \
  64                                bset_mem_set_bit(nr, vaddr) : \
  65                                bfset_mem_set_bit(nr, vaddr))
  66#endif
  67
  68#define __set_bit(nr, vaddr)    set_bit(nr, vaddr)
  69
  70
  71static inline void bclr_reg_clear_bit(int nr, volatile unsigned long *vaddr)
  72{
  73        char *p = (char *)vaddr + (nr ^ 31) / 8;
  74
  75        __asm__ __volatile__ ("bclr %1,(%0)"
  76                :
  77                : "a" (p), "di" (nr & 7)
  78                : "memory");
  79}
  80
  81static inline void bclr_mem_clear_bit(int nr, volatile unsigned long *vaddr)
  82{
  83        char *p = (char *)vaddr + (nr ^ 31) / 8;
  84
  85        __asm__ __volatile__ ("bclr %1,%0"
  86                : "+m" (*p)
  87                : "di" (nr & 7));
  88}
  89
  90static inline void bfclr_mem_clear_bit(int nr, volatile unsigned long *vaddr)
  91{
  92        __asm__ __volatile__ ("bfclr %1{%0:#1}"
  93                :
  94                : "d" (nr ^ 31), "o" (*vaddr)
  95                : "memory");
  96}
  97
  98#if defined(CONFIG_COLDFIRE)
  99#define clear_bit(nr, vaddr)    bclr_reg_clear_bit(nr, vaddr)
 100#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
 101#define clear_bit(nr, vaddr)    bclr_mem_clear_bit(nr, vaddr)
 102#else
 103#define clear_bit(nr, vaddr)    (__builtin_constant_p(nr) ? \
 104                                bclr_mem_clear_bit(nr, vaddr) : \
 105                                bfclr_mem_clear_bit(nr, vaddr))
 106#endif
 107
 108#define __clear_bit(nr, vaddr)  clear_bit(nr, vaddr)
 109
 110
 111static inline void bchg_reg_change_bit(int nr, volatile unsigned long *vaddr)
 112{
 113        char *p = (char *)vaddr + (nr ^ 31) / 8;
 114
 115        __asm__ __volatile__ ("bchg %1,(%0)"
 116                :
 117                : "a" (p), "di" (nr & 7)
 118                : "memory");
 119}
 120
 121static inline void bchg_mem_change_bit(int nr, volatile unsigned long *vaddr)
 122{
 123        char *p = (char *)vaddr + (nr ^ 31) / 8;
 124
 125        __asm__ __volatile__ ("bchg %1,%0"
 126                : "+m" (*p)
 127                : "di" (nr & 7));
 128}
 129
 130static inline void bfchg_mem_change_bit(int nr, volatile unsigned long *vaddr)
 131{
 132        __asm__ __volatile__ ("bfchg %1{%0:#1}"
 133                :
 134                : "d" (nr ^ 31), "o" (*vaddr)
 135                : "memory");
 136}
 137
 138#if defined(CONFIG_COLDFIRE)
 139#define change_bit(nr, vaddr)   bchg_reg_change_bit(nr, vaddr)
 140#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
 141#define change_bit(nr, vaddr)   bchg_mem_change_bit(nr, vaddr)
 142#else
 143#define change_bit(nr, vaddr)   (__builtin_constant_p(nr) ? \
 144                                bchg_mem_change_bit(nr, vaddr) : \
 145                                bfchg_mem_change_bit(nr, vaddr))
 146#endif
 147
 148#define __change_bit(nr, vaddr) change_bit(nr, vaddr)
 149
 150
 151static inline int test_bit(int nr, const unsigned long *vaddr)
 152{
 153        return (vaddr[nr >> 5] & (1UL << (nr & 31))) != 0;
 154}
 155
 156
 157static inline int bset_reg_test_and_set_bit(int nr,
 158                                            volatile unsigned long *vaddr)
 159{
 160        char *p = (char *)vaddr + (nr ^ 31) / 8;
 161        char retval;
 162
 163        __asm__ __volatile__ ("bset %2,(%1); sne %0"
 164                : "=d" (retval)
 165                : "a" (p), "di" (nr & 7)
 166                : "memory");
 167        return retval;
 168}
 169
 170static inline int bset_mem_test_and_set_bit(int nr,
 171                                            volatile unsigned long *vaddr)
 172{
 173        char *p = (char *)vaddr + (nr ^ 31) / 8;
 174        char retval;
 175
 176        __asm__ __volatile__ ("bset %2,%1; sne %0"
 177                : "=d" (retval), "+m" (*p)
 178                : "di" (nr & 7));
 179        return retval;
 180}
 181
 182static inline int bfset_mem_test_and_set_bit(int nr,
 183                                             volatile unsigned long *vaddr)
 184{
 185        char retval;
 186
 187        __asm__ __volatile__ ("bfset %2{%1:#1}; sne %0"
 188                : "=d" (retval)
 189                : "d" (nr ^ 31), "o" (*vaddr)
 190                : "memory");
 191        return retval;
 192}
 193
 194#if defined(CONFIG_COLDFIRE)
 195#define test_and_set_bit(nr, vaddr)     bset_reg_test_and_set_bit(nr, vaddr)
 196#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
 197#define test_and_set_bit(nr, vaddr)     bset_mem_test_and_set_bit(nr, vaddr)
 198#else
 199#define test_and_set_bit(nr, vaddr)     (__builtin_constant_p(nr) ? \
 200                                        bset_mem_test_and_set_bit(nr, vaddr) : \
 201                                        bfset_mem_test_and_set_bit(nr, vaddr))
 202#endif
 203
 204#define __test_and_set_bit(nr, vaddr)   test_and_set_bit(nr, vaddr)
 205
 206
 207static inline int bclr_reg_test_and_clear_bit(int nr,
 208                                              volatile unsigned long *vaddr)
 209{
 210        char *p = (char *)vaddr + (nr ^ 31) / 8;
 211        char retval;
 212
 213        __asm__ __volatile__ ("bclr %2,(%1); sne %0"
 214                : "=d" (retval)
 215                : "a" (p), "di" (nr & 7)
 216                : "memory");
 217        return retval;
 218}
 219
 220static inline int bclr_mem_test_and_clear_bit(int nr,
 221                                              volatile unsigned long *vaddr)
 222{
 223        char *p = (char *)vaddr + (nr ^ 31) / 8;
 224        char retval;
 225
 226        __asm__ __volatile__ ("bclr %2,%1; sne %0"
 227                : "=d" (retval), "+m" (*p)
 228                : "di" (nr & 7));
 229        return retval;
 230}
 231
 232static inline int bfclr_mem_test_and_clear_bit(int nr,
 233                                               volatile unsigned long *vaddr)
 234{
 235        char retval;
 236
 237        __asm__ __volatile__ ("bfclr %2{%1:#1}; sne %0"
 238                : "=d" (retval)
 239                : "d" (nr ^ 31), "o" (*vaddr)
 240                : "memory");
 241        return retval;
 242}
 243
 244#if defined(CONFIG_COLDFIRE)
 245#define test_and_clear_bit(nr, vaddr)   bclr_reg_test_and_clear_bit(nr, vaddr)
 246#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
 247#define test_and_clear_bit(nr, vaddr)   bclr_mem_test_and_clear_bit(nr, vaddr)
 248#else
 249#define test_and_clear_bit(nr, vaddr)   (__builtin_constant_p(nr) ? \
 250                                        bclr_mem_test_and_clear_bit(nr, vaddr) : \
 251                                        bfclr_mem_test_and_clear_bit(nr, vaddr))
 252#endif
 253
 254#define __test_and_clear_bit(nr, vaddr) test_and_clear_bit(nr, vaddr)
 255
 256
 257static inline int bchg_reg_test_and_change_bit(int nr,
 258                                               volatile unsigned long *vaddr)
 259{
 260        char *p = (char *)vaddr + (nr ^ 31) / 8;
 261        char retval;
 262
 263        __asm__ __volatile__ ("bchg %2,(%1); sne %0"
 264                : "=d" (retval)
 265                : "a" (p), "di" (nr & 7)
 266                : "memory");
 267        return retval;
 268}
 269
 270static inline int bchg_mem_test_and_change_bit(int nr,
 271                                               volatile unsigned long *vaddr)
 272{
 273        char *p = (char *)vaddr + (nr ^ 31) / 8;
 274        char retval;
 275
 276        __asm__ __volatile__ ("bchg %2,%1; sne %0"
 277                : "=d" (retval), "+m" (*p)
 278                : "di" (nr & 7));
 279        return retval;
 280}
 281
 282static inline int bfchg_mem_test_and_change_bit(int nr,
 283                                                volatile unsigned long *vaddr)
 284{
 285        char retval;
 286
 287        __asm__ __volatile__ ("bfchg %2{%1:#1}; sne %0"
 288                : "=d" (retval)
 289                : "d" (nr ^ 31), "o" (*vaddr)
 290                : "memory");
 291        return retval;
 292}
 293
 294#if defined(CONFIG_COLDFIRE)
 295#define test_and_change_bit(nr, vaddr)  bchg_reg_test_and_change_bit(nr, vaddr)
 296#elif defined(CONFIG_CPU_HAS_NO_BITFIELDS)
 297#define test_and_change_bit(nr, vaddr)  bchg_mem_test_and_change_bit(nr, vaddr)
 298#else
 299#define test_and_change_bit(nr, vaddr)  (__builtin_constant_p(nr) ? \
 300                                        bchg_mem_test_and_change_bit(nr, vaddr) : \
 301                                        bfchg_mem_test_and_change_bit(nr, vaddr))
 302#endif
 303
 304#define __test_and_change_bit(nr, vaddr) test_and_change_bit(nr, vaddr)
 305
 306
 307/*
 308 *      The true 68020 and more advanced processors support the "bfffo"
 309 *      instruction for finding bits. ColdFire and simple 68000 parts
 310 *      (including CPU32) do not support this. They simply use the generic
 311 *      functions.
 312 */
 313#if defined(CONFIG_CPU_HAS_NO_BITFIELDS)
 314#include <asm-generic/bitops/find.h>
 315#include <asm-generic/bitops/ffz.h>
 316#else
 317
 318static inline int find_first_zero_bit(const unsigned long *vaddr,
 319                                      unsigned size)
 320{
 321        const unsigned long *p = vaddr;
 322        int res = 32;
 323        unsigned int words;
 324        unsigned long num;
 325
 326        if (!size)
 327                return 0;
 328
 329        words = (size + 31) >> 5;
 330        while (!(num = ~*p++)) {
 331                if (!--words)
 332                        goto out;
 333        }
 334
 335        __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
 336                              : "=d" (res) : "d" (num & -num));
 337        res ^= 31;
 338out:
 339        res += ((long)p - (long)vaddr - 4) * 8;
 340        return res < size ? res : size;
 341}
 342#define find_first_zero_bit find_first_zero_bit
 343
 344static inline int find_next_zero_bit(const unsigned long *vaddr, int size,
 345                                     int offset)
 346{
 347        const unsigned long *p = vaddr + (offset >> 5);
 348        int bit = offset & 31UL, res;
 349
 350        if (offset >= size)
 351                return size;
 352
 353        if (bit) {
 354                unsigned long num = ~*p++ & (~0UL << bit);
 355                offset -= bit;
 356
 357                /* Look for zero in first longword */
 358                __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
 359                                      : "=d" (res) : "d" (num & -num));
 360                if (res < 32) {
 361                        offset += res ^ 31;
 362                        return offset < size ? offset : size;
 363                }
 364                offset += 32;
 365
 366                if (offset >= size)
 367                        return size;
 368        }
 369        /* No zero yet, search remaining full bytes for a zero */
 370        return offset + find_first_zero_bit(p, size - offset);
 371}
 372#define find_next_zero_bit find_next_zero_bit
 373
 374static inline int find_first_bit(const unsigned long *vaddr, unsigned size)
 375{
 376        const unsigned long *p = vaddr;
 377        int res = 32;
 378        unsigned int words;
 379        unsigned long num;
 380
 381        if (!size)
 382                return 0;
 383
 384        words = (size + 31) >> 5;
 385        while (!(num = *p++)) {
 386                if (!--words)
 387                        goto out;
 388        }
 389
 390        __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
 391                              : "=d" (res) : "d" (num & -num));
 392        res ^= 31;
 393out:
 394        res += ((long)p - (long)vaddr - 4) * 8;
 395        return res < size ? res : size;
 396}
 397#define find_first_bit find_first_bit
 398
 399static inline int find_next_bit(const unsigned long *vaddr, int size,
 400                                int offset)
 401{
 402        const unsigned long *p = vaddr + (offset >> 5);
 403        int bit = offset & 31UL, res;
 404
 405        if (offset >= size)
 406                return size;
 407
 408        if (bit) {
 409                unsigned long num = *p++ & (~0UL << bit);
 410                offset -= bit;
 411
 412                /* Look for one in first longword */
 413                __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
 414                                      : "=d" (res) : "d" (num & -num));
 415                if (res < 32) {
 416                        offset += res ^ 31;
 417                        return offset < size ? offset : size;
 418                }
 419                offset += 32;
 420
 421                if (offset >= size)
 422                        return size;
 423        }
 424        /* No one yet, search remaining full bytes for a one */
 425        return offset + find_first_bit(p, size - offset);
 426}
 427#define find_next_bit find_next_bit
 428
 429/*
 430 * ffz = Find First Zero in word. Undefined if no zero exists,
 431 * so code should check against ~0UL first..
 432 */
 433static inline unsigned long ffz(unsigned long word)
 434{
 435        int res;
 436
 437        __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
 438                              : "=d" (res) : "d" (~word & -~word));
 439        return res ^ 31;
 440}
 441
 442#endif
 443
 444#ifdef __KERNEL__
 445
 446#if defined(CONFIG_CPU_HAS_NO_BITFIELDS)
 447
 448/*
 449 *      The newer ColdFire family members support a "bitrev" instruction
 450 *      and we can use that to implement a fast ffs. Older Coldfire parts,
 451 *      and normal 68000 parts don't have anything special, so we use the
 452 *      generic functions for those.
 453 */
 454#if (defined(__mcfisaaplus__) || defined(__mcfisac__)) && \
 455        !defined(CONFIG_M68000) && !defined(CONFIG_MCPU32)
 456static inline int __ffs(int x)
 457{
 458        __asm__ __volatile__ ("bitrev %0; ff1 %0"
 459                : "=d" (x)
 460                : "0" (x));
 461        return x;
 462}
 463
 464static inline int ffs(int x)
 465{
 466        if (!x)
 467                return 0;
 468        return __ffs(x) + 1;
 469}
 470
 471#else
 472#include <asm-generic/bitops/ffs.h>
 473#include <asm-generic/bitops/__ffs.h>
 474#endif
 475
 476#include <asm-generic/bitops/fls.h>
 477#include <asm-generic/bitops/__fls.h>
 478
 479#else
 480
 481/*
 482 *      ffs: find first bit set. This is defined the same way as
 483 *      the libc and compiler builtin ffs routines, therefore
 484 *      differs in spirit from the above ffz (man ffs).
 485 */
 486static inline int ffs(int x)
 487{
 488        int cnt;
 489
 490        __asm__ ("bfffo %1{#0:#0},%0"
 491                : "=d" (cnt)
 492                : "dm" (x & -x));
 493        return 32 - cnt;
 494}
 495#define __ffs(x) (ffs(x) - 1)
 496
 497/*
 498 *      fls: find last bit set.
 499 */
 500static inline int fls(int x)
 501{
 502        int cnt;
 503
 504        __asm__ ("bfffo %1{#0,#0},%0"
 505                : "=d" (cnt)
 506                : "dm" (x));
 507        return 32 - cnt;
 508}
 509
 510static inline int __fls(int x)
 511{
 512        return fls(x) - 1;
 513}
 514
 515#endif
 516
 517#include <asm-generic/bitops/ext2-atomic.h>
 518#include <asm-generic/bitops/le.h>
 519#include <asm-generic/bitops/fls64.h>
 520#include <asm-generic/bitops/sched.h>
 521#include <asm-generic/bitops/hweight.h>
 522#include <asm-generic/bitops/lock.h>
 523#endif /* __KERNEL__ */
 524
 525#endif /* _M68K_BITOPS_H */
 526