URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [include/] [asm-mips/] [bitops.h] - Rev 1765
Compare with Previous | Blame | View Log
/* * include/asm-mips/bitops.h * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (c) 1994, 1995 Ralf Baechle */ #ifndef __ASM_MIPS_BITOPS_H #define __ASM_MIPS_BITOPS_H #if __mips > 1 /* * These functions for MIPS ISA >= 2 are interrupt and SMP proof and * interrupt friendly */ #include <asm/mipsregs.h> /* * The following functions will only work for the R4000! */ extern __inline__ int set_bit(int nr, void *addr) { int mask, retval, mw; addr += ((nr >> 3) & ~3); mask = 1 << (nr & 0x1f); do { mw = load_linked(addr); retval = (mask & mw) != 0; } while (!store_conditional(addr, mw|mask)); return retval; } extern __inline__ int clear_bit(int nr, void *addr) { int mask, retval, mw; addr += ((nr >> 3) & ~3); mask = 1 << (nr & 0x1f); do { mw = load_linked(addr); retval = (mask & mw) != 0; } while (!store_conditional(addr, mw & ~mask)); return retval; } extern __inline__ int change_bit(int nr, void *addr) { int mask, retval, mw; addr += ((nr >> 3) & ~3); mask = 1 << (nr & 0x1f); do { mw = load_linked(addr); retval = (mask & mw) != 0; } while (!store_conditional(addr, mw ^ mask)); return retval; } #else /* __mips <= 1 */ /* * These functions are only used for MIPS ISA 1 CPUs. Since I don't * believe that someone ever will run Linux/SMP on such a beast I don't * worry about making them SMP proof. */ #include <asm/system.h> #ifdef __KERNEL__ /* * Only disable interrupt for kernel mode stuff to keep usermode stuff * that dares to use kernel include files alive. */ #define __flags unsigned long flags #define __cli() cli() #define __save_flags(x) save_flags(x) #define __restore_flags(x) restore_flags(x) #endif /* __KERNEL__ */ extern __inline__ int set_bit(int nr, void * addr) { int mask, retval; int *a = addr; __flags; a += nr >> 5; mask = 1 << (nr & 0x1f); __save_flags(flags); __cli(); retval = (mask & *a) != 0; *a |= mask; __restore_flags(flags); return retval; } extern __inline__ int clear_bit(int nr, void * addr) { int mask, retval; int *a = addr; __flags; a += nr >> 5; mask = 1 << (nr & 0x1f); __save_flags(flags); __cli(); retval = (mask & *a) != 0; *a &= ~mask; __restore_flags(flags); return retval; } extern __inline__ int change_bit(int nr, void * addr) { int mask, retval; int *a = addr; __flags; a += nr >> 5; mask = 1 << (nr & 0x1f); __save_flags(flags); __cli(); retval = (mask & *a) != 0; *a ^= mask; __restore_flags(flags); return retval; } #undef __flags #undef __cli() #undef __save_flags(x) #undef __restore_flags(x) #endif /* __mips <= 1 */ extern __inline__ int test_bit(int nr, const void *addr) { return 1UL & (((const unsigned int *) addr)[nr >> 5] >> (nr & 31)); } extern __inline__ int find_first_zero_bit (void *addr, unsigned size) { int res; if (!size) return 0; __asm__(".set\tnoreorder\n\t" ".set\tnoat\n" "1:\tsubu\t$1,%2,%0\n\t" "blez\t$1,2f\n\t" "lw\t$1,(%4)\n\t" "addiu\t%4,%4,4\n\t" "beql\t%1,$1,1b\n\t" "addiu\t%0,%0,32\n\t" "li\t%1,1\n" "1:\tand\t%4,$1,%1\n\t" "beq\t$0,%4,2f\n\t" "sll\t%1,%1,1\n\t" "bne\t$0,%1,1b\n\t" "add\t%0,%0,1\n\t" ".set\tat\n\t" ".set\treorder\n" "2:" : "=r" (res) : "r" ((unsigned int) 0xffffffff), "r" (size), "0" ((signed int) 0), "r" (addr) : "$1"); return res; } extern __inline__ int find_next_zero_bit (void * addr, int size, int offset) { unsigned long * p = ((unsigned long *) addr) + (offset >> 5); int set = 0, bit = offset & 31, res; if (bit) { /* * Look for zero in first byte */ __asm__(".set\tnoreorder\n\t" ".set\tnoat\n" "1:\tand\t$1,%2,%1\n\t" "beq\t$0,$1,2f\n\t" "sll\t%2,%2,1\n\t" "bne\t$0,%2,1b\n\t" "addiu\t%0,%0,1\n\t" ".set\tat\n\t" ".set\treorder\n" : "=r" (set) : "r" (*p >> bit), "r" (1), "0" (0) : "$1"); if (set < (32 - bit)) return set + offset; set = 32 - bit; p++; } /* * No zero yet, search remaining full bytes for a zero */ res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr)); return (offset + set + res); } /* * ffz = Find First Zero in word. Undefined if no zero exists, * so code should check against ~0UL first.. */ extern __inline__ unsigned long ffz(unsigned long word) { unsigned int __res; unsigned int mask = 1; __asm__ __volatile__ ( ".set\tnoreorder\n\t" ".set\tnoat\n\t" "move\t%0,$0\n" "1:\tand\t$1,%2,%1\n\t" "beqz\t$1,2f\n\t" "sll\t%1,1\n\t" "bnez\t%1,1b\n\t" "addiu\t%0,1\n\t" ".set\tat\n\t" ".set\treorder\n" "2:\n\t" : "=r" (__res), "=r" (mask) : "r" (word), "1" (mask) : "$1"); return __res; } #endif /* __ASM_MIPS_BITOPS_H */