linux/arch/m32r/include/asm/bitops.h
<<
>>
Prefs
   1#ifndef _ASM_M32R_BITOPS_H
   2#define _ASM_M32R_BITOPS_H
   3
   4/*
   5 *  linux/include/asm-m32r/bitops.h
   6 *
   7 *  Copyright 1992, Linus Torvalds.
   8 *
   9 *  M32R version:
  10 *    Copyright (C) 2001, 2002  Hitoshi Yamamoto
  11 *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
  12 */
  13
  14#ifndef _LINUX_BITOPS_H
  15#error only <linux/bitops.h> can be included directly
  16#endif
  17
  18#include <linux/compiler.h>
  19#include <linux/irqflags.h>
  20#include <asm/assembler.h>
  21#include <asm/byteorder.h>
  22#include <asm/dcache_clear.h>
  23#include <asm/types.h>
  24#include <asm/barrier.h>
  25
  26/*
  27 * These have to be done with inline assembly: that way the bit-setting
  28 * is guaranteed to be atomic. All bit operations return 0 if the bit
  29 * was cleared before the operation and != 0 if it was not.
  30 *
  31 * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
  32 */
  33
  34/**
  35 * set_bit - Atomically set a bit in memory
  36 * @nr: the bit to set
  37 * @addr: the address to start counting from
  38 *
  39 * This function is atomic and may not be reordered.  See __set_bit()
  40 * if you do not require the atomic guarantees.
  41 * Note that @nr may be almost arbitrarily large; this function is not
  42 * restricted to acting on a single-word quantity.
  43 */
  44static __inline__ void set_bit(int nr, volatile void * addr)
  45{
  46        __u32 mask;
  47        volatile __u32 *a = addr;
  48        unsigned long flags;
  49        unsigned long tmp;
  50
  51        a += (nr >> 5);
  52        mask = (1 << (nr & 0x1F));
  53
  54        local_irq_save(flags);
  55        __asm__ __volatile__ (
  56                DCACHE_CLEAR("%0", "r6", "%1")
  57                M32R_LOCK" %0, @%1;             \n\t"
  58                "or     %0, %2;                 \n\t"
  59                M32R_UNLOCK" %0, @%1;           \n\t"
  60                : "=&r" (tmp)
  61                : "r" (a), "r" (mask)
  62                : "memory"
  63#ifdef CONFIG_CHIP_M32700_TS1
  64                , "r6"
  65#endif  /* CONFIG_CHIP_M32700_TS1 */
  66        );
  67        local_irq_restore(flags);
  68}
  69
  70/**
  71 * clear_bit - Clears a bit in memory
  72 * @nr: Bit to clear
  73 * @addr: Address to start counting from
  74 *
  75 * clear_bit() is atomic and may not be reordered.  However, it does
  76 * not contain a memory barrier, so if it is used for locking purposes,
  77 * you should call smp_mb__before_atomic() and/or smp_mb__after_atomic()
  78 * in order to ensure changes are visible on other processors.
  79 */
  80static __inline__ void clear_bit(int nr, volatile void * addr)
  81{
  82        __u32 mask;
  83        volatile __u32 *a = addr;
  84        unsigned long flags;
  85        unsigned long tmp;
  86
  87        a += (nr >> 5);
  88        mask = (1 << (nr & 0x1F));
  89
  90        local_irq_save(flags);
  91
  92        __asm__ __volatile__ (
  93                DCACHE_CLEAR("%0", "r6", "%1")
  94                M32R_LOCK" %0, @%1;             \n\t"
  95                "and    %0, %2;                 \n\t"
  96                M32R_UNLOCK" %0, @%1;           \n\t"
  97                : "=&r" (tmp)
  98                : "r" (a), "r" (~mask)
  99                : "memory"
 100#ifdef CONFIG_CHIP_M32700_TS1
 101                , "r6"
 102#endif  /* CONFIG_CHIP_M32700_TS1 */
 103        );
 104        local_irq_restore(flags);
 105}
 106
 107/**
 108 * change_bit - Toggle a bit in memory
 109 * @nr: Bit to clear
 110 * @addr: Address to start counting from
 111 *
 112 * change_bit() is atomic and may not be reordered.
 113 * Note that @nr may be almost arbitrarily large; this function is not
 114 * restricted to acting on a single-word quantity.
 115 */
 116static __inline__ void change_bit(int nr, volatile void * addr)
 117{
 118        __u32  mask;
 119        volatile __u32  *a = addr;
 120        unsigned long flags;
 121        unsigned long tmp;
 122
 123        a += (nr >> 5);
 124        mask = (1 << (nr & 0x1F));
 125
 126        local_irq_save(flags);
 127        __asm__ __volatile__ (
 128                DCACHE_CLEAR("%0", "r6", "%1")
 129                M32R_LOCK" %0, @%1;             \n\t"
 130                "xor    %0, %2;                 \n\t"
 131                M32R_UNLOCK" %0, @%1;           \n\t"
 132                : "=&r" (tmp)
 133                : "r" (a), "r" (mask)
 134                : "memory"
 135#ifdef CONFIG_CHIP_M32700_TS1
 136                , "r6"
 137#endif  /* CONFIG_CHIP_M32700_TS1 */
 138        );
 139        local_irq_restore(flags);
 140}
 141
 142/**
 143 * test_and_set_bit - Set a bit and return its old value
 144 * @nr: Bit to set
 145 * @addr: Address to count from
 146 *
 147 * This operation is atomic and cannot be reordered.
 148 * It also implies a memory barrier.
 149 */
 150static __inline__ int test_and_set_bit(int nr, volatile void * addr)
 151{
 152        __u32 mask, oldbit;
 153        volatile __u32 *a = addr;
 154        unsigned long flags;
 155        unsigned long tmp;
 156
 157        a += (nr >> 5);
 158        mask = (1 << (nr & 0x1F));
 159
 160        local_irq_save(flags);
 161        __asm__ __volatile__ (
 162                DCACHE_CLEAR("%0", "%1", "%2")
 163                M32R_LOCK" %0, @%2;             \n\t"
 164                "mv     %1, %0;                 \n\t"
 165                "and    %0, %3;                 \n\t"
 166                "or     %1, %3;                 \n\t"
 167                M32R_UNLOCK" %1, @%2;           \n\t"
 168                : "=&r" (oldbit), "=&r" (tmp)
 169                : "r" (a), "r" (mask)
 170                : "memory"
 171        );
 172        local_irq_restore(flags);
 173
 174        return (oldbit != 0);
 175}
 176
 177/**
 178 * test_and_clear_bit - Clear a bit and return its old value
 179 * @nr: Bit to set
 180 * @addr: Address to count from
 181 *
 182 * This operation is atomic and cannot be reordered.
 183 * It also implies a memory barrier.
 184 */
 185static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
 186{
 187        __u32 mask, oldbit;
 188        volatile __u32 *a = addr;
 189        unsigned long flags;
 190        unsigned long tmp;
 191
 192        a += (nr >> 5);
 193        mask = (1 << (nr & 0x1F));
 194
 195        local_irq_save(flags);
 196
 197        __asm__ __volatile__ (
 198                DCACHE_CLEAR("%0", "%1", "%3")
 199                M32R_LOCK" %0, @%3;             \n\t"
 200                "mv     %1, %0;                 \n\t"
 201                "and    %0, %2;                 \n\t"
 202                "not    %2, %2;                 \n\t"
 203                "and    %1, %2;                 \n\t"
 204                M32R_UNLOCK" %1, @%3;           \n\t"
 205                : "=&r" (oldbit), "=&r" (tmp), "+r" (mask)
 206                : "r" (a)
 207                : "memory"
 208        );
 209        local_irq_restore(flags);
 210
 211        return (oldbit != 0);
 212}
 213
 214/**
 215 * test_and_change_bit - Change a bit and return its old value
 216 * @nr: Bit to set
 217 * @addr: Address to count from
 218 *
 219 * This operation is atomic and cannot be reordered.
 220 * It also implies a memory barrier.
 221 */
 222static __inline__ int test_and_change_bit(int nr, volatile void * addr)
 223{
 224        __u32 mask, oldbit;
 225        volatile __u32 *a = addr;
 226        unsigned long flags;
 227        unsigned long tmp;
 228
 229        a += (nr >> 5);
 230        mask = (1 << (nr & 0x1F));
 231
 232        local_irq_save(flags);
 233        __asm__ __volatile__ (
 234                DCACHE_CLEAR("%0", "%1", "%2")
 235                M32R_LOCK" %0, @%2;             \n\t"
 236                "mv     %1, %0;                 \n\t"
 237                "and    %0, %3;                 \n\t"
 238                "xor    %1, %3;                 \n\t"
 239                M32R_UNLOCK" %1, @%2;           \n\t"
 240                : "=&r" (oldbit), "=&r" (tmp)
 241                : "r" (a), "r" (mask)
 242                : "memory"
 243        );
 244        local_irq_restore(flags);
 245
 246        return (oldbit != 0);
 247}
 248
 249#include <asm-generic/bitops/non-atomic.h>
 250#include <asm-generic/bitops/ffz.h>
 251#include <asm-generic/bitops/__ffs.h>
 252#include <asm-generic/bitops/fls.h>
 253#include <asm-generic/bitops/__fls.h>
 254#include <asm-generic/bitops/fls64.h>
 255
 256#ifdef __KERNEL__
 257
 258#include <asm-generic/bitops/sched.h>
 259#include <asm-generic/bitops/find.h>
 260#include <asm-generic/bitops/ffs.h>
 261#include <asm-generic/bitops/hweight.h>
 262#include <asm-generic/bitops/lock.h>
 263
 264#endif /* __KERNEL__ */
 265
 266#ifdef __KERNEL__
 267
 268#include <asm-generic/bitops/le.h>
 269#include <asm-generic/bitops/ext2-atomic.h>
 270
 271#endif /* __KERNEL__ */
 272
 273#endif /* _ASM_M32R_BITOPS_H */
 274