linux/arch/sh/include/asm/bitops-op32.h
<<
>>
Prefs
   1#ifndef __ASM_SH_BITOPS_OP32_H
   2#define __ASM_SH_BITOPS_OP32_H
   3
   4/*
   5 * The bit modifying instructions on SH-2A are only capable of working
   6 * with a 3-bit immediate, which signifies the shift position for the bit
   7 * being worked on.
   8 */
   9#if defined(__BIG_ENDIAN)
  10#define BITOP_LE_SWIZZLE        ((BITS_PER_LONG-1) & ~0x7)
  11#define BYTE_NUMBER(nr)         ((nr ^ BITOP_LE_SWIZZLE) / BITS_PER_BYTE)
  12#define BYTE_OFFSET(nr)         ((nr ^ BITOP_LE_SWIZZLE) % BITS_PER_BYTE)
  13#else
  14#define BYTE_NUMBER(nr)         ((nr) / BITS_PER_BYTE)
  15#define BYTE_OFFSET(nr)         ((nr) % BITS_PER_BYTE)
  16#endif
  17
  18#define IS_IMMEDIATE(nr)        (__builtin_constant_p(nr))
  19
  20static inline void __set_bit(int nr, volatile unsigned long *addr)
  21{
  22        if (IS_IMMEDIATE(nr)) {
  23                __asm__ __volatile__ (
  24                        "bset.b %1, @(%O2,%0)           ! __set_bit\n\t"
  25                        : "+r" (addr)
  26                        : "i" (BYTE_OFFSET(nr)), "i" (BYTE_NUMBER(nr))
  27                        : "t", "memory"
  28                );
  29        } else {
  30                unsigned long mask = BIT_MASK(nr);
  31                unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
  32
  33                *p |= mask;
  34        }
  35}
  36
  37static inline void __clear_bit(int nr, volatile unsigned long *addr)
  38{
  39        if (IS_IMMEDIATE(nr)) {
  40                __asm__ __volatile__ (
  41                        "bclr.b %1, @(%O2,%0)           ! __clear_bit\n\t"
  42                        : "+r" (addr)
  43                        : "i" (BYTE_OFFSET(nr)),
  44                          "i" (BYTE_NUMBER(nr))
  45                        : "t", "memory"
  46                );
  47        } else {
  48                unsigned long mask = BIT_MASK(nr);
  49                unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
  50
  51                *p &= ~mask;
  52        }
  53}
  54
  55/**
  56 * __change_bit - Toggle a bit in memory
  57 * @nr: the bit to change
  58 * @addr: the address to start counting from
  59 *
  60 * Unlike change_bit(), this function is non-atomic and may be reordered.
  61 * If it's called on the same region of memory simultaneously, the effect
  62 * may be that only one operation succeeds.
  63 */
  64static inline void __change_bit(int nr, volatile unsigned long *addr)
  65{
  66        if (IS_IMMEDIATE(nr)) {
  67                __asm__ __volatile__ (
  68                        "bxor.b %1, @(%O2,%0)           ! __change_bit\n\t"
  69                        : "+r" (addr)
  70                        : "i" (BYTE_OFFSET(nr)),
  71                          "i" (BYTE_NUMBER(nr))
  72                        : "t", "memory"
  73                );
  74        } else {
  75                unsigned long mask = BIT_MASK(nr);
  76                unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
  77
  78                *p ^= mask;
  79        }
  80}
  81
  82/**
  83 * __test_and_set_bit - Set a bit and return its old value
  84 * @nr: Bit to set
  85 * @addr: Address to count from
  86 *
  87 * This operation is non-atomic and can be reordered.
  88 * If two examples of this operation race, one can appear to succeed
  89 * but actually fail.  You must protect multiple accesses with a lock.
  90 */
  91static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
  92{
  93        unsigned long mask = BIT_MASK(nr);
  94        unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
  95        unsigned long old = *p;
  96
  97        *p = old | mask;
  98        return (old & mask) != 0;
  99}
 100
 101/**
 102 * __test_and_clear_bit - Clear a bit and return its old value
 103 * @nr: Bit to clear
 104 * @addr: Address to count from
 105 *
 106 * This operation is non-atomic and can be reordered.
 107 * If two examples of this operation race, one can appear to succeed
 108 * but actually fail.  You must protect multiple accesses with a lock.
 109 */
 110static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
 111{
 112        unsigned long mask = BIT_MASK(nr);
 113        unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
 114        unsigned long old = *p;
 115
 116        *p = old & ~mask;
 117        return (old & mask) != 0;
 118}
 119
 120/* WARNING: non atomic and it can be reordered! */
 121static inline int __test_and_change_bit(int nr,
 122                                            volatile unsigned long *addr)
 123{
 124        unsigned long mask = BIT_MASK(nr);
 125        unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
 126        unsigned long old = *p;
 127
 128        *p = old ^ mask;
 129        return (old & mask) != 0;
 130}
 131
 132/**
 133 * test_bit - Determine whether a bit is set
 134 * @nr: bit number to test
 135 * @addr: Address to start counting from
 136 */
 137static inline int test_bit(int nr, const volatile unsigned long *addr)
 138{
 139        return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
 140}
 141
 142#endif /* __ASM_SH_BITOPS_OP32_H */
 143