diff options
Diffstat (limited to 'include/asm-m68k/bitops.h')
-rw-r--r-- | include/asm-m68k/bitops.h | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/include/asm-m68k/bitops.h b/include/asm-m68k/bitops.h new file mode 100644 index 000000000..901fa48a0 --- /dev/null +++ b/include/asm-m68k/bitops.h @@ -0,0 +1,120 @@ +#ifndef _M68K_BITOPS_H +#define _M68K_BITOPS_H +/* + * Copyright 1992, Linus Torvalds. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file README.legal in the main directory of this archive + * for more details. + */ + +/* + * Require 68020 or better. + * + * They don't use the standard m680x0 bit ordering. + * Instead, the use the standard m680x0 bitfield ordering. + * + * Thus, bit 0 is the MSB of addr; bit 32 is the MSB of (addr+1). + */ + +extern __inline__ int set_bit(int nr,void * vaddr) +{ + char retval; + + __asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0" + : "=d" (retval) : "d" (nr), "a" (vaddr)); + + return retval; +} + +extern __inline__ int clear_bit(int nr, void * vaddr) +{ + char retval; + + __asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0" + : "=d" (retval) : "d" (nr), "a" (vaddr)); + + return retval; +} + +extern __inline__ int change_bit(int nr, void * vaddr) +{ + char retval; + + __asm__ __volatile__ ("bfchg %2@{%1:#1}; sne %0" + : "=d" (retval) : "d" (nr), "a" (vaddr)); + + return retval; +} + +extern __inline__ int test_bit(int nr, const void * vaddr) +{ + char retval; + + __asm__ __volatile__ ("bftst %2@{%1:#1}; sne %0" + : "=d" (retval) : "d" (nr), "a" (vaddr)); + + return retval; +} + +extern inline int find_first_zero_bit(void * vaddr, unsigned size) +{ + unsigned long res; + unsigned long *p; + unsigned long *addr = vaddr; + + if (!size) + return 0; + __asm__ __volatile__ (" moveq #-1,d0\n\t" + "1:" + " cmpl %1@+,d0\n\t" + " bne 2f\n\t" + " subql #1,%0\n\t" + " bne 1b\n\t" + " bra 5f\n\t" + "2:" + " movel %1@-,d0\n\t" + " notl d0\n\t" + " bfffo d0{#0,#0},%0\n\t" + "5:" + : "=d" (res), "=a" (p) + : "0" ((size + 31) >> 5), "1" (addr) + : "d0"); + return ((p - addr) << 5) + res; +} + +static inline int find_next_zero_bit (void *vaddr, int size, + int offset) +{ + unsigned long *addr = vaddr; + unsigned long *p = addr + (offset >> 5); + int set = 0, bit = offset & 31, res; + + if (bit) { + /* Look for zero in first longword */ + __asm__("bfffo %1{#0,#0},%0" + : "=d" (set) + : "d" (~*p << bit)); + 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 - 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) +{ + __asm__ __volatile__ ("bfffo %1{#0,#0},%0" + : "=d" (word) + : "d" (~(word))); + return word; +} + +#endif /* _M68K_BITOPS_H */ |