home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-m32r / bitops.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  6.1 KB  |  270 lines

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