linux/arch/avr32/include/asm/bitops.h
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2004-2006 Atmel Corporation
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 */
   8#ifndef __ASM_AVR32_BITOPS_H
   9#define __ASM_AVR32_BITOPS_H
  10
  11#ifndef _LINUX_BITOPS_H
  12#error only <linux/bitops.h> can be included directly
  13#endif
  14
  15#include <asm/byteorder.h>
  16#include <asm/system.h>
  17
  18/*
  19 * clear_bit() doesn't provide any barrier for the compiler
  20 */
  21#define smp_mb__before_clear_bit()      barrier()
  22#define smp_mb__after_clear_bit()       barrier()
  23
  24/*
  25 * set_bit - Atomically set a bit in memory
  26 * @nr: the bit to set
  27 * @addr: the address to start counting from
  28 *
  29 * This function is atomic and may not be reordered.  See __set_bit()
  30 * if you do not require the atomic guarantees.
  31 *
  32 * Note that @nr may be almost arbitrarily large; this function is not
  33 * restricted to acting on a single-word quantity.
  34 */
  35static inline void set_bit(int nr, volatile void * addr)
  36{
  37        unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
  38        unsigned long tmp;
  39
  40        if (__builtin_constant_p(nr)) {
  41                asm volatile(
  42                        "1:     ssrf    5\n"
  43                        "       ld.w    %0, %2\n"
  44                        "       sbr     %0, %3\n"
  45                        "       stcond  %1, %0\n"
  46                        "       brne    1b"
  47                        : "=&r"(tmp), "=o"(*p)
  48                        : "m"(*p), "i"(nr)
  49                        : "cc");
  50        } else {
  51                unsigned long mask = 1UL << (nr % BITS_PER_LONG);
  52                asm volatile(
  53                        "1:     ssrf    5\n"
  54                        "       ld.w    %0, %2\n"
  55                        "       or      %0, %3\n"
  56                        "       stcond  %1, %0\n"
  57                        "       brne    1b"
  58                        : "=&r"(tmp), "=o"(*p)
  59                        : "m"(*p), "r"(mask)
  60                        : "cc");
  61        }
  62}
  63
  64/*
  65 * clear_bit - Clears a bit in memory
  66 * @nr: Bit to clear
  67 * @addr: Address to start counting from
  68 *
  69 * clear_bit() is atomic and may not be reordered.  However, it does
  70 * not contain a memory barrier, so if it is used for locking purposes,
  71 * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
  72 * in order to ensure changes are visible on other processors.
  73 */
  74static inline void clear_bit(int nr, volatile void * addr)
  75{
  76        unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
  77        unsigned long tmp;
  78
  79        if (__builtin_constant_p(nr)) {
  80                asm volatile(
  81                        "1:     ssrf    5\n"
  82                        "       ld.w    %0, %2\n"
  83                        "       cbr     %0, %3\n"
  84                        "       stcond  %1, %0\n"
  85                        "       brne    1b"
  86                        : "=&r"(tmp), "=o"(*p)
  87                        : "m"(*p), "i"(nr)
  88                        : "cc");
  89        } else {
  90                unsigned long mask = 1UL << (nr % BITS_PER_LONG);
  91                asm volatile(
  92                        "1:     ssrf    5\n"
  93                        "       ld.w    %0, %2\n"
  94                        "       andn    %0, %3\n"
  95                        "       stcond  %1, %0\n"
  96                        "       brne    1b"
  97                        : "=&r"(tmp), "=o"(*p)
  98                        : "m"(*p), "r"(mask)
  99                        : "cc");
 100        }
 101}
 102
 103/*
 104 * change_bit - Toggle a bit in memory
 105 * @nr: Bit to change
 106 * @addr: Address to start counting from
 107 *
 108 * change_bit() is atomic and may not be reordered.
 109 * Note that @nr may be almost arbitrarily large; this function is not
 110 * restricted to acting on a single-word quantity.
 111 */
 112static inline void change_bit(int nr, volatile void * addr)
 113{
 114        unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
 115        unsigned long mask = 1UL << (nr % BITS_PER_LONG);
 116        unsigned long tmp;
 117
 118        asm volatile(
 119                "1:     ssrf    5\n"
 120                "       ld.w    %0, %2\n"
 121                "       eor     %0, %3\n"
 122                "       stcond  %1, %0\n"
 123                "       brne    1b"
 124                : "=&r"(tmp), "=o"(*p)
 125                : "m"(*p), "r"(mask)
 126                : "cc");
 127}
 128
 129/*
 130 * test_and_set_bit - Set a bit and return its old value
 131 * @nr: Bit to set
 132 * @addr: Address to count from
 133 *
 134 * This operation is atomic and cannot be reordered.
 135 * It also implies a memory barrier.
 136 */
 137static inline int test_and_set_bit(int nr, volatile void * addr)
 138{
 139        unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
 140        unsigned long mask = 1UL << (nr % BITS_PER_LONG);
 141        unsigned long tmp, old;
 142
 143        if (__builtin_constant_p(nr)) {
 144                asm volatile(
 145                        "1:     ssrf    5\n"
 146                        "       ld.w    %0, %3\n"
 147                        "       mov     %2, %0\n"
 148                        "       sbr     %0, %4\n"
 149                        "       stcond  %1, %0\n"
 150                        "       brne    1b"
 151                        : "=&r"(tmp), "=o"(*p), "=&r"(old)
 152                        : "m"(*p), "i"(nr)
 153                        : "memory", "cc");
 154        } else {
 155                asm volatile(
 156                        "1:     ssrf    5\n"
 157                        "       ld.w    %2, %3\n"
 158                        "       or      %0, %2, %4\n"
 159                        "       stcond  %1, %0\n"
 160                        "       brne    1b"
 161                        : "=&r"(tmp), "=o"(*p), "=&r"(old)
 162                        : "m"(*p), "r"(mask)
 163                        : "memory", "cc");
 164        }
 165
 166        return (old & mask) != 0;
 167}
 168
 169/*
 170 * test_and_clear_bit - Clear a bit and return its old value
 171 * @nr: Bit to clear
 172 * @addr: Address to count from
 173 *
 174 * This operation is atomic and cannot be reordered.
 175 * It also implies a memory barrier.
 176 */
 177static inline int test_and_clear_bit(int nr, volatile void * addr)
 178{
 179        unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
 180        unsigned long mask = 1UL << (nr % BITS_PER_LONG);
 181        unsigned long tmp, old;
 182
 183        if (__builtin_constant_p(nr)) {
 184                asm volatile(
 185                        "1:     ssrf    5\n"
 186                        "       ld.w    %0, %3\n"
 187                        "       mov     %2, %0\n"
 188                        "       cbr     %0, %4\n"
 189                        "       stcond  %1, %0\n"
 190                        "       brne    1b"
 191                        : "=&r"(tmp), "=o"(*p), "=&r"(old)
 192                        : "m"(*p), "i"(nr)
 193                        : "memory", "cc");
 194        } else {
 195                asm volatile(
 196                        "1:     ssrf    5\n"
 197                        "       ld.w    %0, %3\n"
 198                        "       mov     %2, %0\n"
 199                        "       andn    %0, %4\n"
 200                        "       stcond  %1, %0\n"
 201                        "       brne    1b"
 202                        : "=&r"(tmp), "=o"(*p), "=&r"(old)
 203                        : "m"(*p), "r"(mask)
 204                        : "memory", "cc");
 205        }
 206
 207        return (old & mask) != 0;
 208}
 209
 210/*
 211 * test_and_change_bit - Change a bit and return its old value
 212 * @nr: Bit to change
 213 * @addr: Address to count from
 214 *
 215 * This operation is atomic and cannot be reordered.
 216 * It also implies a memory barrier.
 217 */
 218static inline int test_and_change_bit(int nr, volatile void * addr)
 219{
 220        unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
 221        unsigned long mask = 1UL << (nr % BITS_PER_LONG);
 222        unsigned long tmp, old;
 223
 224        asm volatile(
 225                "1:     ssrf    5\n"
 226                "       ld.w    %2, %3\n"
 227                "       eor     %0, %2, %4\n"
 228                "       stcond  %1, %0\n"
 229                "       brne    1b"
 230                : "=&r"(tmp), "=o"(*p), "=&r"(old)
 231                : "m"(*p), "r"(mask)
 232                : "memory", "cc");
 233
 234        return (old & mask) != 0;
 235}
 236
 237#include <asm-generic/bitops/non-atomic.h>
 238
 239/* Find First bit Set */
 240static inline unsigned long __ffs(unsigned long word)
 241{
 242        unsigned long result;
 243
 244        asm("brev %1\n\t"
 245            "clz %0,%1"
 246            : "=r"(result), "=&r"(word)
 247            : "1"(word));
 248        return result;
 249}
 250
 251/* Find First Zero */
 252static inline unsigned long ffz(unsigned long word)
 253{
 254        return __ffs(~word);
 255}
 256
 257/* Find Last bit Set */
 258static inline int fls(unsigned long word)
 259{
 260        unsigned long result;
 261
 262        asm("clz %0,%1" : "=r"(result) : "r"(word));
 263        return 32 - result;
 264}
 265
 266static inline int __fls(unsigned long word)
 267{
 268        return fls(word) - 1;
 269}
 270
 271unsigned long find_first_zero_bit(const unsigned long *addr,
 272                                  unsigned long size);
 273unsigned long find_next_zero_bit(const unsigned long *addr,
 274                                 unsigned long size,
 275                                 unsigned long offset);
 276unsigned long find_first_bit(const unsigned long *addr,
 277                             unsigned long size);
 278unsigned long find_next_bit(const unsigned long *addr,
 279                                 unsigned long size,
 280                                 unsigned long offset);
 281
 282/*
 283 * ffs: find first bit set. This is defined the same way as
 284 * the libc and compiler builtin ffs routines, therefore
 285 * differs in spirit from the above ffz (man ffs).
 286 *
 287 * The difference is that bit numbering starts at 1, and if no bit is set,
 288 * the function returns 0.
 289 */
 290static inline int ffs(unsigned long word)
 291{
 292        if(word == 0)
 293                return 0;
 294        return __ffs(word) + 1;
 295}
 296
 297#include <asm-generic/bitops/fls64.h>
 298#include <asm-generic/bitops/sched.h>
 299#include <asm-generic/bitops/hweight.h>
 300#include <asm-generic/bitops/lock.h>
 301
 302#include <asm-generic/bitops/ext2-non-atomic.h>
 303#include <asm-generic/bitops/ext2-atomic.h>
 304#include <asm-generic/bitops/minix-le.h>
 305
 306#endif /* __ASM_AVR32_BITOPS_H */
 307