home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / include / asm-mips / bitops.h next >
Encoding:
C/C++ Source or Header  |  1995-01-18  |  4.5 KB  |  249 lines

  1. /*
  2.  * include/asm-mips/bitops.h
  3.  *
  4.  * This file is subject to the terms and conditions of the GNU General Public
  5.  * License.  See the file "COPYING" in the main directory of this archive
  6.  * for more details.
  7.  *
  8.  * Copyright (c) 1994, 1995  Ralf Baechle
  9.  */
  10. #ifndef __ASM_MIPS_BITOPS_H
  11. #define __ASM_MIPS_BITOPS_H
  12.  
  13. #ifdef __R4000__
  14.  
  15. #include <asm/mipsregs.h>
  16.  
  17. /*
  18.  * The following functions will only work for the R4000!
  19.  */
  20. extern __inline__ int set_bit(int nr, void *addr)
  21. {
  22.     int    mask, retval, mw;
  23.  
  24.     addr += ((nr >> 3) & ~3);
  25.     mask = 1 << (nr & 0x1f);
  26.     do {
  27.         mw = load_linked(addr);
  28.         retval = (mask & mw) != 0;
  29.         }
  30.     while (!store_conditional(addr, mw|mask));
  31.  
  32.     return retval;
  33. }
  34.  
  35. extern __inline__ int clear_bit(int nr, void *addr)
  36. {
  37.     int    mask, retval, mw;
  38.  
  39.     addr += ((nr >> 3) & ~3);
  40.     mask = 1 << (nr & 0x1f);
  41.     do {
  42.         mw = load_linked(addr);
  43.         retval = (mask & mw) != 0;
  44.         }
  45.     while (!store_conditional(addr, mw & ~mask));
  46.  
  47.     return retval;
  48. }
  49.  
  50. extern __inline__ int change_bit(int nr, void *addr)
  51. {
  52.     int    mask, retval, mw;
  53.  
  54.     addr += ((nr >> 3) & ~3);
  55.     mask = 1 << (nr & 0x1f);
  56.     do {
  57.         mw = load_linked(addr);
  58.         retval = (mask & mw) != 0;
  59.         }
  60.     while (!store_conditional(addr, mw ^ mask));
  61.  
  62.     return retval;
  63. }
  64.  
  65. #else /* !defined(__R4000__) */
  66.  
  67. #include <asm/system.h>
  68.  
  69. #ifdef __KERNEL__
  70. /*
  71.  * Only disable interrupt for kernelmode stuff to keep some
  72.  * usermode stuff alive
  73.  */
  74. #define __flags unsigned long flags
  75. #define __cli() cli()
  76. #define __save_flags(x) save_flags(x)
  77. #define __restore_flags(x) restore_flags(x)
  78. #endif /* __KERNEL__ */
  79.  
  80. extern __inline__ int set_bit(int nr, void * addr)
  81. {
  82.     int    mask, retval;
  83.     int    *a = addr;
  84.     __flags;
  85.  
  86.     a += nr >> 5;
  87.     mask = 1 << (nr & 0x1f);
  88.     __save_flags(flags);
  89.     __cli();
  90.     retval = (mask & *a) != 0;
  91.     *a |= mask;
  92.     __restore_flags(flags);
  93.  
  94.     return retval;
  95. }
  96.  
  97. extern __inline__ int clear_bit(int nr, void * addr)
  98. {
  99.     int    mask, retval;
  100.     int    *a = addr;
  101.     __flags;
  102.  
  103.     a += nr >> 5;
  104.     mask = 1 << (nr & 0x1f);
  105.     __save_flags(flags);
  106.     __cli();
  107.     retval = (mask & *a) != 0;
  108.     *a &= ~mask;
  109.     __restore_flags(flags);
  110.  
  111.     return retval;
  112. }
  113.  
  114. extern __inline__ int change_bit(int nr, void * addr)
  115. {
  116.     int    mask, retval;
  117.     int    *a = addr;
  118.     __flags;
  119.  
  120.     a += nr >> 5;
  121.     mask = 1 << (nr & 0x1f);
  122.     __save_flags(flags);
  123.     __cli();
  124.     retval = (mask & *a) != 0;
  125.     *a ^= mask;
  126.     __restore_flags(flags);
  127.  
  128.     return retval;
  129. }
  130.  
  131. #undef __flags
  132. #undef __cli()
  133. #undef __save_flags(x)
  134. #undef __restore_flags(x)
  135.  
  136. #endif /* !defined(__R4000__) */
  137.  
  138. extern __inline__ int test_bit(int nr, void *addr)
  139. {
  140.     int    mask;
  141.     unsigned long    *a;
  142.  
  143.     a = addr;
  144.     addr += nr >> 5;
  145.     mask = 1 << (nr & 0x1f);
  146.     return ((mask & *a) != 0);
  147. }
  148.  
  149. extern __inline__ int find_first_zero_bit (void *addr, unsigned size)
  150. {
  151.     int res;
  152.  
  153.     if (!size)
  154.         return 0;
  155.  
  156.     __asm__(".set\tnoreorder\n\t"
  157.         ".set\tnoat\n"
  158.         "1:\tsubu\t$1,%2,%0\n\t"
  159.         "blez\t$1,2f\n\t"
  160.         "lw\t$1,(%4)\n\t"
  161.         "addiu\t%4,%4,4\n\t"
  162.         "beql\t%1,$1,1b\n\t"
  163.         "addiu\t%0,%0,32\n\t"
  164.         "li\t%1,1\n"
  165.         "1:\tand\t%4,$1,%1\n\t"
  166.         "beq\t$0,%4,2f\n\t"
  167.         "sll\t%1,%1,1\n\t"
  168.         "bne\t$0,%1,1b\n\t"
  169.         "add\t%0,%0,1\n\t"
  170.         ".set\tat\n\t"
  171.         ".set\treorder\n"
  172.         "2:"
  173.         : "=r" (res)
  174.         : "r" ((unsigned int) 0xffffffff),
  175.           "r" (size),
  176.           "0" ((signed int) 0),
  177.           "r" (addr)
  178.         : "$1");
  179.  
  180.     return res;
  181. }
  182.  
  183. extern __inline__ int find_next_zero_bit (void * addr, int size, int offset)
  184. {
  185.     unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
  186.     int set = 0, bit = offset & 31, res;
  187.     
  188.     if (bit) {
  189.         /*
  190.          * Look for zero in first byte
  191.          */
  192.         __asm__(".set\tnoreorder\n\t"
  193.             ".set\tnoat\n"
  194.             "1:\tand\t$1,%2,%1\n\t"
  195.             "beq\t$0,$1,2f\n\t"
  196.             "sll\t%2,%2,1\n\t"
  197.             "bne\t$0,%2,1b\n\t"
  198.             "addiu\t%0,%0,1\n\t"
  199.             ".set\tat\n\t"
  200.             ".set\treorder\n"
  201.             : "=r" (set)
  202.             : "r" (*p >> bit),
  203.               "r" (1),
  204.               "0" (0)
  205.             : "$1");
  206.         if (set < (32 - bit))
  207.             return set + offset;
  208.         set = 32 - bit;
  209.         p++;
  210.     }
  211.     /*
  212.      * No zero yet, search remaining full bytes for a zero
  213.      */
  214.     res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
  215.     return (offset + set + res);
  216. }
  217.  
  218. /*
  219.  * ffz = Find First Zero in word. Undefined if no zero exists,
  220.  * so code should check against ~0UL first..
  221.  */
  222. extern __inline__ unsigned long ffz(unsigned long word)
  223. {
  224.     unsigned int    __res;
  225.     unsigned int    mask = 1;
  226.  
  227.     __asm__ __volatile__ (
  228.         ".set\tnoreorder\n\t"
  229.         ".set\tnoat\n\t"
  230.         "li\t%2,1\n"
  231.         "1:\tand\t$1,%2,%1\n\t"
  232.         "beq\t$0,$1,2f\n\t"
  233.         "sll\t%2,%2,1\n\t"
  234.         "bne\t$0,%2,1b\n\t"
  235.         "add\t%0,%0,1\n\t"
  236.         ".set\tat\n\t"
  237.         ".set\treorder\n"
  238.         "2:\n\t"
  239.         : "=r" (__res), "=r" (word), "=r" (mask)
  240.         : "1" (~(word)),
  241.           "2" (mask),
  242.           "0" (0)
  243.         : "$1");
  244.  
  245.     return __res;
  246. }
  247.  
  248. #endif /* __ASM_MIPS_BITOPS_H */
  249.